【问题标题】:Determine when a mouse hook has handled the last message确定鼠标钩子何时处理了最后一条消息
【发布时间】:2012-02-16 06:20:47
【问题描述】:

我有一个表单,它的作用类似于下拉菜单,我显示非模态。我在表单上附加了一个鼠标钩子,以确定何时从表单中单击鼠标,以便我知道关闭它 - 通过设置 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

【问题讨论】:

    标签: .net vb.net winforms mouse-hook


    【解决方案1】:

    为什么不只处理焦点事件? Form_LostFocus 会在他们关注另一个控件/表单时告诉您。此时您可以隐藏表单。

    鼠标钩子对于检测表单是否有焦点似乎有点过头了。

    【讨论】:

    • 我使用鼠标钩,因为下拉菜单有两种方式可以离开。一种是单击它(在这种情况下,我希望它关闭)。另一种情况是,它所包含的并且我对其控制有限的属性网格打开了另一种形式 - 即 TypeEditor。在这种情况下,我不想关闭我的下拉菜单。
    • 您可以处理 PropertyGrid 上的 PropertyValueChanged 事件,并在该特定值更改时重新打开下拉列表(带有 TypeEditor 的那个)。如果事件触发,则对话框已关闭,您可以再次打开下拉菜单。
    【解决方案2】:

    您正在绕过 .NET 机制来处理 Windows 事件

    您不应该需要任何本机来处理 WinForms。此外,整个代码都是垃圾收集的,所以你 do 不应该担心删除钩子

    您可能想查看form.deactivate 事件

    【讨论】:

      猜你喜欢
      • 2021-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-06
      相关资源
      最近更新 更多