Как получить текст кнопки при наведении мышки на стороннюю программу? - PullRequest
0 голосов
/ 21 января 2019

Вот мой код:

#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 голосов
/ 21 января 2019

Вы не обрабатываете ошибки. Самое главное, что вторая GetWindowText() не работает и не обновляет ваш буфер wndName, поэтому вы видите, что родительский текст печатается во второй раз.

Вы не можете использовать GetWindowText(), чтобы получить текст дочернего окна в другом процессе. Документация даже гласит:

Если указанное окно является элементом управления, текст элемента управления копируется. 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;
}

ОБНОВЛЕНИЕ : Тем не менее, согласно следующему сообщению в блоге Раймонда Чена:

WindowFromPoint, ChildWindowFromPoint, RealChildWindowFromPoint, когда все это закончится?

Предположим, у вас есть окно верхнего уровня P и дочернее окно C. И предположим, вы спрашиваете одну из вышеперечисленных функций: "Какое окно находится под этой точкой?" когда точка находится прямо над окном C. Функция WindowFromPoint ищет самое сильно вложенное окно, содержащее точку, то есть окно C . С другой стороны, функция ChildWindowFromPoint ищет наименее вложенное окно, содержащее точку, то есть окно P, при условии, что вы передали GetDesktopWindow в качестве начальной точки.

Таким образом, WindowFromPoint() вернет самый глубокий дочерний элемент с указанной экранной координатой, поэтому дальнейшее дочернее окно не будет найдено для ChildWindowFromPoint(), когда указанное родительское окно будет получено из WindowFromPoint().

А согласно ChildWindowFromPoint() документации:

Если точка находится в родительском окне, но не в каком-либо дочернем окне, возвращаемое значение является дескриптором родительского окна .

Таким образом, приведенный выше код не будет иметь результат, который вы ищете. Вместо этого вам нужно что-то вроде этого:

#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;
}

Но этот код имеет проблемы с z-ordering , находя окна, которые находятся позади других окон, а не поверх них. Вместо этого вам может понадобиться что-то вроде этого:

#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)
        {
            HWND hWndRoot = GetAncestor(hWnd, GA_ROOTOWNER); // or GetAncestor(GA_ROOT), or GetAncestor(GA_PARENT), or GetParent(), as needed...
            HWND hWndChild = NULL;

            if ((hWndRoot) && (hWndRoot != hWnd))
            {
                hWndChild = hWnd;
                hWnd = hWndRoot;
            }

            if (!GetWindowTextA(hWnd, wndName, MAX_WND_TEXT))
                wndName[0] = '\0';

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

            if (hWndChild)
            {
                ScreenToClient(hWndChild, &p);

                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;
}

Это все еще не идеально, но лучше, чем предыдущий код.

0 голосов
/ 21 января 2019

Используйте ChildWindowFromPoint после получения дескриптора окна верхнего уровня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...