DwmExtendFrameIntoClientArea weird behavior in Windows 10

I am having problems expanding window frames using DwmExtendFrameIntoClientArea on Windows 10. The images below show the behavior that I get

enter image description here

The white color of the title bar is enlarged from above, and from the sides and from below - the colored edge of the window.

If I set all the fields to -1 to completely break the frames, the window fills with white and completely loses its color edge:

enter image description here

This result is very incompatible, I expected that the white color will expand on all sides of the window, similar to how the color frame expands in Windows 8, or the glass expands in Windows 7 and Vista.

I tried searching on the Internet, but I could not find such problems.

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 it just a problem with Windows 10? Thanks in advance for your help!

Edit: The code I posted works fine with both Aero Lite and high contrast themes in Windows 10, but not with the default Windows 10 theme.

+7
winapi windows-10 dwm
source share
2 answers

When the frame is expanded to the client area, you need to make sure that the procedure for drawing your client area draws pure black anywhere in the glass.

From MSDN :

The easiest way to make sure that extended frames are visible is to paint the entire client area in black. To do this, initialize the hbrBackground element of your WNDCLASS or WNDCLASSEX to the stock handle BLACK_BRUSH. The following figure shows the same standard frame (left) and the extended frame (right) shown earlier. However, this time hbrBackground is set to the BLACK_BRUSH handle received from the GetStockObject function.

enter image description here

Change I tried to accurately reproduce your program from scratch:

 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 this works for me:

enter image description here

Whatever the problem, the code does not look conceptually wrong.

It is possible to cause conventions or crash if you do not expect this ( RegisterClass for example, or using GetModuleHandle on the instance handle passed to WinMain , or calling DwmExtendFrameIntoClientArea , even if the form is deactivated).

+1
source share

The result you get is working as intended. It's a bit strange. Let me explain.

Windows 10 uses a one-pixel blue border theme. Titlebar is white. What you do with it extends the title and borders. Thus, 1 pixel borders become much larger than the title bar. It's just that Windows 10 theme borders are actually part of the window frame, not some kind of magical border, which is always a single pixel.

In Windows 7, the window frame, including the title and the pixel, was essentially a complete piece of glass.

Using a program called Glass8 , which restores Windows Aero to Windows 10, I was able to get the following result. (Window in front of a gray background.)

Aero Glass Demonstration

0
source share

All Articles