Last time I made an example of how to enumerate windows. This time I present to you a class that greatly simplifies the process of searching for specific windows, types of windows, windows belonging to a specific process, having a specific text. You can search for any number of these parameters at the same time, using regular expressions for all string matches to provide optimal flexibility.
using System.Runtime.InteropServices;
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;
namespace Searching_for_windows
{
class Program
{
const int WM_GETTEXT = 0x000D ;
const int WM_GETTEXTLENGTH = 0x000E ;
[DllImport("User32.Dll" )]
private static extern void GetClassName (int hWnd, StringBuilder s, int nMaxCount);
[DllImport("User32.dll" )]
private static extern int GetWindowText (int hWnd, StringBuilder text, int count);
[DllImport("User32.dll" )]
private static extern Int32 SendMessage (int hWnd, int Msg, int wParam, StringBuilder lParam);
[DllImport("User32.dll" )]
private static extern Int32 SendMessage (int hWnd, int Msg, int wParam, int lParam);
static void Main(string [] args)
{
WindowFinder wf = new WindowFinder();
wf.FindWindows(0 , null , null , new Regex("iexplore" ), new WindowFinder.FoundWindowCallback(foundWindow));
wf.FindWindows(0 , null , new Regex(" - Microsoft Visual Studio" ), new Regex("devenv" ), new WindowFinder.FoundWindowCallback(foundWindow));
Console.WriteLine("Done" );
Console.Read();
}
private static bool foundWindow (int handle)
{
printWindowInfo(handle);
return true ;
}
private static void printWindowInfo (int handle)
{
StringBuilder sbClass = new StringBuilder(256 );
GetClassName(handle, sbClass, sbClass.Capacity);
int txtLength = SendMessage(handle, WM_GETTEXTLENGTH, 0 , 0 );
StringBuilder sbText = new StringBuilder(txtLength + 1 );
SendMessage(handle, WM_GETTEXT, sbText.Capacity, sbText);
Console.WriteLine("Handle: " + handle);
Console.WriteLine("Class : " + sbClass);
Console.WriteLine("Text : " + sbText);
Console.WriteLine();
}
}
public class WindowFinder
{
const int WM_GETTEXT = 0x000D ;
const int WM_GETTEXTLENGTH = 0x000E ;
[DllImport("User32.Dll" )]
private static extern void GetClassName (int hWnd, StringBuilder s, int nMaxCount);
[DllImport("User32.dll" )]
private static extern int GetWindowText (int hWnd, StringBuilder text, int count);
[DllImport("User32.dll" )]
private static extern Int32 SendMessage (int hWnd, int Msg, int wParam, StringBuilder lParam);
[DllImport("User32.dll" )]
private static extern Int32 SendMessage (int hWnd, int Msg, int wParam, int lParam);
[DllImport("user32" )]
private static extern int GetWindowThreadProcessId (int hWnd, out int lpdwProcessId);
[DllImport("user32.Dll" )]
private static extern Boolean EnumChildWindows (int hWndParent, PChildCallBack lpEnumFunc, int lParam);
private delegate bool PChildCallBack (int hWnd, int lParam);
private event FoundWindowCallback foundWindow;
public delegate bool FoundWindowCallback (int hWnd);
private int parentHandle;
private Regex className;
private Regex windowText;
private Regex process;
public void FindWindows (int parentHandle, Regex className, Regex windowText, Regex process, FoundWindowCallback fwc)
{
this .parentHandle = parentHandle;
this .className = className;
this .windowText = windowText;
this .process = process;
foundWindow = fwc;
EnumChildWindows(parentHandle, new PChildCallBack(enumChildWindowsCallback), 0 );
}
private bool enumChildWindowsCallback (int handle, int lParam)
{
if (className != null )
{
StringBuilder sbClass = new StringBuilder(256 );
GetClassName(handle, sbClass, sbClass.Capacity);
if (!className.IsMatch(sbClass.ToString()))
return true ;
}
if (windowText != null )
{
int txtLength = SendMessage(handle, WM_GETTEXTLENGTH, 0 , 0 );
StringBuilder sbText = new StringBuilder(txtLength + 1 );
SendMessage(handle, WM_GETTEXT, sbText.Capacity, sbText);
if (!windowText.IsMatch(sbText.ToString()))
return true ;
}
if (process != null )
{
int processID;
GetWindowThreadProcessId(handle, out processID);
Process p = Process.GetProcessById(processID);
if (!process.IsMatch(p.ProcessName))
return true ;
}
return foundWindow(handle);
}
}
}
And the result:
Mark S. Rasmussen
I'm the CTO at
iPaper where I cuddle with databases, mold code and maintain the overall technical & team responsibility. I'm an avid speaker at user groups & conferences. I love life, motorcycles, photography and all things technical. Say hi on
Twitter , write me an
email or look me up on
LinkedIn .