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

лекции / Shchupak_Yu._Win32_API_Razrabotka_prilozheniy_dlya_Windows

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

Модальный диалог

311

 

 

 

Переместите кнопку OK в правый нижний угол окна. Элементы управления перемещаются на форме или мышью, или при помощи клавиш стрелок. В случае использования клавиатуры элемент предварительно нужно выделить.

Добавление элемента управления Рисунок

Предположим, что рисунок, который нужно добавить на форму диалога, находит ся в файле Butterfly.bmp и содержит изображение размером 64 ×90 пикселов, пока занное на рис. 7.4.

Рис. 7.4. Растровый образ в файле Butterfly.bmp

Вы можете взять готовый рисунок, если загрузите исходный код проекта DlgDemo1 из файлов, размещенных на сайте издательства «Питер» (www.piter.com). Впрочем, можно подготовить при помощи любого графического редактора дру гой рисунок примерно таких же размеров. Файл с рисунком должен находиться в папке проекта.

Прежде чем поместить растровый образ на форму диалога, нужно сначала вклю чить его в состав ресурсов проекта. Эта процедура рассматривалась в пятой главе. Добавьте к создаваемому приложению ресурс растрового образа в режиме Импорт, связав ресурс с файлом Butterfly.bmp и назначив ему идентификатор IDB_BUTTERFLY.

Подготовительная работа завершена, и теперь можно приступить к размеще нию рисунка на форме диалога. Щелкните мышью на кнопке Picture, которая на ходится на панели инструментов Controls. Повторите щелчок мышью в том месте формы диалога, куда вы хотите добавить этот элемент (рис. 7.5).

Рис. 7.5. Размещение элемента управления Picture

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

ПРИМЕЧАНИЕ

Обычно идентификаторы элементов управления начинаются с префикса IDC_ (ID for a control). Впрочем, иногда мы будем отступать от этого правила и назначать для отдельных элементов управления идентификаторы, начинающиеся с префикса ID_.

312

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

 

 

Ðèñ. 7.6. Îêíî Picture Properties

Введите в поле ID идентификатор IDC_STATIC_BFLY. В открывающемся списке Type выберите значение Bitmap. После этого станет доступным комбинированный спи сок Image. В нем пока можно найти только один идентификатор IDB_BUTTERFLY, по скольку других растровых образов в файле описания ресурсов пока что нет. Имен но этот идентификатор и нужно выбрать в списке. Значения остальных свойств на вкладке General оставьте такими, какими они применяются по умолчанию.

Стоит обратить внимание на включенную отметку флажка Visible. Она указыва ет, что элемент управления по умолчанию является видимым. В ходе выполнения приложения вы можете скрыть любой элемент управления при помощи функции ShowWindow, передав ей в первом параметре дескриптор элемента управления, а во втором параметре — константу SW_HIDE.

Теперь перейдите на вкладку Styles и включите отметку флажка Sunken, чтобы создать «вдавленную» рамку вокруг элемента управления. Значения остальных свойств на вкладке Styles следует оставить неизменными. Заметим, что если уста новить флажок Notify, то элемент управления будет посылать родительскому окну нотификационные сообщения STN_CLICKED и STN_DBLCLK, когда пользователь де лает одинарный или двойной щелчок мышью на элементе управления. Закройте окно Picture Properties.

После этих действий элемент управления Picture будет отображать картинку с бабочкой, как показано на рис. 7.7. Но прямоугольной рамки элемента Static в этот момент еще нет.

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

Добавление элементов управления Надпись

Займемся информационными надписями. Щелкните мышью на кнопке Static Text и повторите щелчок на форме диалога правее от картинки. На форме появится прямоугольная рамка элемента Static, как показано на рис. 7.7.

Модальный диалог

313

 

 

 

Растяните мышью ограничивающий прямоугольник элемента Static так, что бы его размеры позволяли ввести нужный текст. Двойным щелчком мыши вызо вите окно свойств элемента управления (рис. 7.8).

Ðèñ. 7.8. Îêíî Text Properties

Редактор диалога присваивает по умолчанию всем элементам Static Text иден тификатор IDC_STATIC. Если в ходе выполнения программы не требуется изменять атрибуты элемента управления (например, его местоположение или значение свой ства Caption), то можно оставить значение идентификатора по умолчанию. В про тивном случае необходимо назначить элементу уникальный идентификатор.

Замените идентификатор в поле ID на значение IDC_STATIC_1, так как в ходе работы программы будут изменяться некоторые атрибуты этого элемента.

Поле Caption содержит текстовую строку, которая будет отображаться внутри ограничивающего прямоугольника элемента Static Text. В строке могут использо ваться управляющие символы \t (табуляция) и \n (перевод строки).

Введите в поле Caption текст DlgDemo1. Теперь перейдите на вкладку Styles (рис. 7.9).

Рис. 7.9. Свойства элемента Static Text на вкладке Styles

Открывающийся список Align text позволяет задать выравнивание текста по горизонтали. Можно использовать значение Left (по умолчанию), Center или Right. Флажок Center vertically задает центрирование текста по вертикали. Способы вы равнивания указываются по отношению к ограничивающему прямоугольнику.

Флажок No prefix влияет на интерпретацию символа &. Если этот флажок уста новлен, то символ & отображается. В противном случае символ & предшествует подчеркиваемому символу, что позволяет задавать «горячую» клавишу.

Флажок Border создает рамку вокруг элемента управления.

Выберите значение Center из списка Align text и установите флажки Center vertically и Border. Закройте окно Text Properties.

Теперь форма диалога примет вид, показанный на рис. 7.10.

Осталось добавить еще две информационные надписи. Для этого надо повто рить описанные выше действия и поместить два элемента управления Static Text

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

ниже надписи DlgDemo1. Свойства этих элементов определите в соответствии со следующей таблицей:

ID

Caption

Align text

Установлены флажки

 

 

 

 

IDC_STATIC

Version 1.0

Center

Center vertically

IDC_STATIC

Copyright: Finesoft Corporation, 2005.

Center

Center vertically

 

 

 

 

После этого диалоговое окно примет примерно такой вид, какой показан на рис. 7.11.

Рис. 7.10. Форма диалога после установки элемента IDC_STATIC_1

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

Но что то в этой форме вызывает смутное раздражение. Попытаемся в этом разобраться…

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

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

Интегрированная среда Visual Studio содержит удобный инструмент для ре шения таких задач. Когда программист работает с редактором диалоговых окон, в главном меню Visual Studio появляется пункт Layout, выбор которого вызывает соответствующее подменю. Команды выравнивания из подменю Layout применя ются к группе выделенных элементов.

Модальный диалог

315

 

 

 

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

После выделения группы элементов вызывается нужная команда. Например, если необходимо сделать одинаковыми размеры элементов, то выбирается команда Make Same Size, а всплывающее каскадное меню предоставляет на выбор варианты Width (по ширине), Height (по высоте), Both (по ширине и высоте одновременно).

Для выравнивания позиционирования элементов выбирается команда Align. Чаще всего при работе с этой командой используются параметры Left (по левой границе) и Right (по правой границе).

Команда Space Evenly позволяет выровнять промежутки между элементами при размещении по горизонтали (опция Across) или при размещении по вертикали (опция Down). Команда Center in Dialog перемещает всю группу выделенных эле ментов, центрируя ее либо по горизонтали (опция Horizontal), либо по вертикали (опция Vertical).

Команда Arrange Buttons применяется только для кнопок и позволяет разме щать группу кнопок либо по правому краю, либо по нижнему краю формы диало гового окна.

Воспользуемся инструментом Layout для улучшения внешнего вида создавае мого диалогового окна в приложении DlgDemo1.

Применим команду Make Same Size, чтобы сделать одинаковой ширину всех элементов Static Text, команду Align — для позиционирования всех элементов по левому краю надписи DlgDemo1 и команду Space Evenly — для выравнивания про межутков между элементами по вертикали. На рис. 7.12 показан результат этих манипуляций.

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

Итак, мы завершили проектирование шаблона диалога.

Ради любопытства посмотрим на свойства кнопки OK, которую нам «подарил» редактор диалога. На рис. 7.13 показано окно свойств этого элемента управления, которое, как обычно, вызывается двойным щелчком мыши.

Обратите внимание на включенную отметку флажка Tab stop. Благодаря этому элемент управления получает стиль WS_TABSTOP, означающий, что кнопка OK мо жет получать фокус ввода при работе с диалоговым окном через клавиатурный интерфейс. Этот способ общения пользователя с окном мы рассмотрим позже.

316

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

 

 

Рис. 7.13. Свойства кнопки OK

Если перейти на вкладку Styles, то можно увидеть, что на ней установлен фла жок Default button. Он определяет данную кнопку как кнопку, применяемую по умолчанию. Это означает, что когда ни один из элементов управления не имеет фокуса ввода, то клавиатурный ввод переправляется именно этой кнопке.

Определение диалоговой процедуры и вызов диалога

Реализацию этих этапов рассмотрим на примере исходного кода приложения

DlgDemo1.

Файл DlgDemo1.cpp, входящий в состав проекта, в настоящий момент является точной копией файла MenuDemo1.cpp из листинга 6.1. Текст данного файла нужно отредактировать так, чтобы он соответствовал листингу 7.1.

Листинг 7.1. Проект DlgDemo1

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

// DlgDemo1.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;

 

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("DlgDemo1", hInstance, nCmdShow, WndProc, MAKEINTRESOURCE(IDR_MENU1), 100, 100, 400, 300);

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

Модальный диалог

317

 

 

 

DispatchMessage(&msg);

}

return msg.wParam;

}

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

{

static HINSTANCE hInst;

/* Объявления остальных локальных переменных - из листинга 6.1 */

switch (uMsg)

{

case WM_CREATE:

hInst = GetModuleHandle(NULL);

/* Остальной код обработки сообщения WM_CREATE - из листинга 6.1 */ 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;

default:

break;

}

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;

}

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

// Диалоговая процедура

продолжение

318

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

 

 

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

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

{

switch (uMsg) {

case WM_INITDIALOG: return TRUE;

case WM_COMMAND:

switch (LOWORD(wParam)) { case IDOK:

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

}

break;

}

return FALSE;

}

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

Диалоговая процедура

Диалоговая процедура AboutDlgProc во многом напоминает оконную процедуру. Она должна иметь спецификатор CALLBACK, поскольку вызывается операционной системой. Имя функции может быть произвольным, однако сложилась традиция завершать это имя суффиксом DlgProc.

Функция AboutDlgProc принимает такой же набор параметров, что и обычная оконная процедура. Но некоторые различия между диалоговой процедурой и окон ной процедурой все же есть:

Оконная процедура возвращает значение типа LRESULT, а диалоговая процеду ра — значение типа BOOL.

Если оконная процедура не обрабатывает какое то сообщение, то она вызыва ет DefWindowProc. Если диалоговая процедура не обрабатывает какое то сооб щение, то она возвращает значение FALSE. Если же сообщение обрабатывается диалоговой процедурой, то она возвращает значение TRUE.

Диалоговая процедура не обрабатывает сообщение WM_CREATE. Вместо это го она выполняет инициализацию при обработке специального сообщения

WM_INITDIALOG.

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

Сообщение WM_INITDIALOG является первым сообщением, которое получает диа логовая процедура. Если после обработки этого сообщения процедура возвращает значение TRUE, то Windows помещает фокус ввода на первое дочернее окно элемен та управления, которое имеет стиль WS_TABSTOP. В разрабатываемом диалоговом окне первым элементом управления со стилем WS_TABSTOP является кнопка OK. В то же время при обработке сообщения WM_INITDIALOG диалоговая процедура может ис пользовать функцию SetFocus для того, чтобы установить фокус на какой то другой элемент управления. Но тогда она должна вернуть значение FALSE.

Блок обработки сообщения WM_INITDIALOG является самым удобным местом для инициализации элементов управления, если в этом есть необходимость.

Модальный диалог

319

 

 

 

Основным сообщением, обрабатываемым в диалоговой процедуре, является WM_COMMAND. Напомним, что если источником сообщения WM_COMMAND является элемент управления, то младшее слово параметра wParam содержит идентифика тор элемента управления, старшее слово wParam содержит код уведомления, а па раметр lParam — дескриптор элемента управления.

В нашей программе диалоговая процедура должна обрабатывать только два сообщения WM_COMMAND. Источником первого сообщения является кнопка OK с идентификатором IDOK. Сообщение инициируется, когда пользователь щелкает на кнопке мышью или нажимает клавишу пробела или Enter .

Источником второго сообщения является кнопка закрытия диалогового окна, находящаяся в правой части его заголовка и имеющая идентификатор IDCANCEL. Это сообщение появляется, когда пользователь щелкает мышью на кнопке с кре стиком или нажимает сочетание клавиш Alt+F4.

Обрабатывая оба эти сообщения, диалоговая процедура вызывает функцию EndDialog, после чего возвращает значение TRUE. Для всех остальных сообщений диалоговая процедура возвращает значение FALSE.

Функция EndDialog закрывает модальное диалоговое окно. Она имеет следую щий прототип:

BOOL EndDialog (

 

 

 

HWND hDlg,

//

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

îêíà

INT_PTR nResult

//

значение, возвращаемое

из функции DialogBox

);

 

 

 

Второй параметр функции EndDialog задает значение, которое передается функ ции DialogBox (описываемой ниже) для использования в качестве кода возврата из функции DialogBox. Чаще всего функции EndDialog передается в параметре nResult значение TRUE при обработке команды IDOK и FALSE — при обработке команды

IDCANCEL.

В программе DlgDemo1 код возврата функции DialogBox игнорируется, но на самом деле он может быть использован для проверки выбора, сделанного пользо вателем.

Вызов диалога

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

Оконная процедура программы MenuDemo1, обрабатывая это сообщение, вы зывает функцию MessageBox. Теперь же оконная процедура вызывает функцию

DialogBox:

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

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

Функция DialogBox создает и выводит на экран модальное диалоговое окно, построенное по шаблону IDD_ABOUT. Кроме того, DialogBox сообщает Windows, что диалоговая процедура для обслуживания этого окна имеет адрес AboutDlgProc.

320

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

 

 

В своей реализации функция DialogBox использует вызов CreateWindowEx для создания диалогового окна. После этого она посылает сообщение WM_INITDIALOG диалоговой процедуре, отображает диалоговое окно, блокирует (делает недоступ ным для ввода) родительское окно и запускает цикл обработки сообщений для менеджера диалогового окна.

Функция DialogBox не возвращает управление в WndProc до тех пор, пока окно диалога не будет закрыто.

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

Тестирование приложения

Откомпилируйте и запустите программу. Она должна функционировать так же, как и приложение MenuDemo1.

Выберите пункт меню About…. Если все было сделано правильно, то появится модальное диалоговое окно, внешний вид которого показан на рис. 7.14.

Рис. 7.14. Модальное диалоговое окно About DlgDemo1

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

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

Для реализации столь смелой мечты продолжим наше путешествие по лаби ринтам Win32 API.

Изменение атрибутов элемента управления

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

BOOL EnableWindow(

HWND

hWnd,

// дескриптор элемента

управления

 

BOOL

bEnable // флаг разрешения или

запрещения

ввода от клавиатуры и мыши

};