Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

лекции / Shchupak_Yu._Win32_API_Razrabotka_prilozheniy_dlya_Windows

.pdf
Скачиваний:
0
Добавлен:
11.02.2026
Размер:
13.15 Mб
Скачать

Основы применения

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.

388

Глава 8. Элементы управления общего пользования

 

 

Окно редактора панелей инструментов, показанное на рис. 8.2, разделено на три части. В верхней части окна находится изображение создаваемой панели ин струментов. В левой нижней части располагается изображение растра для теку щей кнопки в натуральную величину, а в правой нижней части — увеличенное изображение растра для текущей кнопки. Растр для каждой кнопки имеет разме ры 16 × 15 пикселов.

Для создаваемой кнопки нужно нарисовать картинку и определить идентифи катор кнопки.

Пользуясь инструментами рисования на панели Graphics, создайте нужный ри сунок на кнопке так же, как это делалось для пиктограмм. После этого сделайте двойной щелчок мышью на изображении кнопки в верхней части окна редактора. В открывшемся диалоговом окне Toolbar Button Properties введите нужный иденти фикатор кнопки. Если кнопка дублирует некоторый пункт меню, то идентифика тор кнопки должен быть таким же, как и у дублируемого пункта меню.

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

Рис. 8.3. Редактор панелей инструментов предлагает заготовку следующей кнопки

Щелкнув на новой кнопке мышью, можно перейти в режим редактирования этой кнопки, повторяя описанные выше действия.

Если текущая кнопка используется как кнопка разделитель между группами кнопок, то изображение на ней создавать не нужно. В качестве идентификатора кнопок разделителей в рассматриваемом примере будет использоваться имено ванная константа ID_SEP (вы можете использовать любое другое имя).

Если нужно изменить порядок размещения уже созданных кнопок, то это мож но сделать при помощи мыши, ухватившись за перемещаемую кнопку и перета щив ее в нужную позицию. Для удаления созданной ранее кнопки просто схвати те ее мышью и переместите за пределы изображения панели инструментов.

Вернемся к нашей программе. Используя описанную процедуру, определите растровый образ панели инструментов, как показано на рис. 8.4.

Рис. 8.4. Растровый образ панели инструментов

Растровый образ должен содержать 11 кнопок, причем две из них используют ся как кнопки разделители. Изображения для кнопок принято нумеровать слева

Элементы управления главного окна

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,

// высота кнопок в пикселах