65.9K
CodeProject 正在变化。 阅读更多。
Home

FindWindow

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (24投票s)

2009年4月4日

CPOL

1分钟阅读

viewsIcon

93748

downloadIcon

6895

FindWindow 是一个用于搜索窗口/控件的工具

引言

市面上有很多程序,例如 Spy++ 或屏幕截图程序,允许用户查找和选择特定的窗口或窗口控件,例如按钮、编辑框等。

这个项目的目标是编写一个易于使用的界面来查找窗口句柄。

  1. 启动应用程序后,开始拖动靶心符号“查找工具”(1)
  2. 将“查找工具”符号移动到所需的窗口
  3. 停止移动并放下鼠标光标,如果你想获取底层窗口的信息
  4. 所选窗口的信息显示在对话框属性中(2)

背景

我已经在 C++ 中编程了这种查找工具很多年。
现在我使用 C#,所以我将我的旧 C++ 代码转换为 C# 代码。

Using the Code

有两个重要的函数用于查找和选择窗口

  1. 函数“MainForm::ChildWindowFromPoint
    参数point 是屏幕上的全局点(通常是鼠标光标)
    返回值:找到的窗口的handle
    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. 函数“MainForm::ShowInvertRectTracker
    参数:要显示/隐藏所选矩形的窗口
    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);
    	}
    }

文件

  • MainForm.cs

    显示 FindWindow 对话框。
    处理鼠标事件(按下 - 移动 - 释放)并显示结果信息。

  • GdiApiWrapper.cs, WinApiWrapper.cs

    基本函数 MainForm::ChildWindowFromPointMainForm::ShowInvertRectTracker 大量使用了基本的 Win API。
    Win API 的签名列在这些文件中。函数列表并不完整。我只实现了此工具所需的函数。

历史

  • 2009 年 4 月 3 日:初始版本
© . All rights reserved.