Проблема при переносе настольного приложения на 64-разрядную версию, поддерживающую специальные возможности Microsoft

#windows #winapi #accessibility

#Windows #winapi #Специальные возможности

Вопрос:

Я переношу настольное приложение, поддерживающее специальные возможности Microsoft, с 32-разрядной версии на 64-разрядную. В этом приложении множество пользовательских элементов управления. При вызове NotifyWinEvent() :

 /*Pseudocode*/
MYSTRUCT *ptr;
allocate and assign data to ptr;
Call NotifyWinEvent(EVENT_OBJECT_FOCUS, hwnd, OBJID_CLIENT, (long)ptr).
  

Код извлекает указатель в IAccessible реализованном методе и использует его:

 /* pseudocode */

TDMETHODIMP CMSAAMyProxy::get_accRole( VARIANT varChild, VARIANT *pvarRole )
{
    if (VT_I4 == varChild.vt)
    {
        MYSTRUCT *ptr = (MYSTRUCT *)varChild.lVal;
        /* Use the ptr here */
    }
}
  

Такой код написан во многих файлах. Хотя приведенный выше код хорошо работает на 32-разрядной версии, на 64-разрядной происходит сбой из-за усечения указателя.

Есть ли какой-либо альтернативный API, который я могу использовать для решения этой проблемы?

Комментарии:

1. Чтобы решить эту проблему, вам придется сделать шаг назад и должным образом проанализировать, в чем проблема. Проблема здесь в том, что ваша реализация использует API вне своего документированного контракта. Аргумент idChild для NotifyWinEvent содержит идентификатор объекта, а не указатель. Это то, что необходимо исправить. Не существует альтернативного API, который можно надежно использовать вне его спецификации.

2. Идентификаторы объектов MSAA недостаточно велики для переноса 64-разрядных указателей. Чтобы передать указатель на NotifyWinEvent() , вам пришлось бы сохранить указатель в переданном HWND через SetWindowsLongPtr() или SetProp() , а затем обратные вызовы WinEvent могут извлечь указатель из HWND . Очевидно, что это не будет работать в рамках процесса. Реальный вопрос в том, почему ваш CMSAAMyProxy класс не содержит необходимый ему указатель? Почему вы вообще пытаетесь передать указатель через NotifyWinEvent() ? Оно не предназначено для этой цели.

3. @RemyLebeau Я согласен с вашей точкой зрения, NotifyWinEvent не следует передавать указатель. Я думаю, это код десятилетней давности. В любом случае я должен проверить альтернативное решение. Я думаю, что здесь может помочь 32-разрядный хэш указателя.