问题
I'm having some trouble extending the window frames using DwmExtendFrameIntoClientArea on Windows 10. The images below show the behaviour I'm getting:
The white titlebar colour is extended from the top, while from the sides and the bottom it extends the coloured edge of the window.
If I set the margins all to -1
to extend the frames all the way, the window is filled with white and loses its coloured edge altogether:
This result is very inconsistent, I was expecting the white colour to be extended on all sides of the window, similar to the way the coloured frame is extended in Windows 8, or the glass is extended in Windows 7 and Vista.
I've tried searching online, but I haven't been able to find any similar issues.
Here is the code I'm using:
#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);
}
Am I doing something wrong or is this just an issue with Windows 10? Thanks in advance for any help!
Edit: The code I posted works perfectly with both Aero Lite and the high contrast themes on Windows 10, but not with the default Windows 10 theme.
回答1:
When the frame has been extended into the client area, you need to make sure that your client area paint procedure draws pure black anywhere the glass should be.
From MSDN:
The easiest way to ensure that the extended frames are visible is to paint the entire client region black. To accomplish this, initialize the hbrBackground member of your WNDCLASS or WNDCLASSEX structure to the handle of the stock BLACK_BRUSH. The following image shows the same standard frame (left) and extended frame (right) shown previously. This time, however, hbrBackground is set to the BLACK_BRUSH handle obtained from the GetStockObject function.
Edit: I tried to reproduce your scratch program as closely as possible:
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.
And it works for me:
Whatever the problem is, the code doesn't look conceptually wrong.
Perhaps calling conventions, or a failure where you don't expect it (RegisterClass
for example, or the use of GetModuleHandle
over the instance handle passed to WinMain
, or calling DwmExtendFrameIntoClientArea
even when the form is being deactivated).
回答2:
The result you are getting is working as intended. It's just a bit weird. Let me explain.
Windows 10 uses a theme with a single pixel blue border. The titlebar is white. What you are doing with this is extending both the titlebar and the borders. So the 1 pixel borders become a lot bigger as well as the titlebar. It's just that Windows 10's theme's borders are actually a part of the window frame and not some magic border that's always a single pixel.
In Windows 7, the Window frame including the titlebar and the pixel was essentially a complete piece of "glass".
With the help of a program called Glass8, which restores Windows Aero in Windows 10, I was able to get the following result. (The window is in front of a gray background.)
来源:https://stackoverflow.com/questions/34414751/dwmextendframeintoclientarea-strange-behaviour-on-windows-10