与DWM自定义窗框:如何正确处理WM_NCCALCSIZE [英] Custom window frame with DWM: how to handle WM_NCCALCSIZE correctly

查看:2030
本文介绍了与DWM自定义窗框:如何正确处理WM_NCCALCSIZE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让使用DWM我的表单自定义窗口框架。
平台是C#的WinForms,Pinvoking DWM。

I'm trying to make a custom window frame for my form using DWM. The platform is C# WinForms, Pinvoking DWM.

继的在制作定制窗框与DWM MSDN文章,主要的步骤是下一个:

Following the MSDN article on making custom window frame with DWM, the main steps are next:


  1. 删除标准框架(非客户区),在回答返回0到WM_NCCALCSIZE消息

  2. 使用扩展帧分成客户区DwmExtendFrameIntoClientArea功能

我处理下一个方式WM_NCCALCSIZE消息:

I handle WM_NCCALCSIZE message in the next way:

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;
   }
}



据的在WM_NCCALCSIZE MSDN文档,

当wParam为TRUE,干脆不处理
NCCALCSIZE_PARAMS矩形将导致客户区返回0调整到
窗口的大小,包括窗框。这将删除
从窗口窗框和标题的项目,留下仅显示
客户区。

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

一切都很好,对我的作品,除了一个问题。
当我最大化/还原窗口,它总是不断增加一点点,当它得到恢复。
我认为,这个问题是这样的:

Everything is fine and works for me except one issue. When I maximize/restore window, it's always growing a little bit when it gets restored. I think, the issue is something like this:


  1. 在当前窗口被恢复,它仅包含客户端区域

  2. Windows会尝试给一些非客户区窗口

  3. 在WM_NCCALCSIZE客户区发展到包含非客户区

所以,像这样的窗口增长一点点,每次我最大化/还原。
我需要删除非客户区绘制自定义表单帧DWM。
我不能简单地设置窗口边框样式none作为然后DWM不会绘制窗口标题和边框。

So, like this window grows a little bit each time I maximize/restore it. I need to remove non-client area to paint custom form frame with DWM. I can't simply set window border style to none as then DWM will not paint the window caption and borders.

请,帮助解决问题,高高兴兴地有一个自定义窗口框架。

Please, help to solve the issue and happily have a custom window frame.

推荐答案

这实际上是在Windows窗体中的错误,有一个解决方法。在功能上 Form.SizeFromClientSize(INT,INT) AdjustWindowRectEx 函数用于大小翻译和它总是使用默认测量和不能被重写。这个功能是从两个地方叫:

This is actually a bug in Windows Forms and there's a workaround. In function Form.SizeFromClientSize(int, int) the AdjustWindowRectEx function is used to translate the size and it always uses the default measurements and can't be overridden. This function is called from two places:


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

  2. SetClientSizeCore

  1. RestoreWindowBoundsIfNecessary in WM_WINDOWPOSCHANGED window message handler
  2. SetClientSizeCore

解决方法是以下内容:


  • 将覆盖在form的CreateParams:

  • Override CreateParams in the Form:

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:

  • Override WndProc and insert the following code to handle WM_WINDOWPOSCHANGED:

        if (m.Msg == WM_WINDOWPOSCHANGED)
        {
            createParamsHack = true;
            base.WndProc(ref m);
            createParamsHack = false;
        }
    


  • 覆盖SetClientSizeCore:

  • Override SetClientSizeCore:

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


  • 这也可能是好主意,覆盖 SizeFromClientSize(大小)返回正确的测量,但它不是绝对必要的。

    It may also be good idea to override SizeFromClientSize(Size) to return the correct measurements, but it is not strictly necessary.

    这篇关于与DWM自定义窗框:如何正确处理WM_NCCALCSIZE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆