Графический интерфейс, является неотъемлемой частью AmigaOS. С каждой новой версией ОС процесс создания GUI для программ упрощается, а его возможности увеличиваются, например появление стандартных риквесторов и интерфейса BOOPSI. Это позволяет программистам больше уделять времени логике программы, а графический интерфейс органично с ней связывать.
Intuition - так называется подсистема AmigaOS, отвечающая за графический интерфейс.
Workbench - графический интерфейс для AmigaDOS.
Preferences - программы, которые позволяют устанавливать конфигурацию.
BOOPSI - подсистема Intuition, представляет из себя объектно-ориентированный системный интерфейс. С помощью него, например, работает MUI.
Библиотеки:
gadtools.library - библиотека, которая применяется при создании GUI стандартными средствами AmigaOS.
asl.library - применяется для работы с риквесторами запроса на выбор файла, группы файлов, шрифта и т.д.
graphics.library - библиотека для работы с графикой (спрайты, анимация, шрифты и т.д.)
workbench.library - для программ использующих возможности Workbench - AppWindow, AppIcon, AppMenuItem.
icon.library - для работы с иконками.
Основные составляющие графического интерфейса программ:
Screens - на "экранах" располагаются окна программ. Программы могут сами создавать экраны для своих нужд (custom или public), а также пользоваться уже существующими общими (public) экранами, например "Workbench Screen".
Windows - основная рабочая область программы.
Menus - линейка меню программы. Обычно содержит список всех возможных действий программы.
Gadgets - графические символы, которые представляют из себя управляющие элементы, например кнопки или стрелки прокрутки.
Requesters - окна для вывода различных сообщений, запросов.
Input events - события, которые принимает и обрабатывает Intuition, например движения мышью, нажатие на кнопку в окне.
AmigaOS через BOOPSI предлагает новый подход в создании программ. Он называется объектно-ориентированный. Наиболее полно реализует эту возможность интерфейс MUI. MUI представляет из себя набор библиотек, главная - muimaster.library, она же использует остальные. И набора "классов" в подкаталоге LIBS:mui/. Также интерфейс содержит программу "MUI" для настройки внешнего вида программ и программу "PSI", которая позволяет создавать "общие" экраны для MUI программ.
2.3.1 Объектно-Ориентированное Программирование (ООП)
Наверняка многие читатели уже знакомы с понятием ООП. Много книг написано на эту тему, в основном о C++. Язык С++ считается довольно трудным для изучения, а грамотное написание программ на этом языке возможно только после специального обучения в соответствующих заведениях, поэтому MUI использует только основные догмы ООП и язык С.
Основные понятия ООП - "класс" и "объект". Класс позволяет рассматривать некоторые логически связанные данные и функции программы как одно целое (единый организм) и затем создавать отдельные экземпляры этого класса ("организма") которые начнут новую "жизнь", они называются объектами. Например функцию вывода текста и переменную содержащую текст можно представить в виде класса "Text", затем создать несколько объектов этого класса, причем каждый объект будет содержать свой текст (для него отводится новая память), а функция вывода текста останется та же самая (объект содержит ссылки на функции), т.е. в памяти будет только одна копия функции вывода текста для всех созданных объектов класса "Text"! Теперь этой функции не нужен аргумент (указатель на строку) т.к. вызывая её из каждого созданного объекта, текст будет печататься из переменной соответствующего объекта.
Переменная объекта, которая содержит текст называется атрибутом объекта, функция - методом, вызов этой функции - посылка объекту сообщения или выполнение метода.
Допустим, мы хотим чтобы объекты выводили текст в определённых координатах (x,y) курсивом. Для этих целей существует "наследование". Мы используем накопленный "опыт" класса Text и на основе его атрибутов и методов создаём новый класс "NewText" он будет состоять из двух атрибутов (x,y) и одного метода (вывод курсивом), а сами объекты класса "NewText" будут содержать в себе три атрибута (x,y, сам текст) и использовать два метода (вывод и вывод курсивом). Класс "Тext" в этом случае называют классом предком или родительским классом, а класс "NewText" потомком класса "Text".
2.3.2 Встроенные классы
MUI содержит множество классов необходимых для создания GUI. Эти классы представлены в виде дерева иерархии. Объекты наследуют все методы и атрибуты родительского класса и классов стоящих выше в иерархии. Например объект класса Image, наследует методы и атрибуты классов Area и Notify.
rootclass - базовый класс BOOPSI | Notify - механизм извещения объектов | +--Application - главный класс программы +--Window - окно программы +--Area - базовый класс для всех GUI элементов | +--Rectangle - чертит прямоугольники для визуального разделения +--Image - графическое изображение +--Text - вывод текста +--String - строка ввода +--Prop - создаёт пропорциональный gadget(ползунок) +--Gauge - индикатор процесса(измеритель) +--Scale - процентная шкала +--Boopsi - интерфейс для BOOPSI классов +--Colorfield - закрашенная область +--List - создаёт линейный список | | | +--Floattext - "плавающий" список | +--Volumelist - список томов | +--Scrmodelist - список экранных режимов | +--Dirlist - список файлов | +--Group - группирует GUI элементы и отвечает за их расположение | +--Virtgroup - управляет виртуальными группами +--Scrollgroup - управляет виртуальными группами с линейками прокрутки +--Scrollbar - создаёт линейку прокрутки +--Listview - создаёт список +--Radio - переключатели (радио-кнопки) +--Cycle - раскрывающися список выбора +--Slider - создаёт ползунок +--Coloradjust - создаёт RGB ползунок (колесо) +--Palette - gadget палитры цветовMUI не имеет отдельных классов для кнопки (Button) и пометки (СheckMark) так как они "находятся" в классе Area. Подробную информацию по каждому классу можно получить из файла MUI/Autodocs/MUI_имя_класса.doc.
2.3.3 Создание программы
Программа может состоять из большого количества объектов или дерева объектов. Это дерево создаётся путем "присоединения" одного объекта к другому.
В основе дерева лежит объект класса Application. Он берёт на себя функции контроля окон программы, различными событиями, Arexx интерфейсом. Один объект этого класса должен обязательно создаваться в программе. К нему присоединяют (SubWindow) объекты класса Window.
Объекты класса Window управляют созданием, закрытием, перемещением, изменениями размера окна и обновлением информации в окне. Для того чтобы в окне появились GUI объекты, его нужно "снабдить" (WindowContents) так называемым корневым (root) объектом. Обычно, этим объектом является объект класса Group.
Одной из самых важных особенностей MUI, является динамическое расположение GUI элементов в окне. Программисту не нужно заботиться о "настоящих" размерах и координатах объекта. Всё, что требуется, это определить некоторые прямоугольные области, в которые помещаются кнопки, списки и другие объекты. Для этих целей предназначены объекты класса Group, они не видны на экране, их задача группировать "присоединённые" (Child) к ним объекты и размещать их в окне горизонтально, вертикально, в колонках, в ярлыках.
Пример дерева объектов MUI программы:
![]()
Только три типа объекта могут присоединять к себе другие, это:
- Application - присоединяет объекты класса Window.
- Window - только один объект, потомок класса Area.
- Group - один или более потомков класса Area.
2.3.4 Принятые обозначения
MUIС_класс
- имя классаMUIM_класс_метод
- имя метода принадлежащего классу "класс"MUIA_класс_атрибут
- имя атрибута принадлежащего классу "класс"MUIV_класс_метод_значение
- предопределённое значение аргумента метода.MUIV_класс_атрибут_значение
- предопределённое значение атрибута, например -MUIV_Window_Height_Default
В описании атрибута класса содержатся следующие буквы: [ISG]
- I: присвоение значения атрибуту возможно во время создания объекта (NewObject()).
- S: возможность изменения значения атрибута функцией set().
- G: возможность чтения значения атрибута функцией get().
Пример описания:
MUIA_Window_Open -- (V4 ) [.SG], BOOL
Атрибут содержит значение типа BOOL, может читаться/устанавливаться, но не может быть установлен во время создания объекта.
2.3.5 Создание и управление объектами встроенных MUI классов
Для того чтобы создать объект используется функция MUI_NewObject(), её прототип:
Object *MUI_NewObject(STRPTR class, Tag tag1, ..., TAG_DONE);
Аргумент
class
- имя класса, например "MUIC_Window".tag1, tag2, ...
- атрибуты объекта, которые нужно установить при его создании, напримерtag1
можно представить в виде "MUIA_Window_Title, title," для установки заголовка окна. Пример создания объекта класса Window:MyWindow = MUI_NewObject(MUIC_Window, MUIA_Window_Title, "Hello", WindowContents, MyGroup, TAG_DONE);Атрибут
WindowContents
содержит указатель на присоединяемую к окну группу (MyGroup
) объектов.Как только объект создан, ему можно посылать сообщения функцией DoMethod(), устанавливать и получать значения атрибутов объекта функциями set() и get().
2.3.6 Удаление объектов
Объекты удаляются с помощью функции MUI_DisposeObject(), прототип:
void MUI_DisposeObject(Object *obj);
Если к объекту "присоединялись" другие объекты, то они также по цепочке удаляются из памяти. Таким образом, удаляя объект класса Application, мы удаляем все объекты программы. Нужно помнить, что если сам объект присоединяли, то его удалят нельзя, это не относится к динамически присоединённым объектам. Пример:
MUI_DisposeObject(app);
Удаляет объект
app
класса Application, присоединённые к нему окна - атрибуты "SubWindow", а также Group объекты этих окон - "WindowContents".2.3.7 Функции DoMethod() и set()
Функция DoMethod() посылает объекту сообщение (выполняет метод). Прототип:
ULONG DoMethod(Object *obj, ULONG Method, ...);
obj
- объект,Method
- имя выполняемого метода. Далее в списке аргументов следуют аргументы к самому методу. Методы могут быть как класса которому принадлежит объект, так и классов предков. Примеры:
DoMethod(MyWindow, MUIM_Window_ToFront);
Перемещает окно
MyWindow
на передний план.
DoMethod(app, MUIM_Application_AboutMUI, MyWindow);
Выполняет метод объекта
app
класса Application, аргументMyWindow
говорит о том, что окно "About MUI" будет появлятся по центру относительноMyWindow
.Функция set() устанавливает атрибуту объекта заданное значение. Атрибуты могут быть как класса которому принадлежит объект, так и классов предков. Пример:
set(MyWindow, MUIA_Window_Open, TRUE);
Устанавливает атрибуту
MUIA_Window_Open
значениеTRUE
, т.е. выполнение этой операции приводит к появлению окнаMyWindow
на экране.2.3.8 Механизм извещения объектов
Механизм извещения объектов - это способ контроля объектов и установки связей между объектами. Он основывается на том, что значения атрибутов объекта определяют его текущее состояние или свойства. "Извещение" позволяет устанавливать реакцию на изменение состояния объекта.
Значения атрибутов объекта могут изменяться или программистом, функцией set(), или действиями пользователя, например во время изменения положения ползунка в окне, атрибут "MUIA_Slider_Level" объекта класса Slider будет динамически изменять своё значение. Таким образом, мы можем связать ползунок и объект класса Gauge (индикатор), чтобы индикатор показывал текущее положение.
Для извещения применяется метод MUIM_Notify, он присутсвует во всех MUI объектах. Рассмотрим его подробнее:
DoMethod(obj, MUIM_Notify, ULONG TrigAttr, ULONG TrigVal, DestObj, ULONG FollowParams, /* ... */);
оbj
- объект-источник.TrigAttr
- атрибут объекта-источника значение которого мы хотим отслеживать.TrigVal
- значение атрибутаTrigAttr
, при котором происходит "извещение". Специальное значение - "MUIV_EveryTime", извещение происходит каждый раз при изменении значения.DestObj
- объект-приёмник с которым связываем "извещение". Предопределённые значения: MUIV_Notify_Self, MUIV_Notify_Window, MUIV_Notify_Application.FollowParams
- количество аргументов следующих далее, а далее следует само "извещение", т.е. какой метод объекта-приёмника нужно выполнить при изменении состояния объекта-источника. Значение атрибутаTrigAttr
содержится в "MUIV_TriggerValue".Примеры:
Объект
MySlider
связываем с объектомMyGauge
. При изменении значенияMUIA_Slider_Level
, выполняется методMUIM_Set
объектаMyGauge
, он устанавливает атрибутMUIA_Gauge_Current
в значениеMUIA_Slider_Level
. В итоге, когда мы перемещаем ползунок, индикатор одновременно с ним изменяет свои показания (см. рисунок):
DoMethod(MySlider, MUIM_Notify, MUIA_Slider_Level, MUIV_EveryTime, MyGauge, 3, MUIM_Set, MUIA_Gauge_Current, MUIV_TriggerValue);В следующем примере объект
MyWindow
контролирует поведение объектаapp
. Когда атрибутMUIA_Window_CloseRequest
объектаMyWindow
примет значение TRUE (окно закрыто) выполнится методMUIM_Application_ReturnID
объектаapp
с аргументомMUIV_Application_ReturnID_Quit
(закрытие приложения). Таким образом, когда мы закрываем окно, программа прекращает свою работу - происходит выход из цикла обработки сообщений (см. пример MUI программы):DoMethod(MyWindow, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, app, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);2.3.9 Пример MUI программы - "HelloWorld!"
/* файл hello_world!.c */ #include <libraries/mui.h> #include <proto/muimaster.h> #include <proto/exec.h> #include <stdio.h> #include <stdlib.h> struct Library *MUIMasterBase; /* указатель на библиотеку */ int main(void) { /* объекты нашей программы: */ Object *app, *TX_helloworld, *GROUP_ROOT, *WI_helloworld; /* "открываем" библиотеку MUI */ MUIMasterBase = OpenLibrary("muimaster.library", MUIMASTER_VMIN); if(!MUIMasterBase) { puts("Can't open muimaster.library"); return(20); } /* Для удобства, вместо прямого вызова функции MUI_NewObject(), * в файле "mui.h" определены макросы типа: * * #define TextObject MUI_NewObject(MUIC_Text * #define End TAG_DONE) * * Атрибуты и методы класса можно найти в файле "Аutodocs/ * MUI_имя_класса.doc". Если у вас редактор GoldEd и настроена * система "Reference": кликните на слове, например на "MUIA_Font", * и в меню "Search" выберите "Reference", в итоге, получите * его подробное описание. * * Создаем объекты: */ TX_helloworld = TextObject, MUIA_Background, MUII_TextBack, MUIA_Frame, MUIV_Frame_Text, MUIA_Font, MUIV_Font_Big, MUIA_Text_Contents, "Hello, World!", MUIA_Text_PreParse, "\33c", MUIA_Text_SetMin, TRUE, End; GROUP_ROOT = GroupObject, Child, TX_helloworld, /* присоединили объект к группе */ End; WI_helloworld = WindowObject, MUIA_Window_Title, "Hello", MUIA_Window_ID, 1, WindowContents, GROUP_ROOT, /* присоединили группу к окну */ End; app = ApplicationObject, MUIA_Application_Title, "HelloWorld!", MUIA_Application_Base, "HELLOWORLD!", SubWindow, WI_helloworld, /* присоединили окно к программе */ End; if(app) { DoMethod(WI_helloworld, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, app, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit); /* открываем окно */ set(WI_helloworld, MUIA_Window_Open, TRUE); /* Цикл обработки сообщений * * Следующий блок программы выполняет "основную работу" - * обрабатывает(посылает сообщения объектам) все события * которые получает наша программа. Этот стандартный блок * обычно используется программистами без изменений. */ { ULONG sigs = 0; while (DoMethod(app,MUIM_Application_NewInput,&sigs) != MUIV_Application_ReturnID_Quit) { if (sigs) { sigs = Wait(sigs | SIGBREAKF_CTRL_C); if (sigs & SIGBREAKF_CTRL_C) break; } } } /* Блок отработал своё - программа получила сообщение о * выходе. * * Удаляем "главный" объект - "app", а так как мы * "присоединили" к нему объект "WI_helloworld", то все * объекты по цепочке удалятся: */ MUI_DisposeObject(app); } CloseLibrary(MUIMasterBase); return(0); }
![]()
В результате получилась программа которая обладает всеми возможностями MUI - полностью настраиваемый GUI, что очень важно и для программиста т.к. система сама следит за правильным расположением (размерами) всех настраиваемых пользователем GUI элементов, например шрифтами; сервисом программы "Exchange"; и т.д. Попробуйте "поиграть" со шрифтом программы: в окне программы "MUI" раздел "Windows/Fonts/Big:" выбирайте разные шрифты (размеры). При этом шрифт нашей программы будет меняться автоматически после нажатия на кнопку "Test" в окне программы "MUI".
Следующая статья будет посвящена созданию класса "helloworld", добавим в него меню и кнопки, а также работе с программой MUIBuilder. Её можно взять из Интернет:
http://aminet.net/dev/mui/MUIBuilder22.lha
Эта программа позволяет визуально создавать интерфейс, а затем "переводить" его в строки кода, кстати, объекты для программы "HelloWorld!" были созданы с помощью неё.
© 1998-2006 Андрей Черешнев | Часть третья | Начало |