我在Windows 10上使用DwmExtendFrameIntoClientArea
扩展窗口框架时遇到一些问题。下面的图片显示了我得到的行为:
白色标题栏颜色从顶部延伸,而从侧面和底部延伸,它延伸了窗口的彩色边缘。
如果我将边距全部设置为-1
以将框架一直延伸,则窗口将填充白色并完全失去其彩色边缘:
这个结果非常不一致,我希望在窗口的所有侧面都可以扩展白色,类似于Windows 8中彩色框架的扩展方式,或者在Windows 7和Vista中扩展了玻璃。
我尝试过在线搜索,但我找不到任何类似的问题。
以下是我正在使用的代码:
#include <windows.h>
#include <dwmapi.h>
#include <stdio.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int main(int argc, char **argv)
{
HINSTANCE hInstance = GetModuleHandle(NULL);
MSG msg;
HWND hwnd;
WNDCLASSW wc;
int message;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.lpszClassName = L"Window";
wc.hInstance = hInstance;
wc.hbrBackground = GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassW(&wc);
hwnd = CreateWindowW(wc.lpszClassName, L"Window",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 350, 250, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
while(1) {
message = GetMessageW(&msg, NULL, 0, 0);
if(message == -1)
{
char x[100];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), x, 100, NULL);
puts(x);
abort();
}
else if(message == 0) break;
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_ACTIVATE:
{
MARGINS m = {50, 50, 50, 50};
HRESULT hr = DwmExtendFrameIntoClientArea(hwnd, &m);
if(!SUCCEEDED(hr))
{
char x[100];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), x, 100, NULL);
puts(x);
abort();
}
break;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
我做错了什么或者这只是Windows 10的一个问题?在此先感谢您的帮助!
编辑:我发布的代码与Windows 10上的Aero Lite和高对比度主题完美配合,但与默认的Windows 10主题无关。
答案 0 :(得分:1)
当框架已扩展到客户区域时,您需要确保客户区绘制程序在 glass 所在的任何位置绘制纯黑色。
来自MSDN:
确保扩展帧可见的最简单方法是将整个客户端区域绘制为黑色。要完成此操作,请将WNDCLASS或WNDCLASSEX结构的 hbrBackground 成员初始化为BLACK_BRUSH库存的句柄。下图显示了前面显示的相同标准框架(左)和扩展框架(右)。但是,这次 hbrBackground 设置为从GetStockObject函数获取的BLACK_BRUSH句柄。
编辑:我尝试尽可能地重现您的临时程序:
program ScratchProgram;
uses
Windows,
Messages,
DwmApi,
UxTheme;
{ Window Procedure }
function WndProc(hWnd: HWND; uiMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
m: TMargins;
begin
case uiMsg of
WM_ACTIVATE:
begin
m.cxLeftWidth := 50;
m.cxRightWidth := 50;
m.cyTopHeight := 50;
m.cyBottomHeight := 50;
DwmExtendFrameIntoClientArea(hWnd, m);
end;
WM_DESTROY:
begin
PostQuitMessage(0);
Result := 0;
Exit;
end;
end;
Result := DefWindowProc(hWnd, uiMsg, wParam, lParam);
end;
function WinMain(hInstance: HINST; hPrevInstance: HINST; lpCmdLine: PChar; nShowCmd: Integer): Integer; stdcall;
var
wc: WNDCLASS;
msg: TMSG;
hWindow: HWND;
instance: HINST;
begin
instance := GetModuleHandle(nil);
wc.style := CS_HREDRAW or CS_VREDRAW;
wc.cbClsExtra := 0;
wc.cbWndExtra := 0;
wc.lpszClassName := 'Window';
wc.hInstance := instance;
wc.hbrBackground := GetStockObject(BLACK_BRUSH);
wc.lpszMenuName := nil;
wc.lpfnWndProc := @WndProc;
wc.hCursor := LoadCursor(0, IDC_ARROW);
wc.hIcon := LoadIcon(0, IDI_APPLICATION);
RegisterClass(wc);
hWindow := CreateWindow(
wc.lpszClassName, // Class Name
'Window', // Title
WS_OVERLAPPEDWINDOW or WS_VISIBLE, // Style
100, 100, // Position
350, 250, // Size
0, // Parent
0, // No menu
instance, // Instance
nil); // No special parameters
ShowWindow(hWindow, SW_SHOW);
while (GetMessage(msg, 0, 0, 0)) do
begin
TranslateMessage(msg);
DispatchMessage(msg);
end;
Result := 0;
end;
begin
WinMain(hInstance, hPrevInst, CmdLine, CmdShow);
end.
它对我有用:
无论问题是什么,代码在概念上看起来都不对。
也许调用约定,或者你不期望它的失败(例如RegisterClass
,或者对传递给GetModuleHandle
的实例句柄使用WinMain
,或者调用{即使表单被停用,也会{1}}。
答案 1 :(得分:0)
您得到的结果按预期工作。有点奇怪。让我解释一下。
Windows 10使用带有单个像素蓝色边框的主题。标题栏为白色。您正在执行的操作是同时扩展标题栏和边框。因此1像素边框以及标题栏变得更大。仅仅是Windows 10主题的边框实际上是窗口框架的一部分,而不是某些魔术边框(总是一个像素)。
在Windows 7中,包括标题栏和像素的窗口框架实质上是一块完整的“玻璃”。
借助于一个名为Glass8的程序,该程序在Windows 10中恢复了Windows Aero,我得到了以下结果。 (该窗口位于灰色背景的前面。)