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

лекции / Shchupak_Yu._Win32_API_Razrabotka_prilozheniy_dlya_Windows

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

Использование других элементов управления

331

 

 

 

Хотелось бы сделать так, чтобы при использовании мыши фокус ввода также переходил автоматически с одной кнопки на другую, как только курсор мыши наводится на эту кнопку. К сожалению, Windows не обеспечивает такого мыши ного интерфейса, поэтому в программе эта проблема решается при помощи обра ботки сообщения WM_SETCURSOR.

Сообщение WM_SETCURSOR посылается активному окну приложения при лю бом перемещении курсора мыши. В нашей программе положение курсора мыши отслеживается только при появлении на экране диалогового окна IDD_ABOUT. Ког да функция AboutDlgProc получает сообщение WM_SETCURSOR, его параметр wParam содержит дескриптор того окна, в котором в данный момент находится курсор. Так как дескрипторы кнопок hBtnOk и hBtnHelp известны, то не составляет труда зафиксировать момент попадания курсора на ту или иную кнопку и вызвать фун кцию SetFocus, если кнопка в этот момент не имеет фокуса ввода.

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

На рис. 7.18 показан вид диалогового окна About DlgDemo2 с пассивным состо янием кнопки OK.

Рис. 7.18. Диалоговое окно About DlgDemo2

Если вы хотите увидеть кнопку OK во всех трех состояниях, да еще и в цветном исполнении, вам придется откомпилировать проект DlgDemo2 и запустить програм му на вашем компьютере.

Флажки

Флажок (Check box) представляет собой маленькое квадратное окно с сопроводи тельным текстом, который обычно размещается справа от этого окна. Флажок действует как двухпозиционный переключатель. Один щелчок вызывает появле ние контрольной отметки (галочки), а другой щелчок приводит к ее исчезнове нию. Соответствующие состояния элемента управления определяют также с по мощью терминов «флажок установлен» и «флажок сброшен».

Этот элемент управления уже не раз использовался при работе со средой Visual Studio. Например, свойства элементов управления в соответствующих окнах за давались как раз с помощью флажков.

Сам флажок тоже обладает набором свойств, и для их определения вызыва ется окно свойств Check Box Properties. На рис. 7.19 показана вкладка Styles в этом окне.

332

Глава 7. Диалоговые окна

 

 

Рис. 7.19. Вкладка Styles в окне свойств флажка

Флажок Auto установлен по умолчанию. Это очень важное свойство. Оно зас тавляет элемент управления отслеживать все щелчки мышью, и при этом элемент управления сам включает или выключает контрольную отметку. Поэтому вы мо жете об этом не беспокоиться. Если же выключить свойство Auto, то программа должна при обработке сообщения WM_COMMAND, поступающего от флажка, вызы вать функцию CheckDlgButton для установки или снятия отметки.

Флажок Left text ставится, если вы хотите поместить сопровождающий текст слева от квадратного окошка.

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

Свойство Push-like изменяет внешний вид флажка так, что он выглядит как нажимаемая кнопка. Вместо установки галочки эта кнопка переходит в нажатое состояние и остается в нем до следующего щелчка мышью.

Флажок Flat применяется, если нужно использовать плоское изображение квад ратного окошка.

Флажок Icon или Bitmap используется, чтобы вместо текста рядом с окошком поместить какой нибудь рисунок. Но так делают очень редко, поэтому здесь эти параметры не будут рассматриваться детально.

Несмотря на то что с включенным свойством Auto флажок сам управляет уста новкой и снятием отметки, все же при первом появлении диалогового окна на экране иногда требуется программная инициализация состояния элемента управ ления. Для этого используется функция CheckDlgButton:

BOOL CheckDlgButton

(

HWND hDlg,

// дескриптор диалогового окна

int nIDButton,

// идентификатор кнопки

UINT uCheck

// состояние отметки

);

 

Параметр uCheck может принимать одно из значений, указанных в табл. 7.4.

Таблица 7.4. Возможные значения параметра uCheck

Константа

Шестнадцатеричное значение

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

 

 

 

BST_UNCHECKED

0x0000

Снять отметку

BST_CHECKED

0x0001

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

BST_INDETERMINATE

0x0002

Установить неопределенное состоя-

 

 

ние (state to grayed). Используется

 

 

только для кнопок, имеющих

 

 

свойство Tri-state

 

 

 

Использование других элементов управления

333

 

 

 

В окнах диалога элементы управления «флажок» используются обычно для выбора независимых параметров.

Переключатели

Переключатель (Radio button) похож на флажок, но имеет круглую форму, а не квад ратную. Жирная точка внутри кружка показывает, что переключатель включен.

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

Устанавливая свойства переключателя в окне свойств Radio Button Properties, проследите, чтобы остался установленным флажок Auto, обеспечивающий авто матическую установку и снятие отметки для переключателя. Если флажок Auto снят, то программа должна при обработке сообщения WM_COMMAND, поступающе го от переключателя, вызвать функцию CheckRadioButton для установки или сня тия отметки.

Кроме того, для первого переключателя в группе связанных взаимоисключаю щих переключателей нужно обязательно установить флажок Group на вкладке General. Все последующие переключатели (в файле описания ресурсов) со сбро шенным флажком Group считаются принадлежащими к этой группе. Если в пос ледовательности описаний элементов управления встречается переключатель с установленным флажком Group, считается, что он начинает новую группу эле ментов Radio button.

Для группировки флажков или переключателей важен порядок их описания

вфайле описания ресурсов. Не забывайте, что определения элементов заносятся

вфайл описания ресурсов по мере размещения их на форме диалога. Впрочем, среда Visual Studio позволяет легко изменить этот порядок (этот вопрос рассмат ривается ниже в разделе «Клавиатурный интерфейс и порядок обхода элементов управления»).

Хотя с установленным флажком Auto переключатель сам управляет установ кой и снятием отметки, при первом появлении диалогового окна может потребо ваться программная инициализация состояния переключателя с помощью функ

ции CheckRadioButton:

BOOL CheckRadioButton

(

HWND hDlg,

// дескриптор диалогового окна

int nIDFirstButton, // идентификатор первой кнопки в группе

int nIDLastButton,

// идентификатор последней кнопки в группе

int nIDCheckButton

// идентификатор выбранной кнопки

);

 

Групповая рамка

Групповая рамка (Group box) — это прямоугольная рамка с надписью, внутри ко торой помещается некоторый набор элементов управления.

Групповая рамка является исключением среди элементов класса BUTTON (см. табл. 7.1). Она не обрабатывает ни сообщения от клавиатуры, ни сообщения от мыши. Она не посылает своему родительскому окну сообщение WM_COMMAND. В ос новном групповая рамка применяется как элемент оформления интерфейса, благо даря которому он становится более удобным и дружественным для пользователя.

334

Глава 7. Диалоговые окна

 

 

Часто групповая рамка используется для объединения в одну группу несколь ких флажков или переключателей. Причем в первом случае состояния флажков в группе не зависят друг от друга. Состояния переключателей, объединенных в груп пу, взаимозависимы, и только один из них может иметь включенное состояние.

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

Пример использования групповой рамки, флажков и переключателей

Рассмотрим применение групповой рамки, флажков и переключателей на приме ре разработки приложения DlgDemo3, являющегося модификацией приложения

DlgDemo1.

Цель модификации — сделать более удобным интерфейс пользователя в этой программе. Дело в том, что для выбора вида фигуры и задания ее цвета пользова тель приложения DlgDemo1 должен трижды выбирать пункт меню DrawShape. Пер вый раз — с командой Shape для выбора вида фигуры, второй раз — с командой Color для установки флажков Red, Green, Blue и третий раз — с командой Color для выбора одного из переключателей, Dark, Medium, Light. Было бы, наверное, удоб нее, если бы по команде DrawShape вызывалось диалоговое окно, содержащее груп пы опций для установки всех атрибутов рисования.

Сказано — сделано. Создайте новый проект с именем DlgDemo3. Скопируйте из папки проекта DlgDemo1 в папку проекта DlgDemo3 файлы с расширениями .cpp, .h и .rc, скорректировав их имена заменой DlgDemo1 на DlgDemo3. Включите эти фай лы в состав проекта. Скопируйте также файл Butterfly.bmp.

Модификация меню в приложении DlgDemo3

В окне Workspace перейдите на вкладку ResourceView, откройте в иерархическом списке папку Menu и щелчком на элементе IDR_MENU1 вызовите редактор меню. Откройте окно свойств Menu Item Properties для пункта Draw shape. В этом окне нужно сбросить флажок Pop-up. После щелчка мышью на нем будет отображено окно с предупреждением, что это действие уничтожит все пункты подменю Draw shape (рис. 7.20).

Рис. 7.20. Предупреждение редактора меню при попытке снять флажок Pop-up

Подтвердите серьезность ваших намерений, нажав кнопку OK. Окно исчезнет, а текстовое поле ID станет доступным для ввода информации. Введите в него иден тификатор IDM_DRAW_SHAPE. После этого закройте окно свойств пункта Draw Shape.

Использование других элементов управления

335

 

 

 

Разработка шаблона диалога

Вы уже умеете делать это. Создайте заготовку шаблона нового диалогового окна. Для этого выполните команду Insert Resource, укажите тип ресурса Dialogи нажмите кнопку New. Затем вызовите окно свойств диалога, дважды щелкнув мышью на форме диалога. В текстовом поле ID укажите идентификатор IDD_SHAPE_PARAM. Перейдите на вкладку Styles и отключите отметку флажка Title bar, после чего закройте окно свойств диалога.

Увеличьте примерно вдвое размер формы по вертикали. Выделите группу из двух элементов, щелкнув на кнопках OK и Cancel. Применив команду Layout Arrange Buttons Bottom, переместите эти кнопки на нижнюю границу формы.

Теперь разместите на форме три групповые рамки. Внутри первой рамки нуж но расположить три переключателя, внутри второй рамки — три флажка, внутри третьей рамки — снова три переключателя, как показано на рис. 7.21.

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

Впроцессе размещения задайте свойства элементов управления в соответствии

стабл. 7.5. Рекомендации по определению состояния флажков Tab stop и Group приводятся ниже в разделе «Клавиатурный интерфейс и порядок обхода элемен тов управления».

Таблица 7.5. Свойства элементов управления на форме диалога IDD_SHAPE_PARAM

Тип элемента

ID

Caption

Флажок Tab stop

Флажок Group

 

 

 

 

 

Group box

IDC_STATIC

Shape

Сброшен

Сброшен

Radio button

ID_RECTANGLE

Rectangle

Установлен

Установлен

Radio button

ID_RHOMB

Rhomb

Сброшен

Сброшен

Radio button

ID_ELLIPSE

Ellipse

Сброшен

Сброшен

Group box

IDC_STATIC

Color components

Сброшен

Сброшен

Check box

ID_RED

Red

Установлен

Сброшен

Check box

ID_GREEN

Green

Сброшен

Сброшен

Check box

ID_BLUE

Blue

Сброшен

Сброшен

Group box

IDC_STATIC

Color intensity

Сброшен

Сброшен

 

 

 

 

 

 

 

 

 

продолжение

336

 

 

Глава 7. Диалоговые окна

 

 

 

 

Таблица 7.5 (продолжение)

 

 

 

 

 

 

 

 

Тип элемента

ID

Caption

Флажок Tab stop

Флажок Group

 

 

 

 

 

Radio button

ID_DARK

Dark

Установлен

Установлен

Radio button

ID_MEDIUM

Medium

Сброшен

Сброшен

Radio button

ID_LIGHT

Light

Сброшен

Сброшен

 

 

 

 

 

Сохраните подготовленный шаблон в файле описания ресурсов при помощи кнопки Save на панели инструментов Visual Studio.

Коррекция шаблона диалога IDD_ABOUT

В окне Workspace перейдите на вкладку ResourceView и откройте шаблон диалога IDD_ABOUT. После этого откройте диалоговое окно Dialog Properties и в поле Caption введите текст About DlgDemo3. Затем нужно открыть окно свойств Text Properties для элемента управления IDC_STATIC_1 и заменить текст DlgDemo1 на строку DlgDemo3.

Модификация исходного кода

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

Листинг 7.3. Проект DlgDemo3

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

// DlgDemo3.cpp #include <windows.h> #include <stdio.h> #include "KWnd.h" #include "resource.h"

#define W

200

// ширина фигуры

#define H

140

// высота фигуры

enum ShapeSize { MAX, MIN };

typedef struct {

 

int id_shape;

// идентификатор фигуры

BOOL fRed;

// компонент красного цвета

BOOL fGreen;

// компонент зеленого цвета

BOOL fBlue;

// компонент синего цвета

int id_bright;

// идентификатор яркости цвета

} ShapeData;

 

ShapeData shapeData;

// Глобальная структура для обмена данными

 

// между ShapeParamDlgProc и WndProc

BOOL CALLBACK ShapeParamDlgProc(HWND, UINT, WPARAM, LPARAM); BOOL CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

//==================================================================== int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPSTR lpCmdLine, int nCmdShow)

{

MSG msg;

KWnd mainWnd("DlgDemo3", hInstance, nCmdShow, WndProc, MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);

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

Использование других элементов управления

337

 

 

 

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return msg.wParam;

}

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

{

static HINSTANCE hInst; HDC hDC;

PAINTSTRUCT ps; RECT rect;

static HMENU hMenu; // дескриптор главного меню int x0, y0, x1, y1, x2, y2;

POINT pt[4];

static ShapeSize shapeSize = MIN; static BOOL bShow = TRUE;

static HBRUSH hBrush, hOldBrush;

char* itemResizeName[2] = { "Decrease!", "Increase!"};

int intensity[3] = { 85, 170, 255 }; // интенсивность RGB-компонентов цвета int brightness;

switch (uMsg)

{

case WM_CREATE:

hInst = GetModuleHandle(NULL); hMenu = GetMenu(hWnd);

SetMenuDefaultItem(GetSubMenu(hMenu, 0), IDM_OPEN, FALSE); CheckMenuRadioItem(GetSubMenu(hMenu, 1), IDM_SHOW_SHAPE,

IDM_HIDE_SHAPE, IDM_SHOW_SHAPE, MF_BYCOMMAND); shapeData.id_shape = ID_RECTANGLE; shapeData.id_bright = ID_DARK;

break;

case WM_COMMAND:

switch (LOWORD(wParam))

{

/*

код обработки для команд IDM_OPEN, IDM_CLOSE, ... , IDM_RESIZE – из листинга 6.1

*/

case IDM_ABOUT:

DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutDlgProc); break;

case IDM_DRAW_SHAPE:

DialogBox(hInst, MAKEINTRESOURCE(IDD_SHAPE_PARAM), hWnd, ShapeParamDlgProc);

break;

default:

break;

}

продолжение

338

Глава 7. Диалоговые окна

 

 

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

InvalidateRect(hWnd, NULL, TRUE);

break;

case WM_PAINT:

/* Код обработки сообщения WM_PAINT из листинга 6.1 */

break;

case WM_DESTROY: PostQuitMessage(0); break;

default:

return DefWindowProc(hWnd, uMsg, wParam, lParam);

}

return 0;

}

//==================================================================== BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,

LPARAM lParam)

{

/* Текст функции - из листинга 7.1 (модифицированный вариант) */

}

//==================================================================== BOOL CALLBACK ShapeParamDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,

LPARAM lParam)

{

static ShapeData shapeDataNew;

switch (uMsg) { case WM_INITDIALOG:

CheckRadioButton(hDlg, ID_RECTANGLE, ID_ELLIPSE, shapeData.id_shape); CheckRadioButton(hDlg, ID_DARK, ID_LIGHT, shapeData.id_bright); CheckDlgButton(hDlg, ID_RED, shapeData.fRed);

CheckDlgButton(hDlg, ID_GREEN, shapeData.fGreen); CheckDlgButton(hDlg, ID_BLUE, shapeData.fBlue); shapeDataNew = shapeData;

return TRUE;

case WM_COMMAND:

switch (LOWORD(wParam)) { case ID_RECTANGLE:

case ID_RHOMB: case ID_ELLIPSE:

shapeDataNew.id_shape = LOWORD(wParam); return TRUE;

case ID_RED:

shapeDataNew.fRed = ~shapeDataNew.fRed; return TRUE;

case ID_GREEN:

shapeDataNew.fGreen = ~shapeDataNew.fGreen;

Использование других элементов управления

339

 

 

 

return TRUE; case ID_BLUE:

shapeDataNew.fBlue = ~shapeDataNew.fBlue; return TRUE;

case ID_DARK: case ID_MEDIUM: case ID_LIGHT:

shapeDataNew.id_bright = LOWORD(wParam); return TRUE;

case IDOK:

shapeData = shapeDataNew; EndDialog(hDlg, TRUE); return TRUE;

case IDCANCEL: EndDialog(hDlg, FALSE); return TRUE;

}

break;

}

return FALSE;

}

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

Конечно, следует обратить внимание на изменения, появившиеся в коде про граммы. Так, структурная переменная shapeData теперь стала глобальной, хотя раньше она объявлялась в теле функции WndProc. Это необходимо для обмена дан ными между WndProc и диалоговой процедурой ShapeParamDlgProc. Поля перемен ной shapeData хранят текущие параметры рисуемой фигуры. В момент запуска про граммы поля глобальной структуры инициализируются нулями.

Также появилась новая функция ShapeParamDlgProc, которая является диалого вой процедурой для окна IDD_SHAPE_PARAM. Обрабатывая сообщение WM_INITDIALOG, эта функция инициализирует элементы управления диалогового окна. Ранее ука зывалось, что если для флажка или переключателя установлено свойство Auto, то эти элементы сами управляют установкой и снятием своих меток, реагируя на щелч ки пользователя. Но при первом появлении диалогового окна на экране программа должна позаботиться об установке меток в соответствии с текущими параметрами фигуры, сохраняемыми в переменной shapeData. Для этого вызываются функции

CheckRadioButton и CheckDlgButton.

Завершив инициализацию, функция ShapeParamDlgProc копирует значение пе ременной shapeData в локальную переменную shapeDataNew. В полях переменной shapeDataNew записываются все изменения состояний флажков и переключателей в блоке обработки сообщения WM_COMMAND. Если диалоговое окно закрывается щелчком на кнопке OK с идентификатором IDOK, то перед его закрытием перемен ной shapeData присваивается значение shapeDataNew. Если диалоговое окно закры вается щелчком на кнопке Cancel с идентификатором IDCANCEL, то переменная shapeData сохраняет то значение, которое она имела до вызова диалогового окна.

В оконной процедуре WndProc обработка сообщения WM_COMMAND расширена новой ветвью:

case IDM_DRAW_SHAPE:

DialogBox(hInst, MAKEINTRESOURCE(IDD_SHAPE_PARAM), hWnd, ShapeParamDlgProc);

break;

340

Глава 7. Диалоговые окна

 

 

В этом блоке кода при помощи функции DialogBox вызывается диалоговое окно

IDD_SHAPE_PARAM.

Откомпилировав этот проект, проверьте работу приложения DlgDemo3.

Клавиатурный интерфейс и порядок обхода элементов управления

Система Windows обеспечивает удобный клавиатурный интерфейс для доступа к элементам управления в диалоговом окне. Перемещение между элементами уп равления осуществляется при помощи клавиши Tab либо при помощи клавиш стрелок. Нажатие клавиши Tab перемещает фокус ввода на следующий элемент управления, который имеет стиль WS_TABSTOP (или для которого установлено свой ство Tab stop), в соответствии с установленным порядком обхода. Порядок обхода элементов управления соответствует последовательности определений этих эле ментов в файле описания ресурсов.

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

Чтобы обеспечить привычный для пользователя клавиатурный интерфейс, следует придерживаться несложных правил. Первому элементу управления в груп пе нужно назначать свойство Tab stop, а если это группа переключателей, то еще и свойство Group. У остальных элементов в группе оба свойства, Tab stop и Group, должны быть выключенными.

Рис. 7.22. Порядок обхода элементов управления в окне диалога IDD_SHAPE_PARAM