在 Windows 中设置深色模式后重绘标题栏

问题描述 投票:0回答:1

我正在使用以下库调用将窗口更改为深色模式:

BOOL dark = TRUE;
DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &dark, sizeof(dark));

这可行,但有一个小警告。标题栏不会更新,直到发生一些其他事件,例如最大化、失去焦点、调整大小等(但不移动窗口)。

我尝试过

UpdateWindow
RedrawWindow
上的大量标志组合,但没有成功。如何强制标题栏重绘?

编辑 我能够通过以编程方式调整窗口大小来强制重置,然后将其重置为之前的大小。但这似乎是一个糟糕的方法。一定有一个合适的解决方案。

c winapi
1个回答
0
投票

这就是我在 Windows 10 上调用

DwmSetWindowAttribute
后触发标题栏重绘的方式(尚未在 Windows 11 上测试)。正如 OP 所提到的,触发 WM_NCPAINT 的常用方法似乎都不起作用。此方法的工作原理是更改然后恢复窗口宽度。它以尽可能不可见的方式实现这一点,并且适用于正常窗口和最大化窗口。它使窗口宽度更小而不是更大,以避免潜在的溢出到辅助监视器上。

if (IsWindowVisible(hwnd) && !IsIconic(hwnd)) {
    // Get the current window rect.
    RECT rect = {};
    ::GetWindowRect(hwnd, &rect);

    if (IsZoomed(hwnd)) {
        // Window is currently maximized.
        WINDOWPLACEMENT placement = {};
        GetWindowPlacement(hwnd, &placement);

        // Remember the old restore rect.
        const RECT oldrect = placement.rcNormalPosition;

        // Change the restore rect to almost the same as the current
        // maximized rect.
        placement.rcNormalPosition = rect;
        placement.rcNormalPosition.right -= 1;
        SetWindowPlacement(hwnd, &placement);

        // Restore and then re-maximize the window. Don't update in-between.
        LockWindowUpdate(hwnd);
        ShowWindow(hwnd, SW_SHOWNORMAL);
        ShowWindow(hwnd, SW_SHOWMAXIMIZED);
        LockWindowUpdate(nullptr);

        // Put back the old restore rect.
        placement.rcNormalPosition = oldrect;
        SetWindowPlacement(hwnd, &placement);
    } else {
        // Window is currently normal. Change and then restore the window width.
        // Use Defer functions to make the change less noticeable. Don't update
        // in-between.
        HDWP defer = BeginDeferWindowPos(2);
        DeferWindowPos(defer, hwnd, NULL, 0, 0,
                       rect.right - rect.left - 1, rect.bottom - rect.top,
                       SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
        DeferWindowPos(defer, hwnd, NULL, 0, 0, rect.right - rect.left,
                       rect.bottom - rect.top,
                       SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
        LockWindowUpdate(hwnd);
        EndDeferWindowPos(defer);
        LockWindowUpdate(nullptr);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.