Win32: CreateDialog вместо нескольких вызовов CreateWindow - есть ли недостатки?

В настоящее время я работаю над программой Win32, для которой требуется главное окно, содержащее множество элементов управления дочерними окнами - кнопки, списки и т. Д. Я считаю, что стандартный способ создания такого окна - сначала вызвать CreateWindow для главного окна, а затем снова для каждого из элементов управления.

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

Используя оператор CLASS в шаблоне диалогового окна, я должен иметь возможность заставить главное окно использовать настраиваемый класс окна (и, следовательно, настраиваемую оконную процедуру) и, таким образом, избежать поведения окна, подобного диалогу. Пример этой техники можно найти в книге Чарльза Петцольда «Окна программирования»: программа HEXCALC в главе 11.

Есть ли недостатки в создании моего главного окна таким образом? Если так, то кто они? Если нет, то почему этот подход используется редко?


person user200783    schedule 10.05.2011    source источник


Ответы (5)


Единственный недостаток CreateDialog, о котором я знаю (по сравнению с повторяющимся CreateWindow, не говоря уже о какой-то тяжелой структуре, просто Win32 против Win32), заключается в том, что ресурсы диалогового окна позиционируют дочерние окна с помощью блоков диалога. Таким образом, макет зависит не только от DPI, но и от настроек темы пользователя (выбор и размер шрифта).

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

Итак, да, вы можете использовать CreateDialog как ярлык для создания группы окон с указанными классами и стилями. Но нет, вы не можете сделать свой макет в редакторе диалогов.

OTOH, вы можете сохранить преобразование DLU ‹-> пикселей, используемое на вашей дизайнерской машине, а затем узнать достаточно о разборе внутреннего формата ресурса DIALOG, чтобы извлечь информацию о позиционировании, затем преобразовать в пиксели и исправить позиционирование более автоматизированным способом.

person Ben Voigt    schedule 18.05.2011
comment
Преобразование диалоговых единиц в пиксели на самом деле довольно просто. См. Функцию MapDialogRect: msdn. microsoft.com/en-us/library/windows/desktop/ - person Brown; 07.06.2012

Вы не можете управлять своим циклом сообщений в главном окне - диспетчер диалогов обрабатывает его за вас. С другой стороны, диспетчер диалогов обрабатывает ускорители клавиатуры, порядок табуляции и ряд других эффектов.

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

person ReinstateMonica Larry Osterman    schedule 10.05.2011
comment
Вы не можете контролировать цикл сообщений в главном окне - вы уверены? Я знаю, что это относится к DialogBox, но для CreateDialog я думал, что вы можете (и действительно должны) использовать обычный насос сообщений. - person user200783; 10.05.2011
comment
Мое плохое, вы правы, что с помощью немодального диалогового окна вы можете управлять им. Но вам нужно вставить вызов IsDialogMessage, чтобы элементы управления получали свои сообщения. - person ReinstateMonica Larry Osterman; 10.05.2011
comment
Диалоговое окно @Larry Modeless не имеет насоса сообщений. Фактически, это одно из различий между немодальным диалоговым окном и модальным диалоговым окном. :-) - person Sujay Ghosh; 18.05.2011

Вы сможете полностью контролировать свое окно, даже если оно было создано с помощью CreateDialog.

Обычно, когда вы создаете свое собственное окно (своего класса), в качестве оконной процедуры используется та процедура, которую вы зарегистрировали в классе. Окна OTOH, созданные с помощью CreateDialog, будут иметь стандартную оконную процедуру диалогового окна (DefDlgProc), которая в основном будет вызывать ваш предоставленный «обработчик диалогового окна».

Если вы хотите иметь полный контроль над всеми сообщениями, вы можете заменить процесс окна только что созданного окна сразу после его создания. Просто вызовите SetWindowLongPtr с параметром GWLP_WNDPROC. Тем не менее, вы можете выполнить автоматическую обработку некоторых специфичных для диалога вещей, вызвав IsDialogMessage в своей процедуре.

person valdo    schedule 12.05.2011
comment
Такое использование GWLP_WNDPROC похоже на технику использования оператора CLASS в шаблоне диалогового окна. Несмотря на очевидные преимущества этих подходов (в том, что касается простоты разработки), похоже, что они используются не очень часто. Вы знаете, почему это могло быть? - person user200783; 13.05.2011
comment
@Paul Baker: мое предположение: (1) не все знают (или осмеливаются) изменять файл ресурсов напрямую, без использования мастера MSVC, (2) никого не волнует, поскольку различия незначительны, (3) теоретически вы можете захотеть, чтобы DefDlgProc был выполнить какую-то инициализацию (например, установить фокус на первый элемент управления с флагом WS_TABSTOP). - person valdo; 13.05.2011

Нет никаких недостатков.

Почему его редко используют? Так как:

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

  • В более сложных случаях люди используют такие вещи, как MFC или ATL (или некоторую внешнюю библиотеку, такую ​​как GTk или Qt), и не беспокоятся о нативной графике Win32.

person user541686    schedule 15.05.2011

У Windows SDK нет недостатков, внутренние библиотеки, такие как MFC, используют Windows SDK.

Люди склонны использовать библиотеки, такие как MFC, поверх Windows SDK, поскольку в библиотеках есть готовые материалы. Однако вызовы Windows SDK выполняются быстрее, чем вызовы библиотеки, поэтому в некоторых ситуациях разработчики вызывают Windows SDK напрямую.

CButton btnOk ;
btnOK.Create(_T("Press Me"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,CRect(100,100,300,300), pParentWnd, 1);

похож на следующий код,

HWND hWnd = CreateWindow("BUTTON","Press Me",WS_CHILD|WS_POPUP|BS_DEFPUSHBUTTON,100,100,300,300,NULL,NULL,GetModuleHandle(NULL),NULL);
ShowWindow(hWnd,SW_SHOW);
person Sujay Ghosh    schedule 18.05.2011
comment
Это так вводит в заблуждение. WS_VISIBLE отлично работает с CreateWindow. UpdateWindow тоже не нужен. Удобство MFC заключается в картах сообщений и автоматическом создании подклассов, а не в создании кнопок. - person Ben Voigt; 18.05.2011
comment
@ Бен, спасибо. Я показывал пример в MFC и Windows SDK. Хотя я не согласен с автоматическим подклассом. Подклассы не встроены, в отличие от карт сообщений и отражения сообщений. - person Sujay Ghosh; 18.05.2011