Cod*_*ard 8 windows winapi themes
从October 2018 Update (version 1809)Win10 开始,Windows资源管理器中已支持Dark主题。
可以在这里配置:
Desktop | Context Menu | Personalize | Colors | Choose your default app mode = DarkHKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize\AppsUseLightTheme=DWORD:0尽管此设置已经存在了一段时间,但它仅影响UWP应用程序。但是,在此Windows 10版本中,它也会影响Windows资源管理器,后者是一个桌面应用程序。这意味着Windows现在对其具有内部支持。但是,Windows资源管理器以外的桌面应用程序目前不受影响。
我想在我的应用程序中使用它。它是如何实现的?是否有某种方式(清单,WINAPI等)订阅新的深色主题?
更新1:
我注意到Windows资源管理器控制面板部分亮而部分暗,因此它应该是每个窗口设置,而不是每个进程设置。
另一个示例:在所有桌面应用程序中,“打开文件”对话框均变暗,而应用程序本身仍保持旧的主题。
更新2:
我尝试SetWindowTheme(hwnd, L"Explorer", NULL);了TreeView和ListView。这会明显改变TreeView样式(+展开按钮变为V),但窗口保持白色。
dya*_*sta 12
见https://github.com/ysc3839/win32-darkmode
这家伙在一些不错的可重用代码(MIT 许可证)中列出了所有内容。
暗模式似乎仍然是 Windows 10 中的一个开发领域,但我相信微软最终会正确记录并将其公开给桌面应用程序。
在那之前,我们一直在使用未记录的仅有序导入,然后自定义绘制和WM_CTLCOLOR*消息来指示如何绘制尚不具有本机暗模式支持的控件。
最基本的新 Windows API 是SetPreferredAppMode( uxtheme@135),在任何窗口创建之前调用,以及AllowDarkModeForWindow( uxtheme@133),在打算使用本机 Windows 10 暗模式支持的任何窗口上调用。
以下是该项目中仅按序导入的完整列表:
using fnRtlGetNtVersionNumbers = void (WINAPI *)(LPDWORD major, LPDWORD minor, LPDWORD build);
// 1809 17763
using fnShouldAppsUseDarkMode = bool (WINAPI *)(); // ordinal 132
using fnAllowDarkModeForWindow = bool (WINAPI *)(HWND hWnd, bool allow); // ordinal 133
using fnAllowDarkModeForApp = bool (WINAPI *)(bool allow); // ordinal 135, removed since 18334
using fnFlushMenuThemes = void (WINAPI *)(); // ordinal 136
using fnRefreshImmersiveColorPolicyState = void (WINAPI *)(); // ordinal 104
using fnIsDarkModeAllowedForWindow = bool (WINAPI *)(HWND hWnd); // ordinal 137
using fnGetIsImmersiveColorUsingHighContrast = bool (WINAPI *)(IMMERSIVE_HC_CACHE_MODE mode); // ordinal 106
using fnOpenNcThemeData = HTHEME(WINAPI *)(HWND hWnd, LPCWSTR pszClassList); // ordinal 49
// Insider 18290
using fnShouldSystemUseDarkMode = bool (WINAPI *)(); // ordinal 138
// Insider 18334
using fnSetPreferredAppMode = PreferredAppMode (WINAPI *)(PreferredAppMode appMode); // ordinal 135, since 18334
using fnIsDarkModeAllowedForApp = bool (WINAPI *)(); // ordinal 139
Run Code Online (Sandbox Code Playgroud)
InitDarkMode 以安全的方式导入和初始化暗模式,仔细检查最小和最大支持的 Windows 10 版本:
void InitDarkMode()
{
fnRtlGetNtVersionNumbers RtlGetNtVersionNumbers = reinterpret_cast<fnRtlGetNtVersionNumbers>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlGetNtVersionNumbers"));
if (RtlGetNtVersionNumbers)
{
DWORD major, minor;
RtlGetNtVersionNumbers(&major, &minor, &g_buildNumber);
g_buildNumber &= ~0xF0000000;
if (major == 10 && minor == 0 && 17763 <= g_buildNumber && g_buildNumber <= 18363) // Windows 10 1809 10.0.17763 - 1909 10.0.18363
{
HMODULE hUxtheme = LoadLibraryExW(L"uxtheme.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (hUxtheme)
{
_OpenNcThemeData = reinterpret_cast<fnOpenNcThemeData>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(49)));
_RefreshImmersiveColorPolicyState = reinterpret_cast<fnRefreshImmersiveColorPolicyState>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(104)));
_GetIsImmersiveColorUsingHighContrast = reinterpret_cast<fnGetIsImmersiveColorUsingHighContrast>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(106)));
_ShouldAppsUseDarkMode = reinterpret_cast<fnShouldAppsUseDarkMode>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(132)));
_AllowDarkModeForWindow = reinterpret_cast<fnAllowDarkModeForWindow>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(133)));
auto ord135 = GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135));
if (g_buildNumber < 18334)
_AllowDarkModeForApp = reinterpret_cast<fnAllowDarkModeForApp>(ord135);
else
_SetPreferredAppMode = reinterpret_cast<fnSetPreferredAppMode>(ord135);
//_FlushMenuThemes = reinterpret_cast<fnFlushMenuThemes>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(136)));
_IsDarkModeAllowedForWindow = reinterpret_cast<fnIsDarkModeAllowedForWindow>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(137)));
if (_OpenNcThemeData &&
_RefreshImmersiveColorPolicyState &&
_ShouldAppsUseDarkMode &&
_AllowDarkModeForWindow &&
(_AllowDarkModeForApp || _SetPreferredAppMode) &&
//_FlushMenuThemes &&
_IsDarkModeAllowedForWindow)
{
g_darkModeSupported = true;
AllowDarkModeForApp(true);
_RefreshImmersiveColorPolicyState();
g_darkModeEnabled = _ShouldAppsUseDarkMode() && !IsHighContrast();
FixDarkScrollBar();
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在其他地方,他利用WM_CTLCOLOR*消息和自定义绘制通知在 Windows(尚未)为我们做的地方绘制黑暗。
请注意FixDarkScrollBar. 这是一个 IAT 挂钩,OpenNcThemeData用于覆盖comctl32. 这是最让我烦恼的部分,我正在寻求解决它。我确定他也是。
我已将此代码改编为我自己的应用程序,并且运行良好。然而,我对使用这些未记录的仅有序 API 感到不舒服(即使尽可能安全),并且完全期望 Microsoft 最终宣布并记录 Win32 应用程序的暗模式并使这项工作变得多余。
经过一些挖掘,我找到了这两种方法。两者均未记录,如有更改,恕不另行通知。
1个
SetWindowTheme(hwnd, L"DarkMode_Explorer", NULL);
Run Code Online (Sandbox Code Playgroud)
2
using TYPE_AllowDarkModeForWindow = bool (WINAPI *)(HWND a_HWND, bool a_Allow);
static const TYPE_AllowDarkModeForWindow AllowDarkModeForWindow = (TYPE_AllowDarkModeForWindow)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(133));
AllowDarkModeForWindow(a_HWND, true);
SetWindowTheme(hwnd, L"Explorer", NULL);
Run Code Online (Sandbox Code Playgroud)
警告: Ordinal 133在其他版本的Windows(包括较新/较旧的Win10版本)上可能具有完全不同的API。
两种方法都具有一定的效果,但并非全部。
例如,TreeView获取选定项目的深色滚动条和深色背景,但其余背景保持默认。
不幸的是,到目前为止,这还不像“调用函数就这样”。似乎即使应用了正确的主题,某些背景色也需要手动处理。
| 归档时间: |
|
| 查看次数: |
1977 次 |
| 最近记录: |