2009-11-16 2 views
0

J'ai un formulaire, qui agit comme une liste déroulante, que je montre non-modal. J'attache un crochet de la souris au formulaire pour déterminer quand la souris est cliquée hors de lui, de sorte que je sais de le fermer - en définissant Visible = False. Parce que je veux que le HookProc gère le dernier clic, je ne peux pas disposer du crochet ou de ma liste déroulante jusqu'à ce que je suis sûr que mon gestionnaire d'événements est revenu à HookProc.Déterminez quand un crochet de la souris a traité le dernier message

Il est un peu difficile à expliquer, mais j'espère que le code ci-dessous fait un peu plus clair: -

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

Répondre

0

Pourquoi ne pas simplement gérer les événements de discussion? Form_LostFocus vous dira quand ils se concentrent sur un autre contrôle/formulaire. À ce stade, vous pouvez cacher votre formulaire.

Un crochet de souris semble être trop puissant pour détecter si votre formulaire est actif ou non.

+0

J'utilise un crochet de la souris, car il y a deux façons dans le menu déroulant peut être la gauche. L'un est en cliquant dessus (auquel cas je veux qu'il se ferme). Un autre est si la grille des propriétés, qu'elle héberge et sur laquelle j'ai un contrôle limité, ouvre une autre forme - c'est-à-dire un TypeEditor. Dans ce cas, je ne veux pas fermer ma liste déroulante. – Jules

+0

Vous pouvez gérer l'événement PropertyValueChanged sur votre PropertyGrid et rouvrir le menu déroulant lorsque cette valeur particulière change (celle avec TypeEditor). Si l'événement se déclenche, la boîte de dialogue a été fermée et vous pouvez à nouveau ouvrir la liste déroulante. –

0

Vous suspendez des mécanismes .NET pour gérer les événements fenêtres

Vous ne devriez pas avoir quoi que ce soit natif de traiter avec WinForms. De plus, le code complet est nettoyé de sorte que vous faire ne devrait pas avoir à vous soucier de la suppression des crochets

Vous pouvez regarder l'événement form.deactivate

Questions connexes