Компилятор ресурсов услужливо добавит стили окон, но если вы создаёте шаблон диалогового окна самостоятельно — вы должны делать это сами
Рэймонд Чен
У клиента возникли проблемы с вложенными диалоговыми окнами. Он использовал нечто очень похожее на окно свойств, с основным диалоговым окном и набором дочерних диалоговых окон, которые поочередно появлялись внутри основного диалогового окна в зависимости от действий пользователя. Клиент обнаружил, что если дочерние диалоговые окна создавались с помощью соответствующей 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.