2009-05-07 3 views
0

J'ai besoin d'obtenir le gestionnaire de la fenêtre enfant d'une certaine application qui est en cours d'exécution. J'ai le gestionnaire de fenêtre principal, mais j'ai besoin de savoir quelle fenêtre enfant spécifique est active, afin d'utiliser SendMessage/PostMessage.Comment obtenir la ChildWindow active d'une application qui n'est pas focalisée?

J'ai finalement réussi à le faire en utilisant le code suivant, en utilisant Firefox:

[DllImport("user32.dll")] 
    static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId); 

    [DllImport("user32.dll", EntryPoint = "GetGUIThreadInfo")] 
    internal static extern bool GetGUIThreadInfo(uint idThread, out GUITHREADINFO threadInfo); 


    private void button1_Click(object sender, EventArgs e) 
    { 
     //start firefox 
     firefox = new Process(); 
     firefox.StartInfo.FileName = @"C:\Program Files\Mozilla Firefox\firefox.exe"; 
     firefox.Start(); 
     Thread.Sleep(10000); 

     // get thread of the main window handle of the process 
     var threadId = GetWindowThreadProcessId(firefox.MainWindowHandle, IntPtr.Zero); 

     // get gui info 
     var info = new GUITHREADINFO(); 
     info.cbSize = (uint)Marshal.SizeOf(info); 
     if (!GetGUIThreadInfo(threadId, out info)) 
      throw new Win32Exception(); 


     // send the letter W to the active window 
     PostMessage(info.hwndActive, WM_KEYDOWN, (IntPtr)Keys.W, IntPtr.Zero); 

    } 

Cela fonctionne très bien! Cependant, si l'application n'est pas active, par exemple, si notepad couvre firefox, GUIThreadInfo est fourni avec tous les membres null. Ce n'est que si firefox est l'application la plus haute (active) de windows, que la structure sera remplie.

Je sais que cela pourrait être résolu en mettant firefox au premier plan, mais je devais éviter de le faire. Est-ce que quelqu'un a une autre idée pour obtenir la fenêtre enfant active d'une application qui n'est pas la fenêtre la plus haute de Windows?

Merci

Répondre

1

Si vous avez la plus haute poignée de fenêtre pour le processus, vous devriez être en mesure d'utiliser GetTopWindow pour recevoir la fenêtre en haut de l'ordre Z. Cela devrait être la fenêtre qui serait active si l'application était configurée pour être l'application active/en cours.


Edit:

Qu'en est-il en utilisant AttachThreadInput pour attacher votre fil à l'autre fil de processus?

Une fois cela fait, GetFocus() et PostMessage()/SendMessage() devraient fonctionner. Assurez-vous juste de détacher l'entrée lorsque vous avez terminé.

The only sample I can find of this est malheureusement en Delphi, mais serait facile à traduire.

+0

Il ne fonctionne pas, retourne toujours le même gestionnaire, n'a pas d'importance si l'accent est mis sur la fenêtre enfant avec la boîte de recherche de la page Google ou la fenêtre enfant la barre d'adresse – Noyoudont

+0

Je pense que la raison en est que la mainWindow de firefox a un enfant. Cet enfant est où la barre d'adresse est. Mais cet enfant a aussi un enfant, et c'est là que se trouve la page google. Donc je pense que le GetTopWindow ne fonctionne pas en profondeur, vérifie juste les enfants de la fenêtre parent (pas les petits-enfants, etc), donc il retourne toujours le même gestionnaire ... – Noyoudont

+0

@Noyoudont: Voir l'approche dans l'échantillon au dessus. Il utilise AttachThreadInput pour contourner ce problème et est probablement une approche beaucoup plus fiable. SI vous avez besoin de moi pour traduire cela en C#, faites le moi savoir. –

Questions connexes