Here is another implementation, using EnumWindows
and EnumChildWindows
.
This answer is not meant to be marked, but shows a different approach to the same problem.
It searches for a depth of 3, which can be increased in the code or even can be got as a constructor or method parameter.
It works.
public class RecursiveWindowSearcher
{
public delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32")]
public extern static int EnumWindows(EnumWindowsProc lpEnumFunc, int lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
private IntPtr windowParent;
private string windowName;
private IntPtr windowPointer;
public RecursiveWindowSearcher(string windowName, IntPtr windowParent)
{
this.windowName = windowName;
this.windowParent = windowParent;
}
public bool WinApiCallback(IntPtr hwnd, IntPtr lParam)
{
Console.WriteLine("Window: {0}", hwnd);
StringBuilder windowNameFar = new StringBuilder(256);
GetWindowText(hwnd, windowNameFar, 256);
if (windowNameFar.ToString() == windowName)
{
windowPointer = hwnd;
return false;
}
Console.WriteLine("Name: {0}", windowNameFar);
if(indent == 6)
{
return false;
}
indent += 2;
EnumChildWindows(hwnd, WinApiCallback, IntPtr.Zero);
indent -= 2;
return true;
}
public IntPtr Find()
{
this.windowPointer = IntPtr.Zero;
if (windowParent == IntPtr.Zero)
{
EnumWindows(WinApiCallback, 0);
}
else
{
EnumChildWindows(windowParent, WinApiCallback, IntPtr.Zero);
}
return windowPointer;
}
}
And the usage is simple enough:
The second constructor parameter is a pointer to an existing window to search starting from. If you have this handle, you can pass it to narrow the search scope to a specific window and its children.
static void Main()
{
IntPtr windowFound = new RecursiveWindowSearcher("Skype for Business ", IntPtr.Zero).Find();
Console.ReadLine();
}