如何使用窗体边框上的控件调整无边框窗体大小?

我有一个无边框的winForm,我需要resize,我设法这样做:

protected override void WndProc(ref Message m) { const int wmNcHitTest = 0x84; const int htLeft = 10; const int htRight = 11; const int htTop = 12; const int htTopLeft = 13; const int htTopRight = 14; const int htBottom = 15; const int htBottomLeft = 16; const int htBottomRight = 17; if (m.Msg == wmNcHitTest) { Console.Write(true + "\n"); int x = (int)(m.LParam.ToInt64() & 0xFFFF); int y = (int)((m.LParam.ToInt64() & 0xFFFF0000) >> 16); Point pt = PointToClient(new Point(x, y)); Size clientSize = ClientSize; ///allow resize on the lower right corner if (pt.X >= clientSize.Width - 16 && pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16) { m.Result = (IntPtr)(IsMirrored ? htBottomLeft : htBottomRight); return; } ///allow resize on the lower left corner if (pt.X = clientSize.Height - 16 && clientSize.Height >= 16) { m.Result = (IntPtr)(IsMirrored ? htBottomRight : htBottomLeft); return; } ///allow resize on the upper right corner if (pt.X <= 16 && pt.Y = 16) { m.Result = (IntPtr)(IsMirrored ? htTopRight : htTopLeft); return; } ///allow resize on the upper left corner if (pt.X >= clientSize.Width - 16 && pt.Y = 16) { m.Result = (IntPtr)(IsMirrored ? htTopLeft : htTopRight); return; } ///allow resize on the top border if (pt.Y = 16) { m.Result = (IntPtr)(htTop); return; } ///allow resize on the bottom border if (pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16) { m.Result = (IntPtr)(htBottom); return; } ///allow resize on the left border if (pt.X = 16) { m.Result = (IntPtr)(htLeft); return; } ///allow resize on the right border if (pt.X >= clientSize.Width - 16 && clientSize.Height >= 16) { m.Result = (IntPtr)(htRight); return; } } else { Console.Write(false + "\n"); } base.WndProc(ref m); } 

问题是我的表单的左边框和右边框有控件,因此上面代码中使用的resize覆盖不适用于有任何类型控件的区域。

这是一个例子:

调整问题的大小

在上图中,您可以看到标记区域内的标签位于我表单的左边框,它不会让我resize。

有没有办法解决这个问题?

这里的问题是它是Label控件获取鼠标通知,而不是无边框forms。 到目前为止,解决此问题的最佳方法是使标签对鼠标透明。 你已经知道如何做到这一点,WM_NCHITTEST也允许返回HTTRANSPARENT。 Windows一直在寻找通知的下一个候选者,它将是标签的父级。

特别容易为标签做,因为您通常根本不会使用鼠标事件:

 using System; using System.Windows.Forms; public class LabelEx : Label { protected override void WndProc(ref Message m) { const int wmNcHitTest = 0x84; const int htTransparent = -1; if (!DesignMode && m.Msg == wmNcHitTest) m.Result = new IntPtr(htTransparent); else base.WndProc(ref m); } } 

适用于任何Control类,如果它是一个按钮,你会想要更有选择性。 可能是你需要的一切,但是如果你有很多不同类型的控制靠近边缘,那仍然很尴尬。 您可以使用的另一种技术在本机Windows编程中称为“子类”。 通常在Winforms中用于为本机Windows控件创建包装.NET类。 它在这里也运行良好,您可以查看任何控件的消息并以这种方式拦截WM_NCHITTEST:

  const int edge = 16; class MouseFilter : NativeWindow { private Form form; public MouseFilter(Form form, Control child) { this.form = form; this.AssignHandle(child.Handle); } protected override void WndProc(ref Message m) { const int wmNcHitTest = 0x84; const int htTransparent = -1; if (m.Msg == wmNcHitTest) { var pos = new Point(m.LParam.ToInt32()); if (pos.X < this.form.Left + edge || pos.Y < this.form.Top + edge|| pos.X > this.form.Right - edge || pos.Y > this.form.Bottom - edge) { m.Result = new IntPtr(htTransparent); return; } } base.WndProc(ref m); } } 

只需为靠近窗口边缘的每个控件创建一个MouseFilter实例:

  protected override void OnLoad(EventArgs e) { base.OnLoad(e); subClassChildren(this.Controls); } private void subClassChildren(Control.ControlCollection ctls) { foreach (Control ctl in ctls) { var rc = this.RectangleToClient(this.RectangleToScreen(ctl.DisplayRectangle)); if (rc.Left < edge || rc.Right > this.ClientSize.Width - edge || rc.Top < edge || rc.Bottom > this.ClientSize.Height - edge) { new MouseFilter(this, ctl); } subClassChildren(ctl.Controls); } } 
Interesting Posts