#c #winapi #com
#c #winapi #ком #com
Вопрос:
Я создаю программу, которая выбирает объект с помощью курсора мыши, используя AccessibleObjectFromPoint(), однако это выдает неверный результат.
Я навел курсор мыши на этот значок, но вместо этого он выбирает другой значок.
Вот мой пример кода:
#include <windows.h>
#include <oleacc.h>
#include <cstdio>
#include <iostream>
#include <string>
#pragma comment(lib, "oleacc.lib")
HRESULT SelectItemAtPoint(POINT point)
{
VARIANT varItem;
IAccessible* pAcc;
HRESULT hr = AccessibleObjectFromPoint(point, amp;pAcc, amp;varItem);
if ((hr == S_OK))
{
hr = pAcc->accSelect((SELFLAG_TAKEFOCUS | SELFLAG_TAKESELECTION), varItem);
VariantClear(amp;varItem);
pAcc->Release();
}
return hr;
}
int main()
{
CoInitialize(NULL);
while (true)
{
POINT pt;
GetCursorPos(amp;pt);
printf("x: %d y: %d", pt.x, pt.y);
SelectItemAtPoint(pt);
Sleep(50);
}
return 0;
}
На изображении я зависал на Unreal Engine, но программа выбрала вместо этого MATLAB.
Я также проверил точки курсора.
Есть способы это исправить?
РЕДАКТИРОВАТЬ: я использую Windows 10 Home с Visual Studio 2017
Комментарии:
1. Вероятно, вы пропустили преобразование координат курсора в координаты экрана перед вызовом
AccessibleObjectFromPoint()
.2. Не
GetCursorPos()
уже в экранных координатах?3. Возможно, UnrealEngine не хочет играть в мяч. Или, возможно, это из-за масштабирования DPI.
4. Как мне это исправить при масштабировании DPI? Я заметил, что при вызове функции происходит смещение.
5. @DavidHeffernan Я, наконец, понял, как это исправить. Спасибо за совет по масштабированию DPI.
Ответ №1:
Цитируется по документации Microsoft:
Microsoft Active Accessibility не использует логические координаты. Следующие методы и функции либо возвращают физические координаты, либо принимают их в качестве параметров.
IAccessible::accHitTest
IAccessible::accLocation
AccessibleObjectFromPoint
По умолчанию клиентское приложение Microsoft Active Accessibility, работающее в среде, отличной от 96 точек на дюйм, не сможет получить правильные результаты от этих вызовов. Например, поскольку положение курсора указано в логических координатах, клиент не может просто передать эти координаты в
AccessibleObjectFromPoint
, чтобы получить элемент, который находится под курсором.Решение состоит из двух частей:
Сделайте клиентское приложение «с поддержкой dpi». Чтобы сделать это, вызовите
SetProcessDPIAware
функцию при запуске. Эта функция поддерживает разрешение всего процесса, что означает, что все окна, принадлежащие процессу, не масштабируются.Используйте функции, которые поддерживают dpi. Например, чтобы получить координаты курсора, вызовите
GetPhysicalCursorPos
функцию. Не использоватьGetCursorPos
; его поведение в приложениях, поддерживающих dpi, не определено.Если ваше приложение выполняет прямую межпроцессную связь с приложениями, не поддерживающими dpi, возможно, вам пришлось конвертировать логические и физические координаты с помощью функций
PhysicalToLogicalPoint
иLogicalToPhysicalPoint
.
Таким образом, изменение GetCursorPos()
на GetPhysicalCursorPos()
решило мою проблему.