Графические пользовательские интерфейсы

На многих персональных компьютерах предлагается пользоваться графическим интерфейсом пользователя (Graphical User Interface (GUI)). Сокращение GUI произносится как «гуи».

GUI был изобретен Дугласом Энгельбартом (Douglas Engelbart) и его исследовательской группой из Стэнфордского исследовательского института.

Затем он был скопирован исследователями из Xerox PARC. Однажды соучредитель компании Apple Стив Джобс (Steve Jobs) посетил PARC, увидел GUI на компьютере Xerox и воскликнул примерно следующее: «Ну надо же! Это ведь будущее компьютерного мира». GUI подтолкнул его на создание нового компьютера, которым стал Apple Lisa. Из-за дороговизны компьютер Lisa потерпел коммерческий провал, но его потомок, Macintosh, имел громадный успех.

Когда компания Microsoft получила прототип компьютера Macintosh, чтобы получить возможность разработки на нем программы Microsoft Office, ее руководство попросило Apple лицензировать этот интерфейс для всех желающих, чтобы он стал промышленным стандартом. (Microsoft выручила намного больше денег от программы Office, чем от MS- DOS, поэтому ей захотелось отказаться от MS-DOS, чтобы получить более совершенную платформу для Office.) Ответственный исполнитель проекта Macintosh в компании Apple Жан-Луи Гассе (Jean-Louis Gassee) в просьбе отказал, а Стив Джобс не стал отменять его решение. В конце концов Microsoft получила лицензию на элементы этого интерфейса. Именно они и стали основой интерфейса системы Windows. Когда Windows стала входить в моду, Apple подала на Microsoft в суд, обвиняя ее в выходе за лицензионные рамки, но судья не согласился с этим, и Windows продолжала наступать Macintosh на пятки. Если бы Гассе согласился со многими специалистами компании Apple, также желающими всеобщего лицензирования программного обеспечения Macintosh, компания Apple, наверное, разбогатела бы на лицензионных сборах и Windows сейчас бы не существовало.

Если на время не принимать во внимание интерфейсы сенсорных экранов, то в GUI есть четыре наиболее важных элемента, обозначаемых символами WIMP. Эти буквы означают соответственно: окна — Windows, значки — Icons, меню — Menus и указывающие устройства — Pointing device. Окна представляют собой прямоугольные области экрана, используемые для запуска программ. Значки являются небольшими обозначениями, на которых можно щелкать мышью с целью выполнения каких-либо действий. Меню представляют собой перечни действий, любое из которых может быть выбрано. И наконец, указывающие устройства — это мыши, трекболы или другая аппаратура, используемая для перемещения указателя по экрану с целью выбора элементов.

Программное обеспечение GUI может быть реализовано либо в качестве кода на уровне пользователя, как это сделано в системах UNIX, либо в самой операционной системе, как в случае с системой Windows. Для ввода в системах GUI по-прежнему используются клавиатура и мышь, а вот вывод практически всегда направляется на специальное устройство, называемое графическим адаптером. Этот адаптер состоит из специального блока памяти, называемого видеопамятью, в которой хранятся изображения, появляющиеся на экране. На графических адаптерах часто ставят 32- или 64-разрядные центральные процессоры и до 4 Гбайт собственной оперативной памяти, отделенной от оперативной памяти самого компьютера.

Каждый графический адаптер поддерживает определенное количество разрешений экрана. Общепринятыми разрешениями (по горизонтали х по вертикали в пикселах) являются 1280 х 960, 1600 х 1200 и 1920 х 1080, 2560 х 1600 и 3840 х 2160. Многие разрешения на практике имеют соотношение сторон экрана 4:3, что соответствует соотношению размеров экрана телевизионных приемников стандартов NTSC и PAL и обеспечивает прямоугольность пикселов на тех же мониторах, которые используются для телевизионных приемников. Высшие разрешения предназначены для широкоэкранных мониторов с соответствующим соотношением сторон. При разрешении 1920 х 1800 (размер видео стандарта full HD) цветной дисплей, имеющий 24 бита на пиксел, требует около 6,2 Мбайт оперативной памяти для хранения всего лишь одного изображения, поэтому при наличии 256 Мбайт и более графический адаптер может одновременно хранить множество изображений. Если весь экран обновляется 75 раз в секунду, видеопамять должна быть способна непрерывно поставлять данные со скоростью 445 Мбайт/с.

Тема программного обеспечения вывода для GUI-интерфейсов слишком обширна. Отдельно о Windows GUI написано множество томов по 1500 страниц (например, Petzold, 2013; Simon, 1997; Rector and Newcomer, 1997). Совершенно очевидно, что в этом разделе мы можем лишь вскользь коснуться этой темы и представить ряд основополагающих понятий. Для конкретизации изложения будет дано описание интерфейса Win32 API, который поддерживается всеми 32-разрядными версиями Windows. В общих чертах программное обеспечение вывода для других GUI-интерфейсов приблизительно сопоставимо с этим, но в деталях оно имеет существенные отличия.

Основным элементом экрана является прямоугольная область, называемая окном. Позиция и размеры окна однозначно определяются за счет задания координат (в пикселах) двух диагонально противоположных углов. Окно может содержать небольшой заголовок, строку меню, строку инструментов, а также вертикальную и горизонтальную полосы прокрутки. Типичное окно показано на рис. 5.28. Заметьте, что отсчет в системе координат Windows начинается с верхнего левого угла и координата y растет вниз, что отличает эту систему координат от декартовой, которая используется в математике.

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

Рис. 5.28. Простое окно, расположенное в позиции (200, 100) на XGA-дисплее


Поэтому Wmdows-программы сориентированы на сообщения. Действия пользователя, работающего с клавиатурой или мышью, перехватываются системой Windows и превращаются в сообщения в адрес той программы, которой принадлежит окно. У каждой программы имеется очередь сообщений, куда посылаются все сообщения, имеющие отношение ко всем ее окнам. Основной цикл программы состоит из отлавливания очередного сообщения и его обработки путем вызова внутренней процедуры для данного типа сообщений. В некоторых случаях сама система Windows может непосредственно вызвать эти процедуры, минуя очередь сообщений. Эта модель существенно отличается от UNIX-модели процедурного кода, которая заставляет использовать системные вызовы для взаимодействия с операционной системой. Тем не менее X-система сориентирована на события.

Чтобы сделать модель программирования более понятной, рассмотрим пример, приведенный в листинге 5.2. Здесь представлена структура основной программы для Windows. Она не носит завершенного характера и не имеет проверки на возникновение ошибок, но имеет достаточную для наших целей детализацию. Программа начинается с включения заголовочного файла штСош8.1п, в котором содержатся многие макросы, типы данных, константы, прототипы функций и другая информация, необходимая Windows-программам.

Листинг 5.3. Структура основной Windows-программы


#include


/* Инициализация мг^сХаББ */

1л1г^с1аББ.1р-Рп1л1г^Ргос = Иг^Ргос; /* процедура, которую следует вызывать для

обработки сообщений, адресованных окну данного класса*/

wndc1aББ.1pБzC1aББName = "Имя программы"; /* Текст для заголовка */

wndc1aББ.hIcon = LoadIcon(NULL, Ю1_АРР1-1САТ101\1); /* загрузка значка */

wndc1aББ.hCuгБoг = LoadCuгБoг(NULL, ЮС_АРР01л1); /* загрузка курсора


мыши */

}

long CALLBACK WndProc(HWND hwnd, UINT message, UINT wParam, long lParam) {

/* Сюда помещаются объявления. */

switch (message) {

case WM_CREATE: ... ; return ... ; case WM_PAINT: ... ; return ... ;

case WM_DESTROY: ... ; return ... ;

}

return(DefWindowProc(hwnd, message, wParam,


Основная программа начинается с описания, дающего ее имя и параметры. Макрос WГNAPI является инструкцией компилятору на использование определенного соглашения о передаче параметров, которая в дальнейшем нас интересовать не будет. Первый параметр, И, является описателем экземпляра и используется для идентификации программы во всей остальной системе. В некоторой степени Win32 является объектно-ориентированной системой, что означает наличие в ней объектов (например, программ, файлов и окон), имеющих определенное состояние, и связанного с ними кода, называемого методами, который оперирует этим состоянием. При обращении к объектам используются дескрипторы, в данном случае программу идентифицирует дескриптор И. Присутствие второго параметра обусловлено соображениями обеспе-

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

Это описание иллюстрирует широко используемое компанией Microsoft соглашение под названием венгерская нотация. Название дано по аналогии с польской нотацией, изобретенной польским логиком Й. Лукашевичем (J. Lukasiewicz) для представления алгебраических формул без использования старшинства действия или скобок. Венгерская нотация была изобретена венгерским программистом, работающим в компании Microsoft, Чарльзом Симони (Charles Simonyi). В ней несколько первых символов идентификатора используются для указания типа. Разрешенные буквы и типы включают: c (символ — character), w (слово — word, которое сейчас означает беззнаковое 16-разрядное целое число), i (32-разрядное целое число со знаком — integer), l (длинное целое число — long, также 32-разрядное целое число со знаком), s (строка — string), sz (строка, заканчивающаяся нулевым байтом — zero),p (указатель — pointer), fn (функция — function) и h (описатель — handle). Таким образом, к примеру, szCmd является строкой, заканчивающейся нулевым байтом, а iCmdShow — целым числом. Многие программисты считают, что подобная кодировка типа в именах переменных особой пользы не приносит, а только затрудняет чтение кода Windows. В системе UNIX аналогичные соглашения отсутствуют.

У каждого окна должен быть связанный с ним объект класса, определяющий его свойства. В листинге 5.2 таким объектом класса является wndclass. У объекта типа WNDCLASS имеется 10 полей, четыре из которых инициализируются в приведенном листинге. В настоящей программе должны быть инициализированы и остальные шесть. Наиболее важным полем является lpfnWndProc, которое представляет собой длинное целое (то есть 32-разрядное) число — указатель на функцию, обрабатывающую сообщения, направляемые этому окну. Другие инициализируемые в листинге поля указывают, какие имя и значок использовать в заголовке и какое обозначение — для указателя мыши.

После инициализации wndclass вызывается процедура RegisterClass для передачи этого объекта системе Windows. В частности, после этого вызова Windows знает, какую процедуру вызывать при возникновении различных событий, которые не проходят через очередь сообщений. Вызов следующей процедуры, CreateWindow, приводит к выделению памяти для структуры данных окна и возвращению дескриптора для последующих обращений к окну. Затем программа осуществляет еще два вызова подряд — для вывода очертаний окна на экран и его окончательного заполнения.

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

За основной программой следует процедура WndProc, обрабатывающая различные сообщения, которые могут быть посланы в адрес окна. Использование здесь ключевого слова CALLBACK, как и использование чуть раньше ключевого слова WINAPI, определяет способ вызова и передачи параметров. Первый параметр является дескриптором используемого окна. Второй параметр — это тип сообщения. Третий и четвертый параметры могут использоваться для предоставления дополнительной информации, если таковая потребуется.

Сообщения типа WM_CREATE и WM_DESTROY посылаются в начале и в конце программы соответственно[35]. Они дают программе возможность, к примеру, выделить память для структур данных, а затем вернуть эту память.

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

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

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

В итоге программа Windows создает, как правило, одно или несколько окон с объектом класса для каждого из них. С каждой программой связаны очередь сообщений и набор процедур обработки. В конечном счете, поведением программы управляют входящие события, обрабатываемые соответствующими процедурами. Это совсем другая модель мира по сравнению с более процедурным представлением, принятым в UNIX. Самим выводом графики на экран занимается пакет, состоящий из сотен процедур, которые собраны воедино в форме интерфейса графических устройств — GDI (Graphics Device Interface). Он может обрабатывать текст и графику и сконструирован таким образом, чтобы быть независимым от платформ и устройств. Перед тем как программа сможет вывести графику в окно, ей нужно получить контекст устройства (device context), представляющий собой внутреннюю структуру данных, в которой содержатся свойства окна, среди которых текущий шрифт, цвет текста, цвет фона и т. д. Во многих вызовах GDI используется контекст устройства либо для вывода графики, либо для получения или установки свойств.

Для получения контекста устройства существует несколько способов. Рассмотрим простой пример его получения и использования:

= GetDC(hwnd);

TextOut(hdc, x, у, psText, iLength);

ReleaseDC(hwnd, Ь^);

Первый оператор осуществляет получение дескриптора контекста устройства — hdc. Во втором операторе контекст устройства используется для вывода строки текста на экран. В нем указываются координаты ^, у) начала вывода строки, дается указатель на саму строку и сообщается ее длина. Третий вызов процедуры приводит к высвобождению контекста устройства, чтобы показать, что программа в данный момент прекратила вывод графики. Заметьте, что hdc используется аналогично дескриптору файла в UNIX. Также заметьте, что ReleaseDC содержит избыточную информацию (использование дескриптора hdc, однозначно определяющего окно). Использование избыточной информации, не имеющей практического значения, встречается в Windows довольно часто.

Другое интересное известие состоит в том, что при получении hdc подобным способом программа может выводить информацию только в имеющуюся в окне область клиента, но не в заголовок и не в другие части окна. Внутри структуры данных контекста устройства поддерживается обособленная область. Любой графический вывод за ее пределы игнорируется. Но для получения контекста устройства есть и другой способ — вызов процедуры GetWindowDC, при котором обособленная область устанавливается на все пространство окна. Другие вызовы устанавливают границы обособленной области по-своему. Системе Windows свойственно иметь несколько вызовов, приводящих практически к одинаковому результату.

Полное рассмотрение GDI не входит в круг освещаемых здесь вопросов. Заинтересовавшиеся работой интерфейса графических устройств могут обратиться за дополнительной информацией по ранее приведенным ссылкам. Но учитывая важность GDI, пожалуй, стоит сказать о нем еще несколько слов. Для получения и высвобождения контекстов устройств в GDI имеется несколько процедур, предоставляющих информацию об этих контекстах, извлекающих и устанавливающих атрибуты контекстов (к примеру, цвета фона), работающих с такими GDI-объектами, как перья, кисти и шрифты, каждый из которых имеет собственные атрибуты. И наконец, в нем конечно же имеется огромное количество GDI-вызовов, используемых для вывода графической информации на экран.

Процедуры вывода графической информации сведены в четыре категории: рисования прямых и кривых линий, рисования закрашенных областей, управления растровыми изображениями, отображения текста. Ранее нам уже встречался пример отображения текста, поэтому давайте кратко взглянем на один из прочих примеров. Вызов

Rectangle(hdc, xleft, ytop, xгight, ybottom);

приводит к выводу на экран закрашенного прямоугольника, имеющего углы с координатами в левой верхней ^Ы^, ytop) и правой нижней (xright, ybottom) областях. К примеру, вызов

Rectangle(hdc, 2, 1, 6, 4);

приведет к выводу на экран прямоугольника, показанного на рис. 5.29. Ширина линий, их цвет, цвет закраски берутся из контекста устройства. Другие GDI-вызовы в чем-то похожи на этот.

Рис. 5.29. Пример прямоугольника, нарисованного с помощью процедуры Rectangle. Каждый квадрат соответствует одному пикселу


<< | >>
Источник: Э. ТАНЕНБАУМ Х. БОС. СОВРЕМЕННЫЕ ОПЕРАЦИОННЫЕ СИСТЕМ Ы 4-е ИЗДАНИЕ. 2015

Еще по теме Графические пользовательские интерфейсы:

  1. Джеф Раскин. Интерфейс: новые направления в проектировании компьютерных систем, 2005
  2. Раскин Джефф. Интерфейс: новые направления в проектировании компьютерных систем, 2005
  3. Правило графической доказательности
  4. Правило графической доказательности
  5. Графическое оформление анкеты
  6. Теория, концепция и практика графической ректификации
  7. 5.3. Графическое представление данных
  8. Глава 5. ТАБЛИЧНОЕ И ГРАФИЧЕСКОЕ ПРЕДСТАВЛЕНИЕ ДАННЫХ1
  9. Бернадет Брэди. Теория, концепция и практика графической ректификации, 0000
  10. Графическое построение мандалы
  11. Расширение графического метода
  12. Правило разработки графических схем
  13. Правило разработки графических схем
  14. Порядок графического построения мандалы
  15. Простой пример графической ректификации, используя карту страны
  16. ГРАФИЧЕСКАЯ НУМЕРОЛОГИЧЕСКАЯ МАНДАЛА - СПОСОБ НАСТРОЙКИ ПОДСОЗНАНИЯ ДЛЯ РАДИЭСТЕЗИЧЕСКОЙ РАБОТЫ