Determine when a mouse hook has handled the last message
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 开发者_如何学PythonObject, 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
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.
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 do SHOULD not have to worry about deleting hooks
You might want to look at the form.deactivate event
精彩评论