winapi - Windows 10 上的 DwmExtendFrameIntoClientArea 奇怪行为

标签 winapi windows-10 dwm

我在使用 DwmExtendFrameIntoClientArea 扩展窗框时遇到了一些麻烦在 Windows 10 上。下图显示了我得到的行为:

enter image description here

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

如果我将边距全部设置为 -1为了一直延伸框架,窗口被白色填充并完全失去了它的彩色边缘:

enter image description here

这个结果很不一致,我原以为白色会延伸到窗口的四面八方,类似于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 的问题?在此先感谢您的帮助!

编辑:我发布的代码与 Aero Lite 和 Windows 10 上的高对比度主题完美兼容,但不适用于默认的 Windows 10 主题。

最佳答案

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

来自 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.

enter image description here



编辑 :我试图尽可能地重现您的临时程序:
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.

它对我有用:

enter image description here

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

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

关于winapi - Windows 10 上的 DwmExtendFrameIntoClientArea 奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34414751/

相关文章:

c++ - 如何正确处理来自 MSFTEDIT_CLASS (RichEdit) 控件的 Windows 消息?

c++ - 无法实现密码过滤器

c# - Win10中的EnumWindows函数只枚举桌面应用

delphi - 扩展 GlassFrame 带来的不良视觉行为

c++ - 如何使用GetNamedSecurityInfo?

c++ - 创建 GDI 矩形图像

python - 如何在 Windows 下的 Python 2 shell 中打印 unicode 字符串?

windows-10 - Jupyter notebook 无法从命令提示符打开

delphi - 在 Delphi 中使用 DWM 非客户端绘制后,标题按钮不响应鼠标单击

uwp - win32 app中的亚克力 Material