gpt4 book ai didi

c# - 带有 DWM : how to handle WM_NCCALCSIZE correctly 的自定义窗框

转载 作者:太空狗 更新时间:2023-10-29 23:23:09 27 4
gpt4 key购买 nike

我正在尝试使用 DWM 为我的表单制作自定义窗口框架。该平台是 C# WinForms,Pinvoking DWM。

MSDN article on making custom window frame with DWM 之后, 主要步骤如下:

  1. 移除标准框架(非客户区),返回 0 作为对 WM_NCCALCSIZE 消息的应答
  2. 使用 DwmExtendFrameIntoClientArea 函数将框架扩展到客户区

我用下一种方式处理 WM_NCCALCSIZE 消息:

protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_NCCALCSIZE:
if (isDwmWindowFramePaintEnabled() && m.WParam != IntPtr.Zero)
{
m.Result = IntPtr.Zero;
}
else
{
base.WndProc(ref m);
}
return;
}
}

根据 MSDN documentation on WM_NCCALCSIZE ,

When wParam is TRUE, simply returning 0 without processing theNCCALCSIZE_PARAMS rectangles will cause the client area to resize tothe size of the window, including the window frame. This will removethe window frame and caption items from your window, leaving only theclient area displayed.

除一个问题外,一切都很好,对我有用。当我最大化/恢复窗口时,它总是在恢复时增长一点点。我认为,问题是这样的:

  1. 当窗口恢复时,它只包含客户区
  2. Windows 试图给窗口一些非客户区
  3. 在 WM_NCCALCSIZE 客户区增长到包含非客户区

所以,每次我最大化/恢复它时,这个窗口都会变大一点。我需要删除非客户区以使用 DWM 绘制自定义表单框架。我不能简单地将窗口边框样式设置为无,因为 DWM 将不会绘制窗口标题和边框。

请帮助解决问题并愉快地拥有自定义窗框。

最佳答案

这实际上是 Windows 窗体中的一个错误,并且有一个解决方法。在函数 Form.SizeFromClientSize(int, int) 中,AdjustWindowRectEx 函数用于转换大小,它始终使用默认测量值,不能被覆盖。这个函数从两个地方调用:

  1. RestoreWindowBoundsIfNecessary 在 WM_WINDOWPOSCHANGED 窗口消息处理程序中
  2. SetClientSizeCore

解决方法如下:

  • 重写表单中的 CreateParams:

    private bool createParamsHack;

    protected override CreateParams CreateParams
    {
    get
    {
    CreateParams cp = base.CreateParams;
    // Remove styles that affect the border size
    if (createParamsHack)
    cp.Style &= ~(int)(WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_THICKFRAME);
    return cp;
    }
    }
  • 覆盖 WndProc 并插入以下代码来处理 WM_WINDOWPOSCHANGED:

        if (m.Msg == WM_WINDOWPOSCHANGED)
    {
    createParamsHack = true;
    base.WndProc(ref m);
    createParamsHack = false;
    }
  • 覆盖 SetClientSizeCore:

    protected override void SetClientSizeCore(int x, int y)
    {
    createParamsHack = true;
    base.SetClientSizeCore(x, y);
    createParamsHack = false;
    }

覆盖 SizeFromClientSize(Size) 以返回正确的测量结果也是个好主意,但这并不是绝对必要的。

关于c# - 带有 DWM : how to handle WM_NCCALCSIZE correctly 的自定义窗框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20085317/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com