You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何定位屏幕文本像素,实现跨分辨率第三方程序自动化?

解决方案

一、优化Tesseract定位流程(基于现有截图识别)

你当前的核心问题是Tesseract识别的文本坐标无法映射到屏幕,解决思路是先锁定目标程序的窗口范围,再在局部截图中识别,最后转换坐标:

  1. 用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为右下角坐标
    }
    
  2. 截取目标窗口的局部截图:
    仅截取windowRect范围内的区域,避免全屏截图的干扰,此时Tesseract识别的坐标是相对于窗口左上角的偏移量。

  3. 转换坐标并执行点击:
    假设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);
    

二、更可靠的无坐标方案(推荐)

模拟鼠标点击仍依赖坐标,直接给控件发送系统消息稳定性更高,步骤如下:

  1. 用Spy++(VS自带工具)分析目标程序的窗口结构,找到"Print"按钮和文本框的控件类名、文本或层级路径。

  2. 用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");
    
  3. 发送消息执行操作:

    [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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 17:52:49