Skip to content

Instantly share code, notes, and snippets.

@zamabuvaraeu
Created January 19, 2026 14:47
Show Gist options
  • Select an option

  • Save zamabuvaraeu/19b0079063e9bf5b3980d08f84516145 to your computer and use it in GitHub Desktop.

Select an option

Save zamabuvaraeu/19b0079063e9bf5b3980d08f84516145 to your computer and use it in GitHub Desktop.

Компилятор ресурсов услужливо добавит стили окон, но если вы создаёте шаблон диалогового окна самостоятельно — вы должны делать это сами

Рэймонд Чен

У клиента возникли проблемы с вложенными диалоговыми окнами. Он использовал нечто очень похожее на окно свойств, с основным диалоговым окном и набором дочерних диалоговых окон, которые поочередно появлялись внутри основного диалогового окна в зависимости от действий пользователя. Клиент обнаружил, что если дочерние диалоговые окна создавались с помощью соответствующей CreateDialogParam функции, всё работало отлично, но если шаблон создавался во время выполнения, навигация с помощью клавиатуры работала некорректно. В частности, одно из дочерних диалоговых окон содержало элемент управления редактированием, и хотя на него можно было установить фокус с помощью мыши, перейти к нему с помощью клавиши Tab было невозможно. С другой стороны, в шаблоне ресурсов такой проблемы не было. Переходы между окнами с помощью клавиши Tab работали без проблем.

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

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

Один из способов выявить это несоответствие — просто сравнить два шаблона диалогового окна через memcmp: один на основе ресурсов, другой — на основе памяти, и посмотреть, в чём они отличаются. В конце концов, если вы хотите узнать, почему ваш шаблон не совпадает с шаблоном, сгенерированным компилятором ресурсов, вы можете просто попросить компилятор ресурсов сгенерировать шаблон, а затем сравнить две версии.

Вместо того чтобы объяснять это, я решил обратиться к своим экстрасенсорным способностям.

Мои экстрасенсорные способности подсказывают мне, что вы забыли указать WS_TABSTOPстиль для элемента управления редактирования при создании шаблона в памяти. (Вероятно, вы не понимали, что это необходимо сделать, поскольку компиляция ресурсов добавляет этот стиль по умолчанию.)

При использовании компилятора ресурсов для генерации шаблона диалогового окна по умолчанию устанавливается ряд стилей в зависимости от типа элемента управления. Например, EDITTEXT: «Если стиль не указан, по умолчанию используется стиль ES_LEFT | WS_BORDER | WS_TABSTOP».

Не было упомянуто, что стиль по умолчанию является дополнительным к стилям по умолчанию для всех элементов управления: WS_CHILD | WS_VISIBLE.

Чтобы отключить один из стилей по умолчанию для элемента управления, используйте ключевое слово NOT. Например, если вы напишете

EDITTEXT IDC_AWESOME, 10, 10, 100, 100, ES_MULTILINE | NOT WS_VISIBLE

Компилятор ресурсов запускается со стилем по умолчанию.

dwStyle = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_BORDER | WS_TABSTOP;

Затем добавляется ES_MULTILINE:

dwStyle |= ES_MULTILINE;
// Значение dwStyle теперь равно
// WS_CHILD | WS_VISIBLE | ES_LEFT | WS_BORDER | WS_TABSTOP | ES_MULTILINE

а затем удаляет WS_VISIBLE:

dwStyle &= ~WS_VISIBLE;
// Значение dwStyle теперь равно
// WS_CHILD | ES_LEFT | WS_BORDER | WS_TABSTOP | ES_MULTILINE

Это окончательный стиль, применяемый к элементу управления.

Компилятор ресурсов пытается вам помочь, предварительно устанавливая стили, которые вам, вероятно, нужны, но если вы не знаете, что эти значения по умолчанию уже установлены, вы можете не осознавать, что вам нужно будет указать их самостоятельно, если вы не используете компилятор ресурсов. Возможно, он был слишком услужлив, и в итоге это привело к беспомощности.

Клиент любезно ответил.

Спасибо! Это помогло.

Для полноты картины, стиль диалогового окна по умолчанию — WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU. Если у вас установлен пользовательский шрифт, то вы также получите DS_SETFONT, а если у вас есть подпись, то вы получите WS_CAPTION.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment