Come ottenere la ChildWindow attiva di un'applicazione non focalizzata?
-
06-07-2019 - |
Domanda
Devo portare il gestore nella finestra figlio di una determinata applicazione in esecuzione. Ho il gestore della finestra principale, ma devo sapere quale finestra figlio specifica è attiva, al fine di utilizzare SendMessage / PostMessage.
Finalmente sono riuscito a farlo usando il seguente codice, usando 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);
}
Funziona molto bene! Tuttavia, se l'applicazione non è attiva, ad esempio, se il blocco note copre firefox, GUIThreadInfo viene fornito con ogni membro null. Solo se Firefox è l'applicazione più attiva (attiva) di Windows, la struttura verrà riempita.
So che questo potrebbe essere risolto portando Firefox in primo piano, ma ho dovuto evitare di farlo. Qualcuno ha un'altra idea per ottenere la finestra figlio attiva di un'applicazione che non è la finestra più in alto in Windows?
Grazie
Soluzione
Se hai l'handle di finestra più in alto per il processo, dovresti essere in grado di usare GetTopWindow per ricevere la finestra nella parte superiore dell'ordine Z. Questa dovrebbe essere la finestra che sarebbe attiva se l'applicazione fosse impostata come l'app attiva / corrente.
Modifica:
Che dire dell'utilizzo di AttachThreadInput per allegare il tuo thread nell'altro thread di processo?
Una volta fatto, GetFocus () e PostMessage () / SendMessage () dovrebbero funzionare. Assicurati di staccare l'input quando hai finito.
L'unico esempio che posso trovare su questo è purtroppo in Delfi, ma sarebbe facile da tradurre.
Altri suggerimenti
Puoi prendere in considerazione l'ottenimento dell'handle della finestra figlio utilizzando GetWindow (hWnd, GW_CHILD) e pubblica il messaggio su questo handle.
Inoltre, tieni presente che su Microsoft Windows Vista e versioni successive . La pubblicazione dei messaggi è soggetta all'UIPI (User Interface Privilege Isolation). Il thread di un processo può pubblicare messaggi solo nelle code dei thread dei thread in processi di livello di integrità inferiore o uguale.