Introduction
There are many programs on the market like Spy++ or screen capture programs which allow the user to find and select a specific window or window-control like Button, Edit, etc.
The goal for this project was to write an easy interface for finding window handles.
- After starting the application, start dragging the bull eye symbol "Finder Tool" (1)
- Move the "Finder Tool" symbol to the desired window
- Stop moving and drop the mouse cursor if you want information about the underlying window
- The information about the selected window is shown in the dialog properties (2)
Background
I have programmed such a finder tool for many years in C++.
Now I use this in C#, so I converted my old C++ code into C# code.
Using the Code
There are two important methods which find and select the window:
- Function "
MainForm::ChildWindowFromPoint
"
Param: point
is the global point on the screen (normally the mouse cursor)
Return: handle
from the found window
static IntPtr ChildWindowFromPoint(Point point)
{
IntPtr WindowPoint = ApiWrapper.Window.WindowFromPoint(point);
if (WindowPoint == IntPtr.Zero)
return IntPtr.Zero;
if (ApiWrapper.Window.ScreenToClient(WindowPoint, ref point) == false)
throw new Exception("ScreenToClient failed");
IntPtr Window = ApiWrapper.Window.ChildWindowFromPointEx
(WindowPoint, point, 0);
if (Window == IntPtr.Zero)
return WindowPoint;
if(ApiWrapper.Window.ClientToScreen(WindowPoint, ref point) == false)
throw new Exception("ClientToScreen failed");
if(ApiWrapper.Window.IsChild
(ApiWrapper.Window.GetParent(Window),Window) == false)
return Window;
ArrayList WindowList = new ArrayList();
while (Window != IntPtr.Zero)
{
Rectangle rect = ApiWrapper.Window.GetWindowRect(Window);
if(rect.Contains(point))
WindowList.Add(Window);
Window = ApiWrapper.Window.GetWindow
(Window, (uint)ApiWrapper.Window.GetWindow_Cmd.GW_HWNDNEXT);
}
int MinPixel = GetSystemMetrics((int)
GetSystem_Metrics.SM_CXFULLSCREEN) *
GetSystemMetrics((int)GetSystem_Metrics.SM_CYFULLSCREEN);
for (int i = 0; i < WindowList.Count; ++i)
{
Rectangle rect = ApiWrapper.Window.GetWindowRect
( (IntPtr)WindowList[i] );
int ChildPixel = rect.Width * rect.Height;
if (ChildPixel < MinPixel)
{
MinPixel = ChildPixel;
Window = (IntPtr)WindowList[i];
}
}
return Window;
}
- Function "
MainForm::ShowInvertRectTracker
"
Param: window to show/hide the selected rectangle
static void ShowInvertRectTracker(IntPtr window)
{
if(window != IntPtr.Zero)
{
Rectangle WindowRect = ApiWrapper.Window.GetWindowRect(window);
IntPtr dc = ApiWrapper.Window.GetWindowDC(window);
ApiWrapper.Gdi.SetROP2(dc, (int)ApiWrapper.Gdi.RopMode.R2_NOT);
Color color = Color.FromArgb(0, 255, 0);
IntPtr Pen = ApiWrapper.Gdi.CreatePen
((int)ApiWrapper.Gdi.PenStyles.PS_INSIDEFRAME, 3 *
GetSystemMetrics((int)GetSystem_Metrics.SM_CXBORDER),
(uint)color.ToArgb());
IntPtr OldPen = ApiWrapper.Gdi.SelectObject(dc, Pen);
IntPtr OldBrush = ApiWrapper.Gdi.SelectObject
(dc, ApiWrapper.Gdi.GetStockObject
((int)ApiWrapper.Gdi.StockObjects.NULL_BRUSH));
ApiWrapper.Gdi.Rectangle(dc, 0, 0, WindowRect.Width,
WindowRect.Height);
ApiWrapper.Gdi.SelectObject(dc, OldBrush);
ApiWrapper.Gdi.SelectObject(dc, OldPen);
ApiWrapper.Window.ReleaseDC(window, dc);
ApiWrapper.Gdi.DeleteObject(Pen);
}
}
Files
- MainForm.cs
Shows the FindWindow
dialog.
Handles the mouse events (down - move - up) and displays the result information.
- GdiApiWrapper.cs, WinApiWrapper.cs
The base functions MainForm::ChildWindowFromPoint
and MainForm::ShowInvertRectTracker
use the base Win API extensively.
The signatures of the Win API are listed in these files. The list of functions is not complete. I only implemented functions that I need for this tool.
History
- 3rd April, 2009: Initial version