2010-06-10 4 views
6

Использование Microsoft Spy ++, я могу видеть, что следующие окна, которые принадлежат к процессу:Получить все оконные ручки для процесса

Обрабатывать ручки окна XYZ, отображаемые в виде дерева так же, как Spy ++ дает мне:

A 
    B 
    C 
    D 
E 
F 
    G 
    H 
    I 
    J 
    K 

Я могу получить процесс, и свойство MainWindowHandle указывает на дескриптор окна F. Если я перечисляю дочерние окна, я могу получить список оконных дескрипторов для G-K, но я не могу понять, как найти дескрипторы окна для A до D. Как я могу перечислять окна, которые не являются дочерними элементами дескриптора, заданными MainWindowHandle объекта Process?

Перечислить Я использую вызов win32:

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

Раньше существовал класс C#, который хорошо дополнял все это на сайте GotDotNet до его GotShutDown. Не могу найти его больше, но он где-то там ... –

ответ

9

Pass IntPtr.Zero в hWnd получить каждый корневой дескриптор окна в системе.

Затем вы можете проверить процесс владельца окон, позвонив по номеру GetWindowThreadProcessId.

+2

Это единственный способ? Попробуй это. Интересно, сколько времени займет эта операция ... – Jeremy

6

Для всех до сих пор интересно, это ответ:

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; 
} 

для WindowsInterop:

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

для 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); 

Теперь можно просто получить каждый корень окно GetRootWindowsOfProcess и их дети по GetChildWindows.

+0

Не просто ваш пример, но GetChildWindows просто не работает в Process.GetCurrentProcess(). MainWindowHandle. Я запускаю дочернее окно (модально или нет), вызываю GetChildWindows, и обратный вызов EnumWindow просто никогда не срабатывает. – dudeNumber4

+0

Какая система? Он работает для меня в Windows 7. – xamid

+0

Вы имеете в виду ОС? Win8. – dudeNumber4