Вы не обрабатываете ошибки. Самое главное, что вторая 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;
}
Это все еще не идеально, но лучше, чем предыдущий код.