开发者

Get all window handles for a process

Using Microsoft Spy++, I can see that t开发者_JAVA技巧he following windows that belong to a process:

Process XYZ window handles, displayed in tree form just like Spy++ gives me:

A
  B
  C
     D
E
F
  G
  H
  I
  J
     K

I can get the process, and the MainWindowHandle property points to the handle for window F. If I enumerate the child windows using I can get a list of window handles for G through K, but I can't figure out how to find the window handles for A through D. How can I enumerate windows that are not children of the handle specified by MainWindowHandle of the Process object?

To enumerate I'm using the win32 call:

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


Pass IntPtr.Zero as hWnd to get every root window handle in the system.

You can then check the windows' owner process by calling GetWindowThreadProcessId.


For everyone still wondering, this is the answer:

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

for WindowsInterop:

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

for 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);

Now one can simply get every root window by GetRootWindowsOfProcess, and their children by GetChildWindows.


You can use EnumWindows to get every top-level window, and then filter the results based on GetWindowThreadProcessId.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜