Поcобие_БЕЛОВ_Графический_интерфейс_API
.pdf241
{SendMessage(hStatus,SB_SETTEXT,1,
(LONG)"Найти фрагмент по выделенному образцу"); return 0;
}
case CM_EDIT_REPLC:
{SendMessage(hStatus,SB_SETTEXT,1,
(LONG)"Заменить найденный фрагмент на указанный образец"); return 0;
}
case CM_VIEW_NORM:
{SendMessage(hStatus,SB_SETTEXT,1,
(LONG)"Показать текущий документ в обычном виде"); return 0;
}
case CM_VIEW_STRC:
{SendMessage(hStatus,SB_SETTEXT,1,
(LONG)"Показать структуру текущего документа"); return 0;
}
case CM_FILE_QUIT:
{ SendMessage(hStatus,SB_SETTEXT, 1, (LONG)"Завершить работу приложения");
return 0;
}
}
return 0;
}
caseWM_DESTROY:
{DestroyMenu(hEditMenu);
DestroyMenu(hViewMenu);
PostQuitMessage(0); return 0;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
Рассмотрим основные дополнения к листингу 4.3.
1. Дополнения, обусловленные созданием строки состояния, были изучены в приложении в листинге 5.4. Только теперь строка состояния включает две части.
242
2. Обработка сообщения WM_MENUSELECT состоит из трех частей:
1) отдельно обрабатывают перемещение по названиям разделов главного меню. Если параметр lParam равен дескриптору главного меню, то определяют значение позиции курсора. Это значение содержится в LOWORD(wParam), если строка связана с разделом меню. Мы знаем, какой раздел соответствует каждой позиции. В первой позиции (ей соответствует LOWORD (wParam)=0) находится раздел «Файл». В этом случае в первой части строки состояния отображают текст «Открыть/закрыть документ или выход»:
SendMessage( hStatus, SB_SETTEXT, 0,
(LONG) "Открыть/закрыть документ или выход"); и стирают текст во второй части строки состояния:
SendMessage( hStatus, SB_SETTEXT, 1, NULL);
Точно так же обрабатывают другие позиции курсора в главном меню. Если строки временных меню указывают на разделы меню, то для них также необходимо предусмотреть обработку перемещения по позициям. Обратите внимание, что условный оператор
if ((HMENU)lParam==hMainMenu)
{ switch (LOWORD(wParam)) { case 0:
} }
завершает обработку сообщения оператором возврата, только если курсор установлен на строке раздела меню, т.е. не все строки меню с дескриптором lParam должны указывать на разделы меню;
2)здесь мы оказываемся, если младшее слово параметра wParam может быть равно идентификатору команды строки меню. Тогда достаточно определить этот идентификатор и послать соответствующий текст сообщения во вторую часть строки состояния. Так, если курсор находится над строкой «Открыть» раздела «Файл», то во второй части строки состояния окажется текст «Открыть новый документ»:
SendMessage(hStatus,SB_SETTEXT,1, (LONG)”Открыть новый документ");
Точно так же поступают для других идентификаторов команд;
3)Обработку завершают возвратом значения 0.
После запуска приложения на экране появится точно такое же окно и с таким же меню, что и после запуска приложения листинга 4.3. Только в этом случае добавлена строка состояния из двух частей. В первой части отображен текст «Готово».
243
Если нажать строку «Файл», в первой части строки состояния появляется текст «Открыть/закрыть документ или выход», а вторая часть остается пустой. Если курсор перемещается на строку «Открыть», то текст в первой части не изменяется, а во второй части появляется текст «Открыть новый документ». Текст во второй части строки состояния будет меняться при перемещении по строкам этого временного меню, а текст в первой части будет постоянным и указывать на текущий раздел меню.
Точно так же будет происходить информирование о строках меню после подключения других разделов к главному меню. Но вторая часть строки состояния будет пустой, если курсор переходит на название раздела меню. После выбора строки меню содержание частей строки состояния остается таким, каким оно было в момент выбора, т.е. строка состояния напоминает о последней выбранной команде.
Упражнения
Упражнения этой главы являются продолжением упражнений четвертой главы.
1.В строке состояния сообщать о действиях со строками меню и текущие координаты курсора мыши.
2.О действиях со строками меню сообщать в строке состояния.
3.Продублировав команды отображаемых строк меню кнопками панели инструментов, отмечать состояние кнопок.
4.Команды отображаемых строк меню продублировать кнопками панели инструментов и обеспечить подсказки к кнопкам.
5.Продублировав команды отображаемых строк кнопками панели инструментов, выдавать сообщения о строках меню при перемещении по ним.
6.О действиях с рисунками сообщать в строке состояния.
7.Продублировав команды меню окна приложения кнопками панели инструментов, в дополнительном окне выдавать сообщения о строках меню.
8.Продублировав команды меню окна приложения кнопками панели инструментов, в дополнительном окне выдавать сообщения о строках меню.
9.О действиях с фигурами и состоянии соответствующих строк меню сообщать в строке состояния.
10.Продублировав команды отображаемых строк меню кнопками панели инструментов, выдавать сообщения о строках меню при перемещении по ним.
244
11.О действиях с курсором мыши сообщать в строке состояния.
12.В строке состояния отобразить путь к текущей строке меню.
13.Строки состояния всех окон отображают информацию об активности окон и перемещении по строкам меню.
14.В строке состояния сообщать о строках меню, включая состояние строк.
15.Обо всем, что происходит в трех окнах, сообщать в строке состояния окна приложения.
16.Продублировав команды отображаемых строк меню кнопками панели инструментов, выдавать сообщения о строках меню при перемещении по ним.
17.Команды меню окон продублировать кнопками панелей инструментов.
18.О действиях с фигурами и состоянии соответствующих строк меню сообщать в строке состояния.
19.Стандартные команды меню продублировать кнопками панели инструментов. В дополнительном окне вьщавать сообщения о строках меню.
20.Стандартные команды меню продублировать кнопками панели инструментов.
21.Команды меню продублировать кнопками панели инструментов.
22.Команды меню продублировать кнопками панели инструментов.
23.Строка состояния содержит информацию о пользователе и данных, даже если выбор был сделан с помощью акселератора.
24.Строка состояния отражает информацию о фигуре и цвете.
25.Строка состояния отражает путь перемещения курсора по строкам меню.
Контрольные вопросы
1.Перечислите основные шаги создания панели инструментов.
2.Что отличает состояние кнопок панели инструментов от состояния строк меню?
3.Какой константой определяют стиль окна панели инструментов, если все кнопки панели должны посылать уведомительные сообщения?
4.Перечислите основные шаги создания строки состояния.
245
ГЛАВА 6. ДИАЛОГОВЫЕ ПАНЕЛИ
Диалоговые панели обеспечивают оперативный обмен информацией между пользователем и приложением. Они представляют собой перекрывающиеся или временные окна и создаются на базе предопределенного в Windows класса диалоговых панелей. Функция окна такого класса обеспечивает специфическое поведение элементов управления панели, например передачу фокуса ввода от одного элемента управления к другому или между группами при нажатии клавиши Tab.
6.1. Характеристики диалоговых панелей
Внешний вид диалоговой панели задают шаблоном панели. Шаблон можно описать тремя способами:
1)включая текст описания шаблона в файл ресурсов приложения. Для изменения внешнего вида панели достаточно редактировать файл ресурсов, не изменяя текста приложения;
2)используя редактор ресурсов интегрированной среды разработки приложения. Эти редакторы позволяют с помощью мыши
иклавиатуры нарисовать панель и сохранить текст описания шаблона в файле ресурсов;
3)создавая шаблон в памяти при работе приложения. Приложение в зависимости от содержания требуемых и предоставляемых данных и способа обмена изменяет вид панели. Функция окна диалоговой панели при этом содержит обработку необходимого и достаточного набора сообщений. Команды, которые не задействованы в текущей конфигурации панели, обычно блокируют. С увеличением потребности в оперативном обмене данными с различными источниками информации увеличивается потребность в этом способе.
В операционной системе имеются и стандартные диалоговые панели. Приложения их вызывают для работы с файлами, выбора цветов и шрифта, работы с принтерами и текстовыми строками и т. д.
В данной главе будут рассмотрен третий способ создания и использования диалоговых панелей и примеры работы со стандартными диалоговыми панелями для работы с файлами, выбора цветов и шрифта.
246
6.1.1. Единицы диалоговой панели
Диалоговые панели используют специальную систему измерения размеров панели и элементов управления на ее поверхности. В этой системе единицы ширины и высоты определяют шириной и высотой используемого в панели шрифта.Одна диалоговая единица ширины составляет четверть средней ширины символов, а высоты – восьмую часть высоты символов системного шрифта.
Размер диалоговой единицы получают с помощью функции
GetDialogBaseUnits:
LONG GetDialogBaseUnits(VOID);
Она возвращает 32-разрядное значение, младшее слово которого равно единице ширины, а старшее слово – единице высоты.
Удобно пользоваться средними значениями ширины и высоты шрифта в диалоговых единицах. Эти значения можно вычислить следующим образом:
//Определяем среднюю ширину и высоту шрифта в пикселях int cxChar, cyChar;
{TEXTMETRIC tm; HDC hdc=GetDC(hwnd); GetTextMetrics(hdc,&tm); ReleaseDC(hwnd.hdc); cxChar=tm.tmAveCharWidlh+1 ; cyChar=tm.tmHeight+tm.tmExternalLeading;
}
//Определяем диалоговые единицы ширины и высоты
DWORD dlgunit =GetDialogBaseUnits(); Int dlgwunit=LOWORD(dlgunit), dlghunit=HIWORD(dlgunit);
//Пересчитываем габариты символов шрифта cxChar=cxChar*4/dlgwunit; cyChar=cyChar*8/dlghunit;
Теперь значения переменных cxChar и cyChar представляют соответственно среднюю ширину и высоту символов шрифта в диалоговых единицах. Обычно содержание элементов панелей задают с помощью текстовых строк. Зная расположение этих элементов на панели, можно корректно определить габариты диалоговой панели и вычислить координаты размещения элементов.
247
6.1.2. Стили диалоговой панели
Диалоговые панели бывают следующих трех типов:
1.Модальные. Приложение приостанавливает свою работу на время активизации собственной модальной диалоговой панели. Функции всех окон (включая их дочерние окна) этого приложения блокируют, поэтому панели нельзя создавать на базе дочерних окон.
2.Системные модальные. После запуска системной модальной диалоговой панели приостанавливают работу все приложения. Пока эта панель находится на экране, нельзя переключиться на работу с другими приложениями.
3.Немодальные. Немодальная диалоговая панель не блокирует ничью работу. Обычно ее создают один раз. Затем при необходимости
еескрывают или отображают с помощью функции ShowWindow. Немодальную панель разрушают функцией DestroyWindow.
Диалоговые панели 1-го и 2-го типа для завершения собственного цикла обработки сообщений и разрушения панели в теле функции своего окна должны содержать вызов функции EndDialog.
Значение стиля панели задают комбинацией констант с префиксом WS_ и с префиксом DS_ из следующей таблицы:
Стиль |
Пояснение к стилю панели |
|
|
DS_3DLOOK |
Этот стиль используют по умолчанию в |
||
|
приложениях Win32 |
|
|
DS_ABSALIGN |
Координаты отсчитывать от левого верхнего |
||
|
угла экрана, иначе отсчет ведется от левого |
||
|
верхнего угла рабочей области |
|
|
|
|
|
|
DS_CENTER |
Центрировать панель на экране |
|
|
DS CENTERMOUSE |
Центрировать курсор мыши в панели |
|
|
DS_CONTEXTHELP |
В заголовке окна панели отобразить кнопку с |
||
|
вопросительным знаком. При ее нажатии |
||
|
курсор мыши принимает вид указателя с |
||
|
вопросительным знаком. Если затем нажать |
||
|
левую клавишу мыши над элементом панели, то |
||
|
функция окна |
панели получит |
сообщение |
|
WM_HELP. При его обработке необходимо |
||
|
вызвать функцию WinHelp, указав третьим |
||
|
аргументом |
HELP_WM_HELP. |
Тогда |
|
отображается подсказка над этим элементом |
||
|
управления |
|
|
|
|
|
|
248
Стиль |
Пояснение к стилю панели |
|
|
DS_CONTROL |
Панель работает как дочернее окно другой |
|
панели, подобно странице блокнота панелей. |
|
Этот стиль позволяет переходить от одной |
|
панели к другой с помощью клавиатуры |
|
|
DS_FIXEDSYS |
Вместо шрифта SYSTEM_FONT загрузить |
|
шрифт SYSTEM_FIXED_FONT |
DS_MODALFRAME |
Модальная панель. Обычно комбинируют с |
|
константами WS_CAPTION И WS_SYSMENU |
|
|
DS_TOFAILCREATE |
Панель создавать, даже если возникли ошибки |
|
создания его элементов управления |
|
|
DS_NOIDLEMSG |
Функции окна-владельца панели не посылать |
|
сообщение WM_ENTERIDLE, иначе это |
|
сообщение будет послано в момент |
|
отображения панели |
|
|
DS_RECURSE |
Стиль панели подобен стилю элементов |
|
управления |
|
|
DS_SETFONT |
Шаблон панели должен содержать размер и имя |
|
шрифта, иначе будет использован системный |
|
шрифт |
|
|
DS_ SETFOREGROUND |
Панель всегда на переднем плане |
DS_SYSMODAL |
Системная модальная панель |
В стиле панели чаще других используют константы
WS_POPUP, WS_BORDER, WS_SYSMENU, WS_CAPTION и DS_MODALFRAME.
Если диалоговая панель имеет рамку, но не имеет заголовка, используют константу WS_DLGFRAME.
Константу DS_SETFONT задают, только если есть гарантия
наличия и поддержки требуемого шрифта.
6.1.3. Функция окна диалоговой панели
Функция окна диалоговой панели описывается разработчиком и должна быть объявлена следующим образом:
BOOL CALLBACK DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam);
На имя этой функции распространяют обычные требования на имена функций. Список формальных параметров подобен списку параметров функции окна. Только через первый параметр передают дескриптор диалогового окна hdlg, а не обычного окна hwnd.
249
Функция окна диалоговой панели не содержит вызов функции DefWindowProc для тех сообщений, которые она не обрабатывает. Если эта функция обрабатывает сообщение, то должна вернуть значение TRUE, а если нет – FALSE. Исключением является только возврат после обработки сообщения WM_INITDIALOG (см. ниже).
Функция окна диалоговой панели не обрабатывает
сообщения WM_CREATE, WM_PAINT и WM_DESTROY.
Функция окна диалога получает сообщение WM_INITDIALOG непосредственно перед отображением панели. При обработке этого сообщения инициализируют переменные для работы с данными и элементы управления панели.
Параметр wParam при этом равен дескриптору элемента управления, который получит фокус ввода сразу после отображения панели. Это первый незаблокированный элемент управления, описанный в шаблоне панели со стилем WM_TABSTOP. Если при обработке этого сообщения фокус ввода не передают другому элементу, возвращают значение TRUE. Если фокус ввода передают другому элементу управления, возвращают значение FALSE
Параметр lParam содержит значение, передаваемое приложением при создании диалоговой панели. Обычно этот параметр указывает на дополнительные данные для диалоговой панели. Здесь не рассматривается этот метод передачи дополнительных данных.
В функцию окна диалога сообщение WM_COMMAND поступает от элементов управления панели. При этом младшее слово параметра wParam содержит идентификатор пославшего сообщение элемента управления.
Необходимо осторожно обрабатывать сообщение
WMCOMMAND с идентификатором IDOK или IDCANCEL.
Функция окна диалога получает сообщение WM_COMMAND с идентификатором IDOK, если клавиша Enter нажата в момент, когда ни одна из кнопок панели не имеет фокуса ввода. Это справедливо для двух различных ситуаций:
1)ни одна из кнопок не имеет стиль WS_DEFPUSHBUTTON;
2)одна из кнопок создана со стилем WS_DEFPUSHBUTTON и идентификатором IDOK.
Функция окна диалога получает сообщение WM_COMMAND с идентификатором IDCANCEL, если нажата клавиша Esc или нажата кнопка с идентификатором IDCANCEL.
250
6.2. Создание диалоговой панели
Диалоговые панели – это окна определенного операционной системой класса окон. Существуют специальные функции для создания диалоговых панелей на базе этого класса и для их создания не вызывают функцию CreateWindow.
Создание и работа с диалоговыми панелями предполагает следующие шаги:
1)описание шаблона диалоговой панели;
2)описание функции окна диалоговой панели;
3)вызов функции создания диалоговой панели;
4)обмен данными между функцией окна, вызвавшего диалоговую панель, и функцией окна диалоговой панели.
Наиболее трудоемким является описание шаблона и функции окна диалоговой панели, а наиболее сложной – реализация обмена данными между функцией окна, создавшего диалоговую панель, и функцией окна диалоговой панели. Сложность обусловлена тем, что полученные в теле функции окна панели данные разрушаются при разрушении диалоговой панели. Для решения этой задачи описывают глобальные объекты, которые принимают значения данных панели и сохраняют их после ее разрушения.
Для создания панели на базе шаблона в памяти вызывают функцию DialogBoxIndirect или CreateDialogIndirect.
6.2.1. Создание модальной диалоговой п анели
Функция DialogBoxIndirect создает диалоговую панель 1-го
или 2-го типа:
int DialogBoxIndirect( HINSTANCE hInstance, LPDLGTEMPLATE lpTemplate,
HWND hWndParent, DLGPROC lpDialogFunc);
Она не возвращает управление, пока функция окна панели не завершит работу вызовом функции EndDialog. Функция DialogBoxIndirect отображает панель (даже если не указан стиль WS_VISIBLE) и активизирует собственный цикл обработки сообщений.
Параметры функции:
1)hInstance – дескриптор текущей копии приложения;
2)lpTemplate – указатель на шаблон диалоговой панели;
3)hWndParent – дескриптор родительского окна панели;
