调整一个无边框的窗体,控件无处不在,没有空space
Resize a borderless form that has controls everywhere, no empty space
我有一个程序将 FormBorderStyle
设置为 None
。我一直在网上查找并找到了一个用于调整表单大小的工作代码,但它仅在表单为空 space 并且没有控件时才有效。虽然我的整个表单充满了控件,但每个边都有控件,而且我无法在边上制作 space 。有没有办法使用 Windows API 或其他方法来扩展调整大小控制,或者在 MouseDown
时使用控件触发调整大小事件?
可以用不同的方式完成。这个答案的主要思想是将面板放在表单上作为内容容器,然后排除它的右下角区域(大小控制矩形),这样这个区域就不再属于面板,并且该矩形的所有鼠标事件都将被路由到表单,甚至面板也没有绘制该区域。
要做到这一点,请执行以下步骤:
Crate Form 并将 BorderStyle 属性 设置为 None
将面板添加到表单作为内容容器并将其名称设置为面板 1 并将面板的 Dock 属性 设置为填充
覆盖 OnSizeChanged
of form and set the region of panel same size as form and then exclude its bottom right corner. This way, the excluded region doesn't belong to panel anymore and all messages including WM_NCHITTEST
将被我们的 WndProc
接收;面板甚至不绘制该区域。
覆盖WndProc
得到WM_NCHITTEST
消息,如果点在我们在OnSizeChanges
中定义的区域内,显示调整大小指针并准备调整大小.
覆盖 OnPaint
以绘制大小夹点
截图:
这是在其容器面板中带有一些控件的表单:
如果将鼠标移到大小手柄上,您会看到鼠标指针变为右下大小指针,您可以使用它调整表单大小。
可以设置表格的MinimumSize
和MaximumSize
,防止表格过小或过大难看。
代码:
完整代码如下:
private int tolerance = 16;
private const int WM_NCHITTEST = 132;
private const int HTBOTTOMRIGHT = 17;
private Rectangle sizeGripRectangle;
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_NCHITTEST:
base.WndProc(ref m);
var hitPoint = this.PointToClient(new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16));
if (sizeGripRectangle.Contains(hitPoint))
m.Result = new IntPtr(HTBOTTOMRIGHT);
break;
default:
base.WndProc(ref m);
break;
}
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
var region = new Region(new Rectangle(0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height));
sizeGripRectangle = new Rectangle(this.ClientRectangle.Width - tolerance, this.ClientRectangle.Height - tolerance, tolerance, tolerance);
region.Exclude(sizeGripRectangle);
this.panel1.Region = region;
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
ControlPaint.DrawSizeGrip(e.Graphics, Color.Transparent, sizeGripRectangle);
}
我有一个程序将 FormBorderStyle
设置为 None
。我一直在网上查找并找到了一个用于调整表单大小的工作代码,但它仅在表单为空 space 并且没有控件时才有效。虽然我的整个表单充满了控件,但每个边都有控件,而且我无法在边上制作 space 。有没有办法使用 Windows API 或其他方法来扩展调整大小控制,或者在 MouseDown
时使用控件触发调整大小事件?
可以用不同的方式完成。这个答案的主要思想是将面板放在表单上作为内容容器,然后排除它的右下角区域(大小控制矩形),这样这个区域就不再属于面板,并且该矩形的所有鼠标事件都将被路由到表单,甚至面板也没有绘制该区域。
要做到这一点,请执行以下步骤:
Crate Form 并将 BorderStyle 属性 设置为 None
将面板添加到表单作为内容容器并将其名称设置为面板 1 并将面板的 Dock 属性 设置为填充
覆盖
OnSizeChanged
of form and set the region of panel same size as form and then exclude its bottom right corner. This way, the excluded region doesn't belong to panel anymore and all messages includingWM_NCHITTEST
将被我们的WndProc
接收;面板甚至不绘制该区域。覆盖
WndProc
得到WM_NCHITTEST
消息,如果点在我们在OnSizeChanges
中定义的区域内,显示调整大小指针并准备调整大小.覆盖
OnPaint
以绘制大小夹点
截图:
这是在其容器面板中带有一些控件的表单:
如果将鼠标移到大小手柄上,您会看到鼠标指针变为右下大小指针,您可以使用它调整表单大小。
可以设置表格的MinimumSize
和MaximumSize
,防止表格过小或过大难看。
代码:
完整代码如下:
private int tolerance = 16;
private const int WM_NCHITTEST = 132;
private const int HTBOTTOMRIGHT = 17;
private Rectangle sizeGripRectangle;
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_NCHITTEST:
base.WndProc(ref m);
var hitPoint = this.PointToClient(new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16));
if (sizeGripRectangle.Contains(hitPoint))
m.Result = new IntPtr(HTBOTTOMRIGHT);
break;
default:
base.WndProc(ref m);
break;
}
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
var region = new Region(new Rectangle(0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height));
sizeGripRectangle = new Rectangle(this.ClientRectangle.Width - tolerance, this.ClientRectangle.Height - tolerance, tolerance, tolerance);
region.Exclude(sizeGripRectangle);
this.panel1.Region = region;
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
ControlPaint.DrawSizeGrip(e.Graphics, Color.Transparent, sizeGripRectangle);
}