如何通过将鼠标悬停在第三方程序上来获取按钮文本?

时间:2019-01-21 12:23:08

标签: c++ winapi

这是我的代码:

#include <iostream>
#include <windows.h>

int main()
{
    POINT p;
    char wndName[60];
    while (true)
    {
        GetCursorPos(&p);
        HWND hWnd = WindowFromPoint(p);

        GetWindowText(hWnd, wndName, 59);
        std::cout << p.x << " " << p.y << std::endl;
        std::cout << wndName << " " << std::endl;
        ScreenToClient(hWnd, &p);
        HWND hWndChild = ChildWindowFromPoint(hWnd, p);
        GetWindowText(hWndChild, wndName, 59);
        std::cout << p.x << " " << p.y << std::endl;
        std::cout << wndName << " " << std::endl;
        Sleep(100);
    }
    return 0;
}

从父窗口打印名称可以正常工作,但是我无法使其在子窗口中正常工作。 子句柄的GetWindowText()与父句柄的打印效果相同。

我希望我的程序仅通过悬停鼠标光标来打印按钮文本,编辑字段中的文本等。

编辑:有任何提示可以帮助我解决此问题吗?

2 个答案:

答案 0 :(得分:0)

您没有执行任何错误处理。最重要的是,第二个GetWindowText()失败并且不会更新wndName缓冲区,这就是为什么您看到第二遍打印父文本的原因。

不能使用GetWindowText()在另一个进程中获取子窗口的文本。 documentation甚至说:

  

如果指定的窗口是控件,则复制控件的文本。 GetWindowText无法在另一个应用程序中检索控件的文本。
  ...
  要在另一个进程中检索控件的文本,请直接发送WM_GETTEXT消息而不是调用GetWindowText()

尝试以下方法:

#include <iostream>
#include <windows.h>

const int MAX_WND_TEXT = 60;

int main()
{
    POINT p;
    char wndName[MAX_WND_TEXT];

    while (true)
    {
        GetCursorPos(&p);
        HWND hWnd = WindowFromPoint(p);
        if (hWnd)
        {
            if (!GetWindowTextA(hWnd, wndName, MAX_WND_TEXT))
                wndName[0] = '\0';

            std::cout << p.x << " " << p.y << std::endl;
            std::cout << "'" << wndName << "'" << std::endl;

            ScreenToClient(hWnd, &p);
            HWND hWndChild = ChildWindowFromPoint(hWnd, p);
            if (hWndChild)
            {
                if (!SendMessageA(hWndChild, WM_GETTEXT, MAX_WND_TEXT, (LPARAM)wndName))
                    wndName[0] = '\0';

                std::cout << p.x << " " << p.y << std::endl;
                std::cout << "'" << wndName << "'" << std::endl;
            }
        }

        Sleep(100);
    }

    return 0;
}

更新:但是,根据Raymond Chen博客上的以下帖子:

WindowFromPoint, ChildWindowFromPoint, RealChildWindowFromPoint, when will it all end?

  

假设您有一个顶层窗口P和一个子窗口C。并假设您询问以上函数之一,“此点下方是哪个窗口?”当点正好位于窗口C上方时。 WindowFromPoint函数查找包含该点的嵌套程度最高的窗口,即窗口C 。另一方面,假设您以GetDesktopWindow作为起点,ChildWindowFromPoint函数将查找包含该点的嵌套最少的窗口,即窗口P。

因此,WindowFromPoint()将在指定的屏幕坐标处返回最深的子窗口,因此ChildWindowFromPoint()将没有其他子窗口可用来查找何时从{{1}获得指定的父窗口。 }。

根据ChildWindowFromPoint()文档:

  

如果该点在父窗口内,但不在任何子窗口内,则返回值是父窗口的句柄

因此,以上代码将不会得到您想要的结果。您将需要以下类似的东西:

WindowFromPoint()

但是,此代码显示了 z排序的问题,即找到位于其他窗口后面而不是它们顶部的窗口。您可能需要这样的东西:

#include <iostream>
#include <windows.h>

const int MAX_WND_TEXT = 60;

int main()
{
    POINT p;
    char wndName[MAX_WND_TEXT];

    while (true)
    {
        GetCursorPos(&p);
        HWND hWnd = ChildWindowFromPoint(GetDesktopWindow(), p);
        if (hWnd)
        {
            if (!GetWindowTextA(hWnd, wndName, MAX_WND_TEXT))
                wndName[0] = '\0';

            std::cout << p.x << " " << p.y << std::endl;
            std::cout << "'" << wndName << "'" << std::endl;

            ScreenToClient(hWnd, &p);
            HWND hWndChild = ChildWindowFromPoint(hWnd, p);
            if ((hWndChild) && (hWndChild != hWnd))
            {
                if (!SendMessageA(hWndChild, WM_GETTEXT, MAX_WND_TEXT, (LPARAM)wndName))
                    wndName[0] = '\0';

                std::cout << p.x << " " << p.y << std::endl;
                std::cout << "'" << wndName << "'" << std::endl;
            }
        }

        Sleep(100);
    }

    return 0;
}

它仍然不完美,但是比以前的代码要好。

答案 1 :(得分:-2)

获取顶级窗口句柄后,使用ChildWindowFromPoint