(версия 14.03.2007)

 

Подсистема оконной графики AWL

 

Здесь кратко описана одна из стандартных подсистем AWL — оконно-графическая. Она дает AWL-приложению возможность (действуя в рамках т.н. оконных сессий) создавать произвольное количество окон и программировать их взаимодействие с пользователем, используя средства ООП. Подсистема winter (WINdowing INTerface) в настоящее время работает только в среде MS Windows, но в ее идеологию заложена переносимость и в другие оконные среды (такие, как X11, MacOS, BeOS…). Ее зависимость от конкретной графической среды сделана минимальна.

Графическую систему можно разбить на две относительно независимые подсистемы, каждая из которых решает определенную часть задачи:

- собственно графический интерфейс (обеспечивающий вывод примитивов графики и текста в некой внешней для него среде);

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

Далее эти две подсистемы рассматриваются в деталях.

 

Графическая подсистема

Графическая подсистема AWL реализована как набор функторов, определенных во встроенном пространстве имен graphics. (Иными словами, для обращения к графическому функтору func_name в общем случае нужен синтаксис graphics!!func_name — но достаточно func_name, если graphics уже является текущим пространством имен.)

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

 

Графические примитивы

Графические примитивы — это функторы, непосредственно выполняющие определенные операции графического вывода. К примеру, graphics!!plot (x, y) выводит единственную точку с координатами (x, y). Заметим, что во всех графических функторах координаты являются целыми числами (применяются все стандартные приведения), а система координат по умолчанию совпадает с принятой в Windows (т.е. началом координат (0, 0) является верхний левый угол области вывода и оси координат направлены вправо и вниз).

Ряд функторов требует задания более чем одной точки в качестве аргументов — в этом случае, каждая точка задается простейшим списком координат вида (x, y). Например, примитив graphics!!line (from, to) рисует отрезок, определенный своей начальной точкой (from) и конечной точкой (to) (при этом отрезок включает начальную точку, но не конечную). Аналогично, примитив graphics!!rect ((top, left), (bottom, right)) рисует прямоугольник, также определенный двумя точками: координатами своего верхнего/левого (top, left) и нижнего/правого (bottom, right) углов.

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

 

Графические оболочки

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

Приведем пример: графическая оболочка graphics!!plot_color (Color, @Core) задает цвет рисования линий (Color) для ядра Core (префикс @ здесь и дальше будем использовать как индикатор «ленивого» вычисления аргумента функтора). Другими словами: эффект этого вызова состоит в том, что для любых графических примитивов, выполняемых внутри Core, цвет рисования линий устанавливается в Color.

В этом и других функторах цвет задается в цветовой модели RGB. Это удобнее делать с помощью набора функторов, определенных в winter.awl.

 

RGB (Red, Green, Blue): задает цвет, явно определенный цветовыми компонентами: красной (Red), зеленой (Green), синей (Blue). Каждая из них может изменяться от 0 до 255, значение по умолчанию — 255.

Для примитивных цветов имеются явные определения:

 

Black (N):                   черный

Red (N):                     красный

Green (N):                  зеленый

Yellow (N):                 желтый

Blue (N):                    синий

Magenta (N):             пурпурный

Cyan (N):                   голубой

Grey (N):                    серый/белый

White (N):                  серый/белый

 

Для каждого примитива аргумент N задает интенсивность данного цвета (от 0 до 255). По умолчанию принимается максимальная интенсивность (255), любой цвет с минимальной интенсивностью (0) является черным.

 

Примеры:

 

graphics!! plot_color (Yellow (), plot (x1, y1));

 

- рисует ярко-желтую точку с координатами (x1, y1).

 

graphics!! plot_color (Green (128), { line ([0 N]; [N 0]); line ([0 0], [N N]) });

 

- рисует бледно-зеленым цветом два отрезка (образующие косой диагональный крест, вписанный в квадрат ([0 0], [N N])).

 

Оболочка plot_color задает не только цвет рисования линий для таких примитивов, как plot и line, но и определяет цвет контура для функторов, рисующих двухмерные объекты, такие как прямоугольники (rect), овалы (oval), многоугольники (polygon) и другие. На эти примитивы также влияет цвет заполнения внутренней области (цвет интерьера), который задается оболочкой graphics!! fill_color (Color, @Core). Аргумент Color задается аналогичным образом. Например:

 

graphics!! plot_color (Red (), fill_color (Cyan (), oval ([50 50], [100 100])));

 

рисует эллипс (вписанный в прямоугольник ([50 50], [100 100])) имеющий красную (Red) границу и голубой (Cyan) интерьер. Понятно, что в этом примере вложенность plot_color и fill_color можно поменять местами, результат от этого не изменится.

 

Заметим также, что при использовании графических оболочек особенно удобно применять компактную нотацию для вложенных вызовов. Именно, синтаксис

 

F (A) :: B

 

эквиваленен

 

F (A, B)

 

но часто бывает удобнее и понятнее, особенно, при большой глубине вложенности оболочек. Так, приведенные выше примеры можно переписать в таком виде:

 

graphics!! plot_color (Yellow ()):: plot (x1, y1);

graphics!! plot_color (Green ()):: { line ([0 N]; [N 0]); line ([0 0], [100 100]) };

 

graphics!! plot_color (Red ()):: fill_color (Cyan ()):: oval ([50 50], [100 100]);

 

Резюмируем: в качестве ядра оболочки может использоваться произвольное AWL-выражение (включая блоки, вызовы других оболочек и любых других функторов), а эффект исполнения оболочки заключается в том, что на время выполнения ядра определенные атрибуты графики (например, цвета) будут изменены. Еще раз подчеркнем, что графические оболочки действуют только на работу графических примитивов: любой другой код выполняется в оболочке так же, как и вне ее. Конечно, оболочки могут быть вложенными — в т. ч. рекурсивно и на произвольную глубину. Например:

 

graphics!! plot_color (Blue ()):: {

            line ([10 100], [20 100]);

            plot_color (Yellow ())::

line ([30 100], [40 100]);

            line ([50 100], [60 100]);

            }

 

В данном примере рисуются три горизонтальных отрезка (с y=100), причем отрезки x=10..20 и x=50..60 рисуются синим (Blue) цветом, а отрезок x=30..40 — желтым (Yellow) цветом. Таким образом, внутренний plot_color временно меняет цвет рисования на желтый, но до входа в него и после выхода из него действуют установки внешнего plot_color, определяющего синий цвет рисования. Аналогично работает fill_color, и большинство других графических оболочек. (Заметим, что вне самого внешнего вызова plot_color/fill_color соответствующие цвета системно-зависимы, и их лучше считать неопределенными.)

 

Приведем список наиболее употребительных примитивов графики.

(Все они определены в пространстве имен graphics)

 

plot (x, y)

 

Рисует одну точку с координатами (x, y). Цвет задается оболочкой plot_color.

 

line ((x0, y0), (x1, y1))

 

Рисует отрезок (вектор) от (включая) точки (x0, y0) до (исключая) точки (x1, y1). Цвет задается оболочкой plot_color.

 

rect ((left, top), (right, bottom))

 

Рисует заполненный прямоугольник, заданный противолежащими углами: верхним/левым (left, top) и нижним/правым (right, bottom). Цвет контура задает plot_color, цвет интерьера задает fill_color.

 

oval ((left, top), (right, bottom))

 

Рисует заполненный овал (эллипс), вписанный в прямоугольник, заданный верхним/левым (left, top) и нижним/правым (right, bottom) углами. Цвет контура задает plot_color, цвет интерьера задает fill_color.

 

round_rect ((left, top), (right, bottom), (x_rad, y_rad))

 

Рисует заполненный прямоугольник с закругленными (эллиптическими дугами) углами, заданный верхним/левым (left, top) и нижним/правым (right, bottom) углами. Значения (x_rad, y_rad) задают x и y радиусы закругления. Цвет контура задает plot_color, цвет интерьера задает fill_color.

 

arc ((left, top), (right, bottom), (x_from, y_from), (x_to, y_to))

chord ((left, top), (right, bottom), (x_from, y_from), (x_to, y_to))

wedge ((left, top), (right, bottom), (x_from, y_from), (x_to, y_to))

 

Все три примитива рисуют разные фрагменты эллипса: дугу (arc), заполненный сегмент (chord) и заполненный сектор (wedge). Для всех примитивов эллипс задается аналогично oval, т.е. вписан в прямоугольник ((left, top), (right, bottom)). Область отсечения эллипса задается (по часовой стрелке) от радиус-вектора (x_from, y_from) до радиус-вектора (x_to, y_to) (координаты относительно центра эллипса). Цвет контура задает plot_color, цвет интерьера (для chord и wedge) задает fill_color.

 

polygon ((x0, y0), (x1, y1), (x1, y2), … (xN, yN), )

 

Рисует заполненный многоугольник, определенный набором точек-вершин (x0, y0) … (xN, yN). Заметим, что в этом функторе список точек должен быть терминированным (т.е. должен завершаться пустым элементом, как показано выше). Цвет контура задает plot_color, цвет интерьера задает fill_color.

 

fill ((left, top), (width, height))

 

Просто заполняет (без оконтуривания) прямоугольную область с левым/верхним углом (left, top), шириной width и высотой height.

 

pixel ((x, y), Color)

 

Выводит единственный пиксел с координатами (x, y) с цветом Color.

(Выполнение данного примитива совершенно не зависит от окружающих его графических оболочек. Аналогичного эффекта можно добиться с помощью

 

plot_color (Color):: plot (x, y)

 

но pixel работает намного быстрее.)

 

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

 

! draw_line (From To Color) = graphics!! plot_color (Color, line (From, To));

 

Теперь вызов draw_line ([50 50], [80 80], Green()) соединяет точки [50 50] и [80 80] отрезком зеленого цвета.

Так же просто определить и новые графические функторы-оболочки. Например:

 

! Red_On_Blue (@X) = graphics!! plot_color (Red ()):: fill_color (Blue ()):: (^X);

 

Теперь (независимо от текущих атрибутов графической среды) вызов

 

Red_On_Blue (graphics!!rect (x0, y0), (x1, y1));

 

рисует синий прямоугольник с красной каймой, определенный координатами углов (x0, y0), (x1, y1). Аналогично,

 

Red_On_Blue (graphics!!{ oval ([10 10], [50 50]); oval ([110 110], [150 150]); });

 

рисует пару кругов с теми же цветами. Если же часто надо выводить объекты с одинаковыми цветами каймы и интерьера, следующее определение упрощает эту задачу:

 

! colored (Color, @_) = graphics!! plot_color (Color):: fill_color (Color):: (^_);

 

и так далее.

 

Тексты и шрифты

 

Конечно, помимо объектов графики не менее важно иметь возможность выводить фрагменты текста. (Впрочем, это — тоже графические объекты.) Важнейшую роль в этом играет примитив graphics!!text, набор аргументов которого предельно прост:

 

graphics!! text (string)

 

Он выводит на экран строку текста, заданную скаляром string (если операнд не является строкой — например, числовой — применяются стандартные приведения). Практически все атрибуты вывода определяются неявно.

Прежде всего, это относится к текущей позиции вывода текста. Это — один из немногих атрибутов графической системы, который явно мутабелен, т.е. меняется от одного вызова к другому. В частности, каждое новое обращение к text изменяет текущую позицию (x, y): y-координата остается неизменной, x-координата увеличивается таким образом, что следующая строка выводится в подбор к предыдущей. Иными словами, следующий код

 

graphics!! text (“Hello, world!!”);

 

имеет абсолютно тот же эффект, что и:

 

graphics!! { text (“Hello”); text (“, ”); text (“world!!”) };

 

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

 

graphics!! text_org (x, y);

 

устанавливает текущую позицию вывода на точку (x, y). При этом следующий символ выводится непосредственно справа от x, а y задает положение базовой линии текста. Подробнее об этом ниже. Другие графические примитивы, помимо text и text_org, на текущую позицию вывода текста не влияют.

Все остальные атрибуты текста задаются неявно, т.е. с помощью функторов-окружений. Приведем их список:

 

font_face (Face, @Core);

 

- выводит Core шрифтом с гарнитурой Face. Гарнитура задается строкой, содержащей системно-определенное имя шрифта: например “Arial”, “Helvetica”, “Times” и т.д.

 

font_size (Size, @Core);

 

- выводит Core шрифтом с кеглем Size. (Кегль задается в пикселах.)

 

font_weight (Weight, @Core);

 

- выводит Core шрифтом с плотностью Weight. Предполагается, что значение 0 соответствует нормальному шрифту, < 0 — более тонкому шрифту, > 0 — более жирному шрифту. (Для большинства шрифтов Windows имеют смысл только значения 0 — нормальный и 1 — полужирный.)

 

font_italic (On_Off, @Core);

font_underline (On_Off, @Core);

font_overstrike (On_Off, @Core);

 

- позволяют изменять такие атрибуты выводимого текста как курсив (font_italic), подчеркивание (font_underline) и перечеркивание (font_overstrike). Во все этих функторах истинное (т.е. ненулевое) значение параметра On_Off означает, что Core выводится с соответствующим атрибутом (курсивом, подчеркиванием или перечеркиванием); ложное (0) значение выключает этот атрибут.

 

font_fgcolor (Color, @Core)

font_bgcolor (Color, @Core)

 

- позволяет задать цвета выводимого текста: цвет собственно шрифта (font_fgcolor) и цвет фона (font_bgcolor). (Цвета задаются так же, как и в plot_color / fill_color.)

 

font_inverse (@Core)

 

- эффект «выворотки»: меняет местами цвет текста и фона. Заметим, что этот функтор не имеет параметров (кроме Core), и его действие не распространяется «вглубь»: вызовы font_fgcolor/font_bgcolor внутри Core имеют стандартный эффект.

 

Следующий пример выводит текст “HELLO!!!”: зеленый на сиреневом фоне, шрифтом Arial с кеглем 24.

 

graphics!! font_face (‘Arial’):: font_size (24):: font_fgcolor (Green ()):: font_bgcolor (Magenta ()):: text “HELLO!!!”;

 

Конечно, в данном примере можно поменять вложенность всех оболочек без какого-либо эффекта для результата. Все «шрифтовые» окружения ведут себя аналогично графическим. Например, они могут быть вложены рекурсивно на неограниченную глубину (переопределяя, при необходимости, эффект друг друга).

 

Помимо собственно вывода текста, необходимо уметь определять его метрические параметры (или просто метрики): ширину, высоту, вертикальное расположение относительно базовой линии. Для этого в графической системе предусмотрена специальная оболочка: graphics!!text_metrics.

 

graphics!!text_metrics (metrics_list, output_flag, @Core)

 

Как и все оболочки, этот вызов выполняет Core, и присваивает metrics_list (должно быть мутабельным выражением!) суммарную информацию о метриках текста, выведенных при вычислении Core. Иными словами, эффект этого функтора такой же, как если б мы выполнили следующее присваивание:

 

metrics_list = (Width, Ascent, Descent, Leading);

 

Элементы этого списка имеют следующее значение:

 

Width: суммарная ширина выведенного текста (т.е. разность между начальным и конечным значениями x-координаты текущей позиции);

 

Ascent: максимальный подъем выведенного текста (т.е. насколько самая верхняя точка выводимого текста выше базовой линии);

 

Descent: максимальный спуск выведенного текста (т.е. насколько самая нижняя точка выводимого текста ниже базовой линии);

 

Leading: предполагаемый интерлиньяж выведенного текста (дополнительное расстояние между подряд идущими строками, не включающее в себя подъем и спуск текста).

 

Значения всех метрик — целые числа, и измеряются они в пикселях. Если ширина прямоугольника, заключающего текст, прямо доступна как Width, то его высота вычисляется как Ascent + Descent (и дополнительно плюс Leading, если необходимо учесть межстрочный интервал).

 

Оболочка text_metrics аккуратно подсчитывает метрики и аккумулирует их для всех элементов text, выводимых в ее ядре. Значение Width является суммой, остальные три метрики — максимумом по всем значениям соответствующих параметров. Приведем примеры:

 

graphics!! text_metrics (m_list, 1, text “Hello!!!”);

 

graphics!! text_metrics (m_list, 1, {

font_size 10 :: text “Small text… ”;

font_size 16 :: text “Bigger text… ”;

font_size 24 :: text “Biggest text !!!”;

});

 

В первом случае мы выводим единственную строку “Hello!!!”, во втором — три строки подряд, с разными кеглями. В обоих случаях text_metrics гарантирует корректный подсчет (и запоминание в m_list) всех размеров выводимого текста. (Заметим, однако, что выполнение в Core text_org никакого влияния на результаты, выдаваемые text_metrics, не оказывает: даже если строки текста выводятся в разные места, их размеры подсчитываются так, будто они выводятся в подбор.)

Мы еще не рассматривали второй аргумент text_metrics (output_flag), дающий очень интересную возможность. Именно, если его значение не равно нулю (т.е. истинно), то реальное выполнение всех обращений к graphics!!text внутри Core будет подавлено: никакой текст реально не будет выведен, хотя все его размеры будут подсчитаны так, как будто вывод на самом деле имел место. Как обычно, значение output_flag влияет исключительно на выполнение вложенных примитивов text, и ни на что другое.

Эту особенность можно использовать для правильного позиционирования выводимого текста перед его выводом. Вот, например, как можно центрировать выводимый текст (Core) в прямоугольнике, заданном параметрами (Origin, Extent):

 

! center_text (Origin Extent @Core): [Metrics TWidth TAscent TDescent TLeading] = graphics!! {

            ` Фиктивный вывод `

            text_metrics (Metrics, 1, (^Core));

            [TWidth TAscent TDescent TLeading] = Metrics;

 

            ` Установка правильной позиции `

            text_org (

                        Origin[0] + (Extent[0] - TWidth) % 2,

                        Origin[1] + TAscent + (Extent[1] - TAscent - TDescent) % 2

                        );

 

            ` Реальный вывод! `

            ^Core;

            };

 

Новая оболочка center_text будет работать правильно с любым Core (до тех пор, пока мы не трогаем позицию вывода внутри самого Core). Например:

 

center_text ([10 10], [200 160],

{ font_size 12:: “Маленький и ”; font_size 20:: “большой текст!” });

 

выводит текст

Маленький и большой текст!

 

точно по центру прямоугольника с началом [10 10] и размерами [200 160].

 

Начиная с AWL 0.5.1 можно выводить произвольные символы Unicode. Вызов

 

graphics!!unichar (Code);

 

выводит символ Unicode с кодом Code (заметим, что Code вычисляется как целое число, а не строка!). Используются та же позиция вывода и те же атрибуты, что и для graphics!!text. Конечно, этот же функтор можно использовать и для вывода ASCII-символов (т.к. первые 256 символов Unicode совпадают с ASCII).

 

Оконные объекты («виджеты») и их работа

 

Интерфейс пользователя с оконной системой реализуют экранные элементы диалога, или «виджеты» (widgets). Каждый из них является производным от библиотечного класса Widget, реализованного в модуле winter.awl.

 

Виртуальные функторы Widget

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

 

  • Widget!! on_open:

on_open (Extent)

 

- Инициализация виджета. Метод on_open вызывается, когда виджет начинает свою работу (обычно, когда окно, содержащее его, отображается на экране). Аргумент Extent содержит размеры виджета в виде списка (Высота, Ширина). Действия по умолчанию отсутствуют.

 

  • Widget!! on_close:

on_close (Extent)

 

- Деинициализация виджета. Метод on_close вызывается, когда виджет завершает свою работу (обычно, когда окно, содержащее его, исчезает с экрана). Аргумент Extent содержит размеры виджета в виде списка (Высота, Ширина). Действия по умолчанию отсутствуют.

 

  • Widget!! on_resize:

on_resize (Extent)

 

- Метод on_resize вызывается каждый раз, когда размеры виджета меняются, при этом параметр Extent содержит новые размеры (Высота, Ширина). Реакция по умолчанию отсутствует, однако последние актуальные размеры виджета автоматически сохраняются в Widget!!Height и Widget!!Width.

 

  • Widget!! on_paint:

on_paint (Area)

 

- Метод on_paint может вызываться многократно, каждый раз, когда оконная система требует перерисовать видимую область виджета полностью или частично — например, ввиду того, что часть виджета, ранее закрытая другим окном, теперь стала видимой. Обычно on_paint также вызывается в самом начале работы виджета, сразу после on_open. Кроме того, прямоугольник, определяющий область рисования, передается параметром Area, в виде ((Left, Top), (Right, Bottom)). Этот метод — единственный, который неявно создает графическое окружение (т.е. в нем можно непосредственно обращаться ко всем

графическими примитивам). Какая-либо перерисовка по умолчанию отсутствует (иными словами, клиентская область виджета по умолчанию считается «невидимой» или «прозрачной»).

 

  • Widget!! on_focus:

on_focus (InOut)

 

- Метод on_focus вызывается всякий раз, когда виджет получает (тогда InOut истинно), или теряет (тогда InOut ложно) т.н. «фокус ввода». Только виджет, имеющий фокус ввода, способен получать сообщения от клавиатуры — такие, как on_char или on_key.

 

  • Widget!! on_char:

on_char (Code)

 

- Метод on_char вызывается при нажатии любой клавиши, которая может быть интерпретирована как ввод символа из стандартного ASCII-набора. Параметр Code содержит ASCII-код введенного символа в виде числа (не строки!).

 

  • Widget!! on_key:

on_key (Event Code)

 

- Метод on_key вызывается как при нажатии, так и при отпускании большинства клавиш. Конкретное событие определяется параметром Event:

Event < 0 — клавиша отпущена,

Event > 0 — клавиша нажата Event раз подряд (возможно, больше 1 раза).

Параметр Code задает код клавиши. Для большинства алфавитно-цифровых клавиш код совпадает с ASCII-кодом символа. Для остальных подробный список приведен ниже.

 

  • Widget!! on_mouse_click:

on_mouse_click (Event State Point)

 

- Метод on_mouse_click вызывается при нажатии и при отпускании кнопки мыши, когда курсор мыши находится в области виджета. Параметр Event определяет конкретное событие:

-1 — отпускание кнопки мыши

1 — нажатие кнопки мыши

2 — двойной щелчок кнопки мыши

 

Младшие 16 битов параметра State содержат нажатой/отпущенной клавиши, старшие 16 битов — код, определяющий состояние прочих клавиш. Параметр Point задает точку, в которой находится курсор мыши в виде списка (X, Y).

 

  • Widget!! on_mouse_move:

on_mouse_move (State From To)

 

- Метод on_mouse_move вызывается при любом перемещении курсора мыши, связанном с областью виджета: когда курсор перемещается в пределах виджета, входит в виджет или выходит из него. Параметры From и To сообщают (соответственно) начальную и конечную точки перемещения курсора, в виде списков (X, Y). Один из этих параметров (но не оба) может быть равен undef (если курсор входит в виджет, то параметр From не определен, если курсор выходит из виджета, то параметр To не определен).

Параметр State содержит в старших 16 битах текущее состояние кнопок мыши (аналогично on_mouse_click).

 

  • Widget!! on_mouse_wheel:

on_mouse_wheel ()

 

- Метод on_mouse_wheel зарезервирован для обработки сообщений от колеса мыши.

 

  • Widget!! on_timer:

on_timer ()

 

- Метод on_timer зарезервирован для обработки сообщений, связанных с таймером.

 

Далее следует список кодов клавиатуры, доступных как параметр Code в on_key:

 

KB_Left, KB_Up, KB_Right, KB_Down: стрелки;

KB_Home, KB_End, KB_PgUp, KB_PgDn, KB_Ins, KB_Del, KB_Center: цифровая клавиатура, последний код соответствует [5];

KB_F1KB_F12: функциональные клавиши;

KB_Shift, KB_Ctrl, KB_Alt, KB_CapsLk, KB_NumLk, KB_ScrollLk: переключатели регистров;

KB_Pause: пауза.

 

Кнопкам мыши соответствуют следующие коды. (Они доступны как параметр State в on_mouse_move и on_mouse_click.)

 

MB_Left, MB_Middle, MB_Right: левая, средняя и правая кнопки;

MB_Ext1, MB_Ext2: дополнительные кнопки 1 и 2 (если они есть).

 

(Все эти коды являются флагами и могут комбинироваться: скажем, MB_Left|MB_Middle означает, что нажаты левая и средняя кнопки мыши.)

 

Методы Widget (не виртуальные)

 

-         with_widget (@Core);

 

Является оболочкой, обеспечивающей выполнение кода Core для текущего экземпляра Widget. Заметим, что (за исключением метода on_paint!), все прочие обработчики событий требует использования этой оболочки для рисования чего-либо в клиентской области виджета. Также заметим, что метод может использоваться для отрисовки произвольного виджета (не обязательно того, который получает сообщение).

 

-         close_widget ();

 

Закрывает окно, содержащее текущий виджет.

 

-         alert_box (title message flags);

 

Выводит модальное окно-предупреждение, с заголовком title и текстом message (параметр flags пока игнорируется). Заметим, что созданное окно связано с окном, содержащим текущий виджет.

 

-         alert_beep (param);

 

Стандартный (для Windows) звуковой сигнал – предупреждение. (Значение param зарезервировано.)

 

Оконные сессии

 

Вся работа с виджетами выполняется в рамках текущей оконной сессии. Для запуска сессии требуется обращение к WinSession:

 

WinSession (

            (Widget1, (Left1, Top1), (Width1, Height1)),

            (Widget2, (Left2, Top2), (Width2, Height2)),

           

            (WidgetN, (LeftN, TopN), (WidthN, HeightN)),

            );

 

Этот вызов открывает N окон верхнего уровня (управляемых Windows), каждое из которых содержит один из виджетов (Widget1WidgetN), причем для каждого окна начальные координаты заданы списком (LeftN, TopN), а начальные размеры (окна в целом, включая обрамление) — списком (WidthN, HeightN). Заметим, что размеры могут отсутствовать — в этом случае они вычисляются, исходя из размеров самого виджета. Также надо отметить, что список аргументов WinSession должен быть терминированным — обратите внимание на запятую перед закрывающей скобкой.

После того, как все окна открываются (при этом для каждого виджета вызываются, в указанном порядке, on_open, on_resize и on_paint), оконная сессия начинает работу. Она продолжается до тех пор, пока открыто хотя бы одно окно, и немедленно завершается, когда последнее окно сессии закрывается, после чего выполнение кода нормально продолжается за вызовом WinSession. Заметим, что оконные сессии нереентранты (нельзя начать новую сессию, не завершив предыдущую). Однако, пока сессия работает, можно открывать новые окна с виджетами. В качестве результата вызов WinSession возвращает внутренний счетчик сообщений, обработанных на протяжении сессии.

 

(Продолжение следует…)

 



Hosted by uCoz