DwmExtendFrameIntoClientArea在Windows 10上的奇怪行为

YmF*_*TY0 7 winapi dwm windows-10

我在使用DwmExtendFrameIntoClientAreaWindows 10 扩展窗口框架时遇到了一些麻烦.下面的图片显示了我得到的行为:

在此输入图像描述

白色标题栏颜色从顶部延伸,而从侧面和底部延伸窗口的彩色边缘.

如果我将边距全部设置-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);
}
Run Code Online (Sandbox Code Playgroud)

我做错了什么或者这只是Windows 10的一个问题?在此先感谢您的帮助!

编辑:我发布的代码与Windows 10上的Aero Lite和高对比度主题完美配合,但与默认的Windows 10主题无关.

Ian*_*oyd 1

当框架延伸到客户区域时,您需要确保客户区域绘制程序在玻璃应该在的任何地方绘制纯黑色。

来自MSDN

确保扩展帧可见的最简单方法是将整个客户区域涂成黑色。要实现此目的,请将WNDCLASSWNDCLASSEX结构的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.
Run Code Online (Sandbox Code Playgroud)

它对我有用:

在此输入图像描述

无论问题是什么,代码在概念上看起来都没有错误。

也许是调用约定,或者在您不期望的情况下失败(RegisterClass例如,使用GetModuleHandle传递给 的实例句柄WinMain,或者DwmExtendFrameIntoClientArea即使在表单被停用时也进行调用)。

  • 您正在使用 Aero Lite 主题。我刚刚测试了我的代码,它也与 Aero Lite 主题完美配合,但仍然不适用于标准主题。 (2认同)