Какая альтернатива GWL_USERDATA для хранения указателя объекта?

В приложениях Windows, над которыми я работаю, у нас есть пользовательская структура, которая находится прямо над Win32 (не спрашивайте). Когда мы создаем окно, наша обычная практика - помещать thisв область пользовательских данных окна via SetWindowLong(hwnd, GWL_USERDATA, this), что позволяет нам иметь MFC-подобный обратный вызов или тесно интегрировать WndProc, в зависимости. Проблема в том, что это не будет работать на Win64, поскольку LONG имеет ширину всего 32 бита. Как лучше решить эту проблему, которая работает как на 32-, так и на 64-битных системах?

22.08.2008 18:16:51
2 ОТВЕТА
РЕШЕНИЕ

SetWindowLongPtr был создан, чтобы заменить SetWindowLong в этих случаях. Параметр LONG_PTR позволяет хранить указатель для 32-битных или 64-битных компиляций.

LONG_PTR SetWindowLongPtr(      
    HWND hWnd,
    int nIndex,
    LONG_PTR dwNewLong
);

Помните, что константы тоже изменились, поэтому использование теперь выглядит так:

SetWindowLongPtr(hWnd, GWLP_USERDATA, this);

Также не забывайте, что теперь, чтобы получить указатель, вы должны использовать GetWindowLongPtr :

LONG_PTR GetWindowLongPtr(      
    HWND hWnd,
    int nIndex
);

И использование будет выглядеть (опять же, с измененными константами):

LONG_PTR lpUserData = GetWindowLongPtr(hWnd, GWLP_USERDATA);
MyObject* pMyObject = (MyObject*)lpUserData;
37
22.08.2008 18:32:57

Другой альтернативой является SetProp / RemoveProp (когда вы создаете подкласс для окна, которое уже использует GWLP_USERDATA)

Еще одна хорошая альтернатива - это WLDPROC в стиле ATL, для получения дополнительной информации см.

9
28.08.2008 20:38:17
Проблема с thunking (по крайней мере, в статье) заключается в том, что он зависит от процессора, поскольку полагается на низкоуровневую сборку - статья касается только x86; и вопрос ОП о другой архитектуре. Существует мало веских причин для выбора метода, специфичного для процессора, когда доступен процессорно-нейротальный метод: Get / SetWindowLongPtr работает как с 32-битными, так и с 64-битными компиляциями.
BrendanMcK 29.12.2011 11:48:29
@BrendanMcK IIRC элемент управления ссылками Windows использует GWLP_USERDATA, поэтому, если вы создаете подкласс, вам нужно хранить свои данные в другом месте. Да, это зависит от процессора, см. Masm32.com/board/index.php?topic=4572.0 для версии x64 (не удалось найти примеры еще в 08 IIRC)
Anders 29.12.2011 16:27:31
(Ах, это еще один из тех старых ответов, которые как-то появились как «новые» в поле RSS из-за недавнего редактирования ...) Да, я согласен с первой частью ответа; Get / SetProp - это путь при создании подклассов. Еще мало причин использовать ассемблер, когда есть API, который работает. (Возможно, через несколько лет код необходимо будет изменить, чтобы добавить версию ARM!)
BrendanMcK 29.12.2011 22:56:21
@BrendanMcK ARM будет только WinRT AFAIK. Причиной использования Thunking является производительность; MOV + JMP быстрее, чем все остальное ...
Anders 29.12.2011 23:59:48
... и я бы спросил, действительно ли перфект оправдан во многих из этих случаев; Любой, кто думает, что перфом может быть проблемой, должен будет сначала измерить, прежде чем прибегать к ассемблеру. Я уверен, что есть законные применения для thunks, но IMO они кажутся оправданными только в крошечном меньшинстве случаев; поэтому очень осторожно рекомендую их по API, которые более читабельны, надежны и удобны в обслуживании.
BrendanMcK 30.12.2011 00:50:51