gpt4 book ai didi

c - 在 Windows 10 上使用 DrawThemeBackground 绘制的部分不正确

转载 作者:太空狗 更新时间:2023-10-29 16:56:47 24 4
gpt4 key购买 nike

问题描述

我想用 C 创建一个 Windows API 应用程序,它在同一个非客户区呈现菜单和标题按钮,类似于 Firefox notice the menu and caption buttons

为了做到这一点,我确定解决方案需要:

  • 输入 WS_POPUP,以便菜单与顶部对齐
  • 取得非客户区(呈现菜单的地方)的所有权
  • 手动渲染最小化/最大化/关闭按钮

该解决方案需要适用于 Windows 7、8 和 10(理想情况下也适用于 future 版本)。

现在的样子

I have a test program available on GitHub .

在我的应用中,我覆盖了相应的事件:

WM_NCCALCSIZEWM_NCHITTESTWM_NCLBUTTONDOWNWM_NCLBUTTONUPWM_NCMOUSEMOVE >WM_NCPAINT

然后我重新绘制这些事件的非客户区:WM_NCACTIVATE, WM_SETTEXT

这是我如何进行渲染的示例:

// globals set elsewhere
RECT customAreaRect, minRect, maxRect, closeRect, coverMenuRect;
BOOL maximized;

// ...

LRESULT OnPaintNCA(HWND hWnd, WPARAM wParam, LPARAM lParam) {
RECT windowRect;
HRGN hRgn = NULL;
GetWindowRect(hWnd, &windowRect);
if (wParam == 1) {
hRgn = CreateRectRgnIndirect(&windowRect);
} else {
hRgn = (HRGN)wParam;
}

if (hRgn) {
// Carve out the area for custom content
HRGN captionButtonRgn = CreateRectRgnIndirect(&customAreaRect);
CombineRgn(hRgn, hRgn, captionButtonRgn, RGN_XOR);
DeleteObject(captionButtonRgn);

// Force default painting for non-client area
LRESULT ret = DefWindowProc(hWnd, WM_NCPAINT, (WPARAM)hRgn, 0);

// black background covering part of menu, behind buttons
HDC hDC = GetWindowDC(hWnd);
FillRect(hDC, &coverMenuRect, (HBRUSH)GetStockObject(BLACK_BRUSH));

HTHEME hTheme = OpenThemeData(hWnd, TEXT("WINDOW"));

DrawThemeBackground(hTheme, hDC, WP_MINBUTTON, partState, minRect, NULL);
DrawThemeBackground(hTheme, hDC, maximized ? WP_RESTOREBUTTON : WP_MAXBUTTON, partState, maxRect, NULL);
DrawThemeBackground(hTheme, hDC, WP_CLOSEBUTTON, partState, closeRect, NULL);

CloseThemeData(hTheme);
}
}

渲染结果如下: screenshot showing what I have now不幸的是,用于部件的样式(最小化、最大化/恢复、关闭)看起来像 Windows 7/8 的样式,而不是 native Windows 10 控件。几天来,我一直在寻找一种方法来做到这一点,但没有运气。我需要帮助了解如何使用 Windows API 为 Windows 10 呈现这些按钮。

当前状态(以及我到目前为止所做的尝试)

我的第一个直觉是我需要正确启用视觉样式。

下面是我尝试过的一些相关项目设置的截图: target platform version

embed manifest

其他想法

我没有什么可以尝试的了。在认输之前,我打算尝试一些事情:

  • 想法 1:使用 GetThemeStream它允许您检索控件的大小/位图。

    • 像这样加载 aero msstyles 文件:

    HMODULE themeFile = LoadLibraryEx(TEXT("C:\\Windows\\Resources\\Themes\\aero\\aero.msstyles"), NULL, LOAD_LIBRARY_AS_DATAFILE);

    • 像这样获取部分(最小化按钮、最大化按钮等)的位图(传递加载的主题文件):

    GetThemeStream(h, WP_MAXBUTTON, MAXBS_NORMAL, TMT_DISKSTREAM, (void**)&buffer, &bufferSize, themeFile);

    • 加载位图;它似乎是 PNG 格式(我还没有做到这一点)
    • 绘制位图
  • 想法 2:从具有标题区域的隐藏窗口复制非客户区域(以及最小化、最大化、关闭按钮)。

    • 创建一个带有标题和最小/最大按钮的窗口,但不要激活它。
    • 在非客户端绘制中,获取该窗口的 DC 并捕获最小/最大/关闭按钮的像素
    • 使用 bitblt 渲染它们

最佳答案

我认为问题来自尝试在操作系统版本 >= Win Vista 上使用 WM_NCPAINT。由于 Vista 所有 NC 渲染都由 DWM(桌面窗口管理器)控制。如果您仍然敢于处理 WM_NCPAINT,DWM 渲染将被关闭,您将获得“老式”外观:

From the Shell Revealed Blog :

The DWM doesnt have any legacy worries because applications cannot draw inside the glass frame, since its rendered and managed by a totally different process. If an application tries to do it, Windows will detect it and remove the glass frame entirely (and therefore revert to the Basic frame), so that the application can draw what it wants to draw.

要获得正确的结果,您必须执行“DWM way”(特别是“删除标准框架”和“在扩展框架窗口中绘图”部分)。这是通过让 DWM 在客户区内渲染框架来实现的,因此您可以在其上绘制。此外,使用此解决方案,您不必自己绘制标题按钮。 This answer summarizes the required steps (在“Aero 支持的解决方案”下)。

需要注意的是,您可能必须自己绘制菜单并且您不能为此使用大部分 GDI API,因为 GDI 会忽略 alpha channel 并且如果框架是半透明的(Vista 和 Win默认为 7,Win8+ 带有扩展)。如果源是包含带 alpha channel 的 32bpp 位图的内存 DC,则 BitBlt() 有效。 GDI+ 也适用。

关于c - 在 Windows 10 上使用 DrawThemeBackground 绘制的部分不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39319441/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com