Программирование на Visual C++. Архив рассылки
Шрифт:
Группы обрабатываются следующим образом. Сначала вычисляются координаты огибающего прямоугольника группы, то есть минимального прямоугольника, содержащего все контролы в ней. Далее размеры этого прямоугольника увеличиваются на dx и dy соответственно (dx и dy имеют то же значение, что и в обсуждении выше). После этого к каждому контролу в группе применяются следующие правила:
• DLSZ_MOVE_X: контрол сдвигается вдоль оси X пропорционально изменению ширины группы (то есть её огибающего прямоугольника).
• DLSZ_MOVE_Y: контрол сдвигается вдоль оси Y пропорционально изменению высоты группы.
• DLSZ_SIZE_X: действует аналогично DLSZ_MOVE_X, но ширина контрола также изменяется пропорционально изменению ширины группы.
• DLSZ_SIZE_Y:
Проиллюстрирую сказанное простым примером. Допустим, у нас есть диалог с тремя расположенными в ряд кнопками. Если написать для него карту масштабирования вида:
то этот диалог будет масштабироваться следующим образом:
Рисунок 3. Масштабирование с использованием групп
Мы не будем надолго задерживаться на внутренней реализации класса CDialogResize<>, так как там нет почти ничего интересного. Когда вы вызываете функцию DlgResize_Init, начальные положения всех контролов в диалоге запоминаются во внутренних структурах WTL. Функция DlgResize_UpdateLayout использует новые размеры диалога и сохранённые ранее координаты контролов, чтобы назначить им новое положение в соответствии с заданными флагами. Что касается карты масштабирования, она просто превращается в статический массив структур _AtlDlgResizeMap, для доступа к которому используется функция GetDlgResizeMap. Структура _AtlDlgResizeMap хранит заданные вами в карте значения:
Хочу отметить несколько особенностей реализации класса CDialogResize<>, которые можно использовать в своих целях.
1. Элемент может встречаться в карте масштабирования более одного раза.
2. Элемент, не включённый в группу, двигается относительно его текущего положения.
3. Элемент, включённый в группу, масштабируется с учётом его начального положения (но без учёта его текущей позиции).
Таким образом мы можем, к примеру, отмасштабировать элемент по горизонтали, включив его в группу, а затем отдельно увеличить его высоту. Пример диалога с тремя кнопками, который мы рассмотрели выше, имел один недостаток: при увеличении высоты диалога кнопки не растягивались по вертикали. Теперь мы знаем, как решить эту проблему:
Кроме этого, можно включить элемент в несколько групп. Хотя на его местоположение повлияет только последняя группа, этот приём позволит сложным образом влиять на другие контролы. Но не стоит забывать о чувстве меры. Такие приёмы делают вашу программу более запутанной и более медлительной. Нетривиальное масштабирование контролов в диалоге лучше реализовать вручную, а не заниматься неочевидными фокусами с CDialogResize<>.
Контролы – ещё один важный элемент операционной системы Windows. Во времена DOS каждому программисту зачастую приходилось изобретать собственный графический интерфейс. Под Windows задача упростилась: хотя сложные нестандартные "фичи" пользовательского интерфейса по-прежнему приходится разрабатывать вручную, в вашем распоряжении всегда есть базовый набор элементов, которые можно использовать для взаимодействия с пользователем или попытаться построить на их основе более сложные контролы.
Библиотека WTL предоставляет программисту классы для удобной работы со стандартными
контролами, а также предоставляет средства для расширения их функциональности. Кроме того, в WTL входит несколько нестандартных контролов (кнопка с картинками, гиперссылка и др.), которые вы также можете использовать в приложениях. Рассмотрим все эти классы более подробно.Мы с вами уже изучили класс CWindow, который предоставляет целый набор обёрток для функций Win32 API, предназначенных для работы с окнами. При работе с контролами этот класс также можно использовать. Но гораздо удобнее использовать специальные классы контролов, которые описаны в файле atlctrls.h. Полный список этих классов приведён в таблице 5.
Контрол | Соответствующий класс |
---|---|
Статический текст или изображение (static control) | CStatic |
Кнопка (button) | CButton |
Простой список (list box) | CListBox |
Комбинированный список (combo box) | CComboBox |
Поле ввода (edit box) | CEdit |
Полоса прокрутки (scroll bar) | CScrollBar |
Список изображений (image list) | CImageList |
Расширенный список (list view) | CListViewCtrl |
Дерево (tree view) | CTreeViewCtrl, CTreeViewCtrlEx |
Заголовок (header) | CHeaderCtrl |
Панель инструментов (toolbar) | CToolBarCtrl |
Строка состояния (status bar) | CStatusBarCtrl |
Окно с закладками (tab control) | CTabCtrl |
Всплывающая подсказка (tooltip) | CToolTipCtrl |
Ползунок (trackbar) | CTrackBarCtrl |
Регулятор (up-down control) | CUpDownCtrl |
Индикатор прогресса (progress bar) | CProgressBarCtrl |
Горячая клавиша (hot key) | CHotKeyCtrl |
Окно с анимацией (animate control) | CAnimateCtrl |
Расширенное поле ввода (rich edit) | CRichEditCtrl |
Список с возможностью перетаскивания (drag list box) | CDragListBox |
Полоска-контейнер (rebar control) | CReBarCtrl |
Комбинированный список с картинками (ComboBoxEx control) | CComboBoxEx |
Выбор даты/времени (date and time picker) | CDateTimePickerCtrl |
Календарь на меcяц (month calendar) | CMonthCalendarCtrl |
"Плоская" полоса прокрутки (flat scroll bar) | CFlatScrollBar |
IP-адрес (IP address control) | CIPAddressCtrl |
Пейджер (pager control) | CPagerCtrl |
Каждый из этих классов порождён от CWindow и содержит все его методы. В дополнение каждый класс предоставляет:
• Метод GetWndClassName. Этот метод позволяет узнать имя класса окна, соответствующего данному контролу.
• Метод Create. В отличие от аналогичного метода из класса CWindow, он не принимает имя класса, так как оно извлекается при помощи GetWndClassName.
• Обёртки для стандартных сообщений, которые используются для управления контролом. Например, для статических контролов это сообщения STM_GETICON, STM_GETIMAGE, STM_SETICON и STM_SETIMAGE. Используя обёртки, вы можете не вспоминать, каким образом упаковываются в wParam и lParam параметры этих сообщений.