DwmExtendFrameIntoClientArea在Windows 10上的奇怪行为

7
我在使用Windows 10时,使用DwmExtendFrameIntoClientArea扩展窗口框架时遇到了一些问题。下面的图片显示了我得到的结果:

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的问题?非常感谢您提供的任何帮助!

编辑:我发布的代码在Windows 10的Aero Lite和高对比度主题下完美运行,但在默认的Windows 10主题下不起作用。


几乎是一个好问题。但是,问题没有提出来。请解释一下,期望的结果应该是什么。 - IInspectable
1
我期望它能够简单地扩展标题栏的白色,类似于Windows 8上彩色框架的扩展或Windows 7和Vista上的玻璃效果。目前的结果不一致,看起来很丑陋。 - YmFzZTY0
请编辑您的问题以包含此信息。 - IInspectable
2个回答

1
当框架已经扩展到客户区时,您需要确保您的客户区绘制过程在任何玻璃应该出现的地方绘制纯黑色
来自MSDN
为确保扩展框架可见,最简单的方法是将整个客户区域涂成黑色。为此,请将WNDCLASSWNDCLASSEX结构的hbrBackground成员初始化为存储库BLACK_BRUSH的句柄。下图显示了先前显示的相同标准框架(左)和扩展框架(右)。然而,这一次hbrBackground设置为从GetStockObject函数获得的BLACK_BRUSH句柄。

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

我正在将背景设置为黑色。在我的问题的代码中,第21行: wc.hbrBackground = GetStockObject(BLACK_BRUSH); - YmFzZTY0
2
你正在使用Aero Lite主题。我刚刚测试了我的代码,它也可以完美地与Aero Lite主题配合使用,但仍然无法与标准主题配合使用。 - YmFzZTY0

0

你得到的结果符合预期。只是有点奇怪,让我来解释一下。

Windows 10使用带有单像素蓝色边框的主题,标题栏为白色。你所做的是扩展标题栏和边框。因此,1个像素的边框变得更大,同时标题栏也变大了。只是Windows 10主题的边框实际上是窗口框架的一部分,而不是始终为单个像素的魔法边框。

在Windows 7中,窗口框架包括标题栏和像素基本上是一个完整的“玻璃”。

通过名为Glass8的程序,可以在Windows 10中恢复Windows Aero,我能够获得以下结果。(窗口在灰色背景前方。)

Aero Glass Demonstration


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接