[Win32] Formar modo oscuro, cómo usar C++, WinForm, WPF, juzgar el modo de color, responder al mensaje de cambio de color, establecer el color oscuro de la barra de título.

Es 2023, si el programa que escribimos no admite el modo oscuro, entonces no está justificado.

Determinar si es modo oscuro

En Windows, para determinar si el modo de color del sistema actual es oscuro, se puede realizar consultando la clave de registro.

Aquí está el código de ejemplo en 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
{
    
    
    // 无法确定当前主题
}

Aquí está el código de ejemplo de 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();
}

Establecer el modo oscuro de la ventana

Windows viene con una WinAPI en modo oscuro, a la que se puede llamar directamente para convertir la barra de título de la ventana en un color oscuro.

Aquí está el código de ejemplo en 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;
}

Aquí está el código de muestra en 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
}

Responde al cambio de color

Cuando cambia el color del sistema, THEMECHANGEDse envía un mensaje a todas las ventanas:

En C++, puede capturar este mensaje en WndProc y luego realizar operaciones específicas.Por ejemplo, como se mencionó anteriormente, establecer el modo oscuro de la ventana.

#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);
    }
}

Para C#, si usa WinForm o WPF, puede usar directamente la SystemEventsclase encapsulada de C#, que tiene un UserPreferenceChangedevento, suscribiéndose a este evento, juzgando la categoría específica y, finalmente, realizando la operación:

SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;

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

Supongo que te gusta

Origin blog.csdn.net/m0_46555380/article/details/129945529
Recomendado
Clasificación