Click here to Skip to main content
15,886,199 members
Articles / Desktop Programming / Win32
Article

FindWindow

Rate me:
Please Sign up or sign in to vote.
4.88/5 (25 votes)
4 Apr 2009CPOL1 min read 91.8K   6.8K   71   7
FindWindow is a tool for searching windows/controls

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.

  1. After starting the application, start dragging the bull eye symbol "Finder Tool" (1)
  2. Move the "Finder Tool" symbol to the desired window
  3. Stop moving and drop the mouse cursor if you want information about the underlying window
  4. 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:

  1. Function "MainForm::ChildWindowFromPoint"
    Param: point is the global point on the screen (normally the mouse cursor)
    Return: handle from the found window
    C#
    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;
    
    	// create a list to hold all children under the point
    	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);
    	}
    
    	// search for the smallest window in the list
    	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;
    }
  2. Function "MainForm::ShowInvertRectTracker"
    Param: window to show/hide the selected rectangle
    C#
    static void ShowInvertRectTracker(IntPtr window)
    {
    	if(window != IntPtr.Zero)
    	{
    		// get the coordinates from the window on the screen
    		Rectangle WindowRect = ApiWrapper.Window.GetWindowRect(window);
    		// get the window's device context
    		IntPtr dc = ApiWrapper.Window.GetWindowDC(window);
    
    		// Create an inverse pen that is the size of the window border
    		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());
    
    		// Draw the rectangle around the window
    		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);
    
    		//release the device context, and destroy the pen
    		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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) ModuleSoft
Germany Germany
My name is Jörg Bausch.
Currently I am a freelancer/consultant in Germany.
I have been developing professionally since 1994.
In the past i have worked as a programmer and projectleader.
My favorite language is C++ but in the last years i developed
more and more C# applications.

I am interested in new technologies and look for new projects.

Visit my site: www.modulesoft.de
This is a Organisation (No members)


Comments and Discussions

 
GeneralMy vote of 5 Pin
Paul M Watt10-Oct-12 5:31
mentorPaul M Watt10-Oct-12 5:31 
GeneralMy vote of 5 Pin
blueasa6-May-12 8:10
blueasa6-May-12 8:10 
Generalthanks and one question about detecting desktop items Pin
BillWoodruff6-Nov-09 0:21
professionalBillWoodruff6-Nov-09 0:21 
GeneralRe: thanks and one question about detecting desktop items Pin
Jörg Bausch6-Nov-09 3:50
Jörg Bausch6-Nov-09 3:50 
GeneralRe: thanks and one question about detecting desktop items [modified] Pin
BillWoodruff6-Nov-09 16:36
professionalBillWoodruff6-Nov-09 16:36 
Thanks, Jörg,

Just to make sure my first comment was clear : your FindWindow app now, when it is over the Desktop, or any Desktop item does not report anything which, I assume, is by design. Whether or not the "Desktop" is a Window : there's a "metaphysical" question Smile | :)

I am very familiar with George Mamaladze's GlobablHook, one of the "classic gems" of CodeProject, imho. What attracted me to your project was that you are reporting what window got the events while, to my knowledge, George's GlobalHook reports only mouse and key events and does not report what window the event was received by : but I will go and take another look at his source code.

I've recently commented on GlobalHook[^] and[^] in the context of using it with Visual Studio 2010 beta 2.

fyi : your demo compiles and runs fine in VS 2010 beta 2 against FrameWork 4.0.

thanks ! Bill

"Many : not conversant with mathematical studies, imagine that because it [the Analytical Engine] is to give results in numerical notation, its processes must consequently be arithmetical, numerical, rather than algebraical and analytical. This is an error. The engine can arrange and combine numerical quantities as if they were letters or any other general symbols; and it fact it might bring out its results in algebraical notation, were provisions made accordingly." Ada, Countess Lovelace, 1844

modified on Friday, November 6, 2009 10:56 PM

GeneralRe: thanks and one question about detecting desktop items Pin
Jörg Bausch6-Nov-09 23:22
Jörg Bausch6-Nov-09 23:22 
GeneralWPF Pin
Siavash Mortazavi6-Apr-09 16:11
Siavash Mortazavi6-Apr-09 16:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.