Партнерка на США и Канаду по недвижимости, выплаты в крипто
- 30% recurring commission
- Выплаты в USDT
- Вывод каждую неделю
- Комиссия до 5 лет за каждого referral
При создании диалогового окна оно получает сообщение WM_CREATE, как и любое другое окно. Но в момент получения WM_CREATE в диалоговом окне еще не созданы ЭУ, описанные в шаблоне окна. Поэтому их нельзя проинициализировать в обработчике данного сообщения. Внутренняя оконная процедура диалоговых окон Windows обрабатывает сообщение WM_CREATE, как раз чтобы выполнить создание ЭУ. После того. как все они созданы, диалоговому окну посылается сообщение WM_INITDIALOG, чтобы окно смогло произвести необходимую инициализацию ЭУ. В подклассах CDialog сообщение WM_INITDIALOG приводит к вызову функции-члена OnInitDialog:
virtual BOOL OnInitDialog() |
В OnInitDialog можно выполнить все действия, необходимые для подготовки окна к работе – например, пометить кнопку с зависимой фиксацией или поместить текст в строку ввода В момент вызова OnInitDialog диалоговое окно на экран еще не выведено. Возвращаемое значение OnInitDialog указывает Windows, что делать с фокусом ввода. Если OnInitDialog возвращает TRUE, то Windows устанавливает фокус ввода на первый по порядку обхода ЭУ окна. Если требуется установить фокус на другой элемент, надо сделать это в OnInitDialog вызовом SetFocus у класса ЭУ и вернуть из OnInitDialog значение FALSE. Получить указатель на CWnd для ЭУ с известным идентификатором можно функцией GetDlgItem, например:
GetDlgItem( IDC_EDIT )->SetFocus(); |
При перегрузке OnInitDialog надо обязательно вызывать OnInitDialog базового класса.
Чтобы по нажатию кнопок OK и Отмена вызывались виртуальные функции CDialog::OnOK и OnCancel, у этих кнопок в шаблоне окна должны быть идентификаторы IDOK и IDCANCEL.
Функцию-член OnOK можно перегрузить для выполнения специализированной обработки перед закрытием окна, например, для извлечения данных из ЭУ и, возможно, для проверки корректности этих данных (например, что число попадает в допустимый диапазон). В собственной реализации OnOK обязательно надо закрыть диалоговое окно вызовом EndDialog или вызывать для этого OnOK из базового класса. Если этого не сделать, при нажатии кнопки OK окно не будет закрываться.
Обработчик OnCancel вызывается не только при нажатии кнопки с идентификатором IDCANCEL, но и по нажатию клавиши Esc или при закрытии окна кнопкой в строке заголовка. OnCancel перегружается редко, т. к. по нажатию кнопки Отмена обычно не требуется считывать данные из ЭУ. По умолчанию CDialog::OnCancel вызывает EndDialog с параметром IDCANCEL, чтобы закрыть диалоговое окно и проинформировать вызывающую функцию, что изменения в диалоговом окне должны быть проигнорированы.
За исключением специфического сообщения WM_INITDIALOG, диалоговые окна получают те же самые сообщения, что и все остальные окна. Вы можете добавить записи в карту сообщений диалогового окна для обработки любых необходимых сообщений и уведомлений. Допустим, в диалоговом окне есть кнопка Сброс с идентификатором IDC_RESET. Чтобы при нажатии этой кнопки вызывался обработчик OnReset, надо добавить в карту сообщений запись:
ON_BN_CLICKED( IDC_RESET, OnReset ) |
В диалоговых окнах можно обрабатывать даже сообщения WM_PAINT (например, чтобы сделать у окна необычный фон), но обработчики OnPaint используются редко, т. к. элементы управления сами перерисовывают свою экранную область.
1.2.1 Применение ClassWizard для создания подкласса CDialog
Вполне возможно добавить в проект подкласс CDialog вручную, но эта типичная операция выполняется гораздо быстрее с помощью ClassWizard. Сначала надо вызвать его командой меню ViewÞClassWizard, нажать кнопку Add Class, выбрать из появившегося меню вариант New и заполнить окно с параметрами нового класса. В нем надо указать имя класса, имя базового класса (CDialog), и идентификатор ресурса для шаблона окна (рис. 8.3).

Рис. 8.3. Использование ClassWizard'а для создания подкласса CDialog.
ClassWizard'ом удобно пользоваться для добавления обработчиков уведомлений от элементов управления окна. Допустим, вы хотите написать обработчик BN_CLICKED для нажимаемой кнопки с идентификатором IDC_RESET. Вот что для этого нужно сделать:
1) В окне проекта на закладке ClassView щелкнуть правой кнопкой на имени класса диалогового окна.
2) Выбрать из контекстного меню команду Add Windows Message Handler.
3) В появившемся окне в списке Class Or Object To Handle выделить идентификатор кнопки (IDC_RESET).
4) В списке New Windows Messages/Events выделить уведомление BN_CLICKED.
5) Нажать кнопку Add Handler и ввести имя функции-обработчика.
После выполнения этих действий, в класс диалогового окна будет добавлена новая функция-член с указанным вами именем, и для нее в карту сообщений класса будет внесена запись ON_BN_CLICKED.
1.3 Создание модального диалогового окна
После того, как вы разработали шаблон диалогового окна и объявили подкласс CDialog, для создания и вывода модального диалогового окна осталось немного: создать объект вашего подкласса CDialog и вызвать у него функцию-член DoModal. DoModal вернет управление только после закрытия диалогового окна. В качестве возвращаемого значение будет передан параметр функции EndDialog. Приложения обычно проверяют значение, возвращенное DoModal, чтобы выполнить некоторые действия только при возврате значения IDOK. При другом значении (обычно IDCANCEL), информация, введенная в диалогом окне, игнорируется.
Конструктору CDialog в качестве параметров передается идентификатор ресурса шаблона и указатель на окно-владельца диалогового окна. Если указатель CWnd* не задавать, владельцем станет главное окно приложения. Обычно в подклассах MFC заводится конструктор, который можно использовать вообще без параметров, например:
CMyDialog::CMyDialog( CWnd* pOwnerWnd = NULL ) : CDialog( IDD_MYDIALOG, pOwnerWnd ) {} |
Такой конструктор позволяет создать и вызвать диалоговое окно всего двумя операторами:
CMyDialog dlg; if ( dlg. DoModal() == IDOK ) { // Пользователь нажал кнопку OK } |
1.4 Механизм обмена данными с элементами управления (DDX/DDV)
Типичное диалоговое окно предоставляет пользователю для выбора некоторый набор параметров, собирает введенные данные и делает их доступными приложению, создавшему окно. Удобный способ хранения введенных данных – открытые переменные-члены класса диалогового окна. Приложение, пользующееся окном, может изменять эти переменные-члены для инициализации окна или для получения данных после его закрытия.
Допустим, есть диалоговое окно с двумя строками ввода, в которых пользователь может ввести имя и номер телефона. Заведем для этих характеристик две открытых переменных-члена в классе диалогового окна:
class CMyDialog : public CDialog { public: CMyDialog( CWnd* pParentWnd = NULL ) : CDialog( IDD_MYDIALOG, pParentWnd ) {} CString m_strName; CString m_strPhone; }; |
Когда в приложении выводится модальное окно и оно закрывается по кнопке OK, надо получить введенные параметры, например, так:
CMyDialog dlg; if ( dlg. DoModal() == IDOK ) { CString strName = dlg. m_strName; CString strPhone = dlg. m_strPhone; TRACE( "Имя=%s, телефон=%s", strName, strPhone ); } |
Этот текст можно немного изменить, чтобы окно выводилось на экран проинициализированным некоторыми значениями "по умолчанию":
CMyDialog dlg; dlg. m_strName = "Иванов"; dlg. m_strPhone = "111-1111"; if ( dlg. DoModal() == IDOK ) { CString strName = dlg. m_strName; CString strPhone = dlg. m_strPhone; TRACE( "Имя=%s, телефон=%s", strName, strPhone ); } |
В этом примере предполагается, что m_strName и m_strPhone каким-то образом связаны с ЭУ окна – так, что присвоение значений переменным как-то приводит к вставке соответствующего текста в строки ввода или что чтение значений переменных аналогично считыванию текста из строк ввода.
Такая связь переменных-членов и ЭУ не обеспечивается автоматически: ее должен создать программист. Во-первых, можно перегрузить OnInitDialog и OnOK и включить в них операторы для передачи данных между переменными-членами класса и ЭУ. Допустим, строкам ввода были присвоены идентификаторы IDC_NAME и IDC_PHONE. Тогда класс CMyDialog может быть реализован так:
class CMyDialog : public CDialog { public: CMyDialog::CMyDialog( CWnd* pParentWnd = NULL ) : CDialog( IDD_MYDIALOG, pParentWnd ) {} CString m_strName; CString m_strPhone; protected: virtual BOOL OnInitDialog(); virtual void OnOK(); }; BOOL CMyDialog::OnInitDialog() { CDialog::OnInitDialog(); SetDlgItemText( IDC_NAME, m_strName ); SetDlgItemText( IDC_PHONE, m_strPhone ); return TRUE; } void CMyDialog::OnOK() { GetDlgItemText( IDC_NAME, m_strName ); GetDlgItemText( IDC_PHONE, m_strPhone ); CDialog::OnOK(); } |
Представьте, насколько простой бы стала разработка классов диалоговых окон, если бы не пришлось заботиться об инициализации ЭУ в OnInitDialog и считывании данных из них в OnOK – например, если бы для сопоставления ЭУ и переменных членов можно было пользоваться некоторой "картой данных". Именно в этом в MFC состоит назначение механизма диалогового информационного обмена (Dialog Data Exchange, DDX). DDX прост в использовании, и во многих случаях он позволяет не перегружать функций OnInitDialog и OnOK, даже если в диалоговом окне несколько десятков ЭУ.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |


