Территориальность
Любой видимый элемент Turbo Vision имеет два важнейших свойства: он полностью контролирует изображение в пределах выделенного ему участка экрана и знает, как обрабатывать связанные с этим участком события – нажатие на клавиши или отметку мышью. Эти свойства определяются двумя псевдоабстрактными методами объекта TView (этот объект является родителем всех остальных видимых элементов Turbo Vision): Draw и HandleEvent.
Метод Draw знает, как рисовать объект, но не знает, когда это нужно делать. Метод HandleEvent, наоборот, знает когда, но не знает как. Эти методы в наибольшей степени воплощают основной принцип программ, управляемых событиями: процесс создания изображений и процесс обработки событий – это два разных процесса в том смысле, что в первом случае мы сообщаем программе как создается изображение, а во втором – когда это нужно делать. Обработке событий посвящена следующая глава.
В этой главе мы рассмотрим некоторые детали технической реализации видимых элементов, которые дадут нам возможность разобраться в том, что именно делает видимый элемент и как он это делает. Эти сведения помогут Вам правильно использовать видимые элементы в Вашей программе.
Видимый элемент владеет прямоугольным участком экрана. Правильно сконструированный элемент обязан заполнять нужным изображением всю выделенную ему область, иначе на экране останется "мусор". Чтобы элемент мог заполнить область, он должен знать координаты закрепленного за ним участка. Эти координаты хранятся в двух полях – Origin и Size, каждое из которых имеет тип TPoint. Поле Origin задает координаты левого верхнего угла области, выделенной элементу, поле Size – размер этой области, т.е. показывает на каком расстоянии от Origin находится его правый нижний угол. Минимальный по размеру видимый элемент, который может хоть что-то вывести на экран, имеет Size.X = Size.Y=1.
Объект TPoint крайне прост, он только определяет координаты некоторой точки на экране и не имеет никаких методов:
type TPoint = object X: Integer; {Горизонтальная координата} Y: Integer; {Вертикальная координата} end;
Координаты в Turbo Vision имеют две особенности. Во-первых, они указывают позицию на экране, начиная с 0, а не с 1, как это принято в стандартных для Турбо Паскаля подпрограммах работы с текстовым экраном (например, GotoXY из модуля CRT). Во-вторых, все координаты задаются относительно границ той группы видимых элементов, в которой создается и используется новый элемент. В Turbo Vision любой видимый элемент входит в состав какой-то группы, поскольку все элементы в конечном счете принадлежат программе, которая сама по себе является группой.
Для указания всех четырех координат видимого элемента и действий над ними используется тип TRect следующего вида:
type TRect = object A: TPoint; {Левый верхний угол } В: TPoint; {Правый нижний угол} Procedure Assign(XA,YA,XB,YB: Integer); {Назначает значения параметров полям А и В} Procedure Copy(R: Trect); {Устанавливает все поля, равными прямоугольнику R} Procedure Move(ADX,ADY: Integer); {Смещает прямоугольник, добавляя ADX к А.Х, В.Х и ADY к А. Y, B.Y} Procedure Grow(ADX,ADY: Integer); {Изменяет размер, вычитая ADX из А.Х и прибавляя ADX к В.Х; вычитая ADY из A.Y и прибавляя ADY к B.Y} Procedure Intersect(R: TRect); {Изменяет положение и размер прямоугольника до области, определенной пересечением R и текущего положения элемента} Procedure Union(R: Trect); {Изменяет прямоугольник до области, определяемой объединением R и текущего положения элемента} Function Contains(P: TPoint): Boolean; {Возвращает TRUE, если точка принадлежит элементу} Function Equals(R: Trect): Boolean; {Возвращает True, если положение и размеры прямоугольника R и элемента одинаковы} Function Empty: Boolean; {Возвращает TRUE, если элемент пустой, т.е. если его поля Size.X и Size,У. равны нулю} end;
С помощью полей Owner^.Origin и Owner^.size видимый элемент может определить положение и размер своего владельца, т.е. той группы, в состав которой он входит, а с помощью метода:
Procedure GetExtend(var R: Trect)
Получить в R свои текущие координаты (напомню, что положение и размеры большинства видимых элементов могут меняться в ходе работы программы). Обычно обращение к GetExtend используется перед тем, как задать максимально возможные координаты вновь создаваемого видимого элемента. Например, если внутри окна TWindow нужно поместить скроллер так, чтобы он занял всю внутреннюю часть окна, можно использовать такой фрагмент:
type MyWindow = object (TWindow) ….. Constructor Init; ….. end; Constructor MyWindow.Init; var S: PScroller{Указатель на скроллер} R: TRect; HS, VS: PScrollBar;{Указатели на полосы скроллера} ….. begin ….. GetExtend(R);{Получаем координаты окна} R.Grow(-1, -1);{Уменьшаем их на 1} S: = New(PScroller, Init(S, HS, VS)){Создаем скроллер} Insert(S);{Помещаем скроллер в окно} ….. end;