2010-04-27 8 views
9

Ich versuche herauszufinden, ob ein Fenster mit bestimmten Daten von einem Prozess geöffnet wurde. Dieser Prozess erzeugt mehrere Fenster, und ich muss sie alle überprüfen.Finde Fenster mit spezifischem Text für einen Prozess

Ich habe keine Probleme, den Prozess zu finden, mit

foreach (Process p in Process.GetProcesses()) 
{ 
    if (p.MainModule.FileName.ToLower().EndsWith("foo.exe")) 
    FindChildWindowWithText(p); //do work 

das Problem ist, was als nächstes zu tun ist. Ich kann Process 'MainWindowText nicht verwenden, da er sich mit dem Fenster ändert, das aktiviert ist.

Dann habe ich versucht, Windows-Funktion EnumChildWindows und GetWindowText zu verwenden, aber ich bin mir nicht sicher, ob ich ein korrektes Handle zu EnumChildWindows übergeben. Das EnumChildWindows funktioniert wie erwartet, wenn MainWindowHandle übergeben wird, aber das MainWindowHandle ändert natürlich mit aktivem Fenster. So habe ich Process.Handle übergeben, aber ich bekomme verschiedene Griffe und unterschiedliche Ergebnisse beim Umschalten der App Windows. (Ich verstehe, dass EnumChildWindows gibt Griffe nicht nur Fenster, aber Kontrollen in .net sprechen, das ist kein Problem, wenn ich die Beschriftung des Fensters bekommen konnte auch)

Vielleicht tue ich das der falsche Weg und Ich brauche einen anderen Ansatz - wieder ist mein Problem so einfach wie ein Fenster mit Text zu finden, der bestimmten regulären Ausdrücken entspricht. So würde ich wahrscheinlich eine Funktion benötigen, die alle Fenster auflistet, die in der Taskleiste oder so sichtbar sind.

Dank

Antwort

19

Sobald Sie den Prozess haben, können Sie alle aufzuzählen, die Fenster in der Prozess- und Test falls vorhanden von ihnen stimmen mit dem Fenster überein, nach dem Sie suchen.

Sie die folgenden P benötigen/Invoke Erklärungen

[DllImport("user32", SetLastError=true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
private extern static bool EnumThreadWindows(int threadId, EnumWindowsProc callback, IntPtr lParam); 

[DllImport("user32", SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam); 

[DllImport("user32", SetLastError = true, CharSet = CharSet.Auto)] 
private extern static int GetWindowText(IntPtr hWnd, StringBuilder text, int maxCount); 

Die followng ist ein Beispiel eines Paares von Funktionen, die verwendet werden können, um die Fenster in einem bestimmten Verfahren zu finden, habe ich verstanden, aus Ihrer Frage, dass Sie Habe den Prozess, das Problem ist das Aufzählen der Fenster.

public static IntPtr FindWindowInProcess(Process process, Func<string, bool> compareTitle) 
{ 
    IntPtr windowHandle = IntPtr.Zero; 

    foreach (ProcessThread t in process.Threads) 
    { 
    windowHandle = FindWindowInThread(t.Id, compareTitle); 
    if (windowHandle != IntPtr.Zero) 
    { 
     break; 
    } 
    } 

    return windowHandle; 
} 

private static IntPtr FindWindowInThread(int threadId, Func<string, bool> compareTitle) 
{ 
    IntPtr windowHandle = IntPtr.Zero; 
    EnumThreadWindows(threadId, (hWnd, lParam) => 
    { 
    StringBuilder text = new StringBuilder(200); 
    GetWindowText(hWnd, text, 200); 
    if (compareTitle(text.ToString())) 
    { 
     windowHandle = hWnd; 
     return false; 
    } 
    return true; 
    }, IntPtr.Zero); 

    return windowHandle; 
} 

Dann können Sie die FindWindowInProcess Funktion aufrufen, um ein Fenster zu finden, die Titel endet mit „ABC“ als ein Beispiel ist.

IntPtr hWnd = FindWindowInProcess(p, s => s.EndsWith("ABC")); 
if (hWnd != IntPtr.Zero) 
{ 
    // The window was found.... 
} 

Natürlich können Sie s ersetzen => s.EndsWith („ABC“) mit jedem Ausdruck, die Ihre Suchkriterien für das Fenster befriedigen, könnte es ein regex usw.

hier auch sein ist eine Version von FindThreadWindow, die auch die erste Ebene der untergeordneten Fenster überprüft. Sie könnten dies weiterführen und es zu einer rekursiven Funktion machen, wenn Ihre Fenster tiefer in der Hierarchie liegen.

private static IntPtr FindWindowInThread(int threadId, Func<string, bool> compareTitle) 
{ 
    IntPtr windowHandle = IntPtr.Zero; 
    EnumThreadWindows(threadId, (hWnd, lParam) => 
    { 
    StringBuilder text = new StringBuilder(200); 
    GetWindowText(hWnd, text, 200);   
    if (compareTitle(text.ToString())) 
    { 
     windowHandle = hWnd; 
     return false; 
    } 
    else 
    { 
     windowHandle = FindChildWindow(hWnd, compareTitle); 
     if (windowHandle != IntPtr.Zero) 
     { 
     return false; 
     } 
    } 
    return true; 
    }, IntPtr.Zero); 

    return windowHandle; 
} 

private static IntPtr FindChildWindow(IntPtr hWnd, Func<string, bool> compareTitle) 
{ 
    IntPtr windowHandle = IntPtr.Zero; 
    EnumChildWindows(hWnd, (hChildWnd, lParam) => 
    { 
    StringBuilder text = new StringBuilder(200); 
    GetWindowText(hChildWnd, text, 200);   
    if (compareTitle(text.ToString())) 
    { 
     windowHandle = hChildWnd; 
     return false; 
    } 
    return true; 
    }, IntPtr.Zero); 

    return windowHandle; 
} 
+0

sehr aufwendige Antwort, wirkt wie ein Charme. – Axarydax

+0

In FindChildWindow ... sollte nicht hChildWnd anstelle von hWnd nach Überprüfung des Ergebnisses von compareTitle sein? – seveves

3

Anstatt Prozesse und die Suche nach dem Fenster aufzählt, ich die Fenster aufzuzählen würde (mit EnumWindows) und den Prozess (mit GetGuiThreadInfo) finden.

+0

Oder GetWindowsThreadProcessId (http://msdn.microsoft.com/en-us/library/ms633522(VS.85).aspx). –

Verwandte Themen