2009-05-07 3 views
0

Мне нужно получить обработчик к дочернему окну определенного приложения, которое работает. У меня есть обработчик главного окна, но мне нужно знать, какое конкретное дочернее окно активно, чтобы использовать SendMessage/PostMessage.Как получить активное ChildWindow приложения, которое не сфокусировано?

я наконец-то удалось это сделать, используя следующий код, с помощью 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); 

    } 

Это работает очень хорошо! Однако, если приложение неактивно, например, если блокнот покрывает firefox, GUIThreadInfo содержит каждый элемент null. Только если firefox является самым большим (активным) приложением окон, структура будет заполнена.

Я знаю, что это может быть исправлено, если включить Firefox на передний план, но мне нужно было избежать этого. Есть ли у кого-нибудь другая идея получить активное дочернее окно приложения, которое не является самым верхним окном в Windows?

Благодаря

ответ

1

Если у вас есть верхний дескриптор окна для процесса, вы должны быть в состоянии использовать GetTopWindow получить окно в верхней части Z порядка. Это должно быть окно, которое было бы активным, если приложение было настроено как активное/текущее приложение.


Edit:

Что об использовании AttachThreadInput, чтобы прикрепить нить к другой технологической цепочке?

После того, как вы это сделали, GetFocus() и PostMessage()/SendMessage() должны работать. Просто убедитесь, что вы отсоедините вход, когда закончите.

The only sample I can find of this, к сожалению, в Delphi, но будет легко перевести.

+0

Это не работает, всегда возвращает один и тот же обработчик, не имеет значения, если фокус находится на дочернем окне с окном поиска на странице Google или дочернее окно с адресная строка – Noyoudont

+0

Я думаю, причина в том, что mainWindow firefox имеет одного ребенка. Этот ребенок - это адресная строка. Но у этого ребенка также есть ребенок, и именно там находится страница google. Итак, я думаю, что GetTopWindow не работает в глубину, просто проверяет дочерние элементы родительского окна (а не внуков и т. Д.), Поэтому он всегда возвращает тот же обработчик ... – Noyoudont

+0

@Noyoudont: см. Подход в образце выше. Он использует AttachThreadInput для решения этой проблемы и, вероятно, является гораздо более надежным подходом. ЕСЛИ вам нужно, чтобы я перевел это на C#, дайте мне знать. –

0

Вы можете подумать о получении ручки детского окна с помощью функции GetWindow (hWnd, GW_CHILD) и отправить сообщение на этот дескриптор.

Также следует знать, что на Microsoft Windows Vista and later. Message posting is subject to User Interface Privilege Isolation (UIPI). The thread of a process can post messages only to message queues of threads in processes of lesser or equal integrity level.