移动受限的对话框窗体
如何限制对话框窗体的移动区域。 适用于 MDI 应用程序。
引言
此代码允许您限制对话框窗体的移动区域。 我使用了 VS2008,目标框架是 2.0,但如果更改为 3.0 或 3.5,它也能正常工作
背景
这个想法来自 C# 消息板上的一篇帖子。 发帖人的老板抱怨说,对话框窗体没有包含在他为他开发的 MDI 应用程序中。
我最初的想法是“他有什么问题?”,但稍加思考后,我有点同意他的看法。 我们开发 MDI 应用程序是为了能够在同一个定义的环境中拥有多个窗口。 为什么任何对话框不应该也被限制在其中呢?
最初两个显而易见的事情是处理 Move
或 LocationChanged
事件,但这两个事件都发生在窗体移动之后,因此窗体“跳回” - 不是很优雅。 解决方案来自重写 WndProc
并捕获一些 Windows 消息。 一点点 Marshalling,就这样。
实际上,限制窗体的移动相当简单,但稍微复杂的是,即使窗体停止了,鼠标光标仍然继续移动。
使用代码
所有代码都有注释,应该是不言自明的。
在 Form1
中,将对话框要限制到的相关 Form
传递给 Form2
(受限制的对话框)构造函数。 我在源代码/演示中提供了三个不同的例子。 还有一个第四个例子,它创建一个子窗体 (Form3
),该窗体又在点击按钮时调用 Form2
。
Form2
是真正发生的地方。 重写了三个 Windows 消息:WM_NCLBUTTONDOWN
、WM_ENTERSIZEMOVE
和 WM_MOVING
。
当标题栏(非 客户端 区域)被左键单击时,会发生 WM_NCLBUTTONDOWN
。 在这里,我根据提供的限制、大小、对话框的位置和光标的当前位置,设置了一个适合光标的矩形。
当 WM_ENTERSIZEMOVE
发生时,我只是将光标剪裁到上面设置的矩形。
当移动窗体时,会重复发送 WM_MOVING
。 每次收到此消息时,都会将左、上、右和下坐标与传递的矩形进行比较,如果超出限制,则使用 Marshalling 来禁止移动。
用法
可能,使用此方法最简单的方法是将 Form2
保存为模板,这样就可以根据需要在项目中轻松添加多次。
致谢
感谢 Luc Pattyn 最初帮助我找到了 WndProc
,以及 Harvey Saayman 提出了最初的问题!
Bug
如果使用箭头键移动窗体,则不会完全按照预期响应(我将继续研究这个问题)。
历史
- 2008 年 2 月 19 日 v1.00。
- 2008 年 2 月 22 日 v.1.01:添加了一个 MDI 子示例来解决 Harvey 的问题,在下面的消息中。 我将很多代码从调用窗体移到对话框窗体(这样更有意义),并添加了关闭按钮禁用和边框宽度允许的选项。
- 2008 年 2 月 25 日 v1.02:添加了启用、禁用或隐藏窗体的系统上下文菜单关闭项的选项(以及禁用关闭按钮),并且如果上面禁用或隐藏,则禁用通过 Alt+F4 关闭。