2009-05-21 7 views
3

J'ai un C#/app NET et je veux mettre en œuvre le comportement suivant:.programme est de déterminer si la fenêtre active dans .NET

J'ai un menu contextuel. Chaque fois que l'utilisateur clique sur quelque chose dans l'application qui est pas le menu contextuel, je veux fermer le menu contextuel. Cependant, chaque fois qu'un utilisateur n'est pas dans l'application, je ne veux rien faire.

J'essaie de gérer cela via l'événement LostFocus, mais je n'arrive pas à déterminer si mon application est la fenêtre active. Le code ressemble à ceci.

private void Button_LostFocus(object sender, System.EventArgs e) 
    { 
     if (InActiveWindow()) { 
      CloseMenu() 
     } 
     else { 
      // not in active window, do nothing 
     } 
    } 

Ce que j'ai besoin de savoir est de savoir comment implémenter la méthode InActiveWindow().

Répondre

4

Vous pouvez effectuer une P/Appel dans GetForegroundWindow() et comparer le HWND renvoyé à la propriété form.Handle de l'application.

Une fois que vous avez le handle, vous pouvez également appeler GetAncestor() pour obtenir la fenêtre du propriétaire root. Cela devrait être le handle de la fenêtre de démarrage principale de votre application, si celle-ci se trouve dans votre application.

1

Il semble que la principale raison pour laquelle cela est difficile est que le popup perd son focus avant que le formulaire principal soit désactivé, ainsi la fenêtre active sera toujours dans l'application au moment de cet événement. Vraiment, vous voulez savoir si ce sera toujours la fenêtre active après la fin de l'événement.

Vous pouvez mettre en place une sorte de schéma où vous vous souvenez qu'un popup perd du focus, mettez de côté le fait que vous devrez le fermer, et dans l'événement LostFocus ou Deactivate du formulaire principal de l'application annuler la note vous dit que vous devez le fermer; mais le problème est quand allez-vous traiter la note?

Je pense qu'il pourrait être plus facile, au moins si la popup est un enfant direct de la forme principale (que je soupçonne dans votre cas, il peut être) pour accrocher le Focus ou peut-être même Click événement du formulaire principal et l'utiliser ferme la fenêtre si elle est ouverte (peut-être en analysant sa liste de formulaires enfants pour ceux qui implémentent une interface ICloseOnLostFocus, de sorte que la fenêtre contextuelle aura une chance de participer à la décision et de faire tout ce qu'elle doit faire). Je voudrais savoir d'un meilleur document expliquant ce que tous ces événements signifient réellement et comment ils sont séquencés l'un par rapport à l'autre, MSDN laisse beaucoup à désirer en les décrivant.

2

Je suis tombé sur votre question tout en travaillant sur un projet et basé sur Reed Copsey's answer, j'ai écrit ce code rapide qui semble bien faire le travail.

Voici le code:

Public Class Form1 
    '''<summary> 
    '''Returns a handle to the foreground window. 
    '''</summary> 
    <Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _ 
    Private Shared Function GetForegroundWindow() As IntPtr 
    End Function 

    '''<summary> 
    '''Gets a value indicating whether this instance is foreground window. 
    '''</summary> 
    '''<value> 
    '''<c>true</c> if this is the foreground window; otherwise, <c>false</c>. 
    '''</value> 
    Private ReadOnly Property IsForegroundWindow As Boolean 
     Get 
      Dim foreWnd = GetForegroundWindow() 
      Return ((From f In Me.MdiChildren Select f.Handle).Union(
        From f In Me.OwnedForms Select f.Handle).Union(
        {Me.Handle})).Contains(foreWnd) 
     End Get 
    End Property 
End Class 

je n'avais pas trop de temps pour le convertir en C# que je travaille sur un projet avec un délai de 2 jours, mais je crois que vous pouvez rapidement faire la conversion.

Voici la version C# du code VB.NET:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    [System.Runtime.InteropServices.DllImport("user32.dll")] 
    private static extern IntPtr GetForegroundWindow(); 

    ///<summary>Gets a value indicating whether this instance is foreground window.</summary> 
    ///<value><c>true</c> if this is the foreground window; otherwise, <c>false</c>.</value> 
    private bool IsForegroundWindow 
    { 
     get 
     { 
      var foreWnd = GetForegroundWindow(); 
      return ((from f in this.MdiChildren select f.Handle) 
       .Union(from f in this.OwnedForms select f.Handle) 
       .Union(new IntPtr[] { this.Handle })).Contains(foreWnd); 
     } 
    } 
} 
Questions connexes