Instantly share code, notes, and snippets.
Created
June 27, 2025 19:11
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save PatoFlamejanteTV/3ab7d0493cd57b544c54165791498106 to your computer and use it in GitHub Desktop.
Dark-Purple version form the WindHawk's dark Win32 menu mod by Mgg Sk.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==WindhawkMod== | |
// @id mystic-menus | |
// @version 1.3 | |
// @author UltimateQuack, Mgg Sk | |
// @github https://github.com/PatoFlamejanteTV | |
// @include * | |
// @compilerOptions -lUxTheme -lGdi32 | |
// @name Purple-Dark mode context menus | |
// @description Enables a dark purple mode for all win32 menus. | |
// ==/WindhawkMod== | |
// ==WindhawkModReadme== | |
/*...*/ | |
// ==/WindhawkModReadme== | |
// ==WindhawkModSettings== | |
/*...*/ | |
// ==/WindhawkModSettings== | |
#include <uxtheme.h> | |
#include <vsstyle.h> | |
#include <windows.h> | |
#include <windhawk_api.h> | |
#include <winnt.h> | |
const COLORREF crItemForeground = 0xFFFFFF; | |
const COLORREF crItemDisabled = 0xAAAAAA; | |
const HBRUSH brBackground = CreateSolidBrush(0x2f002f); //0x262626 | |
const HBRUSH brItemBackgroundHot = CreateSolidBrush(0x3a0169); //0x353535 | |
const HBRUSH brItemBackgroundSelected = CreateSolidBrush(0x5a008a); //0x454545 | |
#define WM_UAHDRAWMENU 0x91 | |
#define WM_UAHDRAWMENUITEM 0x92 | |
union UAHMENUITEMMETRICS | |
{ | |
struct { | |
DWORD cx; | |
DWORD cy; | |
} rgsizeBar[2]; | |
struct { | |
DWORD cx; | |
DWORD cy; | |
} rgsizePopup[4]; | |
}; | |
struct UAHMENUPOPUPMETRICS | |
{ | |
DWORD rgcx[4]; | |
DWORD fUpdateMaxWidths : 2; | |
}; | |
struct UAHMENU | |
{ | |
HMENU hMenu; | |
HDC hdc; | |
DWORD dwFlags; | |
}; | |
struct UAHMENUITEM | |
{ | |
int iPosition; | |
UAHMENUITEMMETRICS umim; | |
UAHMENUPOPUPMETRICS umpm; | |
}; | |
struct UAHDRAWMENUITEM | |
{ | |
DRAWITEMSTRUCT dis; | |
UAHMENU um; | |
UAHMENUITEM umi; | |
}; | |
//Code based on : https://github.com/notepad-plus-plus/notepad-plus-plus/blob/bab3573be708bb908b8080e3e2007ea78a7f1932/PowerEditor/src/NppDarkMode.cpp | |
#pragma region CodeBasedOnNotepad++ | |
void DrawUAHMenuNCBottomLine(HWND hWnd) | |
{ | |
MENUBARINFO mbi = { sizeof(mbi) }; | |
if (!GetMenuBarInfo(hWnd, OBJID_MENU, 0, &mbi)) | |
return; | |
RECT rcClient; | |
GetClientRect(hWnd, &rcClient); | |
MapWindowPoints(hWnd, nullptr, (LPPOINT)&rcClient, 2); | |
RECT rcWindow; | |
GetWindowRect(hWnd, &rcWindow); | |
OffsetRect(&rcClient, -rcWindow.left, -rcWindow.top); | |
// the rcBar is offset by the window rect | |
RECT rcAnnoyingLine = rcClient; | |
rcAnnoyingLine.bottom = rcAnnoyingLine.top; | |
rcAnnoyingLine.top--; | |
HDC hdc = GetWindowDC(hWnd); | |
FillRect(hdc, &rcAnnoyingLine, brBackground); | |
ReleaseDC(hWnd, hdc); | |
} | |
#pragma endregion CodeBasedOnNotepad++ | |
//Code based on https://github.com/adzm/win32-darkmode/blob/darkmenubar/win32-darkmode/win32-darkmode.cpp | |
#pragma region CodeBasedOnWin32DarkMode | |
thread_local HTHEME g_menuTheme = nullptr; | |
//Processes messages related to custom menubar drawing. | |
//Returns true if handled, false to continue with normal processing | |
bool CALLBACK UAHWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* lpResult) | |
{ | |
switch (uMsg) | |
{ | |
case WM_UAHDRAWMENU: | |
{ | |
const auto* pUdm = (UAHMENU*)lParam; | |
RECT rc; | |
//Get the menubar rect | |
MENUBARINFO mbi { sizeof(MENUBARINFO) }; | |
GetMenuBarInfo(hWnd, OBJID_MENU, 0, &mbi); | |
RECT rcWindow; | |
GetWindowRect(hWnd, &rcWindow); | |
//The rcBar is offset by the window rect | |
rc = mbi.rcBar; | |
OffsetRect(&rc, -rcWindow.left, -rcWindow.top); | |
FillRect(pUdm->hdc, &rc, brBackground); | |
return true; | |
} | |
case WM_UAHDRAWMENUITEM: | |
{ | |
auto* pUDMI = (UAHDRAWMENUITEM*)lParam; | |
const HBRUSH* pbrBackground = &brBackground; | |
//Get the menu item string | |
wchar_t menuString[256] = { 0 }; | |
MENUITEMINFO mii = { sizeof(mii), MIIM_STRING }; | |
{ | |
mii.dwTypeData = menuString; | |
mii.cch = (sizeof(menuString) / 2) - 1; | |
GetMenuItemInfoW(pUDMI->um.hMenu, pUDMI->umi.iPosition, TRUE, &mii); | |
} | |
//Get the item state for drawing | |
DWORD dwFlags = DT_CENTER | DT_SINGLELINE | DT_VCENTER; | |
int iTextStateID = 0; | |
if ((pUDMI->dis.itemState & ODS_INACTIVE) || (pUDMI->dis.itemState & ODS_DEFAULT)) | |
iTextStateID = MBI_NORMAL; | |
else if (pUDMI->dis.itemState & ODS_HOTLIGHT) | |
iTextStateID = MBI_HOT; | |
else if (pUDMI->dis.itemState & ODS_SELECTED) | |
iTextStateID = MBI_PUSHED; | |
else if ((pUDMI->dis.itemState & ODS_GRAYED) || (pUDMI->dis.itemState & ODS_DISABLED)) | |
iTextStateID = MBI_DISABLED; | |
if (pUDMI->dis.itemState & ODS_HOTLIGHT) | |
pbrBackground = &brItemBackgroundHot; | |
else if (pUDMI->dis.itemState & ODS_SELECTED) | |
pbrBackground = &brItemBackgroundSelected; | |
if (pUDMI->dis.itemState & ODS_NOACCEL) | |
dwFlags |= DT_HIDEPREFIX; | |
if (!g_menuTheme) | |
g_menuTheme = OpenThemeData(hWnd, L"Menu"); | |
const DTTOPTS opts { sizeof(opts), DTT_TEXTCOLOR, iTextStateID != MBI_DISABLED ? crItemForeground : crItemDisabled }; | |
FillRect(pUDMI->um.hdc, &pUDMI->dis.rcItem, *pbrBackground); | |
DrawThemeTextEx(g_menuTheme, pUDMI->um.hdc, MENU_BARITEM, MBI_NORMAL, menuString, mii.cch, dwFlags, &pUDMI->dis.rcItem, &opts); | |
return true; | |
} | |
case WM_THEMECHANGED: | |
{ | |
CloseThemeData(g_menuTheme); | |
g_menuTheme = nullptr; | |
return false; | |
} | |
default: | |
return false; | |
} | |
} | |
#pragma endregion | |
using RtlGetNtVersionNumbers_T = void (WINAPI *)(LPDWORD, LPDWORD, LPDWORD); | |
RtlGetNtVersionNumbers_T RtlGetNtVersionNumbers; | |
using DefWindowProcW_T = decltype(&DefWindowProcW); | |
DefWindowProcW_T DefWindowProcW_Original; | |
enum AppMode | |
{ | |
Default, | |
AllowDark, | |
ForceDark, | |
ForceLight, | |
Max | |
}; | |
using FlushMenuThemes_T = void(WINAPI*)(); | |
using SetPreferredAppMode_T = AppMode(WINAPI*)(AppMode); | |
using ShouldAppsUseDarkMode_T = bool(WINAPI*)(); | |
FlushMenuThemes_T FlushMenuThemes; | |
SetPreferredAppMode_T SetPreferredAppMode; | |
ShouldAppsUseDarkMode_T ShouldAppsUseDarkMode; | |
AppMode g_currentAppMode; | |
LRESULT CALLBACK DefWindowProcW_Hook(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) | |
{ | |
if(g_currentAppMode == AppMode::ForceDark || (g_currentAppMode == AppMode::AllowDark && ShouldAppsUseDarkMode())) | |
{ | |
LRESULT lResult = 0; | |
if(UAHWndProc(hWnd, uMsg, wParam, lParam, &lResult)) | |
return lResult; | |
if(uMsg == WM_ACTIVATE || uMsg == WM_NCPAINT) | |
{ | |
lResult = DefWindowProcW_Original(hWnd, uMsg, wParam, lParam); | |
DrawUAHMenuNCBottomLine(hWnd); | |
return lResult; | |
} | |
} | |
return DefWindowProcW_Original(hWnd, uMsg, wParam, lParam); | |
} | |
//Applies the theme to all menus. | |
void ApplyTheme(const AppMode inputTheme = Max) | |
{ | |
AppMode theme = inputTheme; | |
//Get the saved theme from the settings. | |
if(theme == Max) | |
{ | |
const PCWSTR savedTheme = Wh_GetStringSetting(L"AppMode"); | |
if(wcscmp(savedTheme, L"AllowDark") == 0) | |
theme = AllowDark; | |
else if(wcscmp(savedTheme, L"ForceLight") == 0) | |
theme = ForceLight; | |
else | |
theme = ForceDark; | |
Wh_FreeStringSetting(savedTheme); | |
} | |
//Apply the theme | |
FlushMenuThemes(); | |
SetPreferredAppMode(theme); | |
g_currentAppMode = theme; | |
} | |
//Checks if the windows build is 18362 or later. | |
bool IsAPISupported() | |
{ | |
if(!RtlGetNtVersionNumbers) | |
{ | |
const HMODULE hNtDll = LoadLibraryExW(L"ntdll.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); | |
const FARPROC pRtlGetNtVersionNumbers = GetProcAddress(hNtDll, "RtlGetNtVersionNumbers"); | |
RtlGetNtVersionNumbers = reinterpret_cast<RtlGetNtVersionNumbers_T>(pRtlGetNtVersionNumbers); | |
} | |
DWORD build; | |
RtlGetNtVersionNumbers(nullptr, nullptr, &build); | |
build &= ~0xF0000000; | |
return build >= 18362; | |
} | |
//Updates the theme of the window when the settings change. | |
void Wh_ModSettingsChanged() | |
{ | |
Wh_Log(L"Settings changed"); | |
ApplyTheme(); | |
} | |
//Import functions | |
BOOL Wh_ModInit() { | |
if(!IsAPISupported()) | |
{ | |
Wh_Log(L"Outdated Windows version!"); | |
return FALSE; | |
} | |
Wh_Log(L"Init"); | |
if(!Wh_SetFunctionHook((void*)DefWindowProcW, (void*)DefWindowProcW_Hook, (void**)&DefWindowProcW_Original)) | |
return FALSE; | |
const HMODULE hUxtheme = LoadLibraryExW(L"uxtheme.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); | |
const FARPROC pSetPreferredAppMode = GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135)); | |
const FARPROC pFlushMenuThemes = GetProcAddress(hUxtheme, MAKEINTRESOURCEA(136)); | |
const FARPROC pShouldAppsUseDarkMode = GetProcAddress(hUxtheme, MAKEINTRESOURCEA(132)); | |
SetPreferredAppMode = reinterpret_cast<SetPreferredAppMode_T>(pSetPreferredAppMode); | |
FlushMenuThemes = reinterpret_cast<FlushMenuThemes_T>(pFlushMenuThemes); | |
ShouldAppsUseDarkMode = reinterpret_cast<ShouldAppsUseDarkMode_T>(pShouldAppsUseDarkMode); | |
ApplyTheme(); | |
return TRUE; | |
} | |
//Restores the default theme. | |
void Wh_ModUninit() | |
{ | |
Wh_Log(L"Restoring the default theme."); | |
ApplyTheme(Default); | |
DeleteObject(brBackground); | |
DeleteObject(brItemBackgroundHot); | |
DeleteObject(brItemBackgroundSelected); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment