A colleague of mine recently asked how to list all the windows on a machine. Microsoft Visual Studio (a developer programming tool) ships with a tool called Spy++ that will list all windows, but Spy++ is a GUI tool and my colleague wanted full programmatic access to windows. Anyway, iterating though all windows is something I do quite frequently so I coded up a short demo. In pseudo-code:
get handle to Desktop window
get all Desktop window info (level, caption, parent)
enqueue desktop window and info
while (queue not empty)
w = dequeue // curr window
print info about w
get all child windows of w
foreach child
get all child info
enqueue child and info
end
end
The image below shows the demo (which I named SpyMinusMinus) running next to the Spy++ GUI tool. You can see the outputs are essentially the same. All code (in C#) listed below the image.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace SpyMinusMinus
{
class Program
{
[DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
static extern int SendMessage(IntPtr hwndControl, uint Msg,int wParam, StringBuilder strBuffer); // get text
[DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
static extern int SendMessage(IntPtr hwndControl, uint Msg, int wParam, int lParam); // text length
[DllImport("user32.dll", EntryPoint = "FindWindowEx", CharSet = CharSet.Auto)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
static void Main(string[] args)
{
Console.WriteLine("\nGet all windows demo\n");
Queue q = new Queue(); // use a Stack instead for depth-first traversal
IntPtr hDesktop = GetDesktopWindow();
WindowInfo wi = new WindowInfo(); wi.handle = hDesktop; wi.level = 0; wi.caption = "(Desktop)"; wi.parent = IntPtr.Zero - 1;
q.Enqueue(wi);
while (q.Count > 0)
{
WindowInfo w = q.Dequeue();
Console.WriteLine(w.ToString());
List children = GetAllChildrenHandles(w.handle, 5000); // 5000 is max children sanity check
for (int i = 0; i < children.Count; ++i)
{
WindowInfo ci = new WindowInfo(); // child window info
ci.handle = children[i];
ci.level = w.level + 1; // parent level + 1
ci.caption = GetCaptionText(children[i]);
ci.parent = w.handle;
q.Enqueue(ci);
}
}
Console.WriteLine("\nEnd demo\n");
Console.ReadLine();
}
static List GetAllChildrenHandles(IntPtr hParent, int maxCount)
{
List result = new List();
int ct = 0;
IntPtr prevChild = IntPtr.Zero;
IntPtr currChild = IntPtr.Zero;
while (true && ct < maxCount)
{
currChild = FindWindowEx(hParent, prevChild, null, null);
if (currChild == IntPtr.Zero) break;
result.Add(currChild);
prevChild = currChild;
++ct;
}
return result;
}
static int GetCaptionTextLength(IntPtr hTextBox)
{
// helper for GetCaptionText
uint WM_GETTEXTLENGTH = 0x000E;
int result = SendMessage(hTextBox, WM_GETTEXTLENGTH,
0, 0);
return result;
}
static string GetCaptionText(IntPtr hTextBox)
{
uint WM_GETTEXT = 0x000D;
int len = GetCaptionTextLength(hTextBox);
if (len <= 0) return null; // no text. consider empty string instead.
StringBuilder sb = new StringBuilder(len + 1);
SendMessage(hTextBox, WM_GETTEXT, len + 1, sb);
return sb.ToString();
}
}
public class WindowInfo
{
public IntPtr handle;
public int level; // 0 = desktop, 1 = all top-level windows, etc.
public string caption; // several things such as app title or textbox text
public IntPtr parent;
public override string ToString()
{
string captionDisplay;
if (caption == null) captionDisplay = "no caption";
else captionDisplay = caption.ToString();
return "handle = " + handle.ToString("X").PadLeft(8, '0') +
" level = " + level.ToString().PadRight(3) +
" caption = " + captionDisplay.ToString().PadRight(40) +
" parent = " + parent.ToString("X").PadLeft(8, '0');
}
}
}

.NET Test Automation Recipes
Software Testing
SciPy Programming Succinctly
Keras Succinctly
R Programming
Visual Studio Live
Microsoft MLADS Conference
DevIntersection Conference
Machine Learning Week
Ai4 Conference
G2E Conference
iSC West Conference
You must be logged in to post a comment.