Лекция 4. Диалоговые окна и стандартные элементы управления
Якунин М.С

[На главную страницу сайта] [Другие темы раздела] [Содержание курса] [Лабораторная работа к лекции] [Скачать задачи] [Следующая лекция]

Методические рекомендации

  1. Обратите особое внимание студентов на добавление элементов управления в период выполнения программы. Это очень важно, так как часто в реальной практике на начало программы неизвестно, какие элементы управления должны присутствовать в диалоговом окне.
  2. Так как немодальные окна чаще используются чем модальные, то необходимо добиться полного понимания студентами процесса работы с немодальными диалоговыми окнами.
  3. Для лучшего понимания работы с диалоговыми окнами и разницы между модальными и немодальными диалоговыми окнами рекомендуется пользоваться примерами. Очень хорошо для этих целей подходит программа из пакета Microsoft Office – Microsoft Word. Примером модального диалогового окна может служить окно “открытия файла”, а примером немодального окна – “найти и заменить”.

План

  1. Модальные и немодальные диалоговые окна
  2. Работа с модальным диалоговым окном
  3. Стандартные элементы управления
  4. Работа с немодальными диалоговыми окнами

Модальные и немодальные диалоговые окна

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

Существует два типа диалоговых окон:

  1. Модальные(modal). Пока открыто модальное диалоговое окно, пользователь не может работать ни с каким другим окном программы. Например, Open File – “Открытие файла”.
  2. Немодальные(modeless). Пока открыто немодальное диалоговое окно, работать с другими окнами программы можно. Например, Find and Replace – “Найти и заменить” редактора Microsoft Word.

Работа с модальным диалоговым окном

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

  1. Используя редактор диалоговых окон, создать диалоговый ресурс с элементами управления.
  2. С помощью ClassWizard создать класс “диалоговое окно”, производный от CDialog, и связать его с ресурсом созданным в п.1.
  3. Используя ClassWizard, добавить в класс диалогового окна переменные члены и функции, предназначенные для обмена и проверки данных.
  4. С помощью ClassWizrd добавить обработчики сообщений для кнопок и других, генерирующих события, элементов управления диалогового окна.
  5. Написать код для инициализации (в функции OnInitDialog) элементов управления и для обработчиков сообщений.
  6. Добавить код, активизирующий диалоговое окно. Он сводится к вызову конструктора вашего класса диалогового окна и последующему вызову функции – члена DoModal().

Стандартные элементы управления

Элемент управления “индикатор продвижения”

Индикатор продвижения – один из самых простых в программировании стандартный элемент управления; его представляет MFC класс CProgressCtrl.

Для инициализации индикатора продвижения необходимо вызвать (обычно это делается в функции OnInitDialog) функции-члены SetRange и SetPos. После этого, при необходимости, нужно вызывать функцию SetPos из обработчиков сообщений.

Элемент управления “ползунок”

Ползунок (класс CSliderCtrl) позволяет вводить аналоговые значения. Программным путем можно создать шкалу, деления которой соответствуют шагу приращения. Текущее положение ползунка возвращает функция – член GetPos.

Элемент управления “наборный счетчик”

Наборный счетчик (класс CSpinButtonCtrl) – это вариант полосы прокрутки, который часто используется совместно с полем ввода. Суть работы данного элемента в том, что пользователь, поместив курсор на счетчик и удерживая левую клавишу мыши, может увеличивать или уменьшать значение в поле ввода. Скорость работы тем выше, чем дольше удерживается клавиша мыши.

Если приложение оперирует в поле ввода только целыми числами, можно полностью обойтись без программирования на C++. Для того чтобы изменить диапазон и схему ускорения набора значений можно воспользоваться функциями-членами SetRange и SetAccel.

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

Элемент управления “графический список”

Элемент управления “графический список” (класс CListCtrl) необходим для создания списка способного отображать не только текст но и графику. Когда пользователь выбирает какой–нибудь элемент, посылается уведомляющее сообщение, которое нужно обработать в классе “диалогового окна”. Элементы идентифицируются целочисленными индексами, начиная с 0.

Элемент управления “древовидный список”

Элемент управления “древовидный список” (класс CTreeCtrl) позволяет легко добавить в программу возможности аналогичные графическим возможностям отображения информации Microsoft Windows Explorer (Проводника).

Графический и древовидный списки имеют некоторые общие черты: они могут работать с одним и тем же списком изображений и совместно использовать одни и те же уведомляющие сообщения. Однако методы идентификации элементов у них разные. В древовидном списке вместо целочисленных индексов применяют описатель HTREEITEM.

Для того чтобы вставить новый элемент необходимо обратиться к функции-члену InsertItem, но перед этим нужно сформировать структуру TV_INSERTSTRUCT, которая идентифицирует строку, индекс в списке изображений и описатель родительского элемента (NULL для элементов верхнего уровня).

Примечание

И графический и древовидный списки получают выводимые ими картинки от стандартного элемента управления – список изображений (класс CImageList). В программе необходимо сначала сформировать список изображений из значков или растровых изображений, а затем передать элементу управления “графический список” или “древовидный список” указатель на этот список. Формировать список лучше всего в функции OnInitDialog.

Добавление элементов управления в период выполнения

Если необходимо добавить элемент управления в период выполнения программы нужно выполнить следующие действия:

  1. Добавить в класс “диалоговое окно” переменную-член для внедряемого элемента управления. MFC-классы таких элементов управления включают CButton, CEdit, CListBox, CComboBox и т.д. Внедряемые C++ объекты конструируются и уничтожаются вместе с объектом “диалоговое окно”.
  2. Выбрать из меню View среды Visual C++ команду Resource Symbols. Добавить константу идентификатор нового элемента управления.
  3. Вызвать функцию-член Create внедряемого элемента управления в том месте программы, где должен создаваться новый элемент управления (обычно это обработчик сообщения WM_INITDIALOG – функция OnInitDialog).
  4. Добавить вручную в производный класс диалогового окна обработчики уведомляющих сообщений, необходимые новому элементу управления.

Сообщение WM_NOTIFY

Раньше элементы управления Windows посылали свои уведомления в сообщениях WM_COMMAND. Однако стандартных 32-х разрядных параметров wParam и lParam недостаточно для передачи всей информации от стандартных элементов управления их объектам-родителям. Корпорация Microsoft решила проблему “пропускной способности”, введя новое сообщение WM_NOTIFY. При отправке такого сообщения wParam содержит идентификатор элемента управления, а lParam служит указателем на структуру NMHDR, модифицируемую данным элементом управления. Эта структура определяется на C++ следующим образом:

typedef struct tagNMHDR {

HWND hwndFrom; // описатель элемента управления, отправляющего сообщение

UINT idFrom; // идентификатор этого элемента

UINT code; // специфичный для этого элемента код уведомления

}NMHDR;

Однако многие элементы управления посылают сообщения WM_NOTIFY с указателями на структуры более крупные, чем NMHDR. Эти структуры содержат не только показанные выше три поля данных, но и дополнительные поля, специфичные для конкретного элемента управления. Например, во многих уведомлениях от древовидных списков передается указатель на структуру NM_TREEVIEW, содержащую структуру TV_ITEM и другие данные. Поэтому сопоставив обработчику сообщение WM_NOTIFY, ClassWizard генерирует указатель на соответствующую структуру.

Работа с немодальными диалоговыми окнами

Известно, что при создании модальных диалоговых окон сначала надо воспользоваться конструктором CDialog с параметром-идентификатором прикрепленного ресурса, чтобы сконструировать объект “диалоговое окно”, а потом вывести модальное диалоговое окно на экран, вызвав функцию-член DoModal. И как только происходит возврат из DoModal, окно прекращает свое существование.

Процесс создания немодальных диалоговых окон сложнее. Начинать необходимо с вызова конструктора CDialog по умолчанию, создавая, тем самым, объект “диалоговое окно”, а вот нужное диалоговое окно создается вызовом функции-члена CDialog::Create, а не функции DoModal. Create получает идентификатор ресурса как параметр и немедленно возвращает управление; при этом диалоговое окно остается на экране. Так что теперь именно программист должен заботиться о том, когда конструировать объект “диалоговое окно”, когда создавать само диалоговое окно, когда его уничтожать и когда обрабатывать данные, введенные пользователем.

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

 

Модальное диалоговое окно

Немодальное диалоговое окно

Используемый конструктор

Конструктор с параметром-идентификатором ресурса.

Конструктор по умолчанию (без параметра)

Функция, используемая для создания окна

DoModal

Create с параметром-идентификатором ресурса.

 

Пользовательские сообщения

Допустим, Вы хотите, чтобы немодальное диалоговое окно уничтожалось, когда пользователь щелкает в этом окне кнопку ОК. Тут сразу же возникает проблема. Как объект “вид” узнает, что пользователь щелкнул кнопку ОК? Диалоговое окно могло бы напрямую обратиться к какой-либо функции-члену класса “вид”, но это бы связало данное диалоговое окно с конкретным классом “вид”. Более удачное решение — диалоговое окно при вызове обработчика кнопки ОК отправляет объекту “вид” пользовательское сообщение (user-defined message). Получив это сообщение, объект “вид” сможет уничтожить диалоговое окно (но не сам объект). Итак, вырисовывается сценарий создания нового диалогового окна

Есть два варианта отправки Windows-сообщений, через функции CWnd::SendMessage или PostMessage. Первая немедленно вызывает функцию-обработчик сообщения, а вторая отправляет сообщение в очередь сообщений Windows. Поскольку PostMessage вносит лишь небольшую задержку, можно считать, что функция-обработчик кнопки ОК уже завершилась, когда объект “вид” получает сообщение.

Принадлежность диалогового окна

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

Поскольку речь идет о Windows, “владелец” диалогового окна — основное окно рамка приложения, а не объект “вид”. Но надо знать, какой именно объект “вид” сопоставлен с диалоговым окном, чтобы отправить этому объекту сообщение. Поэтому ваш класс “диалоговое окно” должен отслеживать свой объект “вид” через переменную член, которую устанавливает конструктор. Параметр pParent конструктора CDialog в данном случае не играет никакой роли.

Контрольные вопросы

  1. Какие типы диалоговых окон вы знаете и чем они различаются?
  2. Какой класс отвечает за работу с диалоговыми окнами?
  3. При помощи какой функции вызывается модальное диалоговое окно?
  4. При помощи какой функции вызывается немодальное диалоговое окно?
  5. Какие два способа отправки сообщений в Windows вы знаете?
  6. Какие стандартные элементы управления вы знаете?
  7. Каким образом можно добавить элемент управления в момент выполнения программы?
  8. [На главную страницу сайта] [Другие темы раздела] [Содержание курса] [Лабораторная работа к лекции] [Скачать задачи] [Следующая лекция]