以编程方式开始移动表单
我正在尝试通过单击按钮来移动表单(使用标题栏)。
我认为使用 SendMessage 这会很简单:
Const WM_LBUTTONDOWN As Integer = &H201
Button1.Capture = False
Cursor.Position = Me.Location + New Size(50, 8)
SendMessage(Me.Handle, WM_LBUTTONDOWN, CType(1, IntPtr), IntPtr.Zero)
但是,尽管如果光标位于表单客户区域中,这会发送消息,但它似乎不会将其发送到表单标题栏(表单以某种方式捕获事件,尽管光标位于标题栏不在客户区)。
我已经在按钮上的 mousedown 和 click 事件中尝试了上面的代码,移动光标然后按下按钮1。
有什么建议么?
I am trying to make a form move (using the titlebar) from a button click.
I thought this would be simple using SendMessage:
Const WM_LBUTTONDOWN As Integer = &H201
Button1.Capture = False
Cursor.Position = Me.Location + New Size(50, 8)
SendMessage(Me.Handle, WM_LBUTTONDOWN, CType(1, IntPtr), IntPtr.Zero)
However, although this sends the message if the cursor is in the forms client area, it does not seem to send it to the forms titlebar (the form captures the event somehow, despite the cursor being on the titlebar not in the client area).
I have tried the above code in both mousedown and click events on the button, moving the cursor and then pressing on the button1.
Any suggestions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您需要
WM_
NC
LBUTTONDOWN
(并将HTCAPTION
作为wParam 传递)。 不过,我仍然不完全确定这会完成您想要做的事情。
通常,允许用户在单击标题栏以外的其他位置时移动表单的方法是处理
WM_NCHITTEST
消息,并在光标位于该区域上方时返回HTCAPTION
您想从哪个位置开始移动。 但是,如果该区域被子控件占用,则还必须从子控件处理WM_NCHITTEST
并返回HTTRANSPARENT
。顺便说一句,实现此目的的一种更简单(尽管稍微不太正确)的方法是像 Mehrdad Afshari 建议,只需设置表单的
Location
属性即可。 你对他评论说“它需要随着鼠标移动而移动”,而这正是你可以而且应该做的。这种方法的问题在于它绕过了 Windows 移动顶级窗口的代码。 这意味着,如果用户未在“显示属性”对话框中选择“拖动时显示窗口内容”选项,则将有效忽略该设置(不会显示拖动轮廓)。 可能还有其他一些我没有想到的缺点。
不过,总的来说,这是一种简单、容易的方法来完成此任务,它是一个完全的 .NET 解决方案,不依赖于任何平台调用(因此它应该可以移植到 Unix 上的 Mono)。
哎呀。 我刚刚意识到我给了你 C# 示例代码,但你的代码似乎是 VB.NET。 我猜您需要的是:
这可能不是在 VB.NET 中表达这一点的最简洁的方式。 我使用 Reflector 来帮助我翻译它。
You would need
WM_
NC
LBUTTONDOWN
(and passHTCAPTION
aswParam
). I'm still not entirely sure this would accomplish what you're trying to do, though.Typically, the way to allow the user to move your form when clicking somewhere other than the title bar is to process the
WM_NCHITTEST
message and returnHTCAPTION
when the cursor is over the area from which you'd like to initiate moving. However, if this area is occupied by a child control, you also have to processWM_NCHITTEST
from the child control and returnHTTRANSPARENT
.Incidentally, an easier—if slightly less correct—way to accomplish this is to do as Mehrdad Afshari suggested, and just set the form's
Location
property. You commented to him that "it needs to move on the mouse move", and that's exactly what you can and should do.The problem with this approach is that it bypasses Windows' code for moving a top-level window. This means that if the user has not selected the "Show window contents while dragging" option in the Display Properties dialog, this will effectively ignore that setting (it won't show a drag outline). There may be other drawbacks that I haven't thought of as well.
On the whole, though, this is a simple, easy way to accomplish this that is a fully .NET solution which doesn't rely on any platform invoke (so it should be portable to Mono on Unix).
Oops. I just realized that I gave you C# example code, but your code seems to be VB.NET. I guess what you would need would be:
This may not be the most succinct way to express this in VB.NET. I used Reflector to help me translate it.
wm_LButtonDown
消息的LParam
值接收客户端坐标中的鼠标位置。 标题栏位于非客户区域,因此请使用wm_NCLButtonDown
消息。 我之前已经看到该消息作为此问题的答案,但我希望有一个更直接的途径:发送wm_SysCommand
消息 到窗口,并指定sc_Move
标志。The
LParam
value for thewm_LButtonDown
message receives the mouse position in client coordinates. The title bar is in the non-client area, so use thewm_NCLButtonDown
message. I've seen that message given as an answer to this question before, but there's a more direct route that I would have expected to work: Send awm_SysCommand
message to the window, and specifysc_Move
flag.迈赫达德是对的,没有必要这样做。 鼠标被捕获,因此您永远无法将其移动得太快。 示例代码:
Mehrdad is right, no need to do this. The mouse is captured so you can never move it too quickly. Sample code: