лекции / Shchupak_Yu._Win32_API_Razrabotka_prilozheniy_dlya_Windows
.pdf
Основы применения |
381 |
|
|
|
|
регистрирует оконные классы элементов управления. Функция имеет следую щий прототип:
BOOL InitCommonControlsEx(LPINITCOMMONCONTROLSEX lpInitCtrls);
В параметре lpInitCtrls передается адрес структурной переменной типа INITCOMMONCONTROLSEX, содержащей информацию о том, какие классы элементов управления должны быть зарегистрированы.
Структура INITCOMMONCONTROLSEX имеет следующее определение:
typedef struct tagINITCOMMONCONTROLSEX {
DWORD |
dwSize; |
// |
размер структуры в байтах |
|
DWORD |
dwICC; |
// |
флаги загрузки классов из |
DLL |
} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;
Второй параметр может принимать одно или несколько значений, перечислен ных в табл. 8.5.
Таблица 8.5. Некоторые из возможных флагов для функции InitCommonControlsEx
Ôëàã |
Загружаются оконные классы для элементов управления |
|
|
ICC_ANIMATE_CLASS |
animate |
ICC_BAR_CLASSES |
toolbar, status bar, slider, tooltip |
ICC_LISTVIEW_CLASSES |
list view, Header |
ICC_PROGRESS_CLASS |
progress bar |
ICC_TAB_CLASSES |
tab, tooltip |
ICC_TREEVIEW_CLASSES |
tree view, tooltip |
ICC_UPDOWN_CLASS |
up-down |
ICC_WIN95_CLASSES |
animate, header, hot key, list view, progress bar, status bar, tab, |
|
tooltip, toolbar, slider, tree view, up-down |
|
|
Полный список флагов можно найти в справочных материалах MSDN. Описание функции InitCommonControlsEx вместе с другими описаниями, необ
ходимыми для использования библиотеки, находятся в файле commctrl.h. Этот файл не входит в группу файлов, ссылки на которые помещены в файле windows.h. Поэтому в начале любого исходного файла, содержащего вызовы функций дан ной библиотеки, необходимо поместить следующую директиву:
#include <commctrl.h>
Помимо этого следует указать компоновщику расположение библиотечного файла comctl32.lib. Если применяется среда разработки Visual Studio 6.0, то до бавьте имя этой библиотеки в текстовое поле Object/library modules диалогового окна настроек проекта, которое вызывается при помощи команды меню Project Settings… Link.
Если вы забудете это сделать, то компоновщик выведет сообщение следующе го вида:
error LNK2001: unresolved external symbol __imp__InitCommonControls@0
Учтите, что если вы забудете вызвать функцию InitCommonControlsEx, то ни ком пилятор, ни компоновщик этого «не заметят», но ваша программа, возможно, бу дет вести себя странным образом. Например, диалоговое окно, в котором был раз мещен элемент управления общего пользования, может вообще не появиться на экране. Так что будьте внимательны!
382 |
Глава 8. Элементы управления общего пользования |
|
|
Элемент управления Rich edit из за его сложности и большого размера распо лагается в его собственной динамически подключаемой библиотеке riched32.dll. Для работы с усовершенствованным редактором нужно загрузить эту библиоте ку при помощи вызова функции LoadLibrary:
LoadLibrary("riched32.dll");
а в начале файлов, использующих функции или константы из данной библиоте ки, поместить директиву
#include <richedit.h>
Создание элементов управления общего пользования
Наиболее традиционным способом создания элемента управления общего пользо вания является вызов функции CreateWindow или CreateWindowEx. Например, при веденный вызов создает панель инструментов:
HWND hwndToolBar = CreateWindow(TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 0, 16, 16, hwndParent, (HMENU)1, hInst, 0);
Имя оконного класса TOOLBARCLASSNAME здесь задается без кавычек, посколь ку это именованная константа, определение которой зависит от набора симво лов, выбранного при построении программы. Для набора символов ANSI имя TOOLBARCLASSNAME заменяется строковой константой ToolbarWindow32, для набо ра символов UNICODE — строковой константой L"ToolbarWindow32". Имена дру гих оконных классов элементов управления общего пользования определяются аналогично.
Обычно элементы управления общего пользования создаются как дочерние окна, что определяется флагом WS_CHILD и передачей дескриптора родительского окна hwndParent.
Альтернативой вызову функции CreateWindow является вызов специализиро ванной функции создания элемента управления, которая в то же время может выполнять некоторую стандартную инициализацию. Например, панель инстру ментов может быть создана функцией CreateToolbarEx.
Для некоторых элементов управления соответствующие оконные классы не определены. Такие элементы управления могут быть созданы только с помощью специализированных функций. В табл. 8.6 приведены сведения об оконных клас сах и специализированных функциях создания для элементов управления обще го пользования.
Таблица 8.6. Оконные классы и специализированные функции создания для элементов управления общего пользования
Элемент управления |
Оконный класс |
Функция создания |
|
|
|
Toolbar |
TOOLBARCLASSNAME |
CreateToolbarEx |
Tooltip |
TOOLTIPS_CLASS |
Íåò |
Status bar |
STATUSCLASSNAME |
CreateStatusWindow |
Tab control |
WC_TABCONTROL |
Íåò |
Property sheet |
Íåò |
PropertySheet |
|
|
|
Основы применения |
|
383 |
|
|
|
|
|
|
|
|
|
|
Элемент управления |
Оконный класс |
Функция создания |
|
|
|
|
|
Property page |
Íåò |
CreatePropertySheetPage |
|
Tree view |
WC_TREEVIEW |
Íåò |
|
List view |
WC_LISTVIEW |
Íåò |
|
Animation |
ANIMATE_CLASS |
Íåò |
|
Header |
WC_HEADER |
Íåò |
|
Image list |
Íåò |
ImageList_Create |
|
Progress bar |
PROGRESS_CLASS |
Íåò |
|
Rich edit |
"RichEdit" (ANSI) èëè L"RichEdit" (UNICODE) |
Íåò |
|
Slider |
TRACKBAR_CLASS |
Íåò |
|
Spin |
UPDOWN_CLASS |
CreateUpDownControl |
|
|
|
|
Стили элементов управления общего пользования
Независимо от способа создания — с помощью CreateWindow или специализиро ванной функции — при вызове соответствующей функции необходимо задать набор стилей элемента управления.
Флаги стилей можно разделить на следующие четыре категории: флаги основ ного стиля окна (с префиксом WS_)1, флаги расширенного стиля окна (WS_EX_)2, флаги основного стиля элемента управления общего пользования (CCS_) и флаги стиля, специфичные для конкретного элемента управления.
Библиотека элементов управления общего пользования поддерживает набор значений стиля с префиксом CCS_. Они применяются для панелей инструментов, строк состояния и заголовков списка просмотра. В табл. 8.7 перечислены эти сти ли с кратким описанием их назначения.
Таблица 8.7. Флаги основного стиля элемента управления общего пользования
Ôëàã |
Эффект |
|
|
CCS_ADJUSTABLE |
Состав кнопок панели инструментов и их последовательность могут |
|
изменяться пользователем |
CCS_BOTTOM |
Элемент управления располагается внизу родительского окна. Этот |
|
стиль установлен по умолчанию для элемента управления Status bar |
CCS_NODIVIDER |
Между элементом управления и родительским окном нет раздели- |
|
тельной линии |
CCS_NOMOVEY |
Элемент управления не может быть растянут или сдвинут по |
|
вертикали |
CCS_NORESIZE |
Размер и позиция элемента управления фиксированы |
CCS_TOP |
Элемент управления располагается вверху родительского окна. Этот |
|
стиль установлен по умолчанию для элемента управления Tool bar |
|
|
Флаги стиля, специфичные для конкретных элементов управления, имеют уникальные префиксы, которые приведены в табл. 8.8.
1 Флаги основного стиля окна приведены в табл. 1.8 (глава 1).
2 Флаги расширенного стиля окна приведены в табл. 1.9 (глава 1).
384 |
Глава 8. Элементы управления общего пользования |
|
|
Таблица 8.8. Префиксы флагов стиля, специфичных для конкретных элементов |
|
управления |
|
|
|
Элемент управления |
Префикс флага стиля |
|
|
Toolbar |
TBSTYLE_ |
Tooltip |
TTS_ |
Status bar |
SBARS_ |
Tab control |
TCS_ |
Property sheet |
Íåò |
Property page |
Íåò |
Tree view |
TVS_ |
List view |
LVS_ |
Animation |
ACS_ |
Header |
HDS_ |
Image list |
Íåò |
Progress bar |
Íåò |
Rich edit |
ES_ |
Slider |
TBS_ |
Spin |
UDS_ |
|
|
Обмен сообщениями
После создания элемента управления общего пользования приложение управ ляет его действиями, посылая необходимые сообщения при помощи функции SendMessage. Для каждого типа элемента управления существуют свои специ фические сообщения.
Например, для добавления элемента в дерево просмотра (Tree view) с дескрипто ром hwndTV необходимо послать элементу управления сообщение TVM_INSERTITEM. Это можно реализовать следующим вызовом функции SendMessage:
hItem = (HTREEITEM)SendMessage(hwndTV, TVM_INSERTITEM, 0,
(LPARAM)(LPTV_INSERTSTRUCT) &tvis);
Альтернативой вызовам функции SendMessageявляется использование набора мак росов, определенных в файле commctrl.h. Например, добавление элемента в дерево можно реализовать, используя макрос TreeView_ InsertItem:
hItem = TreeView_InsertItem (hwndTV, &tvis);
Как видно, текст с макросом выглядит значительно проще для чтения.
К сожалению, файлы Win32 содержат определения макросов не для всех эле ментов управления общего пользования. В файле commctrl.h находятся определе ния макросов только для элементов управления Tab control, Tree view, List view, Animation и Header. Файл prsht.h содержит определения макросов для элемента уп равления Property sheet.
Как и базовые элементы управления, элементы управления общего пользова ния посылают своему родительскому окну уведомляющие сообщения, содержа щие информацию о произошедших событиях. Но если базовые элементы управ ления используют сообщение WM_COMMAND, то элементы управления общего пользования обычно посылают уведомления при помощи сообщений WM_NOTIFY.
Элементы управления главного окна |
385 |
|
|
|
|
Однако не все уведомления реализуются подобным образом. Например, па нель инструментов, использующая сообщение WM_NOTIFY для большинства уве домлений, посылает сообщение WM_COMMAND, когда пользователь нажимает одну из кнопок. Дело в том, что панель инструментов обычно дублирует команды меню, поэтому имеющийся код обработки сообщений WM_COMMAND от команд меню бу дет одновременно обрабатывать и сообщения от кнопок панели инструментов.
Еще одно исключение составляют полосы прокрутки элементов управления
Slider и Spin, которые посылают сообщение WM_VSCROLL или WM_HSCROLL.
Хотя каждый элемент управления общего пользования имеет свой собствен ный набор кодов уведомления, существует набор уведомлений, общий для всех элементов. Эти уведомления приведены в табл. 8.9.
Таблица 8.9. Общие уведомления
Код уведомления |
Описание |
|
|
NM_CLICK |
Пользователь сделал щелчок левой кнопкой мыши |
NM_DBLCLK |
Пользователь сделал двойной щелчок левой кнопкой мыши |
NM_KILLFOCUS |
Элемент управления потерял фокус ввода |
NM_OUTOFMEMORY |
Ошибка «Не хватает памяти» |
NM_RCLICK |
Пользователь сделал щелчок правой кнопкой мыши |
NM_RDBLCLK |
Пользователь сделал двойной щелчок правой кнопкой мыши |
NM_RETURN |
Пользователь нажал клавишу Enter |
NM_SETFOCUS |
Элемент управления получил фокус ввода |
|
|
Не все элементы управления обязательно посылают каждое из этих уведомля ющих сообщений. Например, набор закладок (Tab control) не посылает уведомле ний об изменении фокуса ввода.
Перед использованием каждого элемента управления общего пользования сле дует разобраться с тем, какие уведомляющие сообщения он посылает.
Из за ограниченного объема книги мы рассмотрим приемы работы только со следующими элементами управления общего пользования: Toolbar, Tooltip, Status bar, Progress bar, Slider и Spin.
Элементы управления главного окна
В оформлении главного окна приложения часто применяются следующие эле менты управления общего пользования: панели инструментов, окна подсказки и строки состояния. На рис. 8.1 показано, как выглядят эти элементы управления в основном окне MS Visual Studio 6.0.
Панель инструментов
Панель инструментов — это дочернее окно, обычно расположенное под меню при ложения и содержащее одну или несколько кнопок. Когда пользователь щелкает мышью на кнопке панели инструментов, она посылает сообщение WM_COMMAND своему родительскому окну. Традиционно кнопки панели инструментов соответ ствуют некоторым пунктам в меню приложения, обеспечивая более удобный
386 |
Глава 8. Элементы управления общего пользования |
|
|
способ доступа пользователя к командам меню. Следует отметить, что в простых приложениях меню может отсутствовать, а все необходимые команды могут быть реализованы с помощью панели инструментов.
Рис. 8.1. Панель инструментов, строка состояния и окно подсказки
Кнопки панели инструментов сами по себе не являются окнами. Они реализо ваны как графические объекты, нарисованные на поверхности окна панели инст рументов. Изображения на кнопках поясняют их назначение. Иногда помимо изоб ражения кнопка может содержать текстовую метку, расположенную или правее, или ниже картинки.
Панель инструментов устанавливает одинаковые размеры всех кнопок, а в слу чае наличия текстовых меток определяет размеры так, чтобы разместить самый длинный текст. Поэтому для текстовых меток следует выбирать короткие строки, иначе кнопки могут получиться слишком большими. В большинстве случаев кноп ки на панелях инструментов содержат только растровые изображения, а назначе ние кнопок поясняется с помощью всплывающих окон подсказок.
Чтобы сделать интерфейс панели инструментов более удобным для пользовате ля, кнопки часто объединяют в группы. Кнопки, объединенные в группу, следуют одна за другой, а между группами остается небольшой промежуток. Такие проме жутки реализуются при помощи кнопок стиля TBSTYLE_SEP, называемых кнопками разделителями.
Кроме кнопок, панель инструментов может содержать и другие дочерние окна элементов управления, такие, как, например, комбинированный список (combo box). Встроенные элементы управления создаются при помощи функции CreateWindow.
Элементы управления главного окна |
387 |
|
|
|
|
Для добавления к приложению панели инструментов необходимо выполнить следующую последовательность действий:
1.Определить ресурс растрового образа панели инструментов.
2.Объявить и инициализировать массив структур типа TBBUTTON, содержащий информацию о кнопках панели инструментов.
3.Вызвать функцию CreateToolbarEx для создания и инициализации панели инст рументов.
Рассмотрим реализацию этих шагов на примере разработки приложения ToolBar, представляющего собой модифицированную версию программы MenuDemo1, опи санной в главе 6. В результате модификации к интерфейсу приложения будет до бавлена панель инструментов, дублирующая некоторые команды меню.
Начало разработки приложения ToolBar
Создайте новый проект с именем ToolBar. Скопируйте из папки проекта MenuDemo1 (см. листинг 6.1) в папку проекта ToolBar файлы с расширениями .cpp, .h и .rc, скор ректировав их имена заменой MenuDemo1 на ToolBar. Добавьте эти файлы в состав проекта.
Укажите имя библиотеки comctl32.lib в настройках компоновщика в проекте. В среде Visual Studio 6.0 эти настройки находятся на вкладке Link диалогового окна Project Settings, которое открывается при помощи команды меню Project Settings.
Определение ресурса растрового образа панели инструментов
В главном меню Visual Studio выполните команду Insert Resource. В появившем ся диалоговом окне Insert Resource укажите тип ресурса Toolbar и нажмите кнопку New. В результате будет открыто окно редактора панели инструментов с заготов кой растрового образа панели инструментов, содержащего первую и пока един ственную кнопку (рис. 8.2).
Рис. 8.2. Редактор панелей инструментов с заготовкой растрового образа панели
По умолчанию редактор присваивает растровому образу панели инструментов идентификатор IDR_TOOLBAR1. Если вы хотите изменить назначенный идентифика тор, то на вкладке ResourceView в окне Workspace сделайте щелчок правой кнопкой мыши на элементе IDR_TOOLBAR1и в появившемся контекстном меню выберите пункт Properties. В открывшемся диалоговом окне Toolbar Properties введите в окне редакти рования ID нужный идентификатор.
В нашем проекте можно оставить предложенный редактором идентификатор ресурса IDR_TOOLBAR1.
Элементы управления главного окна |
389 |
|
|
|
|
направо, начиная с нуля. Подразумеваемые индексы изображений, описания изоб ражений и идентификаторы кнопок приведены в табл. 8.10.
Таблица 8.10. Индексы изображений, их описание и идентификаторы кнопок
Индекс изображения |
Описание изображения |
Идентификатор кнопки |
|
|
|
0 |
Прямоугольник |
ID_RECTANGLE |
1 |
Ðîìá |
ID_RHOMB |
2 |
Эллипс |
ID_ELLIPSE |
3 |
— |
ID_SEP |
4 |
Красный кружок |
ID_RED |
5 |
Зеленый кружок |
ID_GREEN |
6 |
Синий кружок |
ID_BLUE |
7 |
— |
ID_SEP |
8 |
Черный квадрат |
ID_DARK |
9 |
Серый квадрат |
ID_MEDIUM |
10 |
Белый квадрат |
ID_LIGHT |
|
|
|
Следует отметить, что идентификаторы кнопок, кроме кнопок разделителей, совпадают с идентификаторами дублируемых пунктов меню.
Закончив визуальное проектирование панели инструментов, сохраните создан ный растровый образ в файле описания ресурсов.
Обратите внимание на то, что теперь в составе проекта появился файл toolbar1.bmp, содержащий растровый образ панели инструментов. Имя этого фай ла использует вторую часть идентификатора панели инструментов.
Если открыть файл описания ресурсов ToolBar.rc в текстовом режиме, то в нем можно найти многострочное определение панели инструментов:
IDR_TOOLBAR1 TOOLBAR DISCARDABLE 16, 15
BEGIN |
|
BUTTON |
ID_RECTANGLE |
BUTTON |
ID_RHOMB |
… |
|
END |
|
Помимо этого в описании ресурсов есть ссылка на указанный файл:
IDR_TOOLBAR1 |
BITMAP DISCARDABLE |
"toolbar1.bmp" |
Заполнение массива структур типа TBBUTTON
Если для создания панели инструментов используется вызов функции CreateToolbarEx, то один из параметров функции должен получить адрес массива струк тур типа TBBUTTON. Структура TBBUTTON определена в файле commctrl.h следую щим образом:
typedef struct _TBBUTTON {
int iBitmap; |
// индекс изображения кнопки или |
|
// ширина кнопки-разделителя (в пикселах) |
int idCommand; |
// идентификатор кнопки |
BYTE fsState; |
// начальное состояние кнопки |
BYTE fsStyle; |
// стиль кнопки |
DWORD dwData; |
// дополнительные данные |
INT_PTR iString; // индекс (относительно нуля) текстовой метки кнопки } TBBUTTON;
390 |
Глава 8. Элементы управления общего пользования |
|
|
Интерпретация полей структуры частично поясняется в комментариях. Поле fsState может принимать комбинацию из следующих значений:
Флаг состояния |
Описание |
|
|
TBSTATE_CHECKED |
Кнопка со стилем TBSTYLE_CHECK находится в нажатом состоянии |
TBSTATE_PRESSED |
Кнопка любого стиля находится в нажатом состоянии |
TBSTATE_ENABLED |
Кнопка доступна (может реагировать на действия мышью) |
TBSTATE_HIDDEN |
Скрытая кнопка (для пользователя недоступна) |
TBSTATE_INDETERMINATE |
Кнопка отображается серым цветом и недоступна для действий |
|
пользователя |
|
|
Поле fsStyle может принимать одно из следующих значений:
Флаг стиля |
Описание |
|
|
TBSTYLE_BUTTON |
Стандартная кнопка. Может быть нажата, но не может оставаться |
|
в нажатом состоянии |
TBSTYLE_SEP |
Разделитель для создания промежутка между группами кнопок. |
|
Может использоваться для резервирования места для дочерних |
|
элементов управления |
TBSTYLE_CHECK |
Кнопка ведет себя, как флажок (check box). Каждый щелчок мыши |
|
изменяет состояние кнопки (нажата / отжата) |
TBSTYLE_GROUP |
Кнопка является членом группы кнопок типа переключателей |
|
(radio button) |
TBSTYLE_CHECKGROUP |
Объединяет свойства стилей TBSTYLE_CHECK и TBSTYLE_GROUP |
|
|
Поле dwData можно не использовать. Но при желании в нем можно сохра нить указатель на дополнительную информацию, специфичную для конкрет ной кнопки. Разработчик может получить значение этого поля, послав сообще ние TB_GETBUTTON.
Последнее поле iString используется только в тех случаях, когда кроме изобра жения кнопка имеет текстовую метку. В этом случае программист должен создать список текстовых строк панели инструментов, отправив сообщения TB_ADDSTRING.
Таким образом, прежде чем вызывать функцию CreateToolbarEx, следует объя вить массив структур типа TBBUTTON:
TBBUTTON tbb[NUM_BUTTONS];
и заполнить поля элементов массива подходящими значениями.
Вызов функции CreateToolbarEx
Функция CreateToolbarEx, создающая и инициализирующая панель инструмен тов, имеет следующий прототип:
HWND CreateToolbarEx( |
|
|
HWND hwnd, |
// дескриптор родительского окна |
|
DWORD ws, |
// стили панели инструментов |
|
UINT wID, |
// идентификатор панели инструментов |
|
int nBitmaps, |
// количество изображений кнопок |
|
HINSTANCE hBMInst, // |
дескриптор экземпляра приложения, содержащего |
|
|
// ресурс растрового образа панели инструментов |
|
UINT wBMID, |
// идентификатор ресурса растрового образа |
|
LPCTBBUTTON lpButtons, |
// адрес массива структур типа TBBUTTON |
|
int iNumButtons, |
// количество кнопок |
|
int dxButton, |
// ширина кнопок в пикселах |
|
int dyButton, |
// высота кнопок в пикселах |
|
