回答
实现此目的的正确方法是将消息处理程序处理程序(例如,通过重写Form.WndProc
)添加到窗体并处理消息WM_NCHITTEST
。 (您可以在PInvoke.net上找到该消息的C#定义)特别是,当您收到消息时,计算命中测试是否针对指定调整大小的区域中的点,如果是,则返回HTBOTTOMRIGHT。默认的窗口过程会为你完成剩下的工作,因为它假设用户点击了窗口边界的右下角,即使你的窗口没有边框。
这个问题需要一点点的Win32 interop,但它会使你的调整大小看起来像其他任何窗口调整大小。
最简单的方法是按@benPearce的说法,在面板的角落放置一个面板,并使用宽度/高度调整窗体大小。它会起作用,但调整大小不会一帆风顺,特别是在Vista和Win7 Basic中,在标准移动和重新调整大小时完全重绘被禁用,而每一步都将尝试重绘。
更新:在这两种方法中,您将不得不弄清楚如何绘制抓手。例如,您可以放置标准抓手的位图。尽管如此,由于您的表单没有标题和边框,因此您不一定会使用标准的Windows视觉效果,您可能会选择更快捷的方式。
更新2:如果您有一个覆盖整个窗口的控件,它将吃掉表单鼠标消息。你必须以某种方式剪辑你想用来调整大小的地方。您有几种选择来处理这个:
- 调整控制,使尺寸调整握一些空间。
- 调整控制区域(通过Region属性)以排除调整大小的控制点。
- 覆盖调整大小控制面板,听取它的MouseEnter消息,并将Capture属性设置为true,这将导致所有更多的鼠标消息到达它。 注意:调整大小完成后,鼠标离开该区域后,您将不得不释放捕获。
我会推荐去选择最简单的选项1。选项3是最复杂的,需要关于鼠标输入在Windows中的工作方式的详细信息,所以我不会推荐它。选项2是选项1的一个很好的选择,但您必须尝试查看ListView控件如何对其区域进行调整。
非常感谢,这对于静态表单非常有用。但是我的表单包含一个填充表单的列表视图。没有WM_NCHITTEST消息被激发。 – 2009-10-08 06:41:38
任何人都在寻找如何绘制抓手,'ControlPaint.DrawSizeGrip'是一个开始。 – AnotherUser 2014-07-02 11:23:38
下面是与Franci的解释相对应的代码,我正在写它,但他同时回答了他的解释,如果这段代码适合您的需求,那么这是很好的解决办法。
protected override void WndProc(ref Message m) {
const int wmNcHitTest = 0x84;
const int htBottomLeft = 16;
const int htBottomRight = 17;
if (m.Msg == wmNcHitTest) {
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;
if (pt.X >= clientSize.Width - 16 && pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16) {
m.Result = (IntPtr) (IsMirrored ? htBottomLeft : htBottomRight);
return;
}
}
base.WndProc(ref m);
}
编辑:写夹子,你可以初始化一个new VisualStyleRenderer(VisualStyleElement.Status.Gripper.Normal)
并使用其PaintBackground()
方法。
有关绘制抓手的更多说明,请参阅http://stackoverflow.com/a/4918111/161052 – JYelton 2012-11-28 20:54:55
非常感谢发布这个伟大的样本和解释。我在下面添加了一些其他代码可能会感兴趣的附加内容。这里的一些代码来自其他stackoverflow帖子,但为了能够在一个代码块中看到它,可能会对其他人有所帮助。 我希望能够调整窗体的大小,而不仅仅是右下角。我也想能够拖动表格。最后,我想要一个阴影。
//***********************************************************
//This gives us the ability to resize the borderless from any borders instead of just the lower right corner
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)
{
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 <= 16 && pt.Y >= 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 && clientSize.Height >= 16)
{
m.Result = (IntPtr)(IsMirrored ? htTopRight : htTopLeft);
return;
}
///allow resize on the upper left corner
if (pt.X >= clientSize.Width - 16 && pt.Y <= 16 && clientSize.Height >= 16)
{
m.Result = (IntPtr)(IsMirrored ? htTopLeft : htTopRight);
return;
}
///allow resize on the top border
if (pt.Y <= 16 && clientSize.Height >= 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 && clientSize.Height >= 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;
}
}
base.WndProc(ref m);
}
//***********************************************************
//***********************************************************
//This gives us the ability to drag the borderless form to a new location
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
private void YOURCONTROL_MouseDown(object sender, MouseEventArgs e)
{
//ctrl-leftclick anywhere on the control to drag the form to a new location
if (e.Button == MouseButtons.Left && Control.ModifierKeys == Keys.Control)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
//***********************************************************
//***********************************************************
//This gives us the drop shadow behind the borderless form
private const int CS_DROPSHADOW = 0x20000;
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ClassStyle |= CS_DROPSHADOW;
return cp;
}
}
//***********************************************************
- 1. 调整边界不窗口在WPF
- 2. 右下角的Tkinter窗口
- 3. CEF 3无边界窗口
- 4. 屏幕右下角的位置窗口
- 5. Silverlight窗口边界
- 6. WPF无边界窗口的DropShadow
- 7. Linux上的无边界窗口
- 8. 可移动的WPF无边界窗口
- 9. 如何绘制弯曲边界的右下角三角形?
- 10. 在Qt主窗口的右下角放置弹出窗口
- 11. 更改窗口的边界
- 12. 无边界窗口带阴影和blurbehind
- 13. Qt的:调整无边界插件
- 14. 右div标签调整窗口
- 15. 右对齐调整窗口大小
- 16. 当调整窗口大小时,带负边界的边框消失
- 17. 角窗口打开不调整的PhoneGap
- 18. 位于窗口右下方的窗口?
- 19. 页脚不会遇到重新调整大小的窗口的右边缘
- 20. 用窗口调整世界的界限resize
- 21. 如果窗口靠近边缘,重新调整下拉菜单
- 22. 调整窗口
- 23. 调整窗口
- 24. DIV与边界调整dragend
- 25. 右边的Visio Dock模板窗口
- 26. ExtJS的4.2 - 删除窗口的边界?
- 27. 边界的窗口与阴影
- 28. 自动调整主窗口调整大小的窗口
- 29. 调整无窗口小部件的窗口大小
- 30. Flex空气应用程序:打开右下角的窗口
发表了一些代码。您可以通过更改控件的宽度和高度来调整大小。 – 2009-10-08 05:50:52
由于Andrew Keith的评论,修改了问题并添加了截图的链接:用户应该能够调整表单的大小。 – 2009-10-08 05:59:21
使用面板查看我的解决方案:http://stackoverflow.com/a/8848440/640781 – edid 2012-01-13 09:42:07