2009-11-16 66 views
0

我有一个窗体,就像一个下拉菜单,它显示非模态。我在表单上附加了一个鼠标钩,以确定鼠标何时被点击,以便我知道关闭它 - 通过设置Visible = False。因为我想HookProc来处理最后一次点击,我不能处置Hook或我的下拉列表,直到我确定我的事件处理程序已返回到HookProc。确定鼠标钩何时处理了最后一条消息

这是一个有点难以解释,但我希望下面的代码使其更清晰一点: -

//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 

回答

0

为什么不直接处理的焦点事件? Form_LostFocus会告诉你他们何时关注另一个控件/表单。此时你可以隐藏你的表格。

鼠标钩看起来像矫枉过正,用于检测表单是否有焦点。

+0

我用鼠标钩子,因为有两种方式下拉可剩下。一个是通过点击它(在这种情况下,我希望它关闭)。另一种情况是,如果物业网格(它所在的并且我有限的控制权)打开另一个表单 - 即类型编辑器(TypeEditor)。在这种情况下,我不想关闭我的下拉菜单。 – Jules 2009-11-24 08:52:43

+0

您可能能够处理PropertyGrid上的PropertyValueChanged事件,并在该特定值发生更改(使用TypeEditor的那个值)更改时重新打开下拉菜单。如果事件触发,则对话框关闭,您可以再次打开下拉菜单。 – 2009-12-01 18:33:18

0

您绕过.NET的机制来处理窗口事件

你不应该需要什么本地处理的WinForms。另外,整个代码回收垃圾,所以你不应该再担心删除的钩

你可能想看看form.deactivate事件