Skip to content

Commit

Permalink
Fix Basic Caption Text 1.1.0 (#1241)
Browse files Browse the repository at this point in the history
- Fix inactive state retrieval
- Remove "Use theme data" option; no edition of Windows ever did this
- Make using small window icons optional
- Refactor code to match modern Windhawk standards
  • Loading branch information
aubymori authored Nov 14, 2024
1 parent 82900d1 commit ee50aef
Showing 1 changed file with 49 additions and 107 deletions.
156 changes: 49 additions & 107 deletions mods/fix-basic-caption-text.wh.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// ==WindhawkMod==
// @id fix-basic-caption-text
// @name Fix Basic Caption Text
// @description Fixes non-DWM frames having hardcoded caption colors
// @version 1.0.0
// @description Fixes non-DWM and UIRibbon frames having incorrect caption colors
// @version 1.1.0
// @author aubymori
// @github https://github.com/aubymori
// @include *
Expand All @@ -12,12 +12,11 @@
// ==WindhawkModReadme==
/*
# Fix Basic Caption Text
Since Windows 10, the caption color has been hardcoded due to different accent
colors needing dark or light text. For whatever reason, this also applies to basic
frames, and as such, they don't pull caption color from the theme anymore. This
results in incorrectly colored and possibly illegible caption text. This mod fixes that.
Since Windows 10, the caption colors on basic themed has been changed to adapt to dark mode
among other things. This mod reverts it to the old behavior of just showing the user-defined
system colors. It also affects the caption color of custom-drawn title text like UIRibbon's.
**This mod requires Windhawk v1.4 or greater.**
You can also optionally make basic windows use small icons instead of downscaling large icons.
**Before**:
Expand All @@ -31,143 +30,86 @@ results in incorrectly colored and possibly illegible caption text. This mod fix

// ==WindhawkModSettings==
/*
- usethemedata: true
$name: Use theme data
$description: Use the theme data for caption color rather than system (classic theme) colors. Disable this if you experience incorrect colors.
- smallicons: true
$name: Small window icons
$description: Use small icons on basic theme windows instead of downscaling large icons
*/
// ==/WindhawkModSettings==

#include <windhawk_api.h>
#include <windhawk_utils.h>
#include <uxtheme.h>

#ifdef _WIN64
# define STDCALL __cdecl
# define SSTDCALL L"__cdecl"

# define THISCALL __cdecl
# define STHISCALL L"__cdecl"
#else
# define STDCALL __stdcall
# define SSTDCALL L"__stdcall"

# define THISCALL __thiscall
# define STHISCALL L"__thiscall"
#endif

#include <uxtheme.h>
#include <vssym32.h>
#include <versionhelpers.h>
#include <windhawk_utils.h>
bool g_bSmallIcons = true;

/* Use theme data or not */
BOOL g_bUseThemeData;
#define _NCWNDMET_Active(pThis) *((DWORD *)pThis + 21)

typedef DWORD (THISCALL *_NCWNDMET__GetCaptionColor_t)(LPVOID, bool);
_NCWNDMET__GetCaptionColor_t _NCWNDMET__GetCaptionColor_orig;
DWORD THISCALL _NCWNDMET__GetCaptionColor_hook(LPVOID pThis, bool bDarkText)
DWORD (__thiscall *_NCWNDMET__GetCaptionColor_orig)(LPVOID, bool);
DWORD __thiscall _NCWNDMET__GetCaptionColor_hook(LPVOID pThis, bool bDarkText)
{
#ifdef _WIN64
constexpr DWORD DEFAULT_INACTIVE_COLOR_DARK = RGB(99, 99, 99);
#else
constexpr DWORD DEFAULT_INACTIVE_COLOR_DARK = RGB(98, 98, 98);
#endif
constexpr DWORD DEFAULT_INACTIVE_COLOR_LIGHT = RGB(179, 184, 186);

DWORD res = _NCWNDMET__GetCaptionColor_orig(pThis, bDarkText);
DWORD dwCapClr;
BOOL bIsInactive = res == (bDarkText
? DEFAULT_INACTIVE_COLOR_DARK
: DEFAULT_INACTIVE_COLOR_LIGHT);

if (g_bUseThemeData)
{
HTHEME hTheme = OpenThemeData(NULL, L"Window");
if (hTheme && S_OK == GetThemeColor(
hTheme,
WP_CAPTION,
bIsInactive ? MB_INACTIVE : MB_ACTIVE,
TMT_TEXTCOLOR,
&dwCapClr
))
{
CloseThemeData(hTheme);
}
else
{
dwCapClr = GetSysColor(
bIsInactive ? COLOR_INACTIVECAPTIONTEXT : COLOR_CAPTIONTEXT
);
}
}
else
{
dwCapClr = GetSysColor(
bIsInactive ? COLOR_INACTIVECAPTIONTEXT : COLOR_CAPTIONTEXT
);
}

return dwCapClr;
return GetSysColor(
(_NCWNDMET_Active(pThis) != 1) ? COLOR_INACTIVECAPTIONTEXT : COLOR_CAPTIONTEXT
);
}

/* Always use small icon */
typedef HICON (__fastcall *_GetWindowIcon_t)(HWND, BOOL);
_GetWindowIcon_t _GetWindowIcon_orig;
HICON __fastcall _GetWindowIcon_hook(HWND hWnd, BOOL bLarge)
{
return _GetWindowIcon_orig(hWnd, FALSE);
if (g_bSmallIcons)
bLarge = FALSE;
return _GetWindowIcon_orig(hWnd, bLarge);
}

void LoadSettings(void)
{
g_bUseThemeData = Wh_GetIntSetting(L"usethemedata");
}
const WindhawkUtils::SYMBOL_HOOK uxthemeDllHooks[] = {
{
{
L"public: unsigned long "
STHISCALL
L" _NCWNDMET::GetCaptionColor(bool)"
},
&_NCWNDMET__GetCaptionColor_orig,
_NCWNDMET__GetCaptionColor_hook,
false
},
{
{
L"struct HICON__ * "
SSTDCALL
L" _GetWindowIcon(struct HWND__ *,int)"
},
&_GetWindowIcon_orig,
_GetWindowIcon_hook,
false
}
};

BOOL Wh_ModInit(void)
{
LoadSettings();

HMODULE hUxTheme = LoadLibrary(L"uxtheme.dll");
HMODULE hUxTheme = LoadLibraryW(L"uxtheme.dll");
if (!hUxTheme)
{
Wh_Log(L"could not load uxtheme; probably unsupported by the application");
Wh_Log(L"Failed to load uxtheme.dll");
return FALSE;
}

WindhawkUtils::SYMBOL_HOOK hooks[] = {
{
{
L"public: unsigned long "
STHISCALL
L" _NCWNDMET::GetCaptionColor(bool)"
},
&_NCWNDMET__GetCaptionColor_orig,
_NCWNDMET__GetCaptionColor_hook,
false
},
{
{
L"struct HICON__ * "
SSTDCALL
L" _GetWindowIcon(struct HWND__ *,int)"
},
&_GetWindowIcon_orig,
_GetWindowIcon_hook,
false
}
};

if (!WindhawkUtils::HookSymbols(
hUxTheme,
hooks,
ARRAYSIZE(hooks)
uxthemeDllHooks,
ARRAYSIZE(uxthemeDllHooks)
))
{
Wh_Log(L"Failed to install hooks");
Wh_Log(L"Failed to hook one or more symbol functions in uxtheme.dll");
return FALSE;
}

return TRUE;
}

void Wh_ModSettingsChanged(void)
{
LoadSettings();
}

0 comments on commit ee50aef

Please sign in to comment.