[Win32] フォームダークモード、C++、WinForm、WPFの使い方、カラーモードの判定、色変更メッセージへの応答、タイトルバーのダークカラーの設定。

2023 年です。私たちが作成するプログラムがダーク モードをサポートしていなければ、それは正当化されません。

ダークモードかどうかを判断する

Windows では、現在のシステムのカラー モードがダークかどうかを判断するには、レジストリ キーを照会することで実現できます。

C++ のサンプル コードは次のとおりです。

HKEY hKey;
const wchar_t* subKey = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
const wchar_t* valueName = L"AppsUseLightTheme";
DWORD value = -1;
DWORD valueSize = sizeof(DWORD);
if (RegOpenKeyEx(HKEY_CURRENT_USER, subKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
    
    
    HRESULT hr = RegGetValue(hKey, nullptr, valueName, RRF_RT_REG_DWORD, nullptr, &value, &valueSize);
    if (hr != S_OK)
    {
    
    
        value = -1;    // 不要假定该键必须存在,如果找不到将返回默认值
    }
    RegCloseKey(hKey);
}

if (value == 0)
{
    
    
    // 当前使用暗色主题
}
else if (value == 1)
{
    
    
    // 当前使用亮色主题
}
else
{
    
    
    // 无法确定当前主题
}

C# のサンプル コードは次のとおりです。

using Microsoft.Win32;

RegistryKey key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize");
if (key != null)
{
    
    
    int appsUseLightTheme = (int)key.GetValue("AppsUseLightTheme", -1);
    if (appsUseLightTheme == 0)
    {
    
    
        // 当前使用暗色主题
    }
    else if (appsUseLightTheme == 1)
    {
    
    
        // 当前使用亮色主题
    }
    else
    {
    
    
        // 无法确定当前主题
    }
    key.Close();
}

ウィンドウをダークモードに設定する

Windows にはダーク モード WinAPI が付属しており、これを直接呼び出してウィンドウのタイトル バーを暗い色に変えることができます。

C++ のサンプル コードは次のとおりです。

#include <windows.h>
#include <dwmapi.h>

int main() {
    
    
	HWND hWnd = GetMainWindowHandle(); // 获取主窗口句柄
	DWORD dwAttribute = DWMWA_USE_IMMERSIVE_DARK_MODE; // 设置暗色模式属性
	BOOL bValue = TRUE; // 启用暗色模式
	DwmSetWindowAttribute(hWnd, dwAttribute, &bValue, sizeof(bValue)); // 设置窗口属性

	return 0;
}

C# のサンプル コードは次のとおりです。

[DllImport("dwmapi.dll", PreserveSig = true)]
public static extern int DwmSetWindowAttribute(IntPtr hwnd, DwmWindowAttribute attr, ref int attrValue, int attrSize);

public static bool EnableDarkModeForWindow(IntPtr hWnd, bool enable)
{
    
    
	int darkMode = enable ? 1 : 0;
	int hr = DwmSetWindowAttribute(hWnd, DwmWindowAttribute.UseImmersiveDarkMode, ref darkMode, sizeof(int));
	return hr >= 0;
}

public enum DwmWindowAttribute : uint
{
    
    
	NCRenderingEnabled = 1,
	NCRenderingPolicy,
	TransitionsForceDisabled,
	AllowNCPaint,
	CaptionButtonBounds,
	NonClientRtlLayout,
	ForceIconicRepresentation,
	Flip3DPolicy,
	ExtendedFrameBounds,
	HasIconicBitmap,
	DisallowPeek,
	ExcludedFromPeek,
	Cloak,
	Cloaked,
	FreezeRepresentation,
	PassiveUpdateMode,
	UseHostBackdropBrush,
	UseImmersiveDarkMode = 20,
	WindowCornerPreference = 33,
	BorderColor,
	CaptionColor,
	TextColor,
	VisibleFrameBorderThickness,
	SystemBackdropType,
	Last
}

色の変化に対応する

システムの色が変わると、THEMECHANGEDすべてのウィンドウにメッセージが送信されます。

C++ では、このメッセージを WndProc でキャプチャし、特定の操作を実行できます (たとえば、前述したように、ウィンドウをダーク モードに設定します)。

#include <Windows.h>
#include <iostream>

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int main() {
    
    
    // 注册窗口类
    WNDCLASS wc = {
    
    };
    wc.lpfnWndProc = WndProc;
    wc.hInstance = GetModuleHandle(NULL);
    wc.lpszClassName = L"MyWindowClass";
    if (!RegisterClass(&wc)) {
    
    
        std::cerr << "Failed to register window class" << std::endl;
        return 1;
    }

    // 创建窗口
    HWND hwnd = CreateWindow(
        L"MyWindowClass",
        L"My Window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, GetModuleHandle(NULL), NULL
    );
    if (!hwnd) {
    
    
        std::cerr << "Failed to create window" << std::endl;
        return 1;
    }

    // 显示窗口
    ShowWindow(hwnd, SW_SHOWDEFAULT);

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
    
    
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    
    
    switch (uMsg) {
    
    
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    case WM_THEMECHANGED:
        std::cout << "Theme changed" << std::endl;
        return 0;
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
}

C# の場合、WinForm または WPF を使用している場合は、このイベントをサブスクライブし、特定のカテゴリを判断して、最終的に操作を実行することで、イベントを持つC# のカプセル化されたSystemEventsクラスを直接使用できます。UserPreferenceChanged

SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;

private void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
{
    
    
    if (e.Category == UserPreferenceCategory.General)
    {
    
    
        // 更新颜色主题
    }
}

おすすめ

転載: blog.csdn.net/m0_46555380/article/details/129945529