Custom window frame with DWM: how to handle WM_NCCALCSIZE correctly

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-05 11:06:45

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 in WM_WINDOWPOSCHANGED window message handler
  2. SetClientSizeCore

The workaround is the following:

  • 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;
        }
    }
    
  • Override WndProc and insert the following code to handle WM_WINDOWPOSCHANGED:

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

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

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!