FindWindow






4.88/5 (24投票s)
FindWindow 是一个用于搜索窗口/控件的工具

引言
市面上有很多程序,例如 Spy++ 或屏幕截图程序,允许用户查找和选择特定的窗口或窗口控件,例如按钮、编辑框等。
这个项目的目标是编写一个易于使用的界面来查找窗口句柄。
- 启动应用程序后,开始拖动靶心符号“查找工具”(1)
- 将“查找工具”符号移动到所需的窗口
- 停止移动并放下鼠标光标,如果你想获取底层窗口的信息
- 所选窗口的信息显示在对话框属性中(2)
背景
我已经在 C++ 中编程了这种查找工具很多年。
现在我使用 C#,所以我将我的旧 C++ 代码转换为 C# 代码。
Using the Code
有两个重要的函数用于查找和选择窗口
- 函数“
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; }
- 函数“
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::ChildWindowFromPoint
和MainForm::ShowInvertRectTracker
大量使用了基本的 Win API。
Win API 的签名列在这些文件中。函数列表并不完整。我只实现了此工具所需的函数。
历史
- 2009 年 4 月 3 日:初始版本