Программирование на Visual C++. Архив рассылки - Алекс Jenter
Шрифт:
Интервал:
Закладка:
Библиотека WTL предоставляет программисту классы для удобной работы со стандартными контролами, а также предоставляет средства для расширения их функциональности. Кроме того, в WTL входит несколько нестандартных контролов (кнопка с картинками, гиперссылка и др.), которые вы также можете использовать в приложениях. Рассмотрим все эти классы более подробно.
Поддержка cтандартных и общих контролов WindowsМы с вами уже изучили класс 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 параметры этих сообщений.
• Обёртки для функций Win32 API, манипулирующих контролом. Такие функции существуют лишь для нескольких контролов (таких, как scroll bar).
Обратите внимание, что функциональность всех классов из atlctrls.h регулируется макросами WINVER, _WIN32_IE и _RICHEDIT_VER. Например, функции, специфичные для контролов из internet Explorer 4.0 и выше, оформлены так:
#if (_WIN32_IE >= 0x0400)
...
#endif //(_WIN32_IE>= 0x0400)
Благодаря этому классы контролов из WTL можно использовать при работе с любой версией контролов, получая при этом доступ ко всему набору возможностей используемой версии.
Полное описание всех функций и классов из atlctrls.h выходит за рамки данной статьи.
"Самодельные" контролыЕсли бы все программы использовали только стандартные контролы, они были бы скучными и неудобными. Поэтому разработчикам часто приходится "изобретать" свои собственные контролы. При этом можно разрабатывать новый контрол "с нуля" или взять за основу уже существующий контрол.
Создавать контролы "с нуля" мы уже умеем. Для этого нужно породить новый класс от CWindowImpl<> и написать обработчики нужных сообщений. Чаще других обрабатываются сообщения WM_CREATE и WM_PAINT, а также клавиатурные и мышиные сообщения. Кроме того, нужно предусмотреть средства для взаимодействия программы с вашим контролом. Для этой цели можно ввести нестандартные сообщения, которые будет понимать ваш контрол, или предусмотреть соответствующие методы в вашем классе.
Если вы решили построить свой контрол на базе существующего, вам также следует использовать класс CWindowImpl<>. Нужно только учесть два момента. Во-первых, базовым классом для вашего контрола должен быть не CWindow, а класс контрола, который вы модифицируете. Базовый класс задаётся во втором параметре шаблона CWindowImpl<> (по умолчанию этот параметр равен CWindow). А во-вторых, для обработки сообщений по умолчанию должна использоваться не функция DefWindowProc (как для обычных окон), а оконная функция соответствующего контрола. Чтобы этого добиться, следует использовать макрос DECLARE_WND_SUPERCLASS вместо DECLARE_WND_CLASS. Этот макрос объявлен так.
#define DECLARE_WND_SUPERCLASS(WndClassName, OrigWndClassName)
static CWndClassInfo& GetWndClassInfo()
{
static CWndClassInfo wc =
{
{ sizeof(WNDCLASSEX), 0, StartWindowProc,
0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL },
OrigWndClassName, NULL, NULL, TRUE, 0, _T("")
};
return wc;
}
Параметр WndClassName определяет имя класса вашего нового контрола. В качестве второго параметра OrigWndClassName следует указать имя класса контрола, который вы взяли за основу. При регистрации вашего класса WndClassName WTL скопирует для него параметры из класса с именем OrigWndClassName, а также сохранит адрес оконной процедуры, связанной с этим классом, в переменной CWindowImplBaseT<>::m_pfnSuperWindowProc и будет обращаться к ней для обработки сообщений, которые не были обработаны через карту сообщений.
С учётом всего сказанного, типичный класс контрола выглядит так.
class CMyCoolControl : public CWindowImpl<CMyCoolControl, CEdit> {
public:
DECLARE_WND_SUPERCLASS(NULL, CEdit::GetWndClassName())
BEGIN_MSG_MAP(CMyCoolControl)
// Карта сообщений
END_MSG_MAP()
…
};
В этом примере новый контрол создаётся на базе поля ввода (которому соответствует класс CEdit). Аналогично используется любой другой контрол.
ПРИМЕЧАНИЕ
Мы уже изучили макрос DDX_CONTROL, входящий в набор макросов DDX. Именно его следует использовать, чтобы связать существующий стандартный контрол (например, нарисованный в редакторе ресурсов) с объектом класса и наделить его дополнительными возможностями.
В библиотеку WTL входит несколько "самодельных" контролов, которые реализованы в файле atlctrlx.h . Вы можете вставлять их в свои программы или использовать как демонстрационные примеры по разработке контролов. Вот список классов, которые написали для вас разработчики WTL.
• CBitmapButton. Кнопка с рисунками.
• CCheckListViewCtrl. Расширенный список с "галочками".
• CHyperLink. Гиперссылка.
• CMultiPaneStatusBarCtrlImpl. Строка состояния с набором панелей.
• CWaitCursor. Курсор типа "песочные часы". Этот класс, в отличие от всех предыдущих, не имеет отношения к контролам.
Поскольку никакой официальной документации на эти классы нет, я приведу их краткое описание. Кроме этого, разобраться с ними вам поможет пример WTLCtlxDemo далее в этой статье.
Класс CBitmapButtonКласс CBitmapButton реализует кнопку, с каждым состоянием которой (нажата/отпущена/выключена/в фокусе) связано изображение. Кроме того, с кнопкой связывается всплывающая подсказка, поясняющая её назначение, и набор расширенных стилей (эти стили не имеют ничего общего с расширенным стилями обычного окна). Каждому стилю соответствует битовый флаг. Полный список флагов приведён в таблице 6.
Флаг Описание BMPBTN_HOVER Кнопка с этим стилем реагирует на присутствие курсора мыши: если он расположен над кнопкой, она переводится в состояние "в фокусе". Если этот стиль не задан, состояние "в фокусе" присваивается кнопке, на которую установлен клавиатурный фокус ввода. Замечу также, что кнопка со стилем BMPBTN_HOVER не реагирует на клавиатуру, то есть нажать на неё можно только мышью. BMPBTN_AUTO3D_SINGLE К кнопке принудительно добавляется трёхмерная рамка толщиной в 1 пиксель. Используя этот стиль, вы можете избавиться от необходимости рисовать трёхмерные рамки на всех изображениях, связанных с состояниями кнопки. BMPBTN_AUTO3D_DOUBLE Аналогичен предыдущему, но к кнопке добавляется рамка толщиной в 2 пикселя (такая, как у всех стандартных кнопок Windows). BMPBTN_AUTOSIZE Кнопка автоматически масштабируется под размер изображений, которые с ней связаны. BMPBTN_SHAREIMAGELISTS Кнопка использует разделяемый список изображений. Это означает, что он не будет уничтожен в деструкторе класса CBitmapButton. BMPBTN_AUTOFIRE Этот стиль имеет отношение к клавиатурному интерфейсу кнопки. Если вы нажали на кнопку, используя клавишу Space, и удерживаете эту клавишу, то кнопка со стилем BMPBTN_AUTOFIRE будет через заданные в системе промежутки времени посылать уведомление BN_CLICKED родительскому окну. Если же этот стиль не задать, уведомление отправится ровно 1 раз – в тот момент, когда вы нажали Space.Стиль кнопки, а также связанный с ней список изображений, задаются в конструкторе класса CBitmapButton, хотя можно установить/изменить их и позже, используя соответствующие методы. Для задания текста всплывающей подсказки также существуют соответствующий метод. Полный список методов класса CBitmapButton приведён в таблице 7.