- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想用 C 创建一个 Windows API 应用程序,它在同一个非客户区呈现菜单和标题按钮,类似于 Firefox
为了做到这一点,我确定解决方案需要:
该解决方案需要适用于 Windows 7、8 和 10(理想情况下也适用于 future 版本)。
I have a test program available on GitHub .
在我的应用中,我覆盖了相应的事件:
WM_NCCALCSIZE
、WM_NCHITTEST
、WM_NCLBUTTONDOWN
、WM_NCLBUTTONUP
、WM_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);
}
}
渲染结果如下: 不幸的是,用于部件的样式(最小化、最大化/恢复、关闭)看起来像 Windows 7/8 的样式,而不是 native Windows 10 控件。几天来,我一直在寻找一种方法来做到这一点,但没有运气。我需要帮助了解如何使用 Windows API 为 Windows 10 呈现这些按钮。
我的第一个直觉是我需要正确启用视觉样式。
Per this article ,检查操作系统版本的调用将获得 Windows 8 除非您通过 list 专门针对 Windows 10。 Click here to view my manifest .这确实有效:
Per the official "Enabling Visual Styles" article ,我确保使用 Common Controls 版本 6。
我没有什么可以尝试的了。在认输之前,我打算尝试一些事情:
想法 1:使用 GetThemeStream它允许您检索控件的大小/位图。
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);
想法 2:从具有标题区域的隐藏窗口复制非客户区域(以及最小化、最大化、关闭按钮)。
最佳答案
我认为问题来自尝试在操作系统版本 >= 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/
问题描述 我想用 C 创建一个 Windows API 应用程序,它在同一个非客户区呈现菜单和标题按钮,类似于 Firefox 为了做到这一点,我确定解决方案需要: 输入 WS_POPUP,以便菜单与
我是一名优秀的程序员,十分优秀!