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

лекции / Shchupak_Yu._Win32_API_Razrabotka_prilozheniy_dlya_Windows

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

Другие элементы управления

431

 

 

 

 

 

 

 

 

 

Код уведомления

Значение

Описание

 

 

 

 

 

TB_THUMBPOSITION

4

Пользователь отпустил кнопку мыши после перемещения

 

 

 

ползунка (это сообщение следует всегда после сообщения

 

 

 

TB_THUMBTRACK)

 

TB_THUMBTRACK

5

Ползунок перемещается с помощью мыши

 

TB_TOP

6

Нажата клавиша «Home» (VK_HOME) — ползунок устанав-

 

 

 

ливается в крайнее левое (верхнее) положение, соответ-

 

 

 

ствующее значению wMin

 

TB_BOTTOM

7

Нажата клавиша «End» (VK_END) — ползунок устанавли-

 

 

 

вается в крайнее правое (нижнее) положение, соответ-

 

 

 

ствующее значению wMax

 

 

 

 

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

Управляющие сообщения

Для управления регулятором предусмотрено несколько десятков сообщений, сим волические коды которых начинаются с префикса TBM_. В табл. 8.15 приведены некоторые из этих сообщений.

Таблица 8.15. Сообщения для управления элементом Slider

Сообщение

wParam

lParam

Описание

 

 

 

 

TBM_GETPOS

0

0

Возвращает текущую позицию ползунка

TBM_SETPOS

fRedraw

newPos

Устанавливает новую позицию ползунка.

 

 

 

Если fRedraw равно TRUE, регулятор

 

 

 

перерисовывается после этого

TBM_SETRANGE

fRedraw

MAKELPARAM

Устанавливает диапазон регулятора

 

 

(wMin, wMax)

 

TBM_SETTICFREQ

wFreq

0

Устанавливает шаг меток

TBM_SETLINESIZE

0

nLineSize

Устанавливает размер «строки»

TBM_SETPAGESIZE

0

nPageSize

Устанавливает размер «страницы»

 

 

 

 

Приложение TrackBar

Для демонстрации применения регуляторов разработаем приложение TrackBar, которое является клоном приложения ModelessDlg, рассмотренного в главе 7. При ложение ModelessDlg позволяло изменять цвет фона окна с помощью полос про крутки. В нашем новом приложении вместо полос прокрутки будут применены элементы управления Slider.

Создайте новый проект с именем TrackBar. Скопируйте из папки проекта

ModelessDlg (см. листинг 7.6) в папку проекта TrackBar файлы ModelessDlg.cpp,

ModelessDlg.rc и resource.h, скорректировав имена первых двух файлов заменой подстроки ModelessDlg на TrackBar. Также скопируйте из папки проекта ToolTip (ли стинг 8.4) файлы KWndEx.cpp и KWndEx.h. Все скопированные файлы нужно доба вить в состав проекта. Также к настройкам проекта на вкладке Link следует доба вить библиотеку comctl32.lib.

Откройте вкладку ResourceView в окне Workspace. В списке ресурсов откройте папку Dialogи вызовите редактор диалоговых окон двойным щелчком мыши на эле

432

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

 

 

менте IDD_MODELESS. Удалите все элементы управления с формы диалога. Размес тите три надписи и три элемента управления Slider, как показано на рис. 8.13.

Рис. 8.13. Форма диалога после размещения элементов управления

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

Элемент

ID

Caption

Свойства

 

 

 

 

Static text

IDC_STATIC_RED

Red

По умолчанию

Static text

IDC_STATIC_GREEN

Green

По умолчанию

Static text

IDC_STATIC_BLUE

Blue

По умолчанию

Slider

IDC_SLIDER_RED

Cтиль меток — Bottom/Right. Установлены

 

 

 

флажки Tick marks, Auto ticks, Border

Slider

IDC_SLIDER_GREEN

 

Slider

IDC_SLIDER_BLUE

Остальные свойства — по умолчанию

 

 

 

 

 

Отредактируйте исходный код в файле TrackBar.cpp, чтобы он соответствовал листингу 8.7.

Листинг 8.7. Проект TrackBar

//////////////////////////////////////////////////////////////////////

// TrackBar.cpp #include <windows.h> #include <stdio.h> #include <commctrl.h>

#include "KWndEx.h" #include "resource.h"

enum UserMsg { UM_CHANGE = WM_USER+1 };

HWND hModelessDlg;

RECT rcWork; // прямоугольник рабочей области

int rgb[3]; // интенсивность для R-, G-, B-компонентов цвета

BOOL CALLBACK ModelessDlgProc(HWND, UINT, WPARAM, LPARAM); void AdjustDlgPlace(HWND, HWND);

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //====================================================================

Другие элементы управления

433

 

 

 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

{

MSG msg;

KWndEx mainWnd("TrackBar", hInstance, nCmdShow, WndProc,

NULL, 100, 100, 400, 270);

while (GetMessage(&msg, NULL, 0, 0)) {

if (!IsDialogMessage(hModelessDlg, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg);

}

}

return msg.wParam;

}

//==================================================================== LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

/* Здесь такой же текст, как в листинге 7.6 */

}

//====================================================================

BOOL CALLBACK ModelessDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

static HWND hSliderRed; static HWND hSliderGreen; static HWND hSliderBlue; static HWND hStaticRed; static HWND hStaticGreen; static HWND hStaticBlue; char text[100];

switch (uMsg) { case WM_INITDIALOG:

//Определяем дескрипторы элементов управления Slider hSliderRed = GetDlgItem(hDlg, IDC_SLIDER_RED); hSliderGreen = GetDlgItem(hDlg, IDC_SLIDER_GREEN); hSliderBlue = GetDlgItem(hDlg, IDC_SLIDER_BLUE); hStaticRed = GetDlgItem(hDlg, IDC_STATIC_RED); hStaticGreen = GetDlgItem(hDlg, IDC_STATIC_GREEN); hStaticBlue = GetDlgItem(hDlg, IDC_STATIC_BLUE);

//Инициализация элементов управления Slider SendMessage(hSliderRed, TBM_SETRANGE, TRUE, MAKELONG(0, 255)); SendMessage(hSliderRed, TBM_SETTICFREQ, 32, 0); SendMessage(hSliderGreen, TBM_SETRANGE, TRUE, MAKELONG(0, 255)); SendMessage(hSliderGreen, TBM_SETTICFREQ, 32, 0); SendMessage(hSliderBlue, TBM_SETRANGE, TRUE, MAKELONG(0, 255)); SendMessage(hSliderBlue, TBM_SETTICFREQ, 32, 0);

//Вывод фона окна для начального состояния регуляторов SendMessage(hDlg, WM_HSCROLL, 0, 0);

продолжение

434

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

 

 

Листинг 8.7 (продолжение)

return TRUE;

case WM_HSCROLL:

// Получаем текущие позиции элементов управления Slider rgb[0] = SendMessage(hSliderRed, TBM_GETPOS, 0, 0); sprintf(text, "Red = %d", rgb[0]); SetWindowText(hStaticRed, text);

rgb[1] = SendMessage(hSliderGreen, TBM_GETPOS, 0, 0); sprintf(text, "Green = %d", rgb[1]); SetWindowText(hStaticGreen, text);

rgb[2] = SendMessage(hSliderBlue, TBM_GETPOS, 0, 0); sprintf(text, "Blue = %d", rgb[2]); SetWindowText(hStaticBlue, text);

// Сообщение родительскому окну об изменении цвета фона SendMessage(GetParent(hDlg), UM_CHANGE, 0, 0);

break;

}

return FALSE;

}

//==================================================================== void AdjustDlgPlace(HWND hParent, HWND hDlg) {

/* Здесь такой же текст, как в листинге 7.6 */

}

//////////////////////////////////////////////////////////////////////

Вблоке обработки сообщения WM_INITDIALOG всем трем регуляторам для уста новки диапазона и шага меток посылаются управляющие сообщения TBM_SETRANGE

иTBM_SETTICFREQ.

Вблоке обработки сообщения WM_HSCROLL мы узнаем текущую позицию для всех трех ползунков, отправляя трижды сообщение TBM_GETPOS. Полученные зна чения rgb[0], rgb[1] и rgb[2] используются для вывода текстовой информации в элементы управления hStaticRed, hStaticGreen и hStaticBlue, а также для формиро вания цвета фона окна. Цвет фона окна устанавливается оконной процедурой WndProc, когда она получает сообщение UM_CHANGE. Именно поэтому далее в коде программы следует отправка сообщения:

SendMessage(GetParent(hDlg), UM_CHANGE, 0, 0);

Рис. 8.14. Окно приложения TrackBar

Другие элементы управления

435

 

 

 

Код обработки сообщения UM_CHANGE, находящийся в теле оконной процеду ры WndProc, здесь не приведен, поскольку все тело процедуры повторяет текст, заимствованный из листинга 7.6.

На рис. 8.14 показан вид работающего приложения.

В настоящий момент ползунки регуляторов задают кремовый цвет фона окна.

Счетчик и поле с прокруткой

Элемент управления счетчик (Spin) реализован как две кнопки со стрелками, с помощью которых пользователь может увеличивать или уменьшать некоторое числовое значение. Значение, связанное со счетчиком, называется его текущей позицией.

Кроме этого счетчик можно ассоциировать с другим элементом управления, называемым приятельским окном (buddy window). Чаще всего таким окном явля ется окно редактирования. Комбинацию счетчика с окном редактирования назы вают также полем с прокруткой. Поле с прокруткой воспринимается пользовате лем как единый элемент управления. Содержимое окна редактирования в таком элементе отображает текущую позицию счетчика (рис. 8.15).

Рис. 8.15. Поле с прокруткой

Не имея ассоциированного с ним окна, счетчик функционирует как упро щенный вариант полосы прокрутки. Например, в элементе управления Tab control счетчик используется для осуществления доступа к дополнительным вкладкам (рис. 8.16).

Рис. 8.16. Элемент управления Spin в правом верхнем углу элемента управления Tab control

Создание счетчика

Счетчик можно создать несколькими способами. В первом способе используется вызов функции CreateWindowEx с указанием оконного класса UPDOWN_CLASS. Во вто ром способе вызывается функция CreateUpDownControl, создающая счетчик и одновременно определяющая его минимальную, максимальную и текущую по зиции, а также его приятельское окно.

Третий способ создания счетчика — при помощи редактора диалоговых окон на этапе визуального проектирования формы диалога. Элемент управления Spin выбирается с помощью мыши на панели инструментов Controls и просто помеща ется в нужное место формы диалога.

Затем надо вызвать окно свойств Spin Properties и на вкладке General в поле ID указать идентификатор элемента управления. На вкладке Styles, показанной на рис. 8.17, можно задать дополнительные свойства счетчика.

436

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

 

 

Рис. 8.17. Свойства элемента Spin на вкладке Styles

Список Orientation предназначен для выбора ориентации элемента управления. По умолчанию используется значение Vertical, но можно также установить значе ние Horizontal.

Список Alignment позволяет выбрать один из трех стилей размещения счет чика:

Alignment

Описание размещения

 

 

Unattached

Счетчик располагается рядом с ассоциированным окном (так, как вы поместили

 

его на форму диалога)

Left

Счетчик располагается в левой части ассоциированного окна (уменьшая тем

 

самым его клиентскую область)

Right

Счетчик располагается в правой части ассоциированного окна (уменьшая тем

 

самым его клиентскую область)

 

 

Флажки на вкладке Styles позволяют задать дополнительные параметры:

Флажок

Интерпретация

 

 

Auto buddy

Автоматический выбор в качестве ассоциированного окна ближайшего

 

предыдущего элемента управления в файле описания ресурсов

Set buddy integer

Вместе с предыдущим флажком определяет синхронную работу счетчика

 

и ассоциированного окна: любое изменение позиции счетчика сразу

 

отображается в ассоциированном окне. Аналогично при вводе

 

в ассоциированное окно допустимого целого числа оно устанавливает новую

 

позицию счетчика

No thousands

Если этот флажок выключен, в изображение десятичного числа после

 

каждых трех цифр вставляется пробел, если включен — пробел не

 

вставляется

Wrap

По умолчанию текущая позиция счетчика не изменяется, если пользователь

 

пытается перейти максимальное (при увеличении) или минимальное (при

 

уменьшении) значение. Если установлен данный флажок, то счетчик рабо-

 

тает как циклический. После максимального значения текущим становится

 

минимальное, и наоборот

Arrow keys

Поддерживается управление счетчиком с помощью клавиш «стрелка вверх»

 

и «стрелка вниз» (независимо от ориентации элемента управления)

 

 

Таким образом, при создании поля с прокруткой необходимо всегда выпол нять два правила. Во первых, элемент управления Spin нужно поместить на форму диалога сразу вслед за размещением приятельского окна редактирова ния. Во вторых, надо установить флажки Auto buddy и Set buddy integer. Отмет ка флажка Arrow keys установлена по умолчанию, и эту установку следует со хранить.

Другие элементы управления

437

 

 

 

Следует отметить высокий «интеллект» поля с прокруткой. Если пользова тель введет в окно редактирования числовое значение больше максимально допу стимого или меньше минимально допустимого, то позиция счетчика будет зафик сирована на соответствующей границе диапазона. Правда, пользователь узнает об этом только после очередного воздействия на стрелки счетчика.

При попытке ввести в окно редактирования нецифровые символы счетчик со храняет текущую позицию.

Сообщения от поля с прокруткой

При нажатии одной из стрелок элемент управления Spin посылает своему роди тельскому окну сообщение WM_VSCROLL или WM_HSCROLL (в зависимости от ори ентации счетчика), в котором младшее слово параметра wParam содержит код SB_THUMBPOSITION. Кроме того, счетчик посылает уведомляющее сообщение

UDN_DELTAPOS в форме сообщения WM_NOTIFY.

Обычно в приложении нет необходимости обрабатывать все сообщения. Час то бывает достаточно получить текущую позицию счетчика, обрабатывая сооб щение WM_VSCROLL или WM_HSCROLL. Это можно сделать, отправив элементу Spin управляющее сообщение UDM_GETPOS.

При непосредственном клавиатурном вводе нового числа в окно редактирова ния элемент Edit Box посылает родительскому окну сообщение WM_COMMAND с ко дом уведомления EN_CHANGE. Если вы хотите, чтобы приложение немедленно от реагировало на изменившуюся текущую позицию счетчика (а он отслеживает все изменения в приятельском окне), то предусмотрите обработку этого сообщения. Пример такой обработки приведен ниже в приложении Spinner.

Управляющие сообщения

Для управления счетчиком предусмотрено более двадцати сообщений, символи ческие коды которых начинаются с префикса UDM_. В табл. 8.16 приведены неко торые сообщения, чаще всего используемые в работе.

Таблица 8.16. Сообщения для управления элементом Spin

Сообщение

wParam

lParam

Описание

 

 

 

 

UDM_GETPOS

0

0

Возвращает текущую позицию счетчика

UDM_SETPOS

0

MAKELPARAM (nPos, 0)

Устанавливает новую позицию

 

 

 

счетчика

UDM_SETBASE

nBase

0

Устанавливает систему счисления.

 

 

 

nBase должно быть равно 10 или 16. По

 

 

 

умолчанию установлена десятичная

 

 

 

система счисления

UDM_SETRANGE

0

MAKELPARAM

Устанавливает минимальную и макси-

 

 

(nUpper, nLower)

мальную позиции для счетчика (в ин-

 

 

 

тервале –0x7FFF...0x7FFF)

 

 

 

 

Если после создания счетчика не определить его диапазон при помощи сооб щения UDM_SETRANGE, то будет использоваться диапазон по умолчанию со значе ниями nLower=100 и nUpper=0. В этом случае «стрелка вверх» вызывает уменьше ние значения счетчика, а «стрелка вниз» — увеличение значения. Чем обусловлен такой оригинальный диапазон по умолчанию, в котором максимум меньше, чем минимум, в справочных материалах MSDN не поясняется.

Рис. 8.18. Форма диалога после размещения элементов управления

438

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

 

 

Сообщения, перечисленные в табл. 8.16, работают с 16 разрядной версией эле мента управления Spin.

Библиотека Comctl32.dll, начиная с версии 4.71, поддерживает 32 разряд ную версию счетчика, который управляется сообщениями, приведенными в табл. 8.17.

Таблица 8.17. Сообщения для управления 32-разрядной версией элемента Spin

Сообщение

wParam

lParam

Описание

 

 

 

 

UDM_GETPOS32

0

(LPBOOL)

Возвращает текущую позицию счетчика.

 

 

pfError

pfError — указатель на булеву переменную,

 

 

 

которая получает значение FALSE, если

 

 

 

значение успешно получено, и TRUE —

 

 

 

в случае ошибки

UDM_SETPOS32

0

nPos

Устанавливает новую позицию счетчика

UDM_SETRANGE32

iLow

iHigh

Устанавливает минимальную и максимальную

 

 

 

позиции для счетчика в интервале от

 

 

 

– 0x7FFFFFFF äî 0x7FFFFFF

 

 

 

 

Приложение Spinner

Для демонстрации применения поля с прокруткой разработаем приложение Spinner, которое является модификацией приложения TrackBar, рассмотренного выше. При ложение TrackBar позволяло изменять цвет фона окна с помощью регуляторов.

В нашем новом приложении вместо каждого регулятора будет при менено поле с прокруткой.

Создайте новый проект с именем Spinner. Скопируйте из пап ки проекта TrackBar (см. листинг 8.7) в папку проекта Spinner фай лы с расширениями .cpp, .h и .rc, скорректировав их имена заме ной подстроки TrackBar на Spinner. Добавьте скопированные файлы в состав проекта. Также к настройкам проекта на вкладке Linkнадо добавить библиотеку comctl32.lib. Затем откройте вкладку ResourceView в окне Workspace. В списке ресурсов откройте папку Dialog и вызовите редактор диалоговых окон двойным щелчком мыши на элементе IDD_MODELESS.

Удалите элементы управления Slider с формы диалога. Раз местите вместо них три пары элементов (элемент Edit Box и ря дом элемент Spin), как показано на рис. 8.18. В каждой паре ука занных элементов счетчик помещается на форму диалога сразу после установки приятельского окна редактирования.

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

Элемент

ID

Свойства

 

 

 

Edit Box

IDC_EDIT_RED

Align text — Centered. Остальные свойства — по умолчанию

Edit Box

IDC_EDIT_GREEN

 

Edit Box

IDC_EDIT_BLUE

 

Spin

IDC_SPIN_RED

Alignment — Right. Установлены флажки Auto buddy, Set buddy

Spin

IDC_SPIN_GREEN

integer. Остальные свойства — по умолчанию

 

Spin

IDC_SPIN_BLUE

 

 

 

 

Приведите текст файла Spinner.cpp к виду, соответствующему листингу 8.8.

Другие элементы управления

439

 

 

 

Листинг 8.8. Проект Spinner

//////////////////////////////////////////////////////////////////////

// Spinner.cpp #include <windows.h> #include <stdio.h> #include <commctrl.h> #include "KWndEx.h" #include "resource.h"

enum UserMsg { UM_CHANGE = WM_USER+1 };

HWND hModelessDlg;

RECT rcWork; // прямоугольник рабочей области

int rgb[3]; // интенсивность для R-, G-, B-компонентов цвета

BOOL CALLBACK ModelessDlgProc(HWND, UINT, WPARAM, LPARAM); void AdjustDlgPlace(HWND, HWND);

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //==================================================================== int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPSTR lpCmdLine, int nCmdShow)

{

MSG msg;

KWndEx mainWnd("Spinner", hInstance, nCmdShow, WndProc,

NULL, 100, 100, 400, 260);

while (GetMessage(&msg, NULL, 0, 0)) {

if (!IsDialogMessage(hModelessDlg, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg);

}

}

return msg.wParam;

}

//==================================================================== LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

/* Здесь такой же текст, как в листинге 7.6 */

}

//====================================================================

BOOL CALLBACK ModelessDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

static HWND hSpinRed; static HWND hSpinGreen; static HWND hSpinBlue; static HWND hStaticRed; static HWND hStaticGreen; static HWND hStaticBlue;

switch (uMsg) { case WM_INITDIALOG:

// Определяем дескрипторы элементов управления Spin hSpinRed = GetDlgItem(hDlg, IDC_SPIN_RED); hSpinGreen = GetDlgItem(hDlg, IDC_SPIN_GREEN); hSpinBlue = GetDlgItem(hDlg, IDC_SPIN_BLUE);

продолжение

440

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

 

 

Листинг 8.8 (продолжение)

hStaticRed = GetDlgItem(hDlg, IDC_STATIC_RED);

hStaticGreen = GetDlgItem(hDlg, IDC_STATIC_GREEN);

hStaticBlue = GetDlgItem(hDlg, IDC_STATIC_BLUE);

// Инициализация элементов управления Spin SendMessage(hSpinRed, UDM_SETRANGE, TRUE, MAKELPARAM(255, 0));

SendMessage(hSpinGreen, UDM_SETRANGE, TRUE, MAKELPARAM(255, 0)); SendMessage(hSpinBlue, UDM_SETRANGE, TRUE, MAKELPARAM(255, 0)); return TRUE;

case WM_VSCROLL:

//Получаем текущие позиции элементов управления Spin rgb[0] = SendMessage(hSpinRed, UDM_GETPOS, 0, 0); rgb[1] = SendMessage(hSpinGreen, UDM_GETPOS, 0, 0); rgb[2] = SendMessage(hSpinBlue, UDM_GETPOS, 0, 0);

//Сообщение родительскому окну об изменении цвета фона SendMessage(GetParent(hDlg), UM_CHANGE, 0, 0);

break;

case WM_COMMAND:

//Обновление фона основного окна после ввода

//через приятельское окно редактирования

if (HIWORD(wParam) == EN_CHANGE) SendMessage(hDlg, WM_VSCROLL, 0, 0);

break;

}

return FALSE;

}

//==================================================================== void AdjustDlgPlace(HWND hParent, HWND hDlg) {

/* Здесь такой же текст, как в листинге 7.6 */

}

//////////////////////////////////////////////////////////////////////

Использование поля с прокруткой, как видите, очень просто. Обратите внима ние на обработку сообщения WM_COMMAND с кодом уведомления EN_CHANGE. Мы отправляем диалоговому окну сообщение WM_VSCROLL, чтобы приложение немед ленно отреагировало на изменившееся вследствие изменения текста в приятельс ком окне состояние счетчика.

На рис. 8.19 показано окно работающего приложения.

Рис. 8.19. Приложение Spinner. С помощью полей прокрутки задан голубой цвет фона окна