如何定位屏幕文本像素,实现跨分辨率第三方程序自动化?
解决方案
一、优化Tesseract定位流程(基于现有截图识别)
你当前的核心问题是Tesseract识别的文本坐标无法映射到屏幕,解决思路是先锁定目标程序的窗口范围,再在局部截图中识别,最后转换坐标:
用
user32.dll获取目标窗口的句柄与屏幕位置:
添加以下API声明:[DllImport("user32.dll", SetLastError = true)] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); public struct RECT { public int Left; public int Top; public int Right; public int Bottom; }调用示例:
// 替换为目标程序的窗口标题或类名(可通过Spy++查看) IntPtr targetWindow = FindWindow(null, "Target App Title"); if (targetWindow != IntPtr.Zero) { GetWindowRect(targetWindow, out RECT windowRect); // windowRect.Left/Top为窗口左上角屏幕坐标,Right/Bottom为右下角坐标 }截取目标窗口的局部截图:
仅截取windowRect范围内的区域,避免全屏截图的干扰,此时Tesseract识别的坐标是相对于窗口左上角的偏移量。转换坐标并执行点击:
假设Tesseract识别到"Print"按钮的左上角相对坐标为(textX, textY),取按钮中心作为点击点(比如加按钮宽高的一半作为偏移),转换为屏幕坐标后执行点击:int btnWidth = 80; // 根据实际按钮宽度调整 int btnHeight = 30; // 根据实际按钮高度调整 int screenX = windowRect.Left + textX + btnWidth / 2; int screenY = windowRect.Top + textY + btnHeight / 2; SetCursorPos(screenX, screenY); mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, screenX, screenY, 0, 0);
二、更可靠的无坐标方案(推荐)
模拟鼠标点击仍依赖坐标,直接给控件发送系统消息稳定性更高,步骤如下:
用Spy++(VS自带工具)分析目标程序的窗口结构,找到"Print"按钮和文本框的控件类名、文本或层级路径。
用
FindWindowEx遍历子控件获取目标句柄:[DllImport("user32.dll", SetLastError = true)] public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);示例(假设按钮是目标窗口的直接子控件):
IntPtr printBtn = FindWindowEx(targetWindow, IntPtr.Zero, "Button", "Print");发送消息执行操作:
[DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern bool SendMessage(IntPtr hWnd, uint Msg, int wParam, string lParam); public const uint BM_CLICK = 0x00F5; public const uint WM_SETTEXT = 0x000C; // 点击Print按钮 if (printBtn != IntPtr.Zero) { SendMessage(printBtn, BM_CLICK, 0, null); } // 向文本框输入内容(先获取文本框句柄) IntPtr textBox = FindWindowEx(targetWindow, IntPtr.Zero, "Edit", null); if (textBox != IntPtr.Zero) { SendMessage(textBox, WM_SETTEXT, 0, "指定输入内容"); }
三、补充注意事项
- 若目标程序是自定义控件(非标准Button/Edit),
FindWindowEx可能无法识别,此时回到Tesseract方案,但需确保截图适配系统DPI,避免坐标偏移。 - 使用
SendKeys前,需激活目标窗口:
调用[DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd);SetForegroundWindow(targetWindow)后再执行SendKeys.SendWait("Text")。
内容的提问来源于stack exchange,提问作者Ozgur Saklanmaz
相关产品推荐
相关产品推荐

