确定鼠标钩子何时处理最后一条消息
我有一个表单,其作用类似于下拉菜单,我显示非模式。我将鼠标挂钩附加到表单上,以确定何时从其中单击鼠标,以便我知道通过设置 Visible = False
来关闭它。
因为我希望 HookProc 处理最后一次单击,所以在确定事件处理程序已返回到 HookProc 之前,我无法处置 Hook 或 Dropdown。
这有点难以解释,但我希望下面的代码能让它更清楚一点:-
//Loop to display the dropdown.
Dim dd as New DropDown
dd.Visible = True
Do While dd.Visible
Application.DoEvents()
NativeMethods.MsgWaitForMultipleObjectsEx(0, IntPtr.Zero, 250, &HFF, 4)
Loop
// I want to dispose dd now, but how can I be sure that e.Handled (See below)
// has been returned to HookProc?
//A handler within dropdown to determine what to do with the mouse click.
Private Sub DropDown_MouseHookClick(ByVal sender As Object, ByVal e As MouseClickEventArgs)
If IWantToCloseTheDropDown Then
e.Handled = True
MyHook.UnHook
Me.Visible = False
End If
// All done, e.Handled is returned to HookProc.
// But which happens first? Will e.Handled arrive at HookProc first, or will
// the form display loop, above, notice that Visible is now False?
End Sub
//The main part of the hooking class.
Public Function MouseHookProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
Dim MyMouseHookStruct As MouseHookStruct = DirectCast(Marshal.PtrToStructure(lParam, GetType(MouseHookStruct)), MouseHookStruct)
If nCode < 0 Then
Return CallNextHookEx(hHook, nCode, wParam, lParam)
Else
Dim handle As Integer = MyMouseHookStruct.hwnd
Dim c As Control = Control.FromHandle(New IntPtr(handle))
If MouseUpOrDown Then
Dim e As MouseHookClickEventArgs
OnMouseClick(e)
If e.Handled Then
Return 1
EndIf
End If
Return CallNextHookEx(hHook, nCode, wParam, lParam)
End If
End Function
I have a form, that acts like a drop-down, that I display non-modal. I attach a mouse hook to the form to determine when the mouse is clicked out of it, so that I know to close it - by setting Visible = False
.
Because I want the HookProc
to handle the last click, I can't dispose the Hook or my Dropdown until I'm sure that my event handler has returned to the HookProc.
It's a bit hard to explain, but I hope the code below makes it a little clearer:-
//Loop to display the dropdown.
Dim dd as New DropDown
dd.Visible = True
Do While dd.Visible
Application.DoEvents()
NativeMethods.MsgWaitForMultipleObjectsEx(0, IntPtr.Zero, 250, &HFF, 4)
Loop
// I want to dispose dd now, but how can I be sure that e.Handled (See below)
// has been returned to HookProc?
//A handler within dropdown to determine what to do with the mouse click.
Private Sub DropDown_MouseHookClick(ByVal sender As Object, ByVal e As MouseClickEventArgs)
If IWantToCloseTheDropDown Then
e.Handled = True
MyHook.UnHook
Me.Visible = False
End If
// All done, e.Handled is returned to HookProc.
// But which happens first? Will e.Handled arrive at HookProc first, or will
// the form display loop, above, notice that Visible is now False?
End Sub
//The main part of the hooking class.
Public Function MouseHookProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
Dim MyMouseHookStruct As MouseHookStruct = DirectCast(Marshal.PtrToStructure(lParam, GetType(MouseHookStruct)), MouseHookStruct)
If nCode < 0 Then
Return CallNextHookEx(hHook, nCode, wParam, lParam)
Else
Dim handle As Integer = MyMouseHookStruct.hwnd
Dim c As Control = Control.FromHandle(New IntPtr(handle))
If MouseUpOrDown Then
Dim e As MouseHookClickEventArgs
OnMouseClick(e)
If e.Handled Then
Return 1
EndIf
End If
Return CallNextHookEx(hHook, nCode, wParam, lParam)
End If
End Function
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为什么不直接处理焦点事件呢? Form_LostFocus 会告诉您他们何时聚焦于另一个控件/表单。那时您可以隐藏您的表单。
鼠标钩子对于检测您的表单是否具有焦点似乎有点过分了。
Why not just handle the focus events? Form_LostFocus will tell you when they focus on another control/form. At that point you can hide your form.
A mouse hook seems like overkill for detecting if your form has focus or not.
您正在绕过 .NET 机制来处理 Windows 事件
您不应该需要任何本机来处理 WinForms。此外,整个代码都会被垃圾收集,因此您
do不必担心删除挂钩,您可能需要查看form.deactivate 事件
You are bypassing .NET mechanisms to handle windows events
You should not need anything native to deal with WinForms. Also the whole code is garbage collected so you
doSHOULD not have to worry about deleting hooksYou might want to look at the form.deactivate event