DwmExtendFrameIntoClientArea strange behaviour on Windows 10

青春壹個敷衍的年華 提交于 2019-12-03 13:48:17

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).

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.)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!