AccessibleObjectFromPoint() возвращает неверный объект

#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() решило мою проблему.