2010-06-10 30 views
6

Verwenden von Microsoft Spy ++ behandelt, kann ich sehen, dass die folgenden Fenster, die zu einem Prozess gehören:Holen Sie sich alle Fenster für einen Prozess

Prozess XYZ Fenstergriffe, in Baumform angezeigt wie Spy ++ gibt mir:

A 
    B 
    C 
    D 
E 
F 
    G 
    H 
    I 
    J 
    K 

Ich kann den Prozess abrufen, und die MainWindowHandle-Eigenschaft zeigt auf den Punkt für Fenster F. Wenn ich die untergeordneten Fenster mit aufzählen, kann ich eine Liste der Fenstergriffe für G durch K erhalten, aber ich kann nicht herausfinden, wie finde die Fenstergriffe für A bis D. Wie kann ich Fenster aufzählen, die keine Kinder des Handle sind, das von MainWindowHandle des Process-Objekts angegeben wird?

aufzuzählen ich den win32 Anruf bin mit:

[System.Runtime.InteropServices.DllImport(strUSER32DLL)] 
      public static extern int EnumChildWindows(IntPtr hWnd, WindowCallBack pEnumWindowCallback, int iLParam); 
+0

Früher gab es eine C# -Klasse, die all dies auf der GotDotNet-Site vor GotShutDown gut verpackt hatte. Kann es nicht mehr finden, aber es ist irgendwo da draußen ... –

Antwort

9

Pass IntPtr.Zero als hWnd jeden Wurzel Fenstergriff in dem System zu erhalten.

Sie können dann den Eigentümerprozess des Windows überprüfen, indem Sie GetWindowThreadProcessId aufrufen.

+2

Ist das der einzige Weg? Werde das versuchen. Ich frage mich, wie zeitaufwändig dieser Vorgang sein wird ... – Jeremy

6

Für alle noch fragen, ist dies die Antwort:

List<IntPtr> GetRootWindowsOfProcess(int pid) 
{ 
    List<IntPtr> rootWindows = GetChildWindows(IntPtr.Zero); 
    List<IntPtr> dsProcRootWindows = new List<IntPtr>(); 
    foreach (IntPtr hWnd in rootWindows) 
    { 
     uint lpdwProcessId; 
     WindowsInterop.User32.GetWindowThreadProcessId(hWnd, out lpdwProcessId); 
     if (lpdwProcessId == pid) 
      dsProcRootWindows.Add(hWnd); 
    } 
    return dsProcRootWindows; 
} 

public static List<IntPtr> GetChildWindows(IntPtr parent) 
{ 
    List<IntPtr> result = new List<IntPtr>(); 
    GCHandle listHandle = GCHandle.Alloc(result); 
    try 
    { 
     WindowsInterop.Win32Callback childProc = new WindowsInterop.Win32Callback(EnumWindow); 
     WindowsInterop.User32.EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle)); 
    } 
    finally 
    { 
     if (listHandle.IsAllocated) 
      listHandle.Free(); 
    } 
    return result; 
} 

private static bool EnumWindow(IntPtr handle, IntPtr pointer) 
{ 
    GCHandle gch = GCHandle.FromIntPtr(pointer); 
    List<IntPtr> list = gch.Target as List<IntPtr>; 
    if (list == null) 
    { 
     throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>"); 
    } 
    list.Add(handle); 
    // You can modify this to check to see if you want to cancel the operation, then return a null here 
    return true; 
} 

für WindowsInterop:

public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam); 

für WindowsInterop.User32:

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

[DllImport("user32.Dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam); 

Nun kann man einfach jede Wurzel erhalten Fenster von GetRootWindowsOfProcess, und ihre Kinder von GetChildWindows.

+0

Nicht nur Ihr Beispiel, sondern GetChildWindows funktioniert einfach nicht in Process.GetCurrentProcess() übergeben. MainWindowHandle. Ich starte ein untergeordnetes Fenster (modally oder nicht), rufe GetChildWindows auf, und der EnumWindow Rückruf feuert einfach nie. – dudeNumber4

+0

Welches System? Es funktioniert bei mir unter Windows 7. – xamid

+0

Sie meinen OS? Win8. – dudeNumber4