Файл: 16. Основы программирования пользовательского интерфейса.pdf
Добавлен: 20.10.2018
Просмотров: 739
Скачиваний: 6
16. Основы программирования пользовательского интерфейса
на базе Win32 API
Стремление сделать прикладные программы как можно более удобными
для рядового пользователя приводит к тому, что большая часть кода
приложения реализует именно интерфейс с пользователем. В течение 90-х
годов сформировался типичный оконный стиль взаимодействия с
приложениями, основанный на использовании стандартного набора
управляющих элементов (УЭ), меню и диалоговых окон. Системы Windows
традиционно поддерживают 6 базовых УЭ и около 15 дополнительных. К
основным УЭ относятся: кнопки разных типов, одно- и многострочные
текстовые редакторы, простые и комбинированные списки, простой
статический текст, полосы прокрутки.
Каждый УЭ с точки зрения системы является дочерним окном,
прикрепленным к какому-либо родителю. В качестве родительского окна
может выступать главное окно приложения или подчиненное окно любого
типа, но сами УЭ родителями быть не могут. Каждый базовый УЭ является
представителем своего стандартного оконного класса, в котором задаются
общие свойства данного типа УЭ, в том числе – предопределенная
стандартная оконная функция, реализующая стандартное поведение УЭ.
Таким образом, ОС отвечает за стандартное поведение своих УЭ и их
прорисовку на экране.
Базовые УЭ можно создавать с помощью системного вызова
CreateWindow, который в случае успеха возвращает дескриптор созданного
УЭ. Пример создания управляющих элементов:
MyButton1 := CreateWindow („BUTTON‟, „Просто Кнопка!‟,
bs_PushButton or ws_Child or ws_Visible, 50, 50, 100, 50,
ParentWin, id_But1, …);
MyEdit1 := CreateWindow(„EDIT‟, 0, es_MultiLine or ws_Child or
ws_Visible, 200, 50, 100, 200, ParentWin, 0, …);
Вызовы CreateWindow, которые создают УЭ, можно располагать в
приложении в двух местах: в главной функции вслед за созданием главного
окна и в оконной функции в обработчике какого-либо события.
Важным аспектом взаимодействия приложения со своими УЭ является
отдача этим элементам определенных команд, таких как “добавить новый
элемент в список”, “удалить выбранный элемент из списка”, “вернуть номер
выбранного в списке элемента”, “вернуть введенный в редакторе текст”,
“установить состояние включено/выключено для кнопки с независимой
фиксацией” и т.д. Для отдачи команд приложение посылает управляющим
элементам соответствующее сообщение. Фактически, основная работа
приложения с УЭ строится на использовании механизма посылки
сообщений. Для этого можно использовать одну из двух системных функций
– либо SendMessage, либо PostMessage. Различие в работе этих функций
состоит в следующем:
SendMessage посылает сообщение сразу в оконную функцию
приложения и ждет обработки этого сообщения оконной функцией.
PostMessage посылает сообщение в очередь сообщений данного
приложения и не ждет пока это сообщение будет обработано.
Чаще используется вызов SendMessage. Оба этих вызова имеют 4
формальных параметра:
дескриптор УЭ, которому посылается сообщение (кому?);
константа, определяющая действие, которое должен выполнить УЭ;
для каждого типа УЭ определен свой набор констант;
дополнительная информация о выполняемом действии (два параметра).
Рассмотрим примеры кодирования наиболее типичных действий:
добавление элемента-строки в список:
SendMessage (MyList, lb_addString, 0, longint(строка));
при этом новая строка добавляется либо в конец не отсортированного
списка, либо в соответствующую позицию отсортированного списка;
запрос номера текущего выбранного элемента в списке:
Nomer := SendMessage (MyList, lb_GetCurSel, 0, 0);
удаление выбранного элемента из списка (элемента с номером Nomer):
SendMessage (MyList, lb_DeleteString, Nomer, 0);
получение из списка текста выбранной строки с номером Nomer:
SendMessage (MyList, lb_GetText, Nomer, строка);
установка
состояния
включено/выключено
у
независимого
переключателя:
SendMessage (MyCheck1, bm_SetCheck, 1/0, 0);
запрос состояния переключателя:
Sost := SendMessage (MyCheck1, bm_GetCheck, 0, 0);
Более подробное описание констант-действий можно получить во
встроенной помощи.
Теперь рассмотрим некоторые возможности по управлению системой
меню с помощью API-функций. Всего Win32 API предоставляет около 40
подобных функций. Естественно, начинать надо с функций, позволяющих
создать в приложении систему меню программным способом.
Программное создание меню выполняется по принципу “снизу -
вверх”, т.е. сначала создаются подменю самого нижнего уровня, которые
после этого подключаются к соответствующим пунктам более высокого
уровня. В самую последнюю очередь создается полоса основного меню
приложения, к которому подключаются подменю более низкого уровня, а уж
затем вся созданная система меню подключается к приложению.
В качестве примера рассмотрим создание двухуровневого меню.
Шаг 1. Создание двух пустых подменю нижнего уровня (функция
CreatePopUpMenu):
SubMenu1 := CreatePopUpMenu;
//
SubMenu1
и SubMenu2 –
дескрипторы
SubMenu2 := CreatePopUpMenu; // подменю, переменные типа
HMenu
Шаг 2. Заполнение созданных подменю элементами. Каждый элемент
добавляется с помощью своего API-вызова AppendMenu, принимающего 4
параметра:
дескриптор меню, в которое добавляется новый элемент;
стиль добавляемого элемента, определяемый как комбинация (с
помощью операции логического сложения) следующих основных
флагов:
o mf_string – элемент является текстовой строкой;
o mf_enabled – элемент является активным;
o mf_disabled – элемент не активный;
o mf_grayed – элемент показан серым цветом, что говорит о его
неактивности в данный момент;
o mf_PopUp – используется при добавлении элемента-подменю;
уникальный идентификатор элемента (например, idm_About);
текст элемента (например, „About‟, „Open‟).
Например:
AppendMenu (SubMenu1, mf_string OR mf_enabled, 100, „Открыть‟);
AppendMenu (SubMenu2, mf_string OR mf_grayed, idm_About, „О
программе‟);
Шаг 3. Создание основного меню с помощью вызова CreateMenu:
MainMenu := CreateMenu;
// MainMenu – дескриптор основного
меню
Шаг 4. Присоединение к основному меню созданных подменю с помощью
вызова AppendMenu, который имеет те же самые параметры, но со
следующими отличиями:
во втором параметре надо использовать флаг mf_PopUp;
третий параметр – это дескриптор присоединяемого подменю
(например, SubMenu1).
Например:
AppendMenu (MainMenu, mf_PopUp OR mf_enabled, SubMenu1,
„Файл‟);
Шаг 5. Присоединение созданного меню к главному окну приложения с
помощью вызова SetMenu, принимающего два параметра:
дескриптор окна, к которому присоединяется меню;
дескриптор присоединяемого меню.
В этом случае в описании оконного класса в поле lpszMenuName
ничего задавать не надо.
Шаг 6. Прорисовка полосы меню выполняется после отображения главного
окна с помощью вызова DrawMenuBar, который имеет только один параметр
- дескриптор окна.
После создания меню можно организовать динамическое управление его
структурой, что очень распространено в современных приложениях,
поскольку позволяет в каждый момент времени предоставлять пользователю
только актуальный набор действий. Для этого можно использовать
следующие функции:
1. Изменение состояния элемента - EnableMenuItem с параметрами:
дескриптор меню или подменю, которому принадлежит изменяемый
элемент;
либо идентификатор элемента, либо его порядковый номер (отсчет –
с нуля), в зависимости от третьего параметра;
комбинация флагов из следующего набора:
o mf_ByCommand – элемент задается идентификатором
(установлен по умолчанию);
o mf_ByPosition – элемент задается порядковым номером;
o mf_enabled – элемент активен;
o mf_disabled – элемент не активен;
o mf_grayed – элемент показан серым цветом.
2. Изменение текста элемента – ModifyMenu с параметрами: