Если вы добавили дополнительное пространство данных к классу DialogBox, к которому должен получить доступ GetWindowLongPtr, следует ли добавить DLGWINDOWEXTRA для доступа к этому дополнительному пространству? - PullRequest
0 голосов
/ 15 мая 2009

При создании класса окна для использования с DialogBox необходимо указать значение DLGWINDOWEXTRA в элементе cbWndExtra структуры WNDCLASS для «дополнительных байтов, необходимых системе для каждого диалогового окна». Если вы добавите свое собственное дополнительное пространство данных в класс DialogBox, к которому нужно обращаться с помощью GetWindowLongPtr(), следует ли добавить DLGWINDOWEXTRA к смещению, чтобы получить доступ к дополнительному пространству?

(Признаюсь, я думаю, что знаю ответ, и таким образом код не нарушается. Но я хочу убедиться, что мои причины соответствуют общей мудрости.)

Основная причина, по которой диалоги используются со своим собственным классом (а не по умолчанию), заключается в том, что каждый класс диалога имеет свой собственный значок. Два отдельных элемента дополнительных данных также прикреплены к каждому окну.

...     
wndclass.cbWndExtra  = DLGWINDOWEXTRA + EXTRASPACE;
wndclass.lpfnWndProc = (WNDPROC) DefDlgProc;
wndclass.hIcon = LoadIcon(hInstance, "ICON_MAIN");
wndclass.lpszClassName = WND_CLASS_VLIST_POPUP;
wndclass.hIconSm = LoadImage(hInstance,
                                 "ICON_MAIN",
                                 IMAGE_ICON,
                                 16,
                                 16,
                                 LR_DEFAULTCOLOR);
...

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

GetWindowLongPtr(hWnd, 0 + DLGWINDOWEXTRA + SOMETHING_IN_EXTRASPACE);

или

GetWindowLongPtr(hWnd, 0 + SOMETHING_IN_EXTRASPACE);

ПРИМЕЧАНИЕ: Позднее редактирование Дэвид Л. Моррис (May-15-2009): удалил неправильный GWLP_USERDATA и заменил на 0 . Исходный вопрос использовался GWLP_USERDATA в звонке на GetWindowLongPtr(), поэтому в принятом ответе упоминается GWLP_USERDATA. Приведенные выше примеры были изначально написаны:

GetWindowLongPtr(hWnd, GWLP_USERDATA + DLGWINDOWEXTRA + SOMETHING_IN_EXTRASPACE);

и

GetWindowLongPtr(hWnd, GWLP_USERDATA + SOMETHING_IN_EXTRASPACE);

1 Ответ

3 голосов
/ 15 мая 2009

На самом деле ... я думаю, что вы делаете ошибку. Значение в GWLP_USERDATA и пространство, выделенное в соответствии с cbWndExtra, представляют собой две разные вещи ...

Значение GWLP_USERDATA является частью пространства, выделенного Windows для каждого окна. Для классов окон так часто требуется бит размером с указатель, что Windows просто включает его в базовую стоимость окна вместе со всеми другими предопределенными «словами окна». Посмотрите документацию для параметра nIndex для GetWindowLongPtr():

Определяет смещение от нуля до значения, которое необходимо получить. Допустимые значения находятся в диапазоне от нуля до количества байтов дополнительной памяти окна, минус размер целого числа.

Итак, GetWindowLongPtr(hWnd, 0) извлекает первые sizeof(LONG_PTR) байтов, выделенных в ответ на cbWndExtra, GetWindowLongPtr(hWnd, sizeof(LONG_PTR)) дает вам следующие данные размером с указатель и так далее. Как следует из названия, nIndex действует как индекс в массив байтов (хотя он всегда возвращает значение размером с указатель). Теперь взглянем на значения индекса, назначенные предопределенным константам данных окна: все они отрицательные, включая GWLP_USERDATA! Фактически, GetWindowLongPtr() начинает индексирование в середину данных окна, причем данные, общие для всех окон, располагаются «до» индекса 0, а все данные, относящиеся к классу окна, находятся после него.

Диалоговые окна построены поверх базовой поддержки, предусмотренной для обычных окон. Поскольку они требуют больше данных, чем обычные окна, необходимо указать не менее DLGWINDOWEXTRA байтов в cbWndExtra. Как и любые другие такие данные, они доступны через положительное значение, переданное GetWindowLongPtr().

Поэтому, когда вы просите

GetWindowLongPtr(hWnd, GWLP_USERDATA + DLGWINDOWEXTRA + 0);

... вы на самом деле получаете данные по индексу -21 + 30 + 0 = 9: значение где-то в собственных данных менеджера диалогов. Не то, что вы хотите!

К настоящему времени вы должны понимать, что при доступе к данным, выделенным через cbWndExtra = DLGWINDOWEXTRA + extra, вам нужно только сместить ваш запрос на DLGWINDOWEXTRA. Итак:

GetWindowLongPtr(hWnd, DLGWINDOWEXTRA + 0);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...