
    1.RawWindow

    UpdateContents

Объявление

    procedure UpdateContents; virtual;

Функция

    Корректировка содержания окна, изображенного на экране.

Описание

    Прикладные программы не должны вызывать этот метод прямо.
Метод Draw для RawWindow вызывает рассматриваемую процедуру
если установлен флаг wUserContents и наступил момент времени
для заполнения содержания окна. Применение метода UpdateContents
в  RawWindow не вызывает никаких изменений. Однако, многие
типы, полученные из RawWindow отвергают действие рассматриваемого
метода: PickList рисует видимую часть перечня выборки; Menu
рисует все видимые подменю и корректирует перечень элементов
меню; Memo рисует видимые линии текста после вычисления
вертикального и горизонтального перемещения; и т.д. Метод
UpdateContents объясняет возможности объектных профессиональных
окон иметь многие общие черты, но широко различаться по задачам,
которые они решают.

Пример

uses
  OpCrt, Opftame, Opwindow;
type
  XWin = object(RawWindow)
    procedure UpdateContents;virtual;
  end;
var
  Win : XWin;

  procedure XWin.UpdateContents;
  var
    Xlo, Ylo, Xhi, Yhi, I, J: Byte;
  begin
    Coordinates(Xlo, Ylo, Xhi, Yhi);
    for I := Ylo to Yhi do
      for J := Xlo to Xhi do
        FastText(Char($40+1), I, J);
    end;

begin
  Win.Init(30, 5, 50, 15);
  Win.wOptionsOn(wBorded+wUserContents);
  Win.Draw;
  {...Use window...}      {Используйте окна}
  Win.Done;
end.

 Win - экземпляр XWin (полученный из RawWindow). Win отвергает
метод UpdateContents из RawWindow. При любом обращении к
Win.Draw Win вызывает UpdateContents из XWin для заполнения
окна. Отметим, что для этого окна устанавливается  флаг
WUserContents. В более сложных примерах XWin имеет свой
конструктор, который устанавливает флаг при любом создании
экземпляра XWin.

   UpdateScreenSize

Объявление

{$IFDEF UseAdjustableWindows}
procedure UpdateScreenSize;

Функция

    Корректировка размера окна, положения и пределов для
текущего размера окна.

Описание

    После того, как RawWindow создано, устанавливаются
по умолчанию пределы по изменению размеров и положения
окна. Максимальные пределы устанавливаются равными размеру
экрана в текущий момент времени. Если после этого будет
изменен режим экрана, эти пределы могут стать недопустимыми.
Фактически, становятся недопустимыми положение и размер окна.
(Предположим, что окно было создано в режиме 43 линии, а
затем окно было переключено в режим 25 линий.) Задача
становится особенно сложной и неприятной в случае, если
окна могут храниться и загружаться из потока, так как нет
никаких гарантий, что размер экрана при загрузке окна
будет такой же как при запоминании. Фактически, главной
движущей силой обеспечения рассматриваемого метода являются
соответствующим образом поддержанные потоки , созданные с
помощью MAKEMENU и MAKESCRN.
    UpdateScreenSize хранит величины размера экрана при
последнем вызове. В случае нового обращения без изменения
размера экрана процедура мгновенно оканчивает работу без
какой-либо временной задержки.
    В противном случае UpdateScreen корректирует пределы для
максимального размера активного окна и максимального положения
с учетом нового размера экрана. Отметим, что минимальные
пределы не изменяются. В случае необходимости UpdateScreenSize
устанавливает новое положение окна с тем, чтобы оно находилось
в пределах новых границ. Усли недостаточно одного изменения
положения окна, метод предпринимает попытку изменить размеры
окна, чтобы окно осталось в пределах границ.
    При вызове UpdateScreenSize окно должно быть неактивным
либо текущим окном. Если это не так, то метод дает ошибку
(epNonFatal+ecWinNotCurrent) и прекращает работу. В случае,
когда размер окна больше размера текущего экрана и не
установлен флаг wResizeable UpdateScreenSize дает ошибку
(epNonFatal+ecWinCoordsBad). Если возникает необходимость
отрегулировать положение окна и его размер UpdateScreenSize
может создавать такие же ошибки, как и процедура
AdjustWindow.
    UpdateScreenSize работает как с увеличенными , так и
с неувеличенными окнами.

Пример

SelectFont8x8(False);           {Подтверждается режим 25 линий}
Win.Init(10, 5, 30, 20);        {Создать и нарисовать окно}
Win.Draw;
SelectFont8x8(True);            {Переключить в режим 43/50 линий}
Win.UpdateScreenSize;           {Корректировка границ окна}
Win.MoveWindow(0,+15);          {Переместить окно в новую
                                 область экрана}
Win.Erase;
SelectFont8x8(False);           {Переключить обратно в режим
                                 25 линий}
Win.UpdateScreenSize;           {Корректировка положения и
                                 границ окна}
Win.Draw;                       {Перерисовать окно}

    Создается окно, а затем его рисуют. При этом экран находится
в режиме 25 линий. Затем экран переключается в режим 43 или
50 линий( предполагается, что используются EGA и VGA), и окно
корректируется в соответсвии с новым размером экрана. Это
позволяет переместить окно в пределах границ более широкого
экрана. Окно стирается и экран переключается обратно в режим
25 линий. Теперь UpdateScreenSize  должна отрегулировать
положение окна с тем, чтобы можо было сохранить окно на
экране. И наконец, окно снова рисуют.

Дополнительно см.

 AdjustWindow

     Записи, связанные с окном

Объявления

procedure wFastWrite(St : string; Row, Col, Attr: Byte);
  {-Write a string}
  {Записать строку}

procedure wFastText(St : string; Row, Col : Byte);
  {-Write St at Row,Col without changing the underlying video attribute}
  { Записать St в строку Row, столбец Col без изменения
     расположенных ниже видеоатрибутов}

procedure wFastVert(St : string; Row, Col, Attr: Byte);
  {-Write a string vertically}
  { Записать строку вертикально}

procedure wFastFill(Number : Word; Ch: Char; Row, Col, Attr: Byte);
  {-Fill Number Chars at Row, Col in Attr}
  { Заполнить Number символов в строку Row, столбец Col в Attr}

procedure wChangeAttribute(Number : Word;Row, Col, Attr : Byte);
  {-Change Number video attributes to Attr starting at Row, Col}
  { Изменить Number видео атрибутов в Attr, начиная с Row, Col}

procedure wFastCenter(St : string; Row, Attr : Byte);
  {-Write St centered on Row in Attr}
  { Записать St по центру строки Row в Attr}

procedure wFastFlush(St : string; Row,  Attr : Byte);
  {-Write St flush right on Row in Attr}
  { Записать St, выравнивая справа, в строку Raw в Attr}

procedure wFastRead(Number, Row, Col : Byte; var St : string);
  {-Read Number Characters from the screen into St starting at Row, Col}
  { Записать Number символов с экрана в St, начиная с Row, Col}

procedure wReadAttribute(Number, Row, Col : Byte; var St : string);
  {-Read Number attributes from the screen into St starting at Row, Col}
  { Считать Number атрибутов с экрана в St, начиная с Row, Col}

procedure wWriteAttribute(St : String; Row, Col : Byte);
  {-Write string of attributes St at Row, Col without changing characters}
  { Записать строку атрибутов St в  Row, Col без изменения символов}

procedure wFlexWrite(St : string; Row, Col : Byte; var FAttrs : FlexAttrs);
  {-Write a string flexibly using window-relative coordinates}
  { Записать строку гибко, используя координаты относительно окна}

procedure wFastWriteCtrl(St : String; Row, Col, Attr, Ctrl : Byte);
  {-Write St at Row, Col in Attr (video attribute) without show.
    Control characters displayed in Ctrl as upper-case letters}
  { Записать St  в строку Row, столбец Col в Attr(видео атрибуты)
    без "снега". Управляющие символы выводятся на экран в Ctrl
    как символы верхнего регистра}


Функция

    Записать, используя координаты относительно границ активного
окна.

Описание

   Рассматриваемые методы предлагают ряд удобных способов
записи и считывания содержания окна. Если кадр  имеет рамку,
точка (1,1) для рассматриваемых процедур находится чуть внутри
верхнего левого угла рамки. В случае, если кадр  не имеет рам-
ки, точка (1,1) совпадает с левым верхним углом кадра.
    Отметим, что координаты, передаваемые каждой процедуре,
располагаются в следующем порядке: строка Row, столбец Col.
Допустимый диапазон для Row : от 1 до Win.Height, а для Col -
от 1 до Win.Width. Рассматриваемые процедуры при необходимости
обрезают границы окна. Не допускается запись или считывание
за пределами текущего окна.
    Если окно не является активным в момент вызова, каждая
процедура создает ошибку (epNonFatal+ecWinNotActive) и прекращает
работу. Отметим, что в случае записи в окно, оно не обязательно
должно быть текущим. Однако, Вы должны гарантировать, что
окно не загорожено другими окнами; рассматриваемые процедуры
слепо записывают в указанные координаты. В случае, если Вам
необходимо записать в частично загороженное окно, определите
каждое окно как StackWindow и воспользуйтесь одноименными
процедурами из названного объекта.
    wFastWrite записывает в указанный видео атрибут. Применение
процедуры вызывает выбор атрибута соответственно для цветного
и монохроматического видео режимов.
    wFastText  записывает строку без изменения ниже расположеных
видео атрибутов. Отметим, что результат работы этой процедуры
не обязательно совпадает с результатом вызова wFastWrite с
атрибутом TextAttr.
    wFastVert записывает строку вертикально.
    wFastFill заполняет окно Number парами символов Ch  и
атрибутов Attr. В случае, если Number больше ширины окна,
заполнение продолжается на следующей строке окна.
    wChangeAttribute изменяет Number видео атрибутов на
указанное значение без изменения соответсвующих символов.
Подобно wFastFill процедура wChangeAttribute переносит
текст на новую строку при достижении границ.
    wFastCenter записывает строку в центре ширины экрана в
указанной строке Row в указанном атрибуте.
    wFastFlush записывает строку, выровненную по правому краю
окна.
    wFastRead  считывает Number символов из окна в  переменную
St . Убедитесь, что переменная , которую Вы передаете для St,
имеет достаточную длину для ввода по крайней мере Number
символов. В случае, если тип Вашей строки отличается от
родового типа String, Вам необходимо использовать опцию
компилятора {$V-} для ослабления контроля типа строки. Если
Number символов превышает число символов в указанной строке
Row, возвращаются только оставшиеся символы строки.
    wReadAttribute  подобна процедуре wFastRead, но она
используется для чтения видео атрибутов, а не для чтения
символов.
    wWriteAttribute изменяет атрибуты величин, указанных в
St, без изменения записанных символов.
    wFlexWrite  записывет строку из одного или более атрибутов.
Более подробно см. в OPCRT.FlexWrite.
    wFastWriteCtrl подобна процедуре wFastWrite за исключением
того, что она особым образомм обрабатывает управляющие символы
(символы с порядковым номером меньше 32 ). Управляющие символы
преобразуются в эквивалентные прописные буквы алфавита, а
затем записываются с использованием атрибута Ctrl. Например,
Ctrl-A (порядковый номер 1) будет записано как буква А.

Примеры

var S: String;
...
Win.wFastWrite('Hello World', 1, 1, TextAttr);
Win.wFastReads(5, 1, 1, S);

    Записывает "Hello World" в верхний левый угол окна с
текстовым атрибрутом по умолчанию для текущего окна, затем
заполняет S первых пять символов, начиная с той же точки
(S будет содержать 'Hello').

Win.Init(30, 5, 50, 15);
Win.wFastFill(Win.Width*Win.Height, #178, 1, 1, TextAttr);

    Заполнить весь экран символом темного фона.

Win.Init(30, 5, 50, 15);
Win.wFastFill(300, #178, 1, 1, TextAttr);

    Арифметическая ошибка(в рассматриваемом окне только
231 байт), но wFastFill обрежет лишние символы.

Win.Init(30, 5, 50, 15);
Win.wFastWrite('Hello', 12, 1, $02);

    Некорректно! Максимальное число строк в этом окне равно 11.
Однако wFastWrite выявит эту ошибку и прекратит выполнение без
каких-либо действий (не выдается никакой код результата).

const
   FAttrs : FlexAttrs = ($07, $01, $02, $03);
...
Win.Init(30, 5, 50, 15);
Win.wFlexWrite('This '^A'is'^A' '^B'a'^B' '^C'test', 1, 1, FAttrs);

   Каждое из четырех слов предложения "This is a test" будет
показано на экране с различными атрибутами. Другие примеры
см. в OPCRT для соответствующих процедур.

Дополнительно см.

    Записи, связанные с кадром.

  wCopy

Объявление

   constructor wCopy(var W : RawWindow);

Функция

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

Описание

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

Пример

var
  Win1, Win2 : RawWindow;
begin
  Win1.InitCustom(2, 2, 10, 10, DefaultColorSet,
                  DefWindowOptions or wBordered);
  Win1.wFrame.AddHeader(' First Window ', heTL);
  if not Win2.wCopy(Win1) then begin
    Writeln('Failed to Init Win2, Status ', InitStatus);
    Halt;
  end;
  Win1.Done;
  Win2.Draw;
end.

    Win1 реализуется через InitCustom; Win2 реализуется через
wCopy и является точной копией Win1, включая его кадры и другие
компоненты.

     wGotoXY

Объявление

     procedure wGotoXY(X, Y : Integer); virtual;

Функция

    Переместить курсор в координаты, связанные с окном.

Описание

    Для текущего окна процедура wGotoXY работает подобно
процедуре GotoXY в блоке UPCRT, устанавливая в новое положение
курсор аппаратных средств в соответствии с координатами X и Y,
связанными с окном. Кроме того, wGotoXY работает с окнами
не являющимися текущими; она запоминает указанное положение
в полях данных окна. Эти координаты будут учтены следующий
раз, когда окно будет сделано текущим.
    Имеется другое отличие от GotoXY; wGotoXY позволяет
установить курсор вне окна. Даже, если X или Y равны нулю,
отрицательные или больше, чем размер окна, процедура wGotoXY
все равно установит курсор в требуемое положение. wGotoXY
не различает, не отбрасывает запросы переместить курсор за пределы
экрана.
       Пример

Win.Init(30, 5, 50, 15);
Win.Draw;
Win.wGotoXY(5, 5);
Write('X');

    Рисует "Х" в точке на 5 стобцов правее и 5 строк ниже,
чем левый верхний угол окна.

Дополнительно см.

wWhereXY                  wWhereXYAbs

     Width

Объявление

    function Width : Word;

Функция

     Возвращает фактическую ширину окна.

Описание

    Возвращает число столбцов в прямоугольнике активного окна.

Пример

Win.wFrame.AddCustomShadow(#178, frBB, 1, 1, Win.Width+2, 1, $02, $70);
Win.wFrame.AddCustomShadow(#178, frRR, 1, 1, Win.Heigt+2, 1, $02, $70);

    Функция Width применяется для добавление тени той же ширины,
что и кадр(на 2 столбца больше, чем окно).

 Дополнительно см.

  Height

      wOptionsAreOn

Объявление

function wOptionsAreOn(OptionCides : LongInt) : Boolean;

Функция

    Возвращает TRUE   в случае, если все опции включены.

Описание

    OptionCodes - преобразованное в битовую форму длинное
целое число, использующее битовые метки, описанные  в
разделе объявлений в рассматриваемом разделе. wOptionsAreOn
возвращает True только, если все указанные опции установлены.
Несколько опций объединяются с помощью численного или.

Примеры

if Win.wOptionsAreOn(wBordered) then begin
  Win.wFrame.AddHeader('Standard Header', heTC);
  Win.wFrame.AddShadow(shBR, shOverWrite);
end;

     Перед добавкой характеристик кадра проверяется, имеет
ли окно рамку.

if Win.wOptionsAreOn(wSaveContents or wUserContents) then
 ...

    Возможно, некорректно. Эти две опции очень редко
устанавливаются одновременно, поэтому выражение  вряд ли
вернет True. Это ,по-видимому, означает следующее:

if Win.wOptionsAreOn(wSaveContents) or
   Win.wOptionsAreOn(wUserContents) then
  {The window can restore its contents}
  {Окно может восстановить свое содержание}
...

  Дополнительно см.

wOptionsOff             wOptionsOn

          wOptionsOff

Объявление

procedure wOptionsOff(OptionCodes : LongInit);

Функция

    Отключение опций

Описание

    Опции, указанные через OptionCodes отменяются. Несколько
опций можно объеденить с помощью численного или.
    Метод вызывается только в случае, если окно не является
активым. В противном случае выдается ошибка (epNonFatal+ecWinIsActive)
и выполнение сразу же прекращается. В ряде редких случаев
wOptionsOff может давать другие ошибки.
    В случае, если выключена опция wBordered,координаты кадров
стягиваются по всем краям; любые черты кадров (заголовки, тени
и т.д.) переносятся и размещаются. Кроме того, становится
недоступным содержание окна, хранящееся в буфере содержания.

Пример

Win.InitCustom(30, 5, 15, DefaultColors, DefWindowOptions or wClear);
{...}
Win.wOptionsOff(wClear);

    Окно реализуется с установленной опцией wClear. Затем в
в программе эта опция отключается.

Дополнительно см.

 wOptionsOn


           wOptionsOn

Объявление

procedure wOptionsOn(OptionCodes : LongInt);

Функция

    Включение опций.

Описание

    Включает все опции, указаные через OptionCodes. Несколько
опций объединяются через численное или.( Добавление вместо
нескольких опций эквивалентно только в случае, когда указанные
опции не содержат взаимно перекрывающихся битов.)
    Этот метод можно вызывать только в случае, если окно не
является активным. В противном случае выдается ошибка
(epNonFatal+ecWinIsActive)  и выполнение процедуры сразу жу
прекращается. wOptionsOn может создавать другие ошибки, например,
(epFatal+ecOuyOfMemory) или (epFatal+ecWinCoordsBad).
    В случае, если включена опция wBordered координаты кадров
увеличиваются по всем сторонам; любые существующие черты
кадров(заголовки,  тени и т.д.) перемещаются и вновь
размещаются. Кроме того, становится недоступным содержание
окна, хранящееся в буфере содержания. Окно будет иметь
тип с рамками по умолчанию (DefWindowFrame).
    Отметим, что более эффективно для создания рамок окна
использовать конструктор InitCustom и установить опцию wBordered
при вызове конструктора. Применение метода wOptionOn для
добавления кадра гарантирует фрагментацию динамически
распределяемой области: буфер ScreenRect для области,
занимаемой окном, должен быть перераспределен , и  при
добавлении рамки должен быть вновь распределен несколько
более емкий буфер.

Примеры

Win.Init(30, 5, 50, 15);
Win.wOptionsOn(wBordered);
if Win.GetLastError <> 0 then
   WriteLn('Failed to add border');

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


Win.Init(30, 5, 50, 15);
Win.Draw;
Win.wOptionsOn(wResizeable);
{...Используйте окно...}
Win.Done;

     Некорректно! Вы не можете включить (или выключить) опцию,
когда окно является активным.

Win.wOptionsOn(wRrsizeable);

    В этом примере не требуется проверки ошибок(предполагается,
что окно неактивное в момент вызова), так как в нем просто
уставливается бит опции. Нижеследующие опции относятся к
той же категории: wUserContents, wSoundEffects, wAltFrame,
wSetMouse, wFullMouseWindow, wResizeable, wAllMouseEvents,
wStoreContents.

Дополнительно см.

wOptionsAreOn           wOptionsOff

          wWhereXY

Объявление

procedure wWhereXY(var X, Y : Unteger); virtual;

Функция

    Возвращает координаты курсора относительно окна.

Описание

    В случае, если окно является текущим wWhereXY возвращает
положение курсора аппаратных средств в координатах,
связанных с окном. В противном случае, процедура возвращает
положение, в котором находился бы курсор, если сделать окно
текущим. Отметим, что X  и Y могут быть равными нулю,
отрицательными или больше , чем размер окна. В указанных
случаях курсор находится вне активного окна.

Пример

var
  X, Y : Integer;
...
Win.Init(30, 5, 50, 15);
Win.Draw;
Win.wGotoXY(1, 1);
Win.wWhereXY(X, Y);

    После вызова wWhereXY параметры X и Y становятся равными 1.

    wWhereXYAbs

Объявление

procedure wWhereXYAbs(var X, Y : Byte);

Функция

    Возвращает абсолютное значение координат курсора.

Описание

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

Пример

Win.Init(30, 5, 50, 15);
Win.Draw;
Win.wGotoXY(1, 1);
Win.wWhereXY(X, Y);

    После вызова wWhereXYAbs параметр X станет равным 30,
а Y - станет равным 5.

     Zoom

Объявление

{$IFDEF UseAdjustableWindows}
procedure Zoom; virtual;

Функция

    Временное увеличение размера окна до максимальных границ.

Описание

    Zoom  сохраняет координаты текущего окна( которые
восстанавливаются при последующем вызове процедуры Unzoom)
и вызывает AdjustWindow для увеличение размеров окон до
максимальных границ. В процессе этого процедура устанавливает
координаты кадра равными координатам ограничивающего кадр
прямоугольника. Все связанные с кадром структуры, например,
заголовки и тени, автоматически регулируются.
    С тем, чтобы распахнуть окно, оно должно быть либо
неактивным, либо текущим. В случае, если окно является
текущим изменение сразу же становится видимым. Процедура
Zoom использует методы виртуального экрана для выполнения
кажущегося мгновенного перехода от одного размера к другому.
Отметим, что для виртуального экрана требуется буфер
временной динамически распределяемой области емкостью
2*ширина_экрана*высота_экрана байт.
    Процедура Zoom  может выдавать различные ошибки  и
предупреждения, включая:

epWarning+ecWinIsZoomed      Если окно уже увеличено
epNonFatal+ecWinNotSizeable  Если не установлен флаг окна
                             wResizeable
epNonFatal+ecWinNotCurrent   Если окно не является текущим
                             или активным
epNonFatal+ecWinCoordsBad    Если ряд ограничительных
                             размеров окна не является
                             взаимосогласованным
epFatal+ecOutOfMemory        Если для увеличения размера
                             буфера недостаточен объем
                             динамически распределяемой памяти.

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

Пример

uses OpCrt, OpFrame, OpWindow;
var Win : RawWindow;
    Result : Word;
begin
  with Win do begin
    Init(30, 5, 50, 15);
    wOptionsOn(wBordered);
    wFrame.AddScrollBar(frRR, 0, 100, DefaultColores);
    Draw;
    Zoom;
    Result := GetLastError;
    if Result <> then
       WriteLn('Failed to zoomed window, Result = ', Result);
    Unzoom;
    Result := GetLastError;
    if Result <> then
       WriteLn('Failed to unzoomed window, Result = ', Result);
    Done;
  end;
end.

    Окно распахивается сразу же после его создания; затем
окно возвращается в исходное состояние.

Дополнительно см.

AdjusnWindow                Unzoom
ResizeWindow









    2. StackWindow

    Всякий раз при рисовании StackWindow указатель помещается в
стек. Со ссылкой на этот указатель методы StackWindow могут
действовать более точно и аккуратно, чем те же процедуры в
RawWindow . Главное преимущество заключается в возможности
записи в окно, частично загороженное другими окнами; можно
выбрать такое окно и переместить его в верхушку стека.
    Дополнительная память, требуемая для использования этих
возможностей, минимальная. OPWINDOW определяет другой объект -
WindowStack, получаемый из PointerStack - который работает в
тесном взаимодействии  с StackWindow и контролирует взаимные
связи между окнами. По умолчанию WindowStack может управлять
одновременно до 8 окон, используя только 32 байта динамически
распределяемой области. WindowStack динамически увеличивает
занимаемую им область, если одновременно активизировано более
чем 8 окон.
    Каждый экземпляр StackWindow использует на 10 байтов больше
памяти, чем RawWindow . Четыре из этих байтов отводятся под
указатель в WindowStack, в который опускается окно после того,
как оно нарисовано. Взаимная связь между этими двумя объектами
приводит к повышению скорости и, кроме того, открывает
возможность управлять одновременно несколькими стеками окон.
Другие четыре байта используются для указания на определяемую
пользователем процедуру, вызываемую при опускания окна в стек.
Эта процедура в с сочетании с номером окна типа word , присвоенным
WindowStack , позволяет корректировать специальный заголовок,
содержащий номер любого окна.
    StackWindow и WindowStack связаны с объектом VirtScreen с
тем, чтобы исключить непрятную вспышку экрана при работе со
стеком окна. Предположим, что Вы имеет пять перекрывающихся окон
на экране и желаете выбрать самое нижнее окно и переместить его
вперед. Управляющая программа WindowStack стирает все четыре
окна, перерисовывает три из них и в конце концов перерисовывает
заданное окно в верхушку стека. В случае, если отдельные шаги
являются визуальными - не важно с какой скоростью они
выполняются - визуальное восприятие будет весьма неприглядным.
OPWINDOW вместо рисования корректирует виртуальный экран,
который копируется на физический экран только после завершения
всех операций. В результате преобразование выглядит чистым и
мгновенным.
    Виртуальный экран отводит достаточный объем динамической
памяти под содержание физического экрана. Необходимо помнить,
что при вызове любого из методов для скрытого StackWindow должны
быть свободными по крайней мере 2*ширина_экрана*высота_экрана
байтов под динамически распределяемую память.
    Для выполнения таких операций временного опускания и
выталкивания из стека управляющая программа окна должна ввести
новое более жесткое дополнительное требование: каждое окно
должно иметь возможность запоминать свое собственное содержание,
когда оно перерисовывается через небольшой промежуток времени
после стирания. В иерархии OPWINDOW это означает, что либо
установлен флаг wSaveContents и буфер содержания размещен, либо
установлен флаг wUserContents, а окно использует метод
UpdateContents , который при необходимости, корректирует
содержание. Каждое StackWindow должно выбрать один из этих
вариантов или же управляющая программа окна, вероятно, выдаст
ошибку (epNonFatal+ecWinInaccesible) . Все типы ObjectProfessional
объектов более высокого уровня, такие как TextEditor, PickList,
Menu отвечают рассмотренному требованию.
    StackWindow использует как свои многие методы RawWindow. Нам не
хотелось бы повторно приводит их описание; они действуют подобно
методам в RawWindow за исключением того, что они работают с
окнами, являющимися активными, но не текущими. (Попытка вызвать
версии этих методв в RawWindow приводит в такой ситуации только
к ошибке.) StackWindow переопределяет следующие методы RawWindow,
применяемые в указанных целях:
    Очистка, прокрутка и сохранение:
procedure Clear; virtual;
    {-Очистить окно в wTextXxx и wBackChar}
procedure ClearContents;
    {-Очистить область внутри активного кадра с wTextXxx и w BackChar}
procedure ScrollHoriz(Cols : Integer); virtual;
    {-Прокрутить содержание горизонтально}
procedure ScrollVert(Rows : Integer); virtual;
    {-Прокрутить содержание вертикально}
procedure SaveContents; virtual;
    {-Запомнить содержание текущего окна в буфере содержания}

    Перенос и изменение размеров:
procedure AdjustWindow(X1, Y1, X2, Y2 : Word); virtual;
    {-Ввести новые координаты и скорректировать все зависимые
      структуры}
procedure MoveWindow(DX, DY : Integer); virtual;
    {-Перенести окно}
procedure ResizeWindow(DX, DY : Integer); virtual;
    {-Изменить размер окна}
procedure Zoom; virtual;
    {-Временно увеличить размер окна до заданных пределов}
procedure Unzoom; virtual;
    {-Вернуть увеличенное окно к прежнему размеру}

    Стрелки перемещение:
procedure DrawAllSliders(HorizVal, VertVal : LongInt); virtual;
    {-Нарисовать или скорректировать все слайды}
procedure ChangeAllScrollBars(MinHoriz, MaxHoriz : LongInt;
                              MinVert, MaxVert : LongInt); virtual;
    {-Изменить пользовательский диапазон для существующий
стрелок перемещение. Стереть слайды}


    Записи, связанные с окном
procedure wFastWrite(St : string; Row, Col, Attr: Byte);
  {-Записать строку, используя связанные с окном координаты}
procedure wFastText(St : string; Row, Col : Byte);
  {-Write St at Row,Col without changing the underlying video attribute}
  { Записать St в строку Row, столбец Col без изменения
    расположенных ниже видеоатрибутов}
procedure wFastVert(St : string; Row, Col, Attr: Byte);
  {-Write a string vertically using window-relative coordinates}
  {-Записать строку вертикально, используя связанные с окном
координаты}
procedure wFastFill(Number : Word; Ch: Char; Row, Col, Attr: Byte);
  {-Fill Number Chars at Row, Col in Attr without snow}
  {Заполнить Attr Number символами, начиная с Row,Col без снега}
procedure wFastCenter(St : string; Row, Attr : Byte);
  {-Write St centered on Row in Attr without snow}
  { Записать St по центру строки Row в Attr, без снега}
procedure wFastFlush(St : string; Row,  Attr : Byte);
  {-Write St flush right on Row in Attr without snow}
  { Записать St, выравнивая справа, в строку Raw в Attr, без снега}
procedure wFastRead(Number, Row, Col : Byte; var St : string);
  {-Read Number Characters from the screen into St starting at Row, Col}
  { Считать Number символов с экрана в St, начиная с Row, Col}
procedure wReadAttribute(Number, Row, Col : Byte; var St : string);
  {-Read Number attributes from the screen into St starting at Row, Col}
  { Считать Number атрибутов с экрана в St, начиная с Row, Col}
procedure wWriteAttribute(St : String; Row, Col : Byte);
  {-Write string of attributes St at Row, Col without changing characters}
  { Записать строку атрибутов St в  Row, Col без изменения символов}
procedure wChangeAttribute(Number : Word;Row, Col, Attr : Byte);
  {-Change Number video attributes to Attr starting at Row, Col}
  { Изменить Number видео атрибутов в Attr, начиная с Row, Col}
procedure wFlexWrite(St : string; Row, Col : Byte; var FAttrs : FlexAttrs);
  {-Write a string flexibly using window-relative coordinates}
  { Записать строку гибко, используя координаты относительно окна}
procedure wFastWriteCtrl(St : String; Row, Col, Attr, Ctrl : Byte);
  {-Write St at Row, Col in Attr (video attribute) without snow.
    Control characters displayed in Ctrl as upper-case letters}
  { Записать St  в строку Row, столбец Col в Attr(видео атрибуты)
    без "снега". Управляющие символы выводятся на экран в Ctrl
    как символы верхнего регистра}

    Записи, связанные с кадром
procedure fFastWrite(St : string; Row, Col, Attr: Byte);
  {-Write a string}
  {Записать строку}
procedure fFastText(St : string; Row, Col : Byte);
  {-Write St at Row,Col without changing the underlying video attribute}
  { Записать St в строку Row, столбец Col без изменения
    расположенных ниже видеоатрибутов}
procedure fFastVert(St : string; Row, Col, Attr: Byte);
  {-Write a string vertically}
  { Записать строку вертикально}
procedure fFastFill(Number : Word; Ch: Char; Row, Col, Attr: Byte);
  {-Fill Number Chars at Row, Col in Attr}
  { Заполнить Number символов со строки Row, столбца Col в Attr}
procedure fChangeAttribute(Number : Word;Row, Col, Attr : Byte);
  {-Change Number video attributes to Attr starting at Row, Col}
  { Изменить Number видео атрибутов в Attr, начиная с Row, Col}
procedure fFastCenter(St : string; Row, Attr : Byte);
  {-Write St centered on Row in Attr}
  { Записать St по центру строки Row в Attr}
procedure fFastFlush(St : string; Row,  Attr : Byte);
  {-Write St flush right on Row in Attr}
  {-Записать St в строку Row в Attr с выравниванием по правому краю}
procedure fFastRead(Number, Row, Col : Byte; var St : string);
  {-Read Number Characters from the screen into St starting at Row, Col}
  { Записать Number символов с экрана в St, начиная с Row, Col}
procedure fReadAttribute(Number, Row, Col : Byte; var St : string);
  {-Read Number attributes from the screen into St starting at Row, Col}
  { Считать Number атрибутов с экрана в St, начиная с Row, Col}
procedure fWriteAttribute(St : String; Row, Col : Byte);
  {-Write string of attributes St at Row, Col without changing characters}
  { Записать строку атрибутов St в  Row, Col без изменения символов}
procedure fFlexWrite(St : string; Row, Col : Byte; var FAttrs : FlexAttrs);
  {-Write a string flexibly using window-relative coordinates}
  { Записать строку гибко, используя координаты относительно окна}
procedure fFastWriteCtrl(St : String; Row, Col, Attr, Ctrl : Byte);
  {-Write St at Row, Col in Attr (video attribute) without show.
    Control characters displayed in Ctrl as upper-case letters}
  { Записать St  в строку Row, столбец Col в Attr(видео атрибуты)
    без "снега". Управляющие символы выводятся на экран в Ctrl
    как символы верхнего регистра}

    Типичный пример применения рассматриваемых процедур:

procedure StackWindow.Clear;
  {-Очистеть окно в wTextXxx и wBackChar}
var NotC : Boolean;
begin
   NotC := not IsCurrent;
   if NotC then begin
     ActivateWrite;
     if wRes <> 0 then Exit;
   end;
   RawWindow.Clear;
   if NotC then
     DeactivateWrite;
  end;

    В случае, если окно уже является текущим StackWindow.Clear
просто вызывает RawWindow.Clear. Если же окно не является
текущим ( или в рассматриваемом случае, если даже оно не
является активным) StackWindow.Clear вызывает ActivateWrite.
ActivateWrite просматривает стек, начиная с его верхушки, и ищет
заданное окно. В случае неуспешного поиска или если найдено
окно, в котором не установлен флаг wSaveContents или флаг
wUserContents, работа ActivateWrite завершается с ошибкой
(epNonFatal+ecWinInaccesible). Затем ActivateWrite распределяет
буфер динамической памяти для виртуального экрана, копирует
физический экран в виртуальный экран и перенаправляет выходной
видеосигнал из OPCRT и OPWINDOW. В случае, когда объем
динамически распределяемой памяти является недостаточным,
ActivateWrite генерирует ошибку (epFatal+ecOutOfMemory). И
наконец, ActivateWrite стирает окна, опущенные в стек после
заданного окна. (Этот шаг выполняется на виртуальном экране,
поэтому он невидимый.)
    При отсутствии ошибок можно для надежности вызвать
RawWindow.Clear , так как заданное окно стало текущим. Операция
очистки Clear выполняется на виртуальном экране.
    В случае, если окно не было текущим, то для начала работы с
ним DeactivateWrite обращает процесс, перерисовывая временно
стертые окна на виртуальный экран, затем перенаправляет выходной
видеосигнал на физический экран, копирует виртуальный экран на
физический экран и размещает буфер динамически распределяемой
памяти.
    Конечно, все это происходит мгновенно; кажется, будто
скрытое другими окнами окно само, как бы по волшебству,
очищается, не разрушая при этом окон, которые его загораживают.
    Целесообразно всегда помнить о ActivateWrite и
DeactivateWrite. Используя их в сочетании с другими методами для
объектов типа окна более высокого уровня, можно выполнять любого
вида корректировки экрана для скрытого окна. При выполнении
программ-утилит MAKEMENU и MAKESCRN Вы можете найти много таких
примеров.
    Прежде чем перейти к подробному описанию типов и методов
StackWindow приведем полный пример, демонстрирующий
использование StackWindow.

program StackWindowExample;   {EXSWIN.PAS}
uses
  OpString, OpCrt, OpFrame, OpWindow;
var
  Win : array[1...3] of StackWindowPtr;
  WinOpts : LongInt;
  I,  J : Integer;
begin
  {Создать три StackWindow с рамками}
  WinOpts := wBordered+wClear+wSaveContents;
  New(Win[1], InitCustom(30, 03, 50, 13, DefaultColorSet, WinOpts));
  New(Win[2], InitCustom(35, 08, 55, 18, DefaultColorSet, WinOpts));
  New(Win[3], InitCustom(10, 13, 60, 23, DefaultColorSet, WinOpts));
  if (Win[1] = nil) or (Win[2] = nil) or (Win[3] = nil) then begin
    WriteLn('Failed to initialize StackWindows');
    Halt;
  end;

  {-Добавить некоторые особенности кадра и нарисовать каждое окно}
  for I := 1 to 3 do
    with Win[I]^ do begin
      wFrame.AddHeader('Window '+Long2Str(I), heTC);
      wFrame.AddShadow(shBR, shOverWrite);
      wFrame.AddScrollBar(frRR, 1, 9, DefaultColorSet);
      EnableExplosions(20);
      Draw;
      for  J := 2 to 10 do
        wFastText('Hello Mars', J, 5);
      DrawSlider(frRR, I);
    end;

    {-Переключение между окнами до нажатия клавиши <Escape>}
    I := 1;
    While ReadKeyWord <> $011B do begin
      Win[I]^.Select;
      Inc(I);
      if I > 3 then
        I := 1;
    end;

    {-Очистить окно 1, даже если оно скрытое}
    Win[1]^.Clear;

    {-Стереть и уничтожить каждое окно}
    for I := 1 to 3 do begin
      J := ReadKeyWord;
      Win[I]^.EraseHidden;
      Win[I]^.Done;
    end;
    {-Удалить стек окна}
    wStack.Done;
  end.

     В рассматриваемом примере необходим массив из трех
указателей в StackWindow. (Может оказаться проще описать массив
StackWindow без использования указателей.) Каждый из трех
объектов StackWindow размещается, используя утверждение New,
которое, кроме того, вызывает конструктор InitCustom для задания
координат, цветов и опций окна.
    Первый цикл For добавляет особенности кадра( используя
возможности RawWindow и Frame), затем рисует кадр и записывает в
него некоторый текст. Цикл While демонстрирует случайный доступ
к окнам, перемещая по очереди каждое окно вперед, пока не будет
нажата клавиша <Escape>. После того, как окно выбрано, оно
становится текущим и будет находится в верхушке стека и
полностью видно.
    Далее, мы показываем, что метод Clear очищает любое из
активных окон, как закрытое, так и не закрытое. EraseHidden
стирает любое окно, а Done удаляет его. (Отметим, что
StackWindow.Erase стирает только текущее окно. Такой выбор
обусловлен тем, что Вы должны иметь возможность исключить
слияние в коде виртуального экрана, если Вам этого не требуется.)
    Последний вызов wStack.Done не является обязательным, а
служит в качестве пояснения. wStack - это глобальная переменная
WindowStack, управляющая активными окнами. Как указано выше
wStack содержит буфер емкостью 32 байта для хранения треков для
вплоть до 8 окон ( емкость буфера будет увеличена, если
активизировано большее число окон). Вызвав wStack.Done, мы
освобождаем всю динамическую память, занятую программой.

    Смешивание объектов RawWindow и StackWindow

    Иногда бывает удобно одновременно иметь на экране объекты
RawWindow и StackWindow. В такой ситуации требуется
дополнительная аккуратность, так как управляющая программа для
WindowStack ничего не знает об RawWindow, а RawWindow отличаются
только между CurrentWindow - текущим окном - и не текущим окном.
    В случае, если RawWindow нарисовано перед каким-либо
StackWindow и Вы стираете все StackWindow перед стиранием
RawWindow, то никаких сложностей не возникает. В этом случае
используется естественный вызов. Кроме того, не возникает
никаких трудностей при записи в любой момент времени в RawWindow
(используя либо программы семейства FastWrite или методы
wFastWrite для объекта), считая, что RawWindow не загорожено
какими-либо другими окнами.
    Более осторожно и аккуратно надо действовать, когда Вы
предполагаете стереть RawWindow после того, как нарисованы
StackWindow, или стираете RawWindow, когда StackWindow еще
являются активными. Рисование RawWindow не вызывает проблем: Вы
просто вызовите метод Draw для RawWindow, который делает окно
текущим окном. Для передачи управления в любое StackWindow
используйте метод StackWindow.Select, который содержит
специальный код, эффективным образом создающий мост между этими
двумя типами объектов. Для передачи управления обратно в
RawWindow снова вызовите метод Draw для RawWindow. Особенно
важно выбрать StackWindow сразу же после стирания RawWindow, так
как RawWindow не знает, какое окно необходимо сделать текущим
после того, как RawWindow будет стерто.

    Типы

    StackWindowProc = procedure (WPtr : WindowPtr);

    Методы Draw и DrawHidden для StackWindow вызывают процедуру
указанного типа непосредственно перед фактическим рисованием
заданного окна. Перед вызовом процедуры окну присваивается
уникальное малое целое число, которое может быть определено
через вызов метода WindowNumber. Если это целесообразно,
StackWindowProc может использовать возможнось откорректировать
заголовок , и в нем будет выводится на экран номер окна. DESKPOP
использует эту возможность для идентификации каждого своего
окна. Присвойте StackWindowProc , вызвав метод SetStackProc.

WindowPtr       = ^StackWindow;
StackWindowPtr  = ^StackWindow;
StackWindow     =
  object(RawWindow)
   ...
  end;

    Здесь приведены типы данных, описывающих объекты
StackWindow. Отметим, что WindowPtr - это синоним StackWindowPtr.
Укороченное имя сделано допустимым по историческим причинам
(StackWindow наиболее близко совпадает с типом окна Turbo
Professional, к которому обращаются через WindowPtr) и, кроме
того, вследствие того, что StackWindow - это наиболее общий тип
окна.

    ActivateWriteActivateWrite

Объявление

    procedure ActivateWrite;


Функция

    Активизация быстрой записи в скрытое окно.

Описание

    Для выполнения ActivateWrite окно должно быть активным,
любые окна, нарисованные поверх его, должны иметь флаг
wSaveContents или флаг wUserContents и необходимо, чтобы
динамическая память имела достаточный объем для активизации
виртуального экрана с размером равным размеру физического экрана
(2*ширина_экрана*высота_экрана байтов). Невыполнение указанных
требований приведет к ошибке (epNonFatal+ecWinInaccesible) или к
ошибке (epFatal+ecOutOfMemory).
    Предполагая, что все вышеперечисленные требования выполнены,
ActivateWrite размещает в памяти виртуальный экран, копирует в
него физический экран, перенаправляет выходной видеосигнал на
виртуальный экран и стирает все окна, опущенные в стек после
рассматриваемого окна.
    После этого любая процедура или метод на основе быстрой
записи для записи на экран будут выполнятся для соответствующего
местонахождения на виртуальном экране. В этот момент времени
единственные процедуры, которые Вы не можете с успехом
использовать - это Write и WriteLn. Вы можете вызвать
OPCRT.FastWrite и соответствующие процедуры; Вы можете вызвать
wFastWrite и соответствующие связанные с окнами методы; Вы
можете вызвать fFastWrite и соответсвующие связанные с кадром
методы; наконец, Вы можете вызвать любой метод более высокого
уровня, которые построены над указанными программами и
процедурами более низкого уровня.
    Выполняемые изменения остаются невидимыми пока не вызвана
процедура DeactivateWrite. Вы должны вызвать DeactivateWrite
перед переключением в другок окно или перед его рисованием.
    В случае, если Вам необходимо выполнить более чем одну
корректировку скрытого окна, более быстрый способ заключается в
использовании ActivateWrite и DeactivateWrite вместо вызова
методов, таких как StackWindow.wFastWrite для каждой
корректировки. Каждое обращение к wFastWrite создает в любом
случае внутренние вызовы к ActivateWrite и DeactivateWrite.
    Отметим, что Вы можете вызвать ActivateWrite даже для
текущего окна. Корректировки экрана продолжают временно
перенаправляться на виртуальный экран, что позволяет Вам
выполнять несколько корректировок, которые будут отражены на
экране одновременно при вызове DeactivateWrite.

Примеры

Win[3]^.Select;
Win[1]^.ActivateWrite;
Win[1]^.Clear;
Win[1]^.wFastWrite('FastWrite', 1, 1, TextAttr);
Win[1]^.wFastCenter('FastCenter', 2, TextAttr);
Win[1]^.DeeactivateWrite;

    Учитывая, что Win[1] не является текущим окном, мы должны
окружить утверждение вывода вызовами ActivateWrite и
DeactivateWrite. Здесь мы можем вызвать даже не объектно
ориентированную процедуру FastWrite, хотя координаты,
используемые в ней, не связаны с окном. Отметим, что в
рассматриваемом примере более эффективно использовать
утверждение With (with Win[1]^ do begin) ; но мы отказались от
этого с тем, чтобы сделать пример более ясным.

Win[3]^.Select;
Win[1]^.ActivateWrite;
Win[1]^.wFastWrite('FastWrite', 1, 3, TextAttr);
Win[2]^.Draw;

    Некорректно! В этом примере отсутствует обращение к
DeactivateWrite. Экран не корректируется пока не будет вызвана
DeactivateWrite.

    Дополнительно см.

    DeactivateWrite

            AssignNumber

    Объявление

procedure AssignNumber;  virtual;

    Функция

Вызывается для присвоения номера окна.

    Описание

    Методы Draw и DrawHidden вызывают рассматриваемый
виртуальный метод перед тем, как опустить окно в стек, что
выполняется до момента фактического рисования окна. По умолчанию
AssignNumber вызывает метод WindowStack, который возвращает
следующий свободной номер окна. Первй номер окна - 1, второй - 2
и т.д. В случае, если окну ранее был присвоен номер окна, а
затем окно стерли, этот номер окна будет повторно использован.
Например, если были нарисованы окна 1, 2 и 3, а затем стерли
окно 2, то следующее нарисованное окно получит номер
2.(Максимальный номер окна равен 2047. Если число активных окон
превышает 2047, им присваивается номер 0.)
    AssignNumber присваивает рассматриваемый номер окна полю
данных объекта и затем вызывает Stackproc окна ( см. ранее тип
StackWindowProc). Присвоив Stackproc имя вашей собственной
процедуры, Вы можете обеспечить вывод на экран номера окна.
    Объекты, полученные из StackWindow, могут вести себя иначе,
отвергая метод AssignNumber.

    Дополнительно см.

SetStackProc               WindowNumber

           DeactivateWrite

    Объявление

procedure DeactivateWrite;

    Функция

    Деактивизация быстрой  записи и изменения изображения.

    Описание

    Действие противоположно действию процедуры ActivateWrite.
Более подробную информацию см. для указанной процедуры.

    Дополнительно см.

ActivateWrite

    Draw

Объявление

procedure Draw ;virtual;

Функция

    Протолкнуть окно в стек и нарисовать его.

Описание

    В случае, если окно уже является текущим Draw вызывает
UpdateContents и прекращает работу. В случае, если окно является
активным, но не текущим,Draw генерирует ошибку (epNonFatal
+ecWinInaccesible) и прекращает работу. Для переноса активного
окна в верхушку стека вы должны вызвать вместо Draw метод
Select.Для записи в скрытое окно вызовите ActivateWrite или
используйте один из методов,названных в начале данного раздела.
    Если окно не является активным, Draw вызывает метод
AssignNumber, помещает адрес окна в wStack -глобальную
переменную WindowStack и, наконец, вызывает RawWindow.Draw для
показа окна. После этого рассматриваемое окно становится
текущим.

    Пример

uses
  OpCrt, OpWindow;
var
  Wins : array[1..3] of SrackWindow;
  WinOpts : LongInt;
  I : Integer;
begin
  {Инициализация трех окон}
  WinOpts := wBordered+wClear+wSaveContents;
  Wins[1].InitCustom(30, 03, 50, 13, DefaultColorSet, WinOpts);
  Wins[2].InitCustom(35, 08, 55, 18, DefaultColorSet, WinOpts);
  Wins[3].InitCustom(40, 13, 60, 23, DefaultColorSet, WinOpts);

  {Нарисовать каждое окно}
  for I := 1 to 3 do
    Wins[1].Draw;
  end.

Вводится массив трех статических StackWindow -переменных,
выполняется их инициализация , а затем их рисуют.

    Дополнительно см.

AssignNumber                    Select

       DrawHidden

    Объявление

procedure DrawHidden(var Under : StackWindow);

    Функция

    Нарисовать окно,протолкнув его в стек ниже окна Under.

    Описание

    Окно не должно быть активным, в противном случае
DrawHidden генерирует ошибку (epNonFatal+ecWinIsActive)
и прекращает работу. В случае, если окно Under не является
активным, DrawHidden только вызывает StackWindow.Draw, помещая
новое окно в верхушку стека. В остальных случаях DrawHidden
проверяет, что окна ниже и включая окно Under могут
самовосстанавливаться (см. ActivateWrite). Если это не так, то
генерируется ошибка (epNonFatal+ecWinInaccesible) и работа
прекращается. В случае, если указанные окна
самовосстанавливаются, DrawHidden создает и активизирует
виртуальный экран, стирает все нижерасположенные окна, включая
окно Under, проталкивает в стек и рисует новое окно,
перерисовывает только что удаленные окна и,наконец,
дезактивирует виртуальный экран с тем, чтобы сделать изменения
видимыми.

    Пример

Win[3]^.DrawHidden(Win[2]^);

    Рисуем Win[3] ниже Win[2] в стеке, предполагая, что Win[2]
уже стало видимым.

             Erase

    Объявление

procedure Erase; virtual;

    Функция

    Стереть окно и вытолкнуть его из стека.

    Описание

    Стираемое окно должно быть самым верхним в стеке. В случае,
если окно не является активным, Erase генерирует ошибку
(epNonFatal+ecWinNotActive);в случае, если окно не является
текущим Erase генерирует ошибку (epNonFatal+ecWinInaccesible).
Для стирания активного, но не текущего окна вызовите
EraseHidden.
    После того, как окно стерте, ему присваивается номер ноль
(см. StackWindow.Draw). Окно, оставшееся в верхушке стека, если
есть какое-либо, корректируется с тем, чтобы обеспечить, что
окно показывает главный кадр (wFrame) вместо альтернативного
кадра.

    Примеры

for I := 1 to 3 do
  Win[I]^.Draw;
  {...Используйте Win[3]...}
  Win[3]^.Erase;

    Рисуем три окна, работаем с третьим окном, затем стираем
третье окно.

for I := 1 to 3 do
  Win[I]^.Draw;
  {...Используйте Win[3]...}
  Win[1]^.Erase;

    Некорректно! Можно стереть только верхнее в стеке окно. В
этом примере будет генерироваться ошибка "окно недоступно window
inaccesible". Воспользуйтесь вместо Erase методом EraseHidden
или вначале выберите Select окно.

    Дополнительно см.

       WindowStack.TopWindow

              EraseHidden

    Объявление

procedure EraseHidden;

    Функция

    Стирается окно, даже если оно  является скрытым в стеке окон.

    Описание

    Метод работает подобно методу Erase, за исключением того, что
в рассматриваемом методе используется техника виртуального
экрана, поэтому можно стереть любое окно в стеке. В методе Erase
такой прием не применяется с тем, чтобы исключить слияние кода
виртуального экрана для приложений, в которых этого не
требуется.

    Пример

  WinOpts := wBordered+wClear+wSaveContents;
  Wins[1].InitCustom(30, 03, 50, 13, DefaultColorSet, WinOpts);
  Wins[2].InitCustom(35, 08, 55, 18, DefaultColorSet, WinOpts);
  Wins[3].InitCustom(40, 13, 60, 23, DefaultColorSet, WinOpts);
  for I := 1 to 2 do
    Win[I]^.Draw;
  {...Используйте Win[2]...}
  Win[1]^.EraseHidden;

    После того, как нарисованы два окна (сохраняя Win[2] как
текущее окно), мы решили стереть окно Win[1]. Учитывая, что
Win[1]  не является текущим, мы используем метод EraseHidden.

             Init

    Объявление

constructor Init(X1, Y1, X2, Y2 : Byte);

    Функция

    Создание проталкиваемого в стек окна с опциями и цветами по
умолчанию.

    Описание

    Генерирует вызов в StackWindow.InitCustom, передавая
DefaultColorSet в параметр Colors и DefWindowOptions в параметр
Options.

    Пример

var Win : array[1..3] of WindowPtr;
begin
  New(Win[1], Init(30, 3, 50, 13));
  New(Win[2], Init(35, 8, 55, 18));
  New(Win[3], Init(40, 13, 60, 23));

  if (Win[1] = nil) or (Win[3] = nil) then begin
     WriteLn('Failed to Init StackWindow'); Halt;
  end;
end;

    Реализованы три StackWindow с цветами и опциями по
умолчанию. Отметим, что в опции окна по умолчанию установлен
флаг wSaveContents. Это делает рассматриваемые окна совместимыми
с методами "случайного доступа" StackWindow подобно
ActivateWrite, DrawHidden, Select и EraseHidden.

              InitCustom

    Объявление

constructor InitCustom(X1, Y1, X2, Y2 : Byte;
                       varColors : ColorSet; Options : LongInt);

    Функция

    Создание окна с общепринятыми опциями.

    Описание

    InitCustom вначале вызывает RawWindow.InitCustom для
выполнения инициализации в полном объеме. Затем она направляет
связанный с окном стек в wStack - глобальный WindowStack по
умолчанию. Кроме того, InitCustom присваивает номеру окна
значение ноль и направляет StackWindowProc окна к программе,
которая ничего не делает.
    В случае неуспешной работы конструктора код ошибки
конструктора хранится в InitStatus.

    Пример

var
   Win : array[1..2] of WindowPtr;
   WinOpts : LongInt;
begin
  WinOpts := wBordered+wClear+wSaveContents+wResizeable;
  New(Win[1], InitCustom(30, 03, 50, 13, DefaultColorSet, WinOpts));
  New(Win[2], InitCustom(35, 08, 55, 18, DefaultColorSet, WinOpts));
  if (Win[1] = nil) or (Win[2] = nil) then begin
     WriteLn('Failed to Init StackWindow, Status ',InitStatus);
     Halt;
  end;
end.

    Мы создаем два StackWindow с цветами по умолчанию, но с
опциями, определяемыми пользователем ( окна будут с рамками, с
изменяемым размером, чистыми при первой зарисовке и сохраняют
содержание при стирании).

    Дополнительно см.

    RawWindow.InitCustom

              Load

    Объявление

Constructor Load(var S : IdStream);

    Функция

    Загрузить StackWindow из потока.

    Описание

    S - это соответствующим образом инициализированный объект
типа потока (например, файлы типа потока, открытые для чтения).
Отметим, что S может быть любым наследником типа IdStream,
включая DosIdStream, BufIdStream, MemIdStream.
    Load считывает следующую последовательность байтов из потока
S. Эти байты должны быть записаны в предыдущем обращении к
StackWindow.Store. Load вначале вызывает RawWindow.Load для
чтения данных предка. Затем конструктор Load читает номер окна и
код указателя для стековой обработки окна.
    В случае, если адрес стековой обработки был зарегистрирован
до вызова Store, он снова регистрируется перед вызовом Load,
затем Load инициализует StackWindow для применения процедуры,
адрес которой зарегистрирован. В противном случае, Load
присваивает окну стековую обработку по умолчанию ( которая
ничего не делает).
    Процедура регистрации потока в случае StackWindow имеет имя
StackWindowStream.

    Пример

uses
  OpString, OpCrt, OpRoot, OpFrame, OpWindow;
var
   Win : array[1..2] of WindowPtr;
   S : BufidStream;
   I : Word;
  {$F+}
  procedure StackProc(WPtr : WindowPtr);
  begin
    with WPtr^ do
      ChangeHeader(0, Long2Str(WindowNumber));
  end;
  {$F-}
  begin
    {Open the stream file and register the data types}
    {Открыть файл типа потока и зарегистрировать типы данных}
    if not S.Init('STACKWIN.STM', SOpen, 1024) then begin
      WriteLn('Failed to Init stream, Status =' , InitStatus);
      Halt;
    end;
    S.RegisterHier(StackWindowStream);
    S.RegisterHier(ExploadingWindowStream);
    S.RegisterPointer(2000,@StackProc);

   {Allocate and read the windows from the stream}
   {Разместить и считать окна из потока}
   for I := 1 to 2 do begin
     Win[I] := WindowPtr(S.GetPtr);
     if Win[I] = nil then begin
       WriteLn('Stream error', S.GetStatus);
       Halt;
     end;
   end;
   S.Done;

  {Draw the windows}
  {Нарисовать окна}
   for I := 1 to 2 do
     Win[I]^.Draw;
   end.

    Реализуются два StackWindow из потока, созданного в примере,
рассмотренном в Store. Так как мы знаем, что поток содержит
рассматриваемые окна, мы регистрируем иерархию расширений окон.
Кроме того, мы регистрируем стековую обработку stackproc с
именем StackProc, которая изменяет первый заголовок окна для
показа в нем номера окна.
    Метод для потока GetPtr вызывает StackWindow.Load косвенным
образом для размещения области динамической памяти для окна и
считывает его данные. Отметим, что для присвоения результата
переменной Win[I]  требуется ядро типа WindowPtr.
    Правила по обработке ошибок при использовании потоков
приведены  в BufIdStream (в OPROOT).

    Дополнительно см.

     RawWindow.Load             Store

               OnStack

    Объявление

function Onstack : Boolean;

    Функция

    Возвращает True в случае, если окно показано в стеке окон.

    Описание

    В случае, если окно является активным, OnStack просматривает
стек окон от его верхушки до низа. При обнаружении окна OnStack
возвращает True.
    В операционной среде, когда перемешаны типа RawWindow и
StackWindow, функция OnStack может оказаться весьма полезной для
различения этих двух типов окон. В случае, если все окна в
системе - окна StackWindow и имеется только один стек
WindowStack, функция OnStack возвращает True тогда и только
тогда, когда IsActive имеет значение True.

    Пример

  with Win[3]^ do
    if OnStack then
      Select
    else
      Draw;

    В случае, если Win[3] уже находится в стеке, то оно будет
выбрано. Если же Win[3] не находится в стеке, оно будет
нарисовано, добавлено в стек и сделано текущим окном.
Приведенный пример - это придуманный пример, так как метод
Select будет автоматически рисовать StackWindow, если его нет в
стеке окон.

    Дополнительно см.

RawWindow.IsActive                     Select

                    Select

    Объявление

procedure Select; virtual;

    Функция

    Сделать окно текущим, протолкнув его в верхушку стека.

    Описание

    В случае, если окно уже является текущим Select только
корректирует его содержание, вызывая UpdateContents. Если же
окно не является активным Select вызывает StackWindow.Draw. В
противном случае Select активизирует виртуальный экран, стирает
окна, закрывающие рассматриваемое, стирает рассматриваемое окно,
перерисовывает другие окна, перерисовывает рассматриваемое и
дезактивирует виртуальный экран.
    Кроме того, Select добавляет специальную логику, которая
обрабатывает случай, когда RawWindow (не в стеке) не является
текущим в момент вызова Select. После активизации виртуального
экрана Select вначале перерисовывает помещенное в верхушку стека
окно, чтобы сделать его текущим. Это оказывает влияние на
дезактивизацию RawWindow (происходит переключение на
альтернативную рамку). После этого может быть выбрана обычная
логика Select, описанная в предыдущем параграфе.

    Пример

I := 1;
while ReadKeyWord <> $011B do begin
  Win[I]^.Select;
  Inc(I);
  if I > 3 then
    I := 1;
  end;

    Выбираем одно из трех окон каждый раз при нажатии клавиши.

    Дополнительно см.

    Draw

            SetStackProc

     Объявление

procedure SetStackProc(SP : StackWindowProc);

    Функция

    Устанавливается стековая обработка для окна.

    Описание

    Стековая обработка вызывается методами Draw и DrawHidden
перед фактичесим проталкиванием в стек и рисованием заданного
окна. Главное подтверждение для использования определяемой
пользователем стековой обработки заключается в показе номера
окна в качестве части заголовка. Этот прием используется в
демонстрационной программе DESKPOP.
    Процедура, передаваемая в качестве параметра в SetStackProc,
компилируется с моделью FAR. Это должна быть глобальная
программа, и она должна иметь параметры, соответствующие
параметрам, заданным типом StackWindowProc.

    Пример

uses
  OpString, OpCrt, OpRoot, OpFrame, OpWindow;
var
   Win : array[1..3] of WindowPtr;
   WinOpts : LongInt;
   I : Integer;

   {$F+}
   procedure UpdateWindowNumber(WPtr : WindowPtr);
   begin
     with WPtr^ do
       ChangeHeader(0, Long2Str(WindowNumber));
   end;
   {$F-}

begin
  WinOpts := wBordered+wClear+wSaveContents;
  New(Win[1], InitCustom(30, 03, 50, 13, DefaultColorSet, WinOpts));
  New(Win[2], InitCustom(35, 08, 55, 18, DefaultColorSet, WinOpts));
  New(Win[3], InitCustom(40, 13, 60, 23, DefaultColorSet, WinOpts));
  for I:= 1 to 3 do
    with Win[I]^ do begin
      wFrame.AddHeader(' ', heTC);
      SetStackProc(UpdateWindowNumber);
    end;

   {Switch between the windowd}
   {Переключение между окнами}
   I := 1;
   repeat
     Win[I]^.Select;
     Inc(I);
     if I = 4 then
        I := 1;
     until ReadKeyWord = $011B; {Escape}
end.

    Передает StackWindowProc с именем UpdateWindowNumber. Это
процедура корректирует номер заголовка 0, используя номер окна,
полученный из функции WindowNumber.

    Дополнительно см.

AssignNumber            WindowNumber
DraW

               Store

    Объявление

procedure Store(var S : IdStream);

    Функция

    Загрузить в поток.

    Описание

    S - это соответствующим образом инициализированный объект
типа потока (например, файлы типа потока, открытые для чтения).
Отметим, что S может быть любым наследником типа IdStream,
включая DosIdStream, BufIdStream, MemIdStream (Хотя, обычно вы не
будете записывать в MemIdStream).
    Store записывает образ StackWindow в поток S. В случае, если
вы для окна установили стековую обработку, не определяемую по
умолчанию, вы должны убедиться, что его адрес зарегистрирован
перед вызовом рассматриваемого метода (как показао в
нижеприведенном примере). Store вначале вызывает RawWindow.Store
для записи всей информации окна, затем записывает текущий номер
окна и код указателя для стековой обработки.
    Для обработки ошибок, которые могут возникнуть в ходе
выполнения Store, вызовите функцию GetStatus для потока.
    Процедура регистрации потока для StackWindow имеет имя
StackWindowStream.

    Пример

uses
  OpString, OpCrt, OpRoot, OpFrame, OpWindow;
var
   Win : array[1..2] of WindowPtr;
   S : BufidStream;
   I : Word;
   WinOpts : LongInt;

   {$F+}
   procedure StackProc(WPtr : WindowPtr);
   begin
     with WPtr^ do
       ChangeHeader(0, Long2Str(WindowNumber));
   end;
   {$F-}

begin
  WinOpts := wBordered+wClear+wSaveContents;
  New(Win[1], InitCustom(30, 03, 50, 13, DefaultColorSet, WinOpts));
  New(Win[2], InitCustom(35, 08, 55, 18, DefaultColorSet, WinOpts));
  if (Win[1] = nil) or (Win[2] = nil) then begin
     WriteLn('Failed to Init StackWindow');
     Halt;
  end;
  for I := 1  to 2 do
    with Win[I]^ do begin
      wFrame.AddHeader(' ', heTL);
      EnableExplosions(20);
      SetStackProc(StackProc);
      Draw;
    end;

   {Write the windows  to a stream}
   {Записать окна в поток}
   S.Init('STACKWIN.STM', SCreate , 1024);
   S.RegisterHier(StackWindowStream);
   S.RegisterHier(ExplodingWindowStream);
   S.RegisterPointer(2000, @StackProc);
   for I := 1 to 2 do
     S.PutPtr(Win[I]);
   S.Done;
end.

    Реализуем два объекта StackWindow, добавляем ряд черт и
затем записываем их в поток. Так как предполагается, что окна
будут расширяться, мы регистрируем поток расширяемых окон, а
также заданный поток стековых окон StackWindow. Далее, учитывая,
что для окон используется стековая обработка, не определяемая по
умолчанию, кроме того, регистрируется адрес этой программы.
    Правила обработки ошибок при использовании потока приведены
в BufIdStream  (OPROOT).

    Дополнительно см.

Load                    RawWindow.Store

           wCopy

    Объявление

constructor wCopy(var S : StackWindow);

    Функция

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

    Описание

    Конструктор wCopy работает подобно RawWindow.wCopy за
исключением того, что он копирует поля дополненных данных
StackWindow, включая указатель активного стека и стековую
обработку. Номер окна для нового окна всегда задается равным
нулю с тем, чтобы не активизировать его в первый момент после
вызова wCopy.

    Пример

  WinOpts := wBordered+wClear+wSaveContents+wResizeable;
  New(Win[1], InitCustom(30, 03, 50, 13, DefaultColorSet, WinOpts));
  with Win[1]^.wFrame do begin
    AddHeader('Header', heTC);
    AddShadow(shBR  shOverWrite);
    AddScrollBar(frRR, 1, 9, DefaultColorSet);
  end;
  New(Win[2], wCopy(Win[1]^));
  if Win[2] = nit then begin
    WriteLn('Failed to wCopy window, Status = ', InitStatus);
    Halt;
  end;

    Размещаем и инициализируем Win[2] как точную копию Win[1],
включая все черты окна и кадра.

    Дополнительно см.

RawWindow.wCopy

            WindowNumber

    Объявление

function WindowNumber : Word;

    Функция

    Возвращает номер окна - 0, если окно не является активным и
1 или больше в противном случае.

    Описание

    После того, как каждое StackWindow нарисовано, ему
присваивается уникальный целочисленный номер. В случае, если
этот номер выводится в заголовке каждого окна, он может входить
как элемент в конструкцию пользовательского интерфейса, помогая
пользователю идентифицировать окна и производить переключение
между ними на экране.
    WindowNumber возвращает 0 для всех неактивных окон. Активные
окна получают последние более высокие номера окон, присваиваемые
в порядке их показа. При стирании окна его номер возвращается в
свободный пул. Следующее окно, которое будет нарисовано,
получает самый низкий номер окна в свободном пуле. Максимальный
допустимый номер окна равен 2047.

    Пример

   Wnum := Win[1]^.WindowNumber;

    Возвращает номер окна, присвоенный Win[1] при его
первоначальном проталкивании в стек.

    Дополнительно см.

AssignNumber       SetStackProc
Draw

        3. WindowStack

    WindowStack работает совместно с StackWindow и управляет
взаимными связями между окнами. Существует всего несколько
методов WindowStack, которые вы можете вызывать непосредственно.
Естественно, вследствие того, что WindowStack получают из более
общего PointerStack объекта (описанного в разделе OPROOT), вы,
кроме того, можете вызвать любой из методов PointerStack.
    Особый интерес прдеставляет метод WindowStack, применяемый
для контроля одновременно нескольких окон, включающий поддержку
мыши. EvaluateStackMousePos определяет, в какое из активных окон,
если таковые есть, попала мышь, и возвращает указатель в это
окно. В такой ситуации метод GetPosResults для окна дает более
подробную информацию: находится ли курсор мыши в кадре, в
пределах полосы прокрутки  и т.д.
    OPWINDOW объявляет одну глобальную WindowStack переменную
(фактически, текстовую константу), которая используется для всех
операций. Указанная переменная имеет имя wStack, и обычно на нее
ссылаются при вызове методов WindowStack. Учитывая, что wStack -
это текстовая константа, ее инициализация выполняется
автоматически, и нет необходимости в вызове ее конструктора.
    Вследствие того, что объект WindowStack в настоящее время не
позволяет законным образом применять вместо wStack какой-либо
другой стек, маловероятно, чтобы вы объявили свои собственные
переменные типа WindowStack.
    Ниже приведена программа, которая показывает ряд
возможностей применения WindowStack.

program WindowStackExample;  {EXWSTACK.PAS}
uses OpCrt, OpFrame, OpWindow;
var
  Win : WindowPtr;
  WinOpts : LongInt;
  I, J : Integer;
  S : String;
begin
  {Make three framed, resizable StackWindows}
  {Создать три StackWindow с рамками с изменяемым размером}
  WinOpts := wBordered+wClear+wSaveContents+wResizeable;
  New(Win, InitCustom(30, 3, 50, 13, DefaultColorSet, WinOpts));
  Win^.Draw;
  New(Win, InitCustom(35, 8, 55, 18, DefaultColorSet, WinOpts));
  Win^.Draw;
  New(Win, InitCustom(40, 13, 60, 23, DefaultColorSet, WinOpts));
  Win^.Draw;
  Delay(1000);

  {Demonstrate the use of default wStack}
  {Демонстрируется применение стека wStack}
  for I := 1  to wStack.SP do begin
    Win := WindowPtr(wStack.Peek(I));
    for J := 2 to 10 do
      Win^.wFastWrite('Hello Mars', J, 5, TextAttr);
    Delay(1000);
  end;
  repeat
    Win := wStack.UnStackTop;
    if Win <> nil then begin
      Dispose(Win, Done);
      Delay(1000);
    end;
  until Win = nil;

  wStack.Done;
end.

    В рассматриваемом примере мы разместили и инициализовали три
WindowStack объекта. Отметим, что мы не сохранили какие-либо
отдельные записи для указателей каждого окна. Вместо этого, окна
рисуются сразу же после размещения, а их указатели хранятся в
WindowStack.
    Затем, мы использовали методы SP и Peek, которые wStack
наследует из PointerStack. SP возвращает индекс самого верхнего
элемента в стеке, а Peek возвращает указатель в требуемое место
в стеке. Элемент 1 - это первое опущенное окно. Отметим, что
ядро типа WindowPtr требует преобразования указателя,
возвращаемого Peek, к соответствующему типу. Мы вызываем
программу wFastWrite для StackWindow для записи определенного
текста в каждое из окон; это можно выполнить даже с учетом того,
что первые два окна частично загорожены.
    Метод UnstackTop для WindowStack стирает расположенное в
вершине стека окно и удаляет его из стека. Метод возвращает
указатель к стираемому окну или возвращает nil, если в стеке нет
окна. Мы используем указатель с тем, чтобы по очереди удалить
каждый объект StackWindow.
    И наконец, программа удаляет сам WindowStack. В приведенном
примере это лишь ухищрение, так как программа может завершить
работу в любой момент времени. В случае, если вы тестируете
программу, чтобы убедиться, что удалили всю динамически
распределяемую память, вам важно сделать рассмотренные в примере
действия. Проще всего об этом забыть, так как в программе нет
вызова wStack.Init.

    Константы

wStack : WindowStack = (
  psTop:0; psSize:0; psStatus:0; psBase:nil;
  wsScreen: (vsWidth:0; vsHeight:0; vsVideoSeg:0; vsSize:0;
             vsBufPtr:nil; vsAllocated:False);
  wsLevel:0 );

    По умолчанию WindowStack . Этот стек используют все объекты
StackWindow. Компилятор инициализирует рассматриваемый объект,
делая его готовым к применению. При первом проталкивании окна в
стек объект PointerStack размещает блок динамической памяти
достаточно большого объема для вмещения окон InitStackSize.
(InitStackSize - это константа равная 8, определяемая в OPROOT.)
При необходимости wStack динамически расширяется.

    Типы

WindowStackPtr = ^WindowStack;
WindowStack =
  object(PointerStack)
   ...
  end;

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

          Done

    Объявление

Destructor Done; virtual;

    Функция

    Очистить и разместить.

    Описание

    Вызывает метод Done для опущенного виртуального экрана, а
также PointerStack , из которого WindowStack получен. Действие
метода заключается в освобождении всей динамической памяти,
отведенной WindowStack.

    Пример

   wStack.Done;

    Мы удаляем динамическую память, используемую стандартным
стеком окон wStack.

    Дополнительно см.

PointerStack.Done         VirtScreen.Done


           EvaluateStackMousePos

    Объявление

  {$IFDED UseMouse}
  function EvaluateStackMousePos : WindowPtr;

    Функция

    Вычислить местоположение мыши, используя EvaluatePos.

    Описание

    В случае, если мышь не установлена, EvaluateStackMousePos
всегда возвращает nil. В противном случае она определяет
абсолютное местоположеие курсора мыши, передает эту информацию в
EvaluateStackPos и возвращает результат из названной процедуры.
    Этот метод особенно полезен в приложениях с использованием
нескольких окон, приводимых в действие мышью, так как он
позволяет с помощью мыши передавать управление от одного окна к
другому. Пример возможностей применения рассматриваемой функции
приведен в демонстрационной программе DESKPOP.

    Пример

  Win := wStack.EvaluateStackMousePos;
  if Win <> nil then begin
    UserCode := Win^.PosResults(FramePos, HotCode);
    {...Process results...}
    {Результаты обработки}
   end;

    В случае, если Win не равно nil, Win является указателем в
активное StackWindow, внутри которого в текущий момент времени
находится курсор мыши. При вызове метода PosResults для
рассматриваемого окна получаем дополнительную информацию о
местоположении курсора мыши относительно окна. Более подробную
информацию см. в RawWindow.PosResults.

    Дополнительно см.

EvaluateStackPos                       RawWindow.PosResults


       EvaluateStackPos

    Объявление

function EvaluateStackPos(X, Y : Byte) : WindowPtr;

    Функция

    Вычислить координаты положения и возвратить указатель в
указанное окно, если оно будет найдено.

    Описание

    EvaluateStackPos просматривает от самого верхнего активного
StackWindow до самого нижнего окна, вызывая для каждого окна
метод EvaluatePos, определяя , попадает ли заданная точка с
абсолютными координатами (X, Y) внутрь кадра. Фукция возвращает
указатель в первое найденное такое окно. (Точнее
EvaluateStackPos ищет первое окно, для которого PosResults не
возвращает в качестве первого параметра значение
frOutsideFrame.) В случае, если такое окно не обнаружено
EvaluateStackPos возвращает nil. Отметим, что для возвращаемого
окна уже вызвали EvaluatePos, поэтому сразу же можно вызвать его
метод PosResults.

    Пример

X := 40;
Y := 10;
Win := wStack.EvaluateStackPos(X, Y);
if Win <> nil then begin
   UserCole := Win^.PosResults(FramePos, HotCole);
   {...Process results...}
   {Результаты обработки}
end;

    Указатель возвращается к самому верхнему окну в wStack,
который содержит точку (40, 10). При возвращении допустимого
указателя окна точка вычисляется более подробно. Законченные
примеры применения EvaluatePos и PosResults см. в RawWindow.

    Дополнительно см.

EvaluateStackMousePos          RawWindow.PosResults
RawWindow.EvaluatePos

       Init

    Объявление

constructor Init(Max : Word);

    Функция

    Разместить стек и инициализовать.

    Описание

    Отводится память для управления Max активными окнами.
Подобно PointerStack при необходимости WindowStack автоматически
увеличивает свой размер. Отрицательная сторона такого
автоматического изменения размеров заключается в том, что в
результате происходит дробление динамической памяти. Поэтому
целесообразно выбрать Max достаточно большим для вмещения всех
окон. WindowStack по умолчанию - wStack - имеет начальный размер
равный InitStackSize, являющийся константой равной 8,
определяемой в OPROOT.
    Кроме того, Init инициализует виртуальный экран WindowStack,
но в рассматриваемый момент времени не отводит для него никакой
динамической памяти.

             Load

    Объявление

constructor Load(var S : IdStream);

    Функция

    Загрузить из потока.

    Описание

    S - это соответствующим образом инициализированный объект
типа потока (например, файлы типа потока, открытые для чтения).
Отметим, что S может быть любым наследником типа IdStream,
включая DosIdStream, BufIdStream, MemIdStream.
    Load считывает следующую последовательность байтов из потока
S. Эти байты должны быть записаны в предыдущем обращении к
StackWindow.Store.
    Load использует для выполнения большей части своих функций
процедуру PointerStack.Load. Указанный метод отводит столько же
места в стеке, сколько в нем было при вызове Store, затем
полиморфически загружает все объекты , опущенные в хранящийся
стек, и проталкивает указатели на каждый из объектов в новый стек.
    Учитывая, что WindowStack хранит указатели в StackWindow,
для успешной загрузки через Load потока WindowStack необходимо
зарегистрировать различные специальные типа, связанные с
StackWindow, например, типы для расширяемых окон или для
стековой обработки. Процедура регистрации потока для WindowStack
с именем WindowStackStream сама регистрирует тип StackWindow.
    После того как размещен WindowStack, загружены объекты и
протолкнуты в стек, WindowStack перерисовывает каждое StackWindow
в том порядке, в каком они указаны в стеке.
    В случае неуспешной работы Load по какой-либо причине
ненулевой код статуса будет помещен в InitStatus.

    Пример

uses
  OpCrt, OpRoot, OpFrame, OpWindow;
var
  S : BufIdStreaml
begin
  {Load wStack from a stream}
  S.Init('WINSTACK.STM', SOpen, 1024);
  S.RegisterHier(WindowStackStream);
  S.Get(wStack);
  if S.GetStatus <> 0 then
    Halt;
  S.Done;

  { All the windows have been initialized and drawn in the original order}
  {Все окна инициализированы и нарисованы в исходном порядке}
end.

    В примере загружается глобальный wStack из потока,
созданного в примере для Store. Оба StackWindow в потоке
размещаются, инициализуются и рисуются. Метод Get для потока
вызывает WindowStack.Load косвенным образом.
    Правила по обработке ошибок при использовании потоков
приведены  в BufIdStream (в OPROOT).

    Дополнительно см.

PointerStackLoad                   Store
StackWindow.Load

         Store

    Объявление

procedure Store(var S : IdStream);

    Функция

    Записать в поток

    Описание

    S - это соответствующим образом инициализированный объект
типа потока (например, файлы типа потока, открытые для чтения).
Отметим, что S может быть любым наследником типа IdStream,
включая DosIdStream, BufIdStream, MemIdStream (Хотя, обычно вы не
будете записывать в MemIdStream).
    Store записывает образ StackWindow в поток S. Перед вызовом
этого метода Вы должны убедиться, что сам тип StackWindow , а
также все типы, связанные с StackWindow зарегистрированы
управляющей программой для потока.
    Отметим, что Store записывает не только сам стек
WindowStack, но, кроме того, все окна, размещенные в нем в
рассматриваемый момент времени. Такая возможность является
полезной, если Вы хотите запомнить полное состояние с
использованием нескольких окон, которые, возможно, будут
восстановлены при следующем обращении к программе. Для обработки
ошибок, возникающих при выполение Store, вызовите функцию
GetStatus для потока.
    Процедура регистрации потока для StackWindow имеет имя
StackWindowStream.

    Пример

uses
   OpCrt, OpRoot, OpFrame, OpWindow;
var
  Win : WindowPtr;
  S : BufIdStream;
  WinOpts : LongInt;
  I, J : Word;
begin
  {Make two bordered StackWindows, push onto wStack}
  {Создать два StackWindow с рамкой, протолкнуть в стек wStack}
  WinOpts := wBordered+wClear+wSaveContents+wStoreContetns;
  New(Win, InitCustom(30, 3, 50, 13, DefaultColorSet, WinOpts));
  Win^.Draw;
  New(Win, InitCustom(35, 8, 55, 18, DefaultColorSet, WinOpts));
  Win^.Draw;

  {Fill the windows with text}
  {Заполнить окна текстом}
  for I := 1  to 2 do begin
    Win := WindowPtr(wStack.Peek(I));
    for J := 2 to 10 do
      Win^.wFastWrite('Hello Mars', J, 5, TextAttr);
    Win^G.SaveContents;
  end;

  {Write the window stack and the windows to a stream}
  {Записать стек окон и окна в поток}
  S.Init('WINSTACK.STM', SCreate, 1024);
  S.RegisterHier(WindowStackStream);
  S.Put(wStack);
  S.Done;

  Win := wStack.UnStackTop;
  while Win <> nil do begin
    Dispose(Win, Done);
    Win := wStack.UnStackTop;
  end;
end.

    Записываем глобальный wStack в поток. WindowStack.Store
косвенные образом вызывает метод Put для потока. Будут записаны
оба окна (включая их содержание), находящиеся в рассматриваемый
момент времени в стеке wStack. В Load приведен пример программы
для загрузки рассматриваемого потока.
    Правила обработки ошибок при использовании потока приведены
в BufIdStream  (OPROOT).

    Дополнительно см.

Load                            StackWindow.Store
PointerStack.Store

            TopWindow

    Объявление

function TopWindow : WindowPtr;

    Функция

    Вернуть указатель в окно, находящееся в вершине стека.

    Описание

    TopWindow - это сокращенная запись "WindowPtr(PeekTop)".
Функция возвращает nil в случае, если стек пустой.

    Пример

Win := wStack.TopWindow;

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

    Дополнительно см.

PointerStack.Peek                     PointerStack.PeekTop

           UnstackTop

    Объявление

function UnstackTop : WindowPtr;

    Функция

    Стирает и удаляет окно из вершины стека.

    Описание

    В случае, если стек окон является пустым, данная функция
возвращает nil и больше ничего не делает. В противном случае
функция стирает окно, находящееся в вершине стека, удаляет его
из стека и возвращает указатель в только что стертое окно. Кроме
того, если в ходе операции стирания возникает ошибка UnstackTop
возвращает nil.

    Пример

Win := wStack.UnStackTop;

    Функция стирает верхнее в стеке wStack окно(принимаемое по
умолчанию для WindowStack), удаляет его из стека и возвращает
указатель в окно.

    Дополнительно см.

    PointerStack.Pop                    StackWindowErase







        4.CommandWindow

    CommandWindow - это первый объект в иерархии окон,
интегрирующий ввод с клавиатуры и от мыши с выводом на экран
текста. Полезные в многих приложениях окна часто требуют
определенную форму интерактивного взаимодействия с
пользователем, даже если есть только единственное требование:
"нажать клавишу <Esc> для продолжения" . Для подтверждения этой
возможности CommandWindow вводит указатель в объект
CommandProcessor (описанный в главе 3), который преобразует
ключевые строки в логические команды.
    Наиболее эффективный метод CommandWindow - это метод Process.
При вызове метода Process окно по-существу отключает контроль
клавиатурой методов обработки логических команд (например,
перемещение в список выбора PickList) до тех пор, пока
пользователь не введет для окна одну из команд выхода. В этот
момент времени метод Process прекращает работу, и вызывающая
программа может проверить последнюю ключевую строку и введенную
команду, определяя, что делать дальше.
    В одном важном отношении CommandWindow является абстрактным
объектом. Учитывая, что для него невозможно применить
"универсальный" метод Process, единственное, что он
обеспечивает, должно не приниматься во внимание объектами,
полученными из него. Написание метода Process для объекта с
полным набором черт, подобно некоторому текстовому редактору или
перечню выбора, представляет собой весьма сложную задачу; к
счастью для вас мы уже проделали это для наиболее типичных
возможностей пользовательского интерфейса. Для самого простого
случая, подобно окну статуса проталкивания popup, метод Process
соответственно является наиболее несложным, мы приведем
небольшой пример такого рода.
    CommandWindow предлагает две дополнительные ловушки ,
которые в полной мере отвечают главному назначению
CommandWindow. Первая ловушка - возможность обработки ошибок.
Такая подпрограмма записывает указатель в процедуру, которая
вызывается автоматически из любого места, где возникла ошибка.
Используя преимущества такого указателя вы можете в своих
приложениях сконцентрировать обработку ошибок для всех окон в
одном месте.
    Второй способ - это соединение с системой контекстуально-
зависимой помощи OPHELP. Каждое CommandWindow хранит индекс - номер
раздела OPHELP, который вы выбрали. При вызове пользователем
команды помощи help в любом месте, метод Process вызывает
стандартную подпрограмму обработки помощи (определяемую в
окне CommandProcessor), используя указанный номер раздела.
    Мы покажем несколько позже как использовать названные
ловушки. Но вначале приведем пример, как создать собственное
окно CommandWindow.

program CommandWindowExample; {EXCMDWIN.PAS}
uses
   OpCrt, OpRoot, OpCmd, OpFrame, OpWindow
const
   {Define a trivial KeySet of a few cursor commands}
   {Определить тривиальный KeySet из нескольких команд курсора}
KeyMax = 18;
   KeySet : Array[0..KeyMax] of Byte = (
   {length   keys         command type     key sequence}
   {длина    ключи        тип команды    последовательность ключей}
   3,        $00, $48     ccUp             {Up}      {Вверх}
   3,        $00, $50     ccDown           {Down}    {Вниз}
   3,        $00, $4B     ccLeft           {Left}    {Влево}
   3,        $00, $4D     ccRight          {Right}   {Вправо}
   2,        $1B,         ccQuit);         {Esc}     {Отменить}
type
  SampleWindow =
     object(CommandWindow)
       procedure Process; virtual;
     end;
  var
    Commands : CommandProcessor;
    CmdWin : SampleWindow;
    Finished : Boolean;

   procedure SampleWindow.Process;
   begin
     repeat
       {Get a command}
       {Ввести команду}
       GetNextCommand;
       case GetLastCommand of
          ccUp :   WriteLn('ccUp');
          ccDown : WriteLn('ccDown');
          ccLeft : WriteLn('ccLeft');
          ccRight: WriteLn('ccRight');
          ccQuit : WriteLn('ccQuit');
          ccChar : WriteLn('ccChar: ', Char(Lo(GetLasrKey)));
          else     WriteLn('ccNone');
       end;
     until (GetLastCommand = ccQuit) or (GetLastCommand = ccError);
   end;

begin
   {Make a small CommandProcessor}
   {Создать небольшой командный процессор}
      Commands.Init(@KeySet, KeyMax);

      {Make a bordered CommandWindow}
      {Создать командное окно с рамкой}
  if not CmdWin.InitCustom(30, 5, 50, 15,    {Window coordinates}
                                             {Координаты окна}
           DefaultColorSet,                  {Color set}
                                             {Набор цветов}
           wBordered+wClear+wSaveContents,   {Window options}
                                             {Опции окна}
           Commands,                         {Command processor}
                                             {Командный процессор}
           ucNone)                           {Unit code}
                                             {Код устройства}
  then  begin
     WriteLn('Failes to init CommandWindow. Status = ', InitStatus);
     Halt;
  end;

  {Add headers and draw window}
  {Добавить заголовки и нарисовать окно}
  CmdWin.wFrame.AddHeader(' Command window ', heTC);
  CmdWin.wFrame.AddHeader(' <Esc>  to Quit ', heTC);
  CmdWin.Draw;
   {Get and process commands}
   {Ввести и обработать команды}
   Finished := False;
   repeat
     CmdWin.Process;
     case CmdWin.GetLastCommand of
                   ccQuit : Finished := True;             {Quit}
                                                          {Закончить}
                   ccError : begin                        {Error}
                                                          {Ошибка}
                   WriteLn('Erroe : ', GetLastError);
                   Finished := True;
                 end;
       ccUser0..ccUser55 : WriteLn('user command'); {Handle exit command}
                                               {Обработка команды выхода}
end;
   until Finished;

   {Clean up}
   {Очистить}
   CmdWin.Done;
   Commands.Done;
end.

    SampleWindow - это очень простое расширение CommandWindow,
которое отвергает как раз метод Process. Для подготовки этого
типа мы вначале определим константу типа KeySet в соответствии с
требованиями для командного процессора. Ключи, определяемые в
этом массиве, будут преобразованы в заданные логические команды;
другие ключи будут преобразованы в ccNone. В примере объявляется
переменная CommandProcessor с именем Commands, которая связана с
типом SampleWindow, а также с переменной CmdWin.
    Метод Process для SampleWindow получает константу, вызывая
метод GetNextCommand для CommandWindow, которая ожидает ввода
ключевых строк или действия мыши (хотя в рассматриваемом примере
мыши нет). Далее, пример метода Process проверяет, какая команда
была введена, вызывая GetLastCommand, и переходит в различные
разделы кода в зависимости от команды. Здесь же мы только пишем
какая команда была введена. С двумя исключениями команды
совпадают с командами в KeySet. ccChar - это предопределенное
значение литеры по стандартному коду ASC11 (#32..#126,
#128..#255). В этом случае, вы можете написать саму литеру,
используя функцию GetLastKey . ccNone означает, что ключевая
строка не соответствует какой-либо установленной команде. Цикл
работы метода Process продолжается до тех пор, пока не будет
обнаружен ключ <Esc> (ccQuit) или ошибка (ccError). В
рассматриваемом примере ccError не возникает , так как
SampleWindow никогда ее не устанавливает; тем не менее полезно
иметь привычку проверять ccError.
    В примере вначале инициализуется CommandProcessor для
использования KeySet. Затем инициализуется CommandWindow.
Параметры для названного конструктора включают стандартные
параметры для любого окна - координаты, цвета и опции - плюс два
новых параметра - CommandProcessor и код устройства. Код
устройства будет передаваться в стандартную процедуру помощи
и обработки ошибок, помогая определить источник вызова. В
рассматриваемом примере это не имеет значения, поэтому мы
передаем предопределенную константу ucNone.
    Подобно любому другому окну мы можем добавить заголовки,
используя методы из Frame и RawWindow.
    После того как окно нарисовано, мы вводим цикл обработки
команд, в котором вызывается метод Process и выполняется
проверки последней введенной команды. Последняя команда будет
всегда типа команды выхода; в рассматриваемом случае
единственной командой выхода может быть команда ccQuit. Другие
возможные случаи - это ccError и команды выхода, определяемые
пользователем - ccUser0..ccUser55. Более подробную информацию Вы
найдете в CommandProcessor (глава 3).

    Ловушки обработки ошибок

    Объекты, полученные из CommandWindow, вызывают его метод
GotError при обнаружении ошибки. GotError использует два
параметра - код ошибки и строку сообщения, являющуюся
необязательным вспомогательным средством для программы обработки
ошибок. В свою очередь GotError сохраняет код ошибки в одном из
полей данных CommandWindow, из которого его может забрать метод
GetLastError. После этого GotError вызывает определяемую
пользователем процедуру, ловушку обработки ошибки, передает ему
код ошибки, сообщение об ошибке и код устройства. Принимаемая по
умолчанию процедура обработки ошибок с именем DefaultErrorProc
(объявляемая в OPCMD) просто подает прерывистый звуковой сигнал
и возвращает управление.
    После этого GotError повторно вычисляет код ошибки, который
может быть изменен в подпрограмме, определяемой пользователем. В
случае, если ошибка не относится к классу "фатальных", GotError
устанавливает код хранящейся ошибки равным нулю. В соответствии
с терминологией ObjectProfessional фатальная ошибка -
это ошибка, для которой экземпляр конкретного объекта, где она
возникла, более не пригоден для использования. Это не всегда
означает, что программу необходимо остановить. Изменение класса
ошибки методом GotError означает, что процедура обработки ошибок
отвечает за информирование пользователя о нефатальных ошибках и
предупреждениях, и при возможности она должна выполнять
исправления и устанавливать код ошибки как фатальный, если
исправление невозможно.
    Достаточно просто написать и установить специальную
процедуру обработки :

{$F+}
procedure MyErrorProc(UnitCode : Byte; var ErrorCode : Word;
                     ErrorMsg : string);
   {-Custom error handler}
   {Специальная программа обработки ошибок}
var
  KW : Word;
begin
  if ErrorCode mod 10000 <> 0 then begin
   {Build an error message}
   {Создать сообщение об ошибке}
   if ErrorMsg = '' then
     ErrorMsg := 'Error '+Long2Str(ErrorCode);
   ErrorMsg := ErrorMsg+', Press a key to continue...');

   {Write it to the bottom of the screen and beep}
   {Записать сообщение об ошибке в низ экрана и послать
                              прерывистый сигнал}
   FastWrite(ErrorMsg, ScreenHeight, 1, TextAttr);
   RingBell;

   {Wait for a key}
   {Ждать нажатия клавиши}
   KW := RedKeyWord;

   {Treat all errors as fatal but let warning go}
   {Трактовать все ошибки как фатальные, но допустить выдачу
          предупреждений}
   if ErrorCode div 10000 = etNonFatal then
     ErrorCode := epFatal+(ErrorCode mod 10000);
  end;
end;
{$F-}
...
CmdWin.SetErrorProc(MyErrorProc);

    Здесть целесообразно коротко напомнить о кодах ошибок для
ObjectProfessional. Код представляет собой сумму префикса
ошибок, кратного 10000, и номера ошибки, которых находится в
диапазоне от 0 до 9999. Номер ошибки равный нулю всегда означает
"ошибок нет". Префикс ошибки равный 0 - это фатальная ошибка,
10000 - нефатальная ошибка, 20000- предупреждение, а 30000 -
сообщение, не связанное с ошибками.
    Рассматриваемая процедура обработки ошибок вначале
проверяет, действительно ли произошла ошибка. В случае, если
ошибка имела место, процедура создает сообщение об ошибке. Ряд
объектов передают строку ErrorMsg, поэтому, если она передана,
процедура MyErrorProc использует эту строку. В противном случае
она создает строку на основе кода ошибки. После этого процедура
записывает сообщение, посылает прерывистый сигнал на динамик и
ожидает нажатия клавиши. Кроме того, рассматриваемая процедура
обработки ошибок использует консервативный подход , изменяя
класс любой нефатальной ошибки в фатальный; в результате в
приложениях можно будет прочесть код ошибки, используя метод
GetLastError.
    Для установки программы обработки ошибок используется метод
SetErrorProc для CommandWindow. Каждый экземпляр CommandWindow
(или любой наследник) может иметь собственную уникальную
программу обработки ошибок или же все могут пользоваться одной
программой. Параметр UnitCode , передаваемый в программу
обработки ошибок, помогает различать вызовы из различных
объектов.
    Допустимая процедура обработки ошибок должна быть объявлена
FAR, используя опцию компилятора {$F+}. Это объявление не может
быть вложено внутрь любой другой процедуры и должно иметь точно
те же параметры, которые показаны в вышеприведенном примере.

    Ловушка контекстуально-зависимой помощи

    Ловушка обработки помощи для CommandWindow построена на
основе ловушки, представляемой  CommandProcessor. Эта ловушка
описанав главе 3 вместе с OPCMD. Новые черты его заключаются в
создании индекса помощи, определяемого по умолчанию для
каждого CommandWindow. При инициализации CommandWindow его
индекс помощи по умолчанию устанавливаются равным нулю, что,
по крайней мере для OPHELP, означает, что нет никакого предмета
помощи. Вы можете изменить предмет помощи на другое
значение, используя, например, метод SetHelpIndex:

    CmdWin.SetHelpIndex(100);

    Ряд производных CommandWindow окон в ObjectProfessional
предлагают другие способы получения индекса помощи. Например,
объект Menu имеет флаг с именем mnUseItemForTopic. В случае,
если этот флаг установлен, код активного пункта меню передается
в подпрограмму обработки помощи в качестве индекса помощи,
отвергая любое значение, хранящееся вместе с SetHelpIndex.
Аналогичная опция pkUseItemForTopic доступна для объекта
PickList.
    Для заданного окна вы можете назначить процедуру обработки
помощи для CommandWindow следующим образом:

CmdWin.GetCommandProcessor^.SetHelpProc(MyGetHelpProc);

    Следует помнить, что каждый CommandProcessor одновременно
может иметь только одну ловушку контекстуально-зависимой помощи.
Более подробную информацию Вы найдете в OPCMD.

    Типы

ByteSet = set of Byte;
ByteSetPtr = ^ByteSet;

    Каждое CommandWindow содержит поле, которое указывает на
ByteSet. Допустимыми элементами этого набора являются OPCMD
командные коды. В любом месте, где метод Process для
CommandWindow обнаруживает ввод одного из этих кодов, метод
прекращает работу точно также, как при нажатии обычной команды
выхода. Эта возможность предусмотрена для содействия
комбинированию сложных CommandWindow объектов. Например, метод
Process для объекта PickList, помещенного в экран EntryScreen,
должен прекратить работу при нажатии клавиши Tab, связанной с
другими полями данных в EntryScreen. Добавляя командный код
ccTab в набор ByteSet, мы можем заставить PickList временно
вести себя рассмотренным выше образом. Более подробную
информацию Вы найдете в описании метода SetExinCommands.

CommandWindowPtr = ^CommandWindow;
CommandWindow =
  object(StackWindow)
    ...
  end;

    Здесь приведены типы данных, описывающие CommandWindow
объект.


                 ClassifyError

    Объявление

function ClassifyError(ErrorCode : Word) : Byte;

    Функция

    Возвратить класс заданного кода ошибки.

    Описание

    В случае, если величина (ErrorCode mod 10000) равна нулю
ClassifyError возвращает etNoError, указывая тем самым, что
ошибок нет. В случае, если ErrorCode больше или равен 40000
ClassifyError возвращает etFatal , так как отсутствуют более
высокие допустимые коды ошибок. В остальных случаях
ClassifyError возвращает (ErrorCode div 10000). Более подробную
информацию Вы найдете в приложении D. Коды ошибок.

    Пример

Finished := False;
repeat
  CmdWin.Process;
  case CmdWin.GetLastCommand of
    ccQuit : Finished := True;                   {Quit}
    ccUser0..ccUser55 :WriteLn('user command');  {Handle exit command}
    ccError :                                    {Error}
      begin
        Status := CmdWin.GetLastError;
        if CmdWin.ClassifyError(Status) = etFatal then begin
           WriteLn('Error during Process, Status = ', Status);
           Finished := True;
        end;
    end;
  end;
until Finished;

    Определяется является ли ошибка, вызвавшая прекращение
работы метода Process, фатальной; если ошибка фатальная, то
выводится сообщение о ней и выходим из цикла обработки.

    Дополнительно см.

GetLastError

        GetCommandProcessor

    Объявление

function GetCommandProcessor : CommandProcessorPtr;

    Функция

    Возвратить указатель в командный процессор окна.

    Описание

    Обычно командный процессор CommandProcessor для заданного
CommandWindow известен при входе в CommandWindow.
(CommandProcessor передается в качестве параметра в конструктор
CommandWindow.) Однако, в случае, если это его значение больше
недоступно, функция GetCommandProcessor возвратит указатель в
CommandProcessor для CommandWindow.

    Пример

CmdWin.GetCommandProcessor^.AddCommand(ccUser0, 1, $4400, 0);

    Добавить в командный процессор окна клавишу <F10> ($4400) в
качестве команды выхода ccUser0.

    Дополнительно см.

SetCommandProcessor

     GetExitCommandPtr

    Объявление

function GetExitCommandPtr : ByteSetPtr;

    Функция

    Возвратить указатель в набор особых команд выхода.

    Описание

    В случае, если отсутствуют особые команды выхода,
GetExitCommandPtr возвращает nil. В противном случае она
возвращает указатель в ByteSet, который был первоначально описан
с помощью метода SetExitCommands.
    Обычно названный метод вызывают только в методе Process типа
получаемого  из CommandWindow.

    Пример

if GetExitCommandPtr <> nil then
  if GetLastCommand in GetExitCommandPtr^ then
    Finished := True;

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

    Дополнительно см.

SetExitCommands

        GetHelpIndex

    Объявление

function  GetHelpIndex : Word;

    Функция

    Возвратить номер предмета помощи для рассматриваемого
окна.

    Описание

    Для только что инициированного CommandWindow функция
GetHelpIndex всегда возвращает ноль. В случае, если был сохранен
другой индекс помощи при вызове метода SetHelpIndex, то
функция GetHelpIndex возвращает это значение.
    Обычно названный метод вызывают только в методе Process типа
получаемого  из CommandWindow.

    Пример

RequestHelp(GetHelpIndex);

    Вызывает процедуру обработки помощидля CommandWindow,
используя индекс помощи, запоминаемый  для окна.

    Дополнительно см.

  SetHelpIndex


         GetLastCommand

    Объявление

function  GetLastCommand : Word;

    Функция

    Возвратить последнюю  команду, введенную пользователем.

    Описание

    Для только что инициализованного CommandWindow функция
GetLastCommand возвращает ccNone. После вызова метода Process
функция GetLastCommand возвращает одну из обычных команд выхода
для окна ( в типичных случаях - ccQuit, ccSelect,
ccUser0..ccUser55 или ccError) или одну из команд из набора
особых команд выхода (см. SetExitCommand).
    Кроме того, GetLastCommand можно вызвать из метода Process.
В этом случае функция может возвратить любой код команды, связанный с
CommandProcessor окна. Все такие коды должен интерпретировать
сам метод Process.
    При вызове GetLastCommand хранящееся значение не очищается.
Значение можно вызвать столько раз, сколько необходимо.

    Пример

Finished := False;
repeat
  CmdWin.Process;
  case CmdWin.GetLastCommand of
    ccError;                                  {Fatal error}
    ccQuit : finished := True;                {Quit}
    ccUser0..ccUser55 : WriteLn('user exit'); {Handle exit command}
  end;
until Finished;

    Функция GetLastCommand применяется для определения, что
делать после метода Process.

    Дополнительно см.

GetLastKey                         SetLastCommand


        GetLastError

    Объявление

function GetLastError : word; virtual;

    Функция

    Возвратить код последней ошибки и очистить внутреннюю
переменную.

    Описание

    В случае, если ошибки нет, функция GetLastError возвращает
ноль. В противном случае функция возвращает код ошибки,
записанный в момент, когда метод объекта вызвал метод
CommandWindow.GotError (и GotError не очистила код ошибки) или
при обнаружении проблемы объектами более низкого уровня, такими
как RawWindow или даже Frame. GetLastError имеет доступ ко всем
ошибкам, которые могут возникнуть в CommandWindow или в его
производных типах.
    Все значения ошибок можно интерпретировать как указано в
приложении D.
    Несмотря на то, что GetLastError очищает  внутреннее
значение ошибки, устанавливая его в ноль, возможно, что все же
будут существовать другие ошибки более низкого уровня. Для
очистки всех существующих ошибок вызовите ClearError.

    Пример

    См. пример программы в начале рассматриваемого раздела.

    Дополнительно см.

GotError               RawWindow.ClearErrors


          GetLastKey

    Объявление

function GetLastKey : Word;

    Функция

    Возвратить последнюю ключевую строку, введенную
пользователем.

    Описание

    В большинстве случаев для метода Process или приложений для
решения, что делать дальше, достаточно знать код команды,
возвращаемой GetLastCommand. Помимо других главное назначение
объекта CommandWindow заключается в преобразовании ключевых
строк в команды с тем, чтобы ключевые строки могли бы быть
установлены повторно без воздействия на применение программы.
    Однако, существует по крайней мере два кода команд, которые
требуют дополнительной расшифровки : ccChar и ccCtrlChr. Эти
коды возвращаются при нажатии пользователем обычных
буквенно-цифровых клавиш или, соответственно, при нажатии клавиш
управления. В случае объекта TextEditor код команды ccChar
означает , что соответствующая ключевая строка должна быть
вставлена в соответствующий текстовый буфер. Для объекта
PickList ccChar обычно означает, что пользователь производит
поиск элемента выбора, который начинается с нажатого символа.
    Функция GetLastKey возвращает полное просмотренное слово из
ключевой строки . В случае, если нижний байт (lo(GetLastKey))
равен нулю, то это будет значение ключа по коду ASCII. Высший
байт слова - это код просмотра, который обычно не представляет
интереса при использовании GetLastKey.
    При вызове GetLastKey не происходит очистки записанного
значения. Это значение можно вызывать столько раз сколько
необходимо.

    Пример

repeat
  {Get a command}
  GetNextCommand;
  case GetLastCommand of
    ...
    ccChar :
      WriteLn('ccChar: ', Char(Lo(GetLastKey = ccError);
  end;
until (GetLastCommand = ccQuit) or (GetLastCommand = ccError);

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

    Дополнительно см.

GetLastCommand                 ReadKeyWord(OPCRT)


       GetNextCommand

    Объявление

procedure GetNextCommand; virtual;

    Функция

    Функция вызывается из метода Process для получения следующей
команды от пользователя.

    Описание

    GetNextCommand вызывает функцию GetCommand для
CommandProcessor окна. Указанная функция в свою очередь вызывает
определяемую пользователем функцию GetKeyProc, которая
фактически читает ввод с клавиатуры или с мыши. Следовательно ,
как описано для CommandProcessor, могут возникнуть задачи
фоновой обработки в тот момент времени, когда CommandWindow
будет ждать ввода с клавиатуры.
    GetNextCommand хранит возвращаемый код команды и строку
ключей в качетсве внутренних переменных. Доступ к этим
переменным возможен через вызов GetLastCommand  и GetLastKey.

    Пример

procedure SampleWindow.Process;
begin
  repeat
    GetNextCommand;
    case GetLastCommand of
      ...
    end;
  until (GetLastCommand = ccQuit) or (GetLastCommand = ccError);
end;

var CmdWin : SampleWindow;
  ...
CmdWin.GetCommandProcessor^.SetGetKeyProc(MyReadKey);
CmdWin.GetCommandProcessor^.SetKeyPressedProc(MyKeyPressed);
  ...
CmdWin.Process;

    Задаем в подпрограммах обработки ключевой строки,
определяемых пользователем, для CmdWin указатели в альтернативные
подпрограммы. См. приведенные примеры программ для
CommandProcessor. Метод GetNextCommand для CmdWin будет вызывать
эти подпрограммы, возможно, разрешая выполнение заданий фоновой
обработки при ожидании ввода.

    Дополнительно см.

GetLastCommand                    GetLastKey


               GotError

    Объявление

    procedure GotError(ErrorCode : Word: ErrorMsg : string);

    Функция

    Вызывается при возникновении ошибки.

    Описание

    Этот метод должен вызываться только методами типа
производных из CommandWindow. Он сообщает программе обработки
ошибок объекта, что возникла ошибка, и тем самым дает
возможность определяемой пользователем процедуре обработать
ошибку. Более подробную информацию Вы найдете в
вышерассмотренном материале "Ловушка обработки ошибок".
    ErrorCode должен соответствовать стандартам, приведенным в
приложении D. Не обязательно нужно передавать строку ErrorMsg,
но она может оказаться полезной для программы обработки ошибки.

    Пример

GotError(epFatal+1001, 'My application error message');

    Дополнительно см.

GetLastError

                 Init

    Объявление

constructor Init(X1, Y1, X2, Y2 : Byte; var CP : CommandProcessor;
                UnitCode : Byte);

    Функция

    Создать командное окно с опциями и цветами по умолчанию.

    Описание

    Рассматриваемый конструктор реализует CommandWindow,
используя опции окна по умолчанию (DefWindowOptions) и набор
цветов по умолчанию (DefaultColorSet). Более подробную
информацию Вы найдете в InitCustom.

    Пример

var
  Commands : CommandProcessor;
  CmdWin : SampleWindow;       {descendant of CommandWindow}
begin
  Commands.Init(@KeySet, KeyMax);
  if not CmdWin.Init(30, 5, 50, 15,    {Window coordinates}
                     Commands,         {Command processor}
                     ucNone)           {Unit code}
  then begin
    WriteLn('Failed to init CommandWindow. Status =', InitStatus);
    Halt;
  end;
  ...

    Создать CommandWindow , используя опции и цвета окна по
умолчанию. Рассматриваемое окно будет применять CommandProcessor
объекта с именем Commands.

                    InitCustom

    Объявление

    constructor InitCustom(X1, Y1, X2, Y2 : Byte;
                      var Colors : ColorSet; Options : LongInt;
                      var CP : CommandProcessor; UnitCode : Byte);

    Функция

    Создать командное окно со специальными опциями.

    Описание

    Рассматриваемый конструктор реализует CommandWindow ,
используя заданные опции Options окна и цвета Colors. X1, Y1,
X2, Y2 - координаты внутренней области окна, в которой будет
воспроизведен текст окна. CP - это инициализованный
CommandProcessor, к которому будет обращаться метод Process окна
для преобразования цепочек ключей и нажатий мыши в логические
команды. UnitCode - это значение, идентифицирующее устройство,
на котором в объекте возникла определяемая пользователем ошибка,
Это значение помогает контролировать подпрограммы. Полный
перечень предопределенных кодов устройтв вы найдете в OPROOT в
главе 8. для определяемых пользователем устройств доступные коды
ошибок находятся в диапазоне 100 - 255. Неуспешная работа
InitCustom возможна только в случае неуспешной работы
конструктора-предка(StackWindow.InitCustom). Наиболее вероятная
причина отказа - не хватает памяти. Точная причина может быть
определена на основе InitStatus.

    Пример

    См. пример программы в начале рассматриваемого раздела.

    Дополнительно см.


StackWindow.InitCustom

                 Load

    Объявление


constructor Load(var S : IdStream);

    Функция

    Загрузить CommandWindow из потока.

    Описание

    S - это соответствующим образом инициализированный объект
типа потока (например, файлы типа потока, открытые для чтения).
Отметим, что S может быть любым наследником типа IdStream,
включая DosIdStream, BufIdStream, MemIdStream.
    Load считывает следующую последовательность байтов из потока
S. Эти байты должны быть записаны в предыдущем обращении к
CommandWindow.Store. Load вначале вызывает StackWindow.Load для
получения большей части данных; затем он считывает данные
специфичные для CommandWindow, включая индекс помощи окна,
код устройства, указатель в процедуру обработки ошибок,
указатель CommandProcessor и указатель в набор выходов.
    В случае, если последние три указателя зарегистрированы
перед вызовом Store и, кроме того, они зарегистрированы до
вызова Load, конструктор Load инициализует CommandWindow для
использования снова этих же трех указателей. В случае, если не
зарегистрирована никакая процедура для обработки ошибок
CommandWindow будет использовать процедуру , определяемую по
умолчанию,с именем DefaultErrorProc. В случае, если не
зарегистрирован указатель в набор выходов , то CommandWindow
будет использовать пустой набор выходов.
    Более сложно обстоит дело, когда не зарегистрирован
указатель в CommandProcessor. CommandWindow без каких-либо
исключений должно иметь действующий CommandProcessor прежде, чем
можно будет вызвать метод Process. Но даже в учетом этого Load
не генерирует ошибку, если не находит CommandProcessor. В этой
ситуации программа может объявить CommandProcessor (вызывая
метод SetCommandProcessor) после завершения работы Load.
Собственные производные CommandWindow для Object Professional
используют рассмотренный подход, что позволяет им использовать
специальный CommandProcessor, если вы его уже определили, а в
противном случае использовать стандартный CommandProcessor.
Предупреждаем, что в случае, если Вы забыли зарегистрировать
указатель в CommandProcessor, то до тех пор, пока вы не вызовите
метод Process, ProcessAutoPilot, GetNextCommand или RequestHelp
никаких ошибок не будет обнаружено. Когда это произойдет вы
получите ошибку epFatal+ecNoProcessor.
    Процедура регистрации потока для CommandWindow имеет имя
CommandWindow.Stream.

uses
   OpCrt, OpRoot, OpCmd, OpFrame, OpWindow
const
  {Define a trivial KeySet of a few cursor commands}
  KeyMax = 18;
  KeySet : array[0..KeyMax] of Byte = (
  {length keys       command type    key sequence}
   3,     $00, $48,  ccUp,           {Up}
   3,     $00, $50,  ccDown,         {Down}
   3,     $00, $4B,  ccLeft,         {Left}
   3,     $00, $4D,  ccRight,        {Right}
   2,     $1B,       ccQuit);        {Esc}
type
  SampleWindow =
    object(CommandWindow)
      procedure Process; virtual;
      constructor Load(var S : IdStream);
      procedure Store(var S : IdStream);
   end;
var
  Commands : CommandProcessor;
  S : BufIdStream;
  CmdWin : SampleWindow;
  procedure SampleWindow.Process;
  begin
   {Process commands}
  end;

  constructor SampleWindow.Load(var S : IdStream);
  begin
    if not CommandWindow.Load(S) then
      Fail;
  end;

  procedure SampleWindow.Store(var S : IdStream);
  begin
    CommandWindow.Store(S);
  end;

  {$F+}
  procedure SampleWindowStream(SPtr : IdStreamPtr);
  begin
    CommandWindowStream(SPtr);
    SPtr^.RegisterType(1000, 0, TypeOf(SampleWindow),
                      @SampleWindow.Store, @SampleWindow.Load);
  end;
  {$F-}

begin
  {Initialize CommandProcessor}
  Commands.Init(@KeySet, KeyMax);

  {Load a SampleWindow object from a stream}
  S.Init('CMDWIN.STM', SOpen, 1024);
  S.RegisterHier(SampleWindowStream);
  S.RegisterHier(ExploadingWindowStream);
  S.RegisterPointer(1000, @Commands);
  S.Get(CmdWin);
  S.Done;

  {Get and process commands}
  CmdWin.Draw;
  CmdWin.Process;
  CmdWin.Done;
  Commands.Done;
end.

    Реализуется CmdWin из потока, созданного в примере для
Store. CommandProcessor реализуется обычным способом и
регистрируется с кодом 1000.
    Другой способ определения CommandProcessor для CommandWindow
- вызвать из метода Load для SampleWindow (после возврата
управления мз CommandWindow.Load) процедуру
SetCommandProcessor(Commands). При использовании такого подхода
вам не нужно помнить о необходимости регистрации указателя.
    Правила обработки ошибок при использовании потоков приведены
в BufIdStream (в OPROOT).

    Дополнительно см.

    CommandWindow.Load                 Store


             PeekLastError

    Объявление

    function PeekLastError : Word;

    Функция

    Возвратить код ошибки ввода/вывода без очистки внутренней
переменной.

    Описание

    Рассматриваемая функция работает подобно GetLastError за
исключением того, что внутренняя переменная статуса не
очищается, поэтому может быть снова считан тот же код ошибки.
Метод полезен при разработке метода Process для объектов типа
производных из CommandWindow.

    Пример

    См. Process

    Дополнительно см.

    GetLastError


         Process

    Объявление

procedure  Process; virtual;

    Функция

    Обработка команд.

    Описание

    Метод Process является сердцем CommandWindow, но, если Вы
вызовите его, то , по иронии, Вы только создадите ошибку при
прогоне программы. Это является следствием того, что метод
Process - это абстрактный метод, который должен блокироваться
объектами, использующими возможности CommandWindow.
    Ниже мы опишем основные черты метода Process, т.е.
возможности, которые встречаются во всех действующих
приложениях. Особенности метода, связанные с конкретным его
применением, будут описаны вместе с соответствующими объектами.
    Прикладные программы вызывают метод Process в момент, когда
они готовы передатиь управление от клавиатуры, мыши и экрана в
окно, которое владеет методом. Process - общий термин, который в
зависимости от типа окна может означать Edit - редактировать,
Pick - выбрать, GetMenuChoice - осуществить выбор меню,
EditDataFields - редактировать поля данных, ShowHelp - показать
помощь, BrawseFile - просмотреть файл и т.д. Фактически, еще
до того, как стали ясны преимущества полиморфизма , объекты
Professional имели методы с указанными именами. Используя их в
сочетании с одним виртуальным методом, мы смогли разделить более
объемный код, сделать поведение программ более согласованным и
открыть дверь к настольным управляющим программам с расширяемыми
возможностями типа DESCPOP.
    При переходе контроля к методу Process, метод Process
вначале проверяет существующие ошибки. В случае, если ошибки
есть, метод сразу же прекращает работу. Затем он выполняет
инициализацию специфичную для объекта, возможно, проверяя размер
текущего окна и регулируя внутренние структуры данных в
соответствии с требуемым. После этой инициализации метод Process
рисует окно, если оно не было уже активным, или корректирует его
содержание, при его наличии. В случае, если окно является
активным , но не текущим, метод Process генерирует ошибку
(epNonFatal+ecWinNotCurrent) и прекращает работу. Если такая
ситуация вполне возможна, вы должны перед вызовом метода Process
вызвать Select, например, следующим образом:

if not MyWin.IsCurrent then
  MyWin.Select;
MyWin.Process;

    Методы Process Object Professional всегда выключают опцию
контроля прерываний OPCRT - CheckBreak, поэтому внутри метода
Process клавиша <CtrlBreak> не будет работать. В случае, если
включена опция работы мыши соответсвующего CommandProcessor, то
метод Process сделает курсор мыши видимым.
    После этого метод Process вводит цикл обработки команд, в
котором он вызывает GetNextCommand и выполняет специфичную для
объекта обработку каждой команды до обнаружения команды выхода.
Команды выхода можно разбить на четыре категории:
    - стандартные команды выхода ccQuit (выйти и при возможности
не учитывать результаты) и ccSelect (выход с выбором);
    - определяемые пользователем команды выхода ccUser0..$FFFF,
которые обычно обрабатываются подобно команде ccSelect. Эти
команды появляются только в случае, если вы использовали методы
CommandProcessor для присвоения им цепочек ключей. Более
подробную информацию Вы найдете в CommandProcessor.AddCommand;
    - динамические команды выхода, введенные в набор команд
выхода (см. SetExitCommands);
    - специальная команда ccError, которая говорит о том, что
внтури метода Process или в методе из вызванном произошла
серьезная ошибка.
    Каждый метод Process Object Professional создает
соответствующую поддержку для команды ccHelp, которая указывает
на запрос пользователем помощип. При введении рассматриваемой
команды метод Process вызывает метод RequestHelp, обычно
передавая ему индекс помощип, присвоенный окну CommandWindow
с помощью SetHelpIndex. Там где это имеет смысл (особенно для
объектов PickList и Menu), кроме того, существует опция вместо
этого передать в RequestHelp индекс выбранного в текущий момент
времени элемента.
    По окончании цикла обработки команд каждый метод Process
выполняет очистку, обычно запоминая состоянии своего окна,
восстанавливая контроль прерываний и делает курсор мыши
невидимым, если он был невидимым в начальный момент вызова.
Отметим, что метод Process не стирает окно, даже если оно в
начальный момент было неактивным.
    Сразу же за вызовом метода Process должно быть записано
утверждение case, которое разветвляется по значению
GetLastCommand. Это позволяет прикладным программам выполнять
соответствующие действия на основе того, как пользователь вышел
из окна.

    Пример

procedure SampleWindow.Process;
var;
  Finished : Boolean;
  SaveBreak : Boolean;
  MouseOn : Boolean;
begin
  {Check for pending error}
  SetLastCommand(ccError);
  if PeekLastError <> 0 then
    Exit;
  {Draw initial screen of not already done}

  Draw;
  if GetLastError <> 0 then begin
    GotError(epNonFatal+ecWinNotCurrent, emNullError);
    Exit;
  end;
  {turn break checking off}
  SaveBreak := CheckBreak;
  CheckBreak := False;
  {$IFDEF UseMouse}
  {force mouse cursor on if enabled, off if not}
  HideMousePrim(MouseOn);
  if GetCommandProcessor^.MouseEnabled then
   ShowMouse;
  {$ENDIF}
  {loop processing commands}
  Finished := False;
  repeat
    {get a command}
    GetNextCommand;
    {act on it}
    case GetLastCommand  of
      ccError, ccQuit, ccSelect : Finished := Trie;
      ccUp : WriteLn('ccUp');
      ccDown : WriteLn('ccDown');
      ccChar : WriteLn('ccChar: ', Char(Lo(GetLastKey)));
      ccHelp : RequestHelp(GetHelpIndex);
      ccUser0..$FFFF : Finished := True;
    else
      {process dynamic exit commands}
      if GetExitCommandPtr <> nil then
        if GetLastCommand in GetExinCommandPtr^ then
           Finished := True;
    end;
  until Finished;
  CheckBreak := SaveBreak;
  ShowMousePrim(MouseOn);
end;

    Приведенный пример - эти тривиальный метод обработки,
отвечающий стандартным требованиям для Object Professional,
рассмотренным выше.

    Дополнительно см.

 ProcessAutoPilot

             ProcessAutoPilot

    Объявление

    procedure ProcessAutoPilot(var CmdList; NumCmds : Word);

    Функция

    Обработать команды, начиная с команд в СmdList.

    Описание

    В типичном случае CmdList - это массив байтовых значений,
каждый элемент массива определяет команду, которую метод Process
должен проанализировать. (Массив будет содержать значения типа
Word в случае, если в CommandProcessor окна будут активизированы
команды типа Word.) NumCmds определяет количество команд в
массиве.
    ProcessAutoPilot вызывает метод SetCommandsList для
CommandProcessor для активизации команд массива, затем вызывает
метод Process объекта. Метод Process берет команду из описанного
массива до исчерпания массива или пока не встретится команда
выхода. При исчерпании массива метод Process возвращается в
состояние управления с клавиатуры или от мыши.
    Более подробную информацию Вы найдете в разделе
"Автоматическое выполнение команд" в главе 3 (OPCMD).
    При загрузке CommandWindow из потока без регистрации
CommandProcessor процедура ProcessAutoPilot генерирует ошибку
(epNonFatal+ecNoProcessor).
    Учитывая, что параметр CmdList несимвольного типа,
компилятор не сможет обнаружить ошибки, созданные при задании
CmdList. Метод Process будет слепо пытаться выполнить команды,
соответствующие любому значению в байтах, переданному ему.
Будьте внимательны !

    Пример

const
  CmdList : array[1..3] of Byte = (ccDown, ccDown, ccRight);
  ...
begin
  {... Init/draw a CmdWin...}

  Finished := False;
  repeat
    CmdWin.ProcessAutoPilot(CmdList, 3);
    case CmdWin.GetLastCommand of
      ccQuit, ccError : Finished := True;
      ccUser0..ccUser55 : WriteLn('user command'); {Handle exit command}
    end;
  until Finished;

  Commands.Done;
  CmdWin.Done;
end.

    Передаем в ProcessAutoPilot список из трех команд. При
исчерпании CmdList процедура ProcessAutoPilot будет работать
подобно методу Process.

    Дополнительно см.

CommandProcessor.SetCommandList        Process


                 RequestHelp

    Объявление

procedure RequestHelp(HelpIndex : Word); virtual;

    Функция

    Вызывается методом Process при запросе контекстуально-
зависимой помощи.

    Описание

    RequestHelp вызывает подпрограмму обработки помощи
пользователю, присвоенную процессору CommandProcessor окна
CommandWindow. Обычно, этот метод вызывается только из метода
Process окна.
    RequestHelp передает код устройства для окна, адрес Self
экземпляра и индекс HelpIndex в подпрограмму помощи для
пользователяп. Более подробную информацию Вы найдете в
"Ловушка обработки контекстуально-зависимой помощи" в разделе,
посвященном процессору CommandProcessor в главе 3.
    При отсутствии связанного с окном CommandProcessor (что
возможно только при загрузке CommandWindow из потока) процедура
RequestHelp генерирует ошибку (epNonFatal+ecNoProcessor).

    Пример

{get a command}
GetNextCommand;
{act on it }
case GetLastCommand of
  ccError, ccQuit, ccSelect :
    Finished := True;
  {...}
  ccHelp :
   RequestHelp(GetHelpIndex);
end;

    Вызывается способ обработки помощи по индексу помощи,
присвоенному окну.

               SetCommandProcessor

    Объявление

procedure SetCommandProcessor(var CP : CommandProcessor);

    Функция

    Установить для использования командный процессор.

    Описание

    Командный процессор CommandProcessor назначается для
CommandWindow при инициализации. Метод SetCommandProcessor в
более поздний момент времени изменяет CommandProcessor. Метод
SetCommandProcessor используется при загрузке CommandWindow из
потока, когда не зарегистрирован CommandProcessor.
       CP - это инициализованный объект CommandProcessor.
SetCommandProcessor хранит только адрес CommandProcessor
относительно CommandWindow. Следовательно, заданный
CommandProcessor должен оставаться действующим в течении всего
времени существования CommandWindow. (Например, это не может
быть локальная переменная, которая выходит за границы пока окно
существует.)

    Пример

Commands.Init(@KeySet, KeyMax);
OtherCommands.Init(@OtherKeySet, OtherKeyMax);
CmdWin.Init(30, 5, 50, 15, Commands, ucNone);
{...}
CmdWin.SetCommandProcessor(OtherCommands);

    Заменяет исходный CommandProcessor с именем Commands на
OtherCommands.

    Дополнительно см.

GetCommandProcessor                    Load
Init


            SetErrorProc

    Объявление

procedure SetErrorProc(EP : ErrorProc);

    Функция

    Установить программу обработки ошибок .

    Описание

    При инициализации CommandWindow ему присваивается программа
обработки ошибок по умолчанию (DefaultErrorProc), которая при
возниконовении ошибки только посылает прерывистый звуковой
сигнал. Для задания другой процедуры обработки ошибок для
CommandWindow вызовите процедуру SetErrorProc.
    Процедура EP должна быть объявлена FAR с помощью директивы
{$F+} и не может быть вложена внутрь любой другой процедуры или
функции. Параметры рассматриваемой процедуры должны
соответствовать параметрам типа ErrorProc, которые описаны в
OPROOT.
    Более подробную информацию Вы найдете в пункте "Ловушка
обработки ошибок" в начале этого раздела.

    Пример


var
  Commands : CommandProcessor;
  CmdWin : SampleWindow;                {Derived from CommandWindow}

  {$F+}
procedure MyErrorProc(UnitCode : Byte;
                     var ErrorCode : word; ErrorMsg : string);
var
  KW : Word;
begin
  if ErrorCode <> 0 then begin
    RingBell;
    CmdWin.wFastFill(80, ' ', 1, 1, TextAttr);
    CmdWin.wFastWrite(ErrorMsg, 1, 1, TextAttr);
    KW := ReadKeyWord;
    CmdWin.wFastFill(80, ' ', 1, 1, TextAttr);
  end;
end;
{$F-}

begin
  {...Create/draw CmdWin...}
  CmdWin.SetErrorProc(MyErrorProc);
  CmdWin.Process;
  CmdWin.GotError(1, 'Test Error Message');
  {...}
end.

    Сцепляет MyErrorProc с CmdWin. MyErrorProc будет выводить на
экран дисплея сообщение при возникновении ошибки в любом месте.
Этот пример моделирует ошибку (используя GotError) при возврате
управления из метода Process.

    Дополнительно см.

    GotError


     SetExitCommands

    Объявление

procedure SetExitCommands(ExitSetPtr : ByteSetPtr);

    Функция

    Установить набор специальных команд выхода.

    Описание

    Существует два способа назначения специальных команд выхода
для CommandWindow. Первый способ заключается в использовании
CommandProcessor окна для задания цепочек ключей командам ccQuit,
ccSelect или ccUser0..ccUser55. Команды ccUser0..ccUser55
специально резервируются для пользовательских команд выхода, и в
большинстве случаев их вполне достаточно.
    Другой способ активизируется с помощью метода SetExitCommands.
Вместо работы с цепочками ключей метод SetExitCommands работает
с самими логическими командами. Он действует только для команд,
которые не были интерпретированы методом Process для
CommandWindow. Элементы Commands в наборе из байтов, указанные с
помощью ExitSetPtr, вызывают выход из метода Process точно таким
же образом, как если бы были введены обычные команды выхода. (По
крайней мере, так работает процедура в собственном методе
Process для Object Professional. При написании вами ваших
производных CommandWindow вы можете интерпретировать ExitSetPtr
различными способами, возможно,обеспечив ей приоритет над
другими командами.)
    Конкретезируем сказанное. Предположим, что вы имеете метод
Process, который интерпретирует следующие команды :ccUp, ccDown,
ccLeft, ccRight, ccQuit, ccSelect и ccUser0..$FFFF. Метод
Process будет работать по этим командам независимо от того, что
указывает ExitSetPtr. Теперь предположим, что ExitSetPtr
указывает на набор [ccTab,ccBackTab]. Тогде метод Process для
Object Professional закончит работу при обнаружении любой из
этих команд в каком-либо месте.
    В каких случаях это полезно? Мы добавили эту возможность
главным образом с тем, чтобы повысить гибкость объекта PickList,
который часто встраивается в другие объекты. В объекте
EntryScreen объект PickList может действовать как одно поле
данных. Когда это именно так, мы хотим, чтобы ccTab и ccBackTab
вызвали выход из PickList, так как именно эти команды вызывают
перемещение курсора между полями данных других типов.
Практически было невозможно без заметного дополнительного
усложнения аппаратных средств вставить ccTab и ccBackTab в метод
Process для PickList. Вместо этого мы использовали
SetExitCommands.
    CommandWindow интерпретирует ExitSetPtr равный nil точно
также как указатель в пустой набор. В случае, если ExitSetPtr не
равен nil, он должен указываеть на набор, который остается
действующим на протяжении всего времени существовавния
CommandWindow.
    Даже если будет активизированы команды размером Word,
ExitSetPtr будет работать только с командами в диапазоне от 0 до
255 вследствие ограничения для наборов Turbo Pascal. Помимо
этого, большинство методов Process Object Professional
интерпретирует весь диапазон ccUser0..$FFFF как определяемые
пользователем команды выхода.

    Пример

const
  MyExitCommands : ByteSet = [ccUpLeft..ccDownRight];
  ...
  CmdWin.SetExitCommands(@MyExitCommands);

    Сообщаем CmdWin лист команд, которые метод Process должен
рассматривать как команды выхода.

    Дополнительно см.

GetExitCommandPtr

         SetHelpIndex

    Объявление

    procedure SetHelpIndex(Index : Word);

    Функция

    Установить номер предмета помощи для рассматриваемого
окна.

    Описание

    Заданный номер Index обычно совпадает с номером предмета в
OPHELP-совместимой системе помощи. Это не является
обязательным требованием, так как номер индекса только
передается в определяему пользователем процедуру обработки
помощи при вызове метода RequestHelp.
    Более подробную информацию Вы найдете в "Ловушка обработки
контекстуально-зависимой помощи" в начале рассматриваемого раздела.

    Пример

CmdWin.SetHelpIndex(1000);

    Дополнительно см.

GetHelpIndex              RequestHelp



               SetLastCommand

    Объявление

procedure SetLastCommand(Cmd : Word);

    Функция

    Изменить последнюю команду.

    Описание

    Обычно этот метод используется только в методе Process для
задания запоминаемого значения последней команды. Чаще всего
такая необходимость возникает для сохранения значения ccError
при возникновении ошибки или для изменения ccMouse (левый щелчок
мыши) в ccSelect (Выбрать и выйти из), когда курсор мыши
находится в требуемом месте в момент щелкания.

    Пример

    См. пример для метода Process.

    Дополнительно см.

    GetLastCommand


       Store

    Объявление

procedure Store(var S : IdStream);

    Функция

    Записать в поток

    Описание

    S - это соответствующим образом инициализированный объект
типа потока (например, файлы типа потока, открытые для чтения).
Отметим, что S может быть любым наследником типа IdStream,
включая DosIdStream, BufIdStream, MemIdStream (Хотя, обычно вы не
будете записывать в MemIdStream).
    Store записывает образ StackWindow в поток S. Store вначале
вызывает StackWindow.Store для записи большей части данных ;
затем она записывает данные, специфичные для CommandWindow,
включая индекс помощи окна, код устройства, указатель в
процедуру обработки ошибок, указатель в CommandProcessor и
указатель в набор команд выхода.
    В случае, если вы используете процедуру обработки ошибок или
набор команд выхода, определяемые не по умолчанию, вы должны
зарегистрировать их адреса перед вызовом рассматриваемого
метода. Вы всегда должны регистрировать адрес CommandProcessor,
если только вы не разработали методы Store и Load, которые
присваивают CommandProcessor исключительно для вашего типа окна.
Более подробную информацию Вы найдете в Load.
    Процедура регистрации потока для CommandWindow имеет имя
CommandWindow.Stream.

    Пример


{... same as Load...}

begin
  Commands.Init(@KeySet, KeyMax);
  WinOpts := wBordered+wClear+wSaveContents+wResizeable;
  if not CmdWin.InitCustom(30, 5, 50, 15, DefaultColorSet,
                          WinOpts, Commands, O) then begin
  WriteLn('Failed to Init CommandWindow, Status =', InitStatus);
  Halt;
  end;
  CmdWin.wFrame.AddHeader('Command Window', heTC);
  CmdWin.EnableExplosions(20);
  CmdWin.Draw;

  {Write CmdWin  out to a stream}
  S.Init('CMDWIN.STM', sCreate,  1024);
  S.RegisterHier(SampleWindowStream);
  S.RegisterHier(ExploadingWindowStream);
  S.RegisterPointer(1000, @Commands);
  S.Put(CmdWin);
  S.Done;
  CmdWin.Done;
  Commands.Done;
end.

    Реализуется CmdWin (полученное из CommandWindow) и
записывается в поток. Мы зарегистрировали наш CommandProcessor с
кодом 1000. Программа, загружающая рассматриваемый поток (см.
например, Load) должна создать свой собственный CommandProcessor
и зарегистрировать указатель на него с кодом 1000.
    Правила обработки ошибок при использовании потока приведены
в BufIdStream  (OPROOT).

    Дополнительно см.


Load                           StackWindow.Store





            5. LoadableColorSet

    LoadableColorSet -это программное расширение ColorSet,
описанного в главе 2 (OPCRT).Новый объект добавляет ровно три
метода: Init,Load и Store. Назначение этих методов - разрешить
чтение и запись ColorSet в потоки.Если Вы не хотите использовать
потоки, то вам нет никакой необходимости выбрать
LoadableColorSet вместо обычной процедуры ColorSet.
    LoadableColorSet включает обычную ColorSet как поле данных.
Это поле может быть использовано для доступа к данным и методам
самой процедуры ColorSet.
    Ниже приведена программа , демонстрирующая как записать
ColorSet в поток.

program ColorSetExample;    {EXCOLOR.PAS}
uses
   OpCrt, OpRoot, OpFrame, OpWindow;
var
  MyLcs : LoadableColorSet;
  S : BufIdStream;
  Status : Word;
begin
  {Start off with the default color set}
  MyLcs.Init(DefaultColorSet);

  {Customize the LoadableColorSet}
  with MyLcs.LcsColors do begin
    SetTextAttr($17, $07);
    SetFrameAttr($16, $07);
    SetHeaderAttr($16, $07);
end;

{Make a Stream}
if not S.Init('MYLCS.STM', SCreate, 1024) then begin
  WriteLn('Failed to Create Stream, Status = ', InitStatus);
  Halt;
end;
S.RegisterHier(LoadableColorSetStream);
S.Put(MyLcs);
Status := S.GetStatus;
if Status <> 0 then begin
  WriteLn('Failed to Store MyLcs, Status = ', Status);
  Halt;
end;
S.Done;

{MYLCS.STM is now available for use by other  programs}
end.

    В рассматриваемом примере инициализуется
LoadableColorSet(MyLcs) из набора цветов , принятого по
умолчанию в OPCRT, затем ряд значений изменяется. Создается
новый файл потока, регистрируется тип данных LoadableColorSet и
записывается в поток MyLcs. После этого другая программа может
считать эту LoadableColorSet (см. ниже пример в Load). Таким
образом потоки создают альтернативный механизм для установки и
настройки программы.

          Типы

LoadableColorSet =
  object(Root)
    lcsColors : ColorSet;
     ...
  end;

    Приведен тип данных для LoadableColorSet. Для поля данных
lesColors не предусмотрен метод доступа; Вы должны ссылаться на
это поле прямо. Например, если Вам нужно передавать ColorSet в
метод InitCustom окна, вы должны использовать следующее:

MyWin.InitCustom(X1, Y1, X2, Y2, MyLcs,lcsColors, Options);

    В случае, если необходимо изменить поля цветов в ColorSet,
то введите:

MyLcs.lcsColors.SetTextAttr($17, $07);

        Init

    Объявление

constructor Init(var Colors : ColorSet);

    Функция

    Инициализовать рассматриваемый набор цветов из другого
набора цветов.

    Описание

    Рассматриваемый конструктор вызывает Root.Init, а затем
присваивает Colors полю данных lcsColors. Метод может дать отказ
только в случае отказа Root.Init.

    Пример

MyLcs.Init(DefaultColorSet);

    Для MyLcs в качестве начального набора цветов задается
DefaultColorSet.

    Дополнительно см.

Root.Init

                Load

    Объявление

constructor Load(var S : IdStream);

    Функция

    Загрузить набор цветов из потока.

    Описание

    S - это соответствующим образом инициализированный объект
типа потока (например, файлы типа потока, открытые для чтения).
Отметим, что S может быть любым наследником типа IdStream,
включая DosIdStream, BufIdStream, MemIdStream.
    Load считывает следующую последовательность байтов из потока
S. Эти байты должны быть записаны в предыдущем обращении к
Loadable.ColorSet.Store. Load только вызывает Root.Init , а
затем считывает поле данных lcsColors.
    Процедура регистрации потока для Loadable.ColorSet имеет имя
Loadable.ColorSet.Stream.

    Пример

uses OpCrt, OpRoot, OpFrame, OpWindow;
var Win : WindowPtr;
  MyLcs : LoadableColorSet;
  S : BufIdStream;
begin
  {Load MyColorSet from a stream}
  S.Init('MYLCS.STM', SOpen, 1024);
  S.RegisterHier(LoadableColorSetDtream);
  S.Get(MyLcs);
  S.Done;
  {Use the loaded color set, frame should be  green on black}
  New(Win, InitCustom(30, 5, 50, MyLcs.LcsColors,
                     DefWindowOptions or wBordered));
  Win^.Draw;
  Win^.wFastWfite('Hello World', 1, 1, TextAttr);
  Delay(1000);
  Dispose(Win, Done);
end.

    Загрузить Mylcs из потока, созданного в примере Store. S.Get
вызывает Load косвенным образом через управляющую программу
потока.
    Правила по обработке ошибок при использовании потоков
приведены  в BufIdStream (в OPROOT).

    Дополнительно см.

Store

                  Store

    Объявление

procedure Store(var S : IdStream);

    Функция

    Записать в поток

    Описание

    S - это соответствующим образом инициализированный объект
типа потока (например, файлы типа потока, открытые для чтения).
Отметим, что S может быть любым наследником типа IdStream,
включая DosIdStream, BufIdStream, MemIdStream (Хотя, обычно вы не
будете записывать в MemIdStream).
    Store записывает образ StackWindow в поток S.
    Для проверки и обработки ошибок, которые могут возникнуть
при выполнении Store, вызовите функцию GetStatus для потока.
    Правила обработки ошибок при использовании потока приведены
в BufIdStream  (OPROOT).

    Пример

    См. программу, приведенную во введении к данному разделе.

    Дополнительно см.

Load
            6.PackedWindow

    Объект PackedWindow имеет функцию в какой-то степени сходную
с функцией объекта ScreenRect за исключением того, что хранит
содержание выделенного прямоугольника в "упакованном формате".
Более подробнно, PackedWindow хранит содержание прямоугольника
как пару массивов - один массив содержит символы, а второй
массив - атрибуты , и выполняет по длине серии кодирование
каждого из двух массивов. Такой способ позволяет хранить любую
последовательность из шести и более идентичных байтов в массиве
как запись из пяти байтов. Экономия памяти в результате сжатия
обычно достигает величины от 30 до 90% . Сжатие и расширение
выполняются подпрограммами , написанными на языке Ассемблера,
обеспечивая вполне приемлемую скорость вывода на экран.
    PackedWindow включает множество методов для инициализации
упакованных окон из видеопамяти, воспроизведения их в исходном
или новом положении, записи их в файл и считывания обратно.
    PackedWindow - это объектно-ориентированная версия подобной
же концепции, предусмотренной в модуле Turbo Professional с
именем TPCRT. Фактически, PackedWindow предлагает специальные
методы для записи и чтения файлов на дисках с Turbo Professional
упакованными окнами. (Демонстрационная программа PSCREEN с
именем TSR, которая переводит любой текстовый экран в файл -
использует аналогичный формат упакованного файла. Программа
PSCREEN описана в разделе "Утилиты" в рассматриваемой главе.)
    Кроме того, PackedWindow можно записывать в потоки, тем
самым автоматически обеспечивается возможность управлять
библиотеками упакованных экранов со случайным доступом. Такие
библиотеки идеально подходят для прикладных программ, в которых
требуется большое число экранов со статичесим изображением.
    Ниже приведен пример программы, которая собирает часть
экрана в PackedWindow, а затем восстанавливает его при мигании
экрана дисплея.

program PackedWindowExample; {EXPACKW.PAS}
uses
   OpCrt, OpRoot, OpFrame, OpWindow;
var
  PWin : PackedWindow;
  I, J : Integer;
begin
  {Write some characters to the screen}
  for I := 1  to 25 do
    for J := 1 to 26 do
      FastWrite(Char(64+J), I, J+I, TextAttr);

  {Create a PackedWindow}
  if not PWin.Init(10, 5, ScreenWidth-10, ScreenHeight-5) then begin
    WriteLn('Failed  to Init PackedWindow, Status =', InitStatus);
    Halt;
  end;

  {Clear the initial screen}
  ClsScr;
  FastWrite('Press any key to restore the PackedWindow', 13, 23, TextAttr);
  I := ReadKeyWord;

  {Display the PackedWindow, clean up}
  PWin.Display;
  PWin.Done;
end.

    PWinInit вначале размещает буфер динамически распределяемой
памяти достаточного размера для хранения несжатого экземпляра
заданного прямоугольника. Процедура считывает видеопамять в
соответствующих точках и сжимает данные в буфер. Затем она
возвращает часть буфера, которая ей не требуется. PWin.Display
перерисовывает упакованный образ в исходном положении. В
рассматриваемом примере упакованный образо занимает около 25%
памяти, занимаемой неупакованным буфером. Сжатие с длиной серии
выполняет прекрасную работу для атрибутов окна - так как все окно
нарисовано с одним атрибутом, то для них требуется только пять
байтов. Для символьной части это не так вследствие того, что
последовательности букв алфавита и цифр не сжимаются. Области в
углах окна вполне поддаются сжатию, что определяет общую степень
экономии памяти.

    Запись и чтение упакованных окон

    PackedWindow содержит два набора подпрограмм для записи окон
на диск и для их считывания. Каждый набор представляет собой
пару совместноработающих подпрограмм.
    Упакованные окна, записанные методом Write необходимо
считывает методом Read. Метод Read совместим с файлами
упакованных окон, созданных Turbo Professional 5.0. Кроме того,
Read считывает файлы, созданные утилитой сбора экранов PSCREEN.
Конструктор InitFromMemory использует образу окон, записанные
методом Write и связанные с файлом EXE программы с помощью
утилиты Борланда BINOBJ.
    Окна, записанные с помощью Write, необходимо считывать,
используя процедуру Load. Эти методы базируются на потоках (см.
главу 8). Используя потоки в один файл можно записать любое
число объектов (одного или различных типов). Кроме того, с
помощью потоков Вы можете управлять библиотеками PackedWindow со
случайным доступом.

    Типы

PackRec =
  record
    Link : Word;          {Number of bytes  to next PackRec}
    FillVal : Byte;       {Fill value}
    FillCnt : Word;       {Fill count}
  end;

    Записи, подобные приведенной, определяют серии повторяющихся
байтов на сжатом экране. Учитывая, что ассемблерные программы
имеют доступ к записи, Вам не следует изменять определение
PackRec без одновременного изменения ассемлерного кода.

PackedScreen = array[1..4000] of Byte;

    Это маска для упакованного массива, который записывает и
считывает PackedWindow. Фактический размер варьируется в
зависимости от координат окна и степени сжатия.

PackedWindowPtr = ^PackedWindow;
PacledWindow =
  object(Root)
    ...
  end;

    Это PackedWindow объект. Организация его внутренних структур
данных не может быть изменена без аннулирования как программ на
ассемблере, так и полей существующих упакованных окон.

          Display

    Объявление

procedure Display;

    Функция

    Вывод на экран упакованного окна.

    Описание

    Рисует ранее инициализованное упакованное окно в исходном
положении. В отличие от метода RawWindow.Draw метод Display не
сохраняет нижерасположенные экран, набор координат OPCRT окна
или положение курсора.Используйте PackedWindow в верхней части
StackWindow в случае, если вам необходимы эта черты.

    Пример

PWin.Init(1, 1, 70, 20);
 ...
PWin.Display;

    Перерисовать содержание экрана из исходного положения (1, 1,
70, 20) в то же самое положение.

    Дополнительно см.

MapColors

         DisplayAt

    Объявление

    procedure DisplayAt(Row, Col : Word);

    Функция

    Вывести упакованное окно на экран в строке Row и столбце
Col. При необходимости координаты корректируются с тем, чтобы
они соответствовали экрану.

    Описание

    В случае, если Row или Col равны нулю, то их значение
увеличивается до единицы. В случае, когда любой размер
упакованного окна больше, чем размер текущего экрана DisplayAt
прекращает работу, ничего не делая (ошибка не генерируется).
Если же упакованное окно будет выступать за край экрана, то
корректируются координаты Row и Col таким образом, чтобы окно
соответствовало экрану. Например, если ширина окна равна 40
столбцам, а Col равен 70, то значение Col будет изменено на 41
(для экрана дисплея с 80 символами в строке). В результате окно
будет соответствовать экрану.

    Пример

    PWin.Init(1, 20, 80,  25);
  ...
 PWin.DisplayAt(1, 1);

    Сохраняем последние шесть строк экрана как упакованное окно,
затем воспроизводим их в верхних шести строках экрана.


        Done

    Объявление

destructor Done; virtual;

    Функция

    Удалить упакованный экран.

    Описание

    В случае, если упакованное окно первоначально было размещено
в динамической памяти (т.е. для его инициализации не
использовали процедуру InitFromMemory), деструктор Done удаляет
буфер динамически распределяемой памяти. Затем он вызывает Root.
Done.
    Отметим, что Done не "стирает" образ упакованного окна и не
изменяет экран.

    Пример

PWin.Init(1, 1, 70, 20);
...
PWin.Done;

    Разместить упакованное окно, а затем удалить его.

    Дополнительно см.

InitFromMemory


          Init

    Объявление

constructor Init(XL,  YL, XH, Y, : Byte);

    Функция

    Создать упакованное окно.

    Описание

    Init вначале отводит под буфер динамически распределяемой
памяти 2*(XH-XL+1)*(YH-YL+1) байтов - это размер , требуемый
если не производить сжатия. В случае, если свободной памяти
недостаточно, Init записывает ошибку (epFatal+ecOutOfMemory) в
InitStatus и прекращает работу. Кроме того, Init прекращает
работу, если заданные координаты являются ошибочными (например,
XH меньше XL).
    Затем Init вызывает подпрограмму на ассемблере, которая
читает текущее содержание видеопамяти и вначале упаковывает
символы, а затем атрибуты в буфер динамически распределяемой
памяти.
    И наконец, Init освобождает неиспользуемую часть буфера
динамически распределяемой памяти. В зависимости от степени
возможного сжатия образа неиспользуемая часть буфера может
составлять от 30 до 90% исходного объема динамической памяти.

    Пример

if not PWin.Init(1, 1, ScreenWidth, ScreenHeight) then begin
  WriteLn('Failed to Init PacedWindow, Status =', InitStatus);
  Halt;
end;

    Реализуется PWin и упаковывается весь экран.

    Дополнительно см.

InitFromMemory                 Read
Load

      InitFromMemory

    Объявление

constructor InitFromMemory(P : Pointer);

    Функция

    Инициализация упакованного окна из окна, записанного на диск
с помощью Write и переведенного в файл EXE с помощью BINOBJ.

    Описание

    Рассматриваемый конструктор дает удобный способ
использования предварительно разработанных экранов. Процедура
сбора экрана TSR для PSCREEN (описанная в разделе H.2)
записывает упакованные окна на диск в формате, подходящем для
его применения в InitFromMemory.
    P определяет адрес блока данных BINOBJ. InitFromMemory
инициализует свои внутренние данные из этого блока данных и
записывает указатель в сжатый образ в блок. InitFromMemory не
отводит динамическую память для образа экрана.
    Для объектов PackedWindow, инициализованных с помощью
InitFromMemory , необязательно вызывать Done. Но тем не менее,
целесообразно Done вызывать.

    Пример

uses
   OpCrt, OpRoot, OpFrame, OpWindow;
var
  PWin : PackedWindow;

  {$L PWMEM.OBJ}
  procedure PwMem; extermal;

begin
  {Initialize PWin from memory}
  if  not PWin.InitFromMemory(@PwMem) then begin
   WriteLn('Failed to init PacledWindow, Status = ',InitStatus);
   Halt;
  end;

  {Display the PackedWindow, clean up}
  ClrScr;
  PWin.DisplayAt(1, 1);
  PWin.Done;
end.

    Эта программа содержит упакованное окно, подсоединенное в
ходе компиляции. Связанный файл , созданный при выполнении
программы Борланда BINIBJ для полей, созданных методом Write (в
рассматриваемом случае, используя пример программы для метода
Write.) Были использованы следующие командные строки:

BINOBJ PACKWIN.PW  PWMEM.OBJ PWMEM

    В результате открывается файл с именем PWMEM.OBJ, имеющий
общедоступный идентификатор PWMEM. PWMEM в вышеприведенном
примере указан как начальная точка для InitFromMemory. Директива
$L сообщает компилятору, что PWMEM.OBJ необходимо подсоединить к
программе. Объявление "external" - внешняя процедура - означает,
что компилятор найдет подпрограмму в файле OBJ. В
рассматриваемом случае это совсем не процедура, а просто
некоторые данные, характеризующие сжатое окно. Не пытайтесь
вызвать эту "процедуру"! Отметим, что InitFromMemory ссылается
на PWMEM , используя оператор @ ,который возвращает адрес
"мнимой" процедуры.

    Дополнительно см.

Write

            Load

    Объявление

constructor Load(var S : IdStream);

    Функция

    Загрузить упакованное окно из потока.

    Описание

    S - это соответствующим образом инициализированный объект
типа потока (например, файлы типа потока, открытые для чтения).
Отметим, что S может быть любым наследником типа IdStream,
включая DosIdStream, BufIdStream, MemIdStream.
    Load считывает следующую последовательность байтов из потока
S. Эти байты должны быть записаны в предыдущем обращении к
PackedWindow.Store. Load вначале читает размер упакованного окна
из потока, а затем отводит ровно столько динамической памяти,
сколько необходимо для считывания упакованного образа.
    Процедура регистрации потока для CommandWindow имеет имя
CommandWindow.Stream.

    Пример

uses
  OpCrt, OpRoot, OpFrame, OpWindow;
var
  PWin : PackedWindow;
  S : BufIdStream;
begin
  {Load PWin from a stream}
  S.Init('RACKWIN.STM', SOpen, 1024);
  S.RegisterHier(PackedWindowStream);
  S.Get(PWin);
  S.Done;

  {Display the PackedWindow, clean up}
  PWin.Display;
  PWin.Done;
end.

    Реализует PWin из потока, созданного в примере для Store,
используя метод Get для потока, который вызывает Load косвенным
образом.
    Правила обработки ошибок при использовании потоков приведены
в BufIdStream (в OPROOT).

    Дополнительно см.

Store

        MapColors

    Объявление

procedure MapColors;

    Функция

    Преобразовать цвета упакованного окна для улучшения качества
изображения на моно-черно/белых дисплеях.

    Описание

    Обычно рассматриваемый метод необходимо применять в
ситуациях, когда окно было нарисовано на цветном дисплее,
записано в файл, затем считано с диска на другой машине.
    В случае, если функция UseColor (см. OPCRT) возвращает True,
то процедура MapColors сразу же прекращает работу. В противном
случае она преобразует все значения атрибутов окна, используя
массив ColorMap в OPCRT. ColorMap инициализован для выполнения
соответствующего преобразования, но ,возможно, что у вас
появится желание изменить его; существует большое число способов
для произвольного выбора преобразования 128 цветов в (самое
большее) 10 комбинаций атрибутов на монохроматическом дисплее.
    Отметим, что вызов рассматриваемой процедуры приводит к
долговременным изменениям атрибутов упакованного окна, поэтому
если Вы снова запишите окно в файл после преобразования цветов,
исодная цветовая информация будет утеряна. "Обратное"
преобразование цветов невозможно.

    Пример

    PWin.Read('TET.PW');
PWin.MapColors;
PWin.Display;

    Считать упакованное окно с диска, затем его цвета надо
преобразовать для монохроматического видеорежима. Отметим, что в
случае, если текущий видеорежим разрешает использование цветов,
процедура MapColors ничего не делает.

    Дополнительно см.

UseColor(OPCRT)

               Read

    Объявление

constructor Read(FName : string);

    Функция

    Считать упакованное окно , записанное в память с именем
FName.

    Описание

    Рассматриваемый метод считывает в память упакованное окно,
ранее записанное на диск, используя метод Write. (Отметим,
PSCREEN записывает упакованные окна именно таким образом.)
Ошибки ввода/вывода (наиболее вероятные - не найден файл или
ошибка при считывании) вызывают отказ конструктора; код ошибки
записывается в InitStatus. Кроме того, Read гарантирует, что
файл содержит допустимые упакованные окна. В случае нарушения
этого требования InitStatus будет содержать
epFatal+ecInvalidFormat.
    Read получает размер упакованного окна из потока и отводит
ровно столько динамической памяти сколько надо для упакованного
образа.
    Read использует логику, которая позволяет читать упакованные
окна, записанные программами на Turbo Professional 5.0, а также
записанные в несколько другом формате, используемом
ObjectProfessional.

    Пример

if not PWin.Read('PACKWIN.PW') then begin
   WriteLn('Failed to init PackedWindow, Status = ',InitStatus);
   Halt;
end;

    Считать файл упакованных окон PACKWIN.PW.
    В Write приведен полный пример программы, которая записывает
и считывает упакованные окна.

    Дополнительно см.

InitFromMemory                  Write
Load


         Store

    Объявление

procedure Store(var S : IdStream);

    Функция

    Записать упакованное окно в поток.

    Описание

    S - это соответствующим образом инициализированный объект
типа потока (например, файлы типа потока, открытые для чтения).
Отметим, что S может быть любым наследником типа IdStream,
включая DosIdStream, BufIdStream, MemIdStream (Хотя, обычно вы не
будете записывать в MemIdStream).
    Store записывает данные, описывающие упакованное окно , за
которыми следует сжатый образ, в следующее место в потоке.
    Для проверки и обработки ошибок, которые могут возникнуть в
ходе выполнения Store, вызовите функцию GetStatus для потока.
    Правила обработки ошибок при использовании потока приведены
в BufIdStream  (OPROOT).
    Процедура регистрации потока для PackedWindow имеет имя
PackedWindow.Stream.

    Пример

uses
   OpCrt, OpRoot, OpFrame, OpWindow;
var
  PWin : PackedWindow;
  S : BufIdStream;
  I, J : Word;
begin
  {Write some characters to the screen}
  for I := 1 to 25 do
    for J := 1 to 26 do
      FastWrite(Char(64+J), I, J+I, TextAttr);

  {Create a  PackedWindow  of the entire screen}
  if not  PWin.Init(1, 1, ScreenWidth, ScreenHeight) then begin
  WriteLn('Failed to init PackedWindow, Status = ',InitStatus);
  Halt;
end;

   {Write the   packed window to a stream}
   S.Init('PACKWIN.STM', SCreate, 1024);
   S.RegisterHier(PackedWindowStream);
   S.Put(PWin);
   S.Done;
end.

    Создать упакованное окно и записать его в поток. Пример
программы для загрузки рассматриваемого потока приведен в Load.

    Дополнительно см.

Load


                 Write

    Объявление

function Write(FName : string) : Word;

    Функция

    Записать упакованное окно в FName.

    Описание

    Write возвращает код статуса как результат функции. При
успешной записи статус равен нулю; в противном случае он равен
коду ошибки, соответсвующему кодам ошибок, приведенным в
приложении D.

    Пример

uses
   OpCrt, OpRoot, OpFrame, OpWindow;
var
  PWin : PackedWindow;
  I, J : Integer;
  Status : Word;
begin
  {Write some characters to the screen}
  for I := 1 to 25 do
    for J := 1 to 26 do
      FastWrite(Char(64+J), I, J+I, TextAttr);

  {Create a  PackedWindow  of the entire screen}
  PWin.Init(1, 1, ScreenWidth, ScreenHeight);

  {Write out PWin and destroy it}
  Status := PWin.Write('PACKWIN.PW');
  if Status <> 0 then
    WriteLn('Failed to write PWin, Status = ',Status);
  PWin.Done;

  ClrScr;

  {Read PWin again}
  if not PWin.Reac ('PACKWIN.PW') then begin
    WriteLn('Failed to init PackedWindow, Status = ',InitStatus);
    Halt;
  end;
  PWin.Display;
  PWin.Done;
end.

    Записать PWin на диск, а затем считать его обратно.

    Дополнительно см.

Read


             7. VirtScreen

    VirtScreen - это сокращение термина виртуальный экран. Данный
объект содержит ряд методов, позволяющих рассматривать область
памяти как физический экран дисплея. Вы можете записать в  эту
область из памяти, очистить ее, инициализовать ее из физического
экрана и скопировать обратно на физический экран дисплея. Такие
возможности весьма полезны при создании сложных образов  при
фоновой обработке, когда затем нужно через доли секунды из
сделать видимыми.
    Важной чертой виртуальных экранов является то, что они могут
быть более крупными, чем обычный экран дисплея размером 25 строк
по 80 символов. Объекты VirtScreen могут управлять любым
экраном, общий объем памяти которого не превышает 64 кбайт.
Например, VirtScreen может иметь 80 символов в строке и более
400 строк (считая по 2 байта на клетку, отводимых на пару символ-
атрибут). Копируя соседние области из большого виртуального
экрана на маленький физический экран, мы создаем иллюзию очень
быстрого перемещения.
    VirtScreen предлагает свои собственные методы для очистки,
записи и считывания из виртуального экрана. Вы не можете
использовать утверждения Turbo Pascal Write и WriteLn для записи
в них. (Теоретически возможно выполнить работу оператора WriteLn
на виртуальном экране. Фактически, Turbo Pascal предусматривает
модуль TPSCREEN , который делает именно это. Однако, недостатки
названного метода превышают достоинства и теперь TPSCREEN
является лишь достоянием истории.) VirtScreen предлагает другой
способ записи в виртуальный экран, который имеет более высокую
значимость, так как он связан с другими объектами.
    Как только Вы вызываете метод Activate для VirtScreen
видеосегмент, хранящийся в OPCRT, временно перенаправляется на
виртуальный экран вместо физического экрана. После этого все
подпрограммы для записи и чтения экрана из семейства FastWrite
работают с виртуальным экраном. Учитывая, что все объекты в
ObjectProfessional - ScreenRect, Frame, RawWindow, StackWindow,
PackedWindow и все объекты более высокого уровня - построены на
основе FastWrite, то они будут работать с виртуальным экраном
почти столь же успешно как и с реальной электронно-лучевой
трубкой! (Необходимо сказать "почти", так как вы не можете
вызвать метод Process объекта высокого уровня. Трудно
предположить, что есть люди, которые могут работать в
интерактивном режиме с объектами, которые они не могут видеть.)
При вызове метода Deactivate выходные сообщения снова
направляются в нормальный адрес в видеопамяти.
    Как мы уже говорили StackWindow весьма эффективно используют
виртуальные экраны для корректировки частично загороженных окон.
Если это возможности уже являются встроенными, у вас может не
возникнуть необходимости объявить свои собственные экземпляры
VirtScreen. Мы определили случаи, где дополнительно можно
использовать VirtScreen: первый случай - перенос всего экрана в
целом, а второй случай - прямоугольник с изменяемыми "резиновыми
границами" в программе-утилите MAKESCREEN. Возможно вы найдете
другие способы применения для VirtScreen.
    Ниже приведен пример , который демонстрирует ряд
возможностей VirtScreen.

program VirtScreenExample; {EXVSCR.PAS}
uses
  OpCrt, OpRoot, OpFrame, OpWindow;
const
  Rows = 100;
  Cols = 200;
var
  V : VirtScreen;
  R, C, KW : Word;
  S : String;
  Finished : Boolean;
begin
  {Clear the physical screen}
  TextAttr := $70;
  ClrScr;
  {Allocate a virtual screen}
  if not V.Alloc(Rowc, Cols)  then begin
    WriteLn('Unabke to Init VintScreen, Status =', InitStatus);
    Halt;
  end;

  {Initialize the virtual screen with an interesting pattern}
  V.Clear($07, ' ');
  V.Activate;
  for  R := 1  to Rows do begin
    Str(R:3, S);
    FastWrite(S, R, 1, $07);
    C := (mod 10) + 5;
    while C <= Cols do
     if (C mod 20 = 0) and (C < Cols-5) then begin
       FastWrite(S, R, C+1, $07);
       Inc(C, 5);
     end else begin
       FasrWrite(Char(Byte('a')+((C-R-5) mod 26)), R, C, (C-R) and $7F);
       Inc(C);
     end;
  end;
  V.Deactivate;

  {Scroll around the virtual screen}
  R := 1;
  C := 1;
  Finished := False;
  repeat
    V.CopyToScreen(R, C);
    case ReaxKeyWord   of
     $4800 :               {Up arrow}
       if R > 1 then
         Dec(R);
     $4B00 :               {Left arrow}
       if C > 1 then
         Dec(C);
     $4D00 :               {Right arrow}
       Inc(C);
     $5000 :               {Down arrow}
       Inc(R);
     $011B :               {Escape}
       Finished := True;
   end;
  until Finished;

  V.Done;
end.

    В примере отводится память для виртуального экрана размеров
100 строк по 200 символов (40 000 байтов). Виртуальный экран
очищается, активизируется запись в него, с помощью FastWrite в
нем создается интересная картинка, а затем восстанавливается
запись в нормальный физический экран. Далее, вводится цикл
обработки с клавиатуры, в котором копируется часть виртуального
экрана на физический экран. Изменяя копируемую порцию , нажимая
на клавиши перемещения курсора, создается видимость перемещения
картинки по экрану. Отметим, что мы не ограничиваем изменение
значений R и C границами VirtScreen. Метод CopyToScreen является
достаточно мощным для очистки оставшейся части экрана, используя
текущие значения TextChar и TextAttr (из OPCRT), когда
координаты выходят за границы вирутального экрана.


          Activate

    Объявление

procedure Activate;

    Функция

    Активизировать подпрограмму быстрой записи и чтения для
вирутального экрана.

    Описание

    Activate сохраняет текущие значения VirtualSegment,
VirtualWidth, VirtualHeight (из OPCRT) внутри объекта, затем
устанавливает их в соответствии с виртуальным экраном. Дор тех
пор пока не будет вызвана процедура Deactivate почти все способы
записи в экран(например, FastWrite, RawWindow.FastWrite) будут
перенаправляться вместо физического экрана на виртуальный экран.
Подпрограммы считывания из видеопамяти (например, FastRead)
будун перенаправляться подобным же образом.
    Исключениями являются методы Write и WriteLn, которые
записывают на физический экран. Кроме того, остается видимым на
физическом экране курсор аппаратных средств.
    Будьте внимательны и записывайте строку, которая выходит за
нижний правый угол виртуального экрана. Когда это происходит на
физическом экране особого вреда не бывает. Однако, на
виртуальном экране выход за границу затирает другую часть
динамической памяти Pascal с возможно гибельными последствиями.
Подпрограммы семейства FastWrite не защищают от этой
ошибки;такая защита обеспечивается методом WriteTo для
VirtScreen.
    Activate нельзя вызывать в случае, когда виртуальный экран
уже активизирован, но такая ошибка не выявляется объектами
VirtScreen. Не является ошибкой активизации другого VirtScreen
при активном первом VirtScreen.

     Пример

if not V.Alloc(100, 100) then begin
  WriteLn('Unable to Init VirtScreen, InitStatus =', InitStatus);
  Halt;
end;
V.Activate;
FastWrite('on the virtual screen', 1, 1 $07);
V.Deactivate;
V.CopyToScreen(1, 1);

    Разместить и активизировать виртуальный экран, используя
FastWrite внести в него записи, дезактивировать запись, затем
скопировать виртуальный экран в физический экран.

    Дополнительно см.

Deactivate        WriteTo

     Alloc

    Объявление

constructor Alloc(Height, Width : Word);

    Функция

    Создать виртуальный экран заданных размеров.

    Описание

    Alloc размещает виртуальный экран, который может содержать
Height строк и Width столбцов текста. Произведение
2*Width*Height должно быть меньше 65507 и больше нуля. Alloc
отводит на 15 байтов больше динамической памяти по сравнению с
величиной произведения. В результате конструктор может выбрать
виртуальный видеосегмент в пределах буфера.
     Alloc посылает отказ в случае, если заданные размеры
являются недопустимыми или не хватает свободной динамически
распределяемой памяти. Причина ошибки может быть установлена по
InitStatus.
     Alloc очищает виртуальный экран , используя текущие
значение TextAttr, TextChar из OPCRT. Вы можете инициализовать
их с различными значениями с помощью метода Clear.

    Пример

if not V.Alloc(200, 80) then begin
  WriteLn('Alloc error ', InitStatus);
  Halt;
end;

    Разместить виртуальный экран 200 строк на 80 столбцов
(используя 32 015 байтов динамически распределяемой памяти).

    Дополнительно см.

Init

            Clear

    Объявление

  procedure Clear(Attr : Byte; Fill : Char);

    Функция

    Очистить виртуальный экран.

    Описание

    Заполняет буфер виртуального экрана Word (((Attr shl8) или
Fill). Отметим, что конструкторы Alloc и Init инициируют буфер с
Attr = TextAttr и Fill = TextChar.

    Пример

V.Clear($07, ' ');

    Очистить виртуальный экран и получить области в тускло-белом
на черном.

    Дополнительно см.

CopyFromScreen       Init

              CopyFromScreen

    Объявление

procedure CopyFromScreen(Row, Col : Word);

    Функция

    Скопировать физический экран в точку строка Row, столбец Col
в виртуальном экране.
    Описание

    CopyFromScreen предоставляет способ инициализации по крайней
мере части виртуального экрана из физического экрана. Методы
StackWindow посылают ряд вызовов в CopyFromScreen(1,1) для
виртуального экрана, размер которого совпадает с размером
физического экрана.
    В случае, если Row или Col равны нулю,или если Row или Col
превышают соответствующие размеры виртуального экрана, процедура
CopyFromScreen сразу же прекращает работу. В случае, если
Row+ScreenHeight или Col+ScreenWidth превышают размер
виртуального экрана CopyFromScreen копирует то, что попадает в
границы виртуального экрана.

    Пример

if not V.Alloc(ScreenHeight, ScreenWidth) then begin
  WriteLn('Alloc error ', InitStatus);
  Halt;
end;
V.CopyFromScreen(1, 1);

    Разместить и инициализовать виртуальный экран
соответствующий физическому экрану.

    Дополнительно см.

CopyToScreen

            CopyFromWindow

    Объявление

procedure CopyFromWindow(Row, Col : Word);

    Функция

    Скопировать текущее окно в точку строка Row, столбец Col
в виртуальном экране.

    Описание

    Процедура CopyFromWindow работает подобно CopyFromScreen, но
вместо копирования всего физического экрана она копирует только
часть его в пределах координат текущего OPCRT окна. Эти
координаты соответствуют координатам, устанавливаемым при
последнем вызове процедуры Window. Координаты можно проверить,
считав переменные OPCRT с именами WindMin, WindMax.

    Пример

if not V.Alloc(ScreenHeight, ScreenWidth) then begin
  WriteLn('Alloc error ', InitStatus);
  Halt;
end;
Window(10, 5, 70, 20);
V.CopyFromWindow(5, 10);


    Копировать прямоугольник (10, 5, 70, 20) в виртуальный экран
с теми же относительными координатами.

    Дополнительно см.

CopyToWindow

          CopyToScreen

    Объявление

procedure CopyToScreen(Row, Col : Word);

    Функция

    Скопировать из точки строка Row, столбец Col
на виртуальном экране в физический экран.

    Описание

    С виртуального экрана на физический экран копируется
прямоугольник из ScreenWidth столбцов и ScreenHeight строк в
точку Row, Col.
    В случае, если Row или Col равны нулю, CopyToScreen сразу же
прекращает работу. В случае, если Row или Col больше, чем
соответствующий размер виртуального экрана, процедура
CopyToScreen очищает физический экраны, используя текущие
значения TextAttr, TextChr. Если величины Row+ScreenHeight
или Col+ScreenWidth превышают размер виртуального экрана
CopyToScreen копирует то, что находится в виртуальном экране и
очищает остальную часть физического экрана, используя TextAttr и
TextChr.

    Пример

if not V.Alloc(100, 100) then begin
  WriteLn('Unable to Init VirtScreen,Init Status =', InitStatus);
  Halt;
end;
V.Activate;
FactWrite('on the virtual screen', 1, 1, $07);
V.Deactivate;
V.CopyToScreen(1, 1);

    Разместить и активизировать виртуальный экран, затем с
помощью FastWrite записать в него, дезактивировать запись. После
этого, скопировать виртуальный экран в физический экран.

    Дополнительно см.

CopyFromScreen

      CopyToWindow

    Объявление

procedure CopyToWindow(Row, Col : Word);

    Функция

    Скопировать из точки строка Row, столбец Col
на виртуальном экране в текущее окно.

    Описание

    CopyToWindow работает подобно CopyToScreen , но копирует
вместо физического экрана в область в пределах координат
текущего окна OPCRT. Эти координаты соответствуют координатам,
устанавливаемым при последнем вызове процедуры Window.
Координаты можно проверить, считав переменные OPCRT с именами
WindMin, WindMax.

    Пример

if not V.Alloc(ScreenHeight, ScreenWidth)then begin
  WriteLn('Alloc error ', InitStatus);
  Halt;
end;
Window(10, 5, 70, 20);
V.CopyFromWindow(5, 10);
V.CopyToWindow(4, 10);

    Эффективным способом сдвинуть содержание заданного окна на
одну строку ниже, копируя его в виртуальный экран, а затем
обратно в окно, исользуя параметр Row, уменьшенный на единицу.

    Дополнительно см.

CopyFromWindow

     Deactivate

    Объявление

procedure Deactivate;

    Функция

    Дезактивировать быстрый доступ в виртуальный экран.

    Описание

    Восстанавливаются величины VirtualSegment,VirtualWidth и
VirtualHeight, записанные при вызове Activate. Обычно это
вызывает перенаправление выхода FastWrite на физический экран.
     Является ошибкой вызвать Deactivate, если виртуальный экран
еще на был активизирован, но объекты VirtScreen эту ошибку не
обнаруживают. Не является ошибочным дезактивировать VirtScreen с
тем, что вернуть управление в другой ранее активизированный
VirtScreen.

    Пример

if not V.Alloc(100, 100) then begin
  WriteLn('Unable to Init VirtScreen,Init Status =', InitStatus);
  Halt;
end;
V.Activate;
FactWrite('on the virtual screen', 1, 1, $07);
V.Deactivate;
FastWrite('on the physicol screen', 1, 1, $07);

    Записать одну строку в виртуальный экран, вызвать Deactivate
для восстановления обычной записи, затем записывать в физический
экран.

    Дополнительно см.

Activate

           Done

    Объявление

destructor Done; virtual;

    Функция

    Удалить виртуальный экран.

    Описание

    В случае, если исходный буфер виртуального экрана был удален
из динамической памяти, буфер уничтожается. Внутренние поля
VirtScreen заполняются нулями и вызывается метод Root.Done.

    Пример

if not V.Alloc(100, 100) then begin
  WriteLn('Unable to Init VirtScreen,Init Status =', InitStatus);
  Halt;
end;
...
V.Dont;

    Разместить , а затем удалить виртуальный экран.

    Дополнительно см.

Alloc               Init


         Init

    Объявление

constructor Init(Height, Width : Word; BufSeg : Word);

    Функция

    Инициировать виртуальный экран с предварительно размещенным
буфером.

    Описание

    Используйте рассматриваемый конструктор вместо Alloc, если
Вам необходимо иметь полный котроль над местом расположения
буфера виртуального экрана. Веская причина использовать Init
возникает , когда Вы имеете страницы варианта текста на
видеоадаптере CGA (или более мощном) и хотите их использовать
для сохранения виртуального экрана. OPCRT имеет функцию
GetPageSegment, которая возвращает соответствующее значение для
передачи в BufSeg.
    BufSeg - это адрес сегмента базы VirtScreen. Вы должны сами
гарантировать, что доступны по крайней мере 2*Width*Height
байтов памяти, отсчитывая от этого сегмента. Init не делает
попыток "отвести" эту память, и VirtScreen.Done также не будет
удалять ее. Init возвращает ошибку только в случае, если
заданные размеры являются недопустимыми.
     Init очищает виртуальный экран , используя текущие
значение TextAttr, TextChar из OPCRT. Вы можете инициализовать
их с различными значениями с помощью метода Clear.

    Пример

if not V.Init(ScreenHeight, ScreenWidth, GetPageSegment(1)) then begin
   WriteLn('Init error ', InitStatus);
   Halt;
end;

    Инициализовать виртуальный экран, используя видео страницу 1
цветого графического адаптера.

    Дополнительно см.

Alloc

        Load

    Объявление

constructor Load(var S : IdStream);

    Функция

    Загрузить упакованное окно из потока.

    Описание

    S - это соответствующим образом инициализированный объект
типа потока (например, файлы типа потока, открытые для чтения).
Отметим, что S может быть любым наследником типа IdStream,
включая DosIdStream, BufIdStream, MemIdStream.
    Load считывает следующую последовательность байтов из потока
S. Эти байты должны быть записаны в предыдущем обращении к
VirtScreen.Store. Load cчитывает размер виртуального экрана из
потока. В случае, если экран был первоначально размещен в
динамической памяти (через вызов Alloc) конструктор Load отводит
для него буфер повторно. В случае, если экран был первоначально
инициализован с помощью Init, Load использует только
первоначально заданный сегмент виртуального экрана.
    Отметим, что Load не считывает содержание виртуального
экрана и не инициализует буфер экрана. Для объектов VirtScreen
главное назначение Load и Store - запомнить размеры виртуального
экрана.
    Процедура регистрации потока для CommandWindow имеет имя
CommandWindow.Stream.

    Пример

uses
  OpCrt, OpRoot, OpFrame, OpWindow;
var
  V : VirtScreen;
  S : BufIlStream;
begin
  {Load V from a stream}
  S.Init ('VIRTSCR.STM', SOpen, 1024);
  S.RegisterHier(VirtScreenStream);
  S.Get(V);
  S.Done;

  {Use the VirtScreen}
  V.Clear(TeztAttr, ' ');
  ...
end.

    Реализует V из потока, созданного в примере для Store,
используя метод Get для потока, который вызывает Load косвенным
образом.
    Правила обработки ошибок при использовании потоков приведены
в BufIdStream (в OPROOT).

    Дополнительно см.

Store

      ReadFrom

    Объявление

procedure ReadFrom(Number : Byte; Row, Col : Word; var S : string);

    Функция

    Считать ряд символов из виртуального экрана, начиная со
строки Row и столбца Col.

    Описание

    Вызов ReadFrom обеспечивает почти то же , что и следующие
операторы:

V.Activate;
FastRead(Number, Row, Col, S);
V.Deactivate;

    Различия следующие - ReadFrom заканчивает чтение при
достижении края виртуального экрана, тогда как FastRead этого не
делает; ReadFrom может работать несколько быстрее, так как для
нее заранее известно, что не требуется проводить контроль
"снега".
    Вы должны гарантировать, что строка S достаточно длинная для
размещения Number символов. В противном случае возможна
ситуация, когда ReadFrom затрет часть области памяти, к которой
она не должна обращаться.

    Пример

if not V.Alloc(100, 100) then begin
  WriteLn('Unable to Init VirtScreen,Init Status =', InitStatus);
end;
V.Activate;
FastWrite('on the virtual screen', 1, 1, $07);
V.Deactivate;
FastWrite('on the virtual screen', 1, 1, $07);
V.RedFrom(30, 1, 1, S);

    Считываем 30 символов из верхнего левого угла виртуального
экрана в строку S. В S будет введено "on the virtual screen".

    Дополнительно см.

FastRead(OPCRT)       WriteTo

           ScrollHoriz

    Объявление

procedure ScrollHoriz(Cols : Integer; Attr : Byte; Fill: Char);

    Функция

    Перенести содержание по горизонтали.

    Описание

    В случае, если Cols равен нулю, ScrollHoriz ничего не
делает; если Cols больше нулю - ScrollHoriz сдвигает содержание
виртуального экрана влево; если Cols меньше нуля ScrollHoriz
сдвигает содержание виртуального экрана вправо.
     Только что заполненные колонки виртуального экрана
ScrollHoriz имеет атрибут Attr и символ Fill. В случае, если
Cols больше ширины виртуального экрана, то очищается весь
виртуальный экран.

    Пример

if not V.Alloc(100, 100) then begin
  WriteLn('Unable to Init VirtScreen,Init Status =', InitStatus);
  Halt;
end;
V.Clear($07, ' ');
V.Write('on the virtual screen', 1, 1, $07);
V.ScrollHoriz(1, $07, ' ');

    После переноса верхний левый угол виртуального экрана
содержит "n the virtual screen". Отметим, что на физическом
экране ничего не появится.

    Дополнительно см.

ScrollVert

         ScrollVert

    Объявление

procedure ScrollVert(Rows : Integer; Attr : Byte; Fill : Char);

    Функция

    Перенести содержание по вертикали.

    Описание

    Работает аналогично процедуре ScrollHoriz, но перенос
выполняется по вертикали, а не по горизонтали. Этот метод
полезен, когда вы используете виртуальный экран типа текстового
экрана с обычным переносом текста , записывая строки в нижнюю
часть экрана и передвигая старый текст из верха.

    Пример

const
  Height = 200;
var
  Row : Word;
  F : Text;
  S : String[80];
begin
  if not V.Alloc(Height, 80) then begin
    WriteLn('Unable to Init VirtScreen,Init Status =', InitStatus);
    Halt;
  end;
  V.WriteTo('on the virtual screen', 1, 1, $07);

  {...Open a text file for reasing...}

  {...Write the text file to the virtual screen
                      just like the TYPE  command}
  Row := 0;
  while not Eof(F) do begin
    ReadLn(F, S);
    if Row = Height then
     {Make space for another row}
     V.ScrollVert(1, $07, ' ')
    else
      Inc(Row);
   {Write the string to the current row}
   V.WriteTo(S, Row, 1, $07);
  end;

  {... Do something with the results ... }
end.

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

    Дополнительно см.

    ScrollHoriz

      Store

    Объявление

procedure Store(var S : IdStream);

    Функция

    Записать в поток.

    Описание

    S - это соответствующим образом инициализированный объект
типа потока (например, файлы типа потока, открытые для чтения).
Отметим, что S может быть любым наследником типа IdStream,
включая DosIdStream, BufIdStream, MemIdStream (Хотя, обычно вы не
будете записывать в MemIdStream).
    Store записывает данные, описывающие виртуальный экран,
включая его размеры и сегмент буфера, если он был инициализован
через вызов процедуры Init. Store не записывает содержание
виртуального экрана в поток.
    Для проверки и обработки ошибок, которые могут возникнуть в
ходе выполнения Store, вызовите функцию GetStatus для потока.
    Правила обработки ошибок при использовании потока приведены
в BufIdStream  (OPROOT).
    Процедура регистрации потока для PackedWindow имеет имя
PackedWindow.Stream.

    Пример

uses
  OpCrt, OpRoot, OpFrame, OpWindow;
var
  V : VirtScreen;
  S : BufIdStream;
begin
  {Allocate a virtual screen}
  if nlt V.Alloc(200, 80) then begin
    WriteLn('Unable to Init VirtScreen,Init Status =', InitStatus);
    Halt;
  end;

  {Write the virtual screen to a stream}
  S.Init('VIRTSCR.STM', SCreate, 1024);
  S.RegisterHier(VirtScreenStream);
  S.Put(V);
  S.Done;
  V.Done;
end.

    Записать размеры и флаги виртуального экрана в поток.

    Дополнительно см.

Load

     vCols

    Объявление

function vCols : Word;

    Функция

    Возвратить число столбцов  в вирутальном экране.

    Описание

     vCols возвращает число, указанное в качестве Width при
реализации VirtScreen.

    Пример

WriteLn('Virtual screen has ', V.vCols, ' columns');

    Выводит число столбцов в виртуальном экране.

    Дополнительно см.

Alloc             vRows

        vRows

    Объявление

function vRows : Word;

    Функция

    Возвратить число строк в виртуальном экране.

    Описание

    vRows возвращает число, заданное в качестве Height при
реализации VirtScreen.

    Пример

WriteLn('Virtual screen has ', V.vRows, ' rows');

    Вывести число строк в виртуальном экране.

    Дополнительно см.

Alloc                         vCols

         WriteTo

    Объявление

procedure WriteTo(S : string; Row, Col : Word; Attr : Byte);

    Функция

    Записать строку в виртуальный экран.

    Описание

    Вызов WriteTo почти равносилен выполнению следующих
операторов:

V.Activate;
FastWrite(S, Row, Col, Attr);
V.Deactivate;

    Отличия от WriteTo следующие: WriteTo оканчивает запись при
достижении границы виртуального экрана, тогда как FastWrite
этого не делает; процедура WriteTo может работать несколько
быстрее, так как она заранее знает, что для нее не требуется
выполнять проверку наличия снега.

    Пример

if not V.Alloc(100, 100) then begin
  WriteLn('Unable to Init VirtScreen,Init Status =', InitStatus);
  Halt;
end;
V.WriteTo('on the virtual screen', 1, 1, $07);

    Записать цепочку символов в левый верхний угол виртуального
экрана.

    Дополнительно см.

FastWrite(OPCRT)         ReadFrom



            D. OPPICK - Списки выбора

    Модуль OPPICK имеет только один тип объекта, но PickList -
это гигант среди объектов! PickList обеспечивает самый общий
способ показа списка произвольных цепочек символов, перемещения
пользователя по списку и осуществления выбора. PickList
отличает от Menu (описанного ниже в данной главе) динамическая
гибкость. Цепочки символов, воспроизводимые с помощью PickList
не обязательно должны быть заранее известны; фактически, ряд
прикладных программ считывают по запросу цепочки символов из
файла на диске или даже изменяют их в ходе процесса выбора.
    Построенный на основе этой главной иде PickList-объект
добавляет многие гибкие черты, которые делают его весьма
полезным в самых разнообразных ситуациях. Списки выбора
предлагают:
    - определяемое пользователем задание каждой цепочки элементов
    - списки с одним или несколькими столбцами
    - несколько способ ориентации в списках
    - горизонтальный и вертикальный перенос для больших списков
    - нормальный, альтернативный или защищенный (не выбираемый)
      статус элементов
    - буквенно-цифровой поиск по списку
    - поддержка мыши
    - специализированные заголовки для "более" и статуса поиска
    - задание цепочки символов с гибкой записью для каждого
      элемента
    - списки с кратным выбором
    Точное значение этих положений станет более ясным из
приведенных ниже примеров и их подробного описания. Последние
два положения являются новыми для ObjectProfessional (по
сравнению с Turbo Professional 5.0).
    Учитывая, что PickList получен из CommandWindow-объекта, он
вобрал в себя все функциональные возможности объектов типа окна.
PickList унаследовал следующие черты:
    - регулируемые цвета, размер и местоположение
    - оформление рамки, включая заголовки, тени или стрелки
      переноса
    - возможность работы с стеком окон или с виртуальным экраном
    - ловушки CommandProcessor, такие как переопределение
      клавиатуры, пользовательские команды выхода, команды
      динамического выхода и задания фоновой обработки
    - ловушки контекстуальнозависимой помощи
    - ловушка обработки ошибок
    Теперь, когда Вы получили некоторе представление о том, что
можно делать объект PickList, перейдем к рассмотрению вопроса,
как применять. Вначале приведем пример простой программы.

program PickListExample; {EXPICK1.PAS}
uses
  OpCrt, OpRoot, OpCmd, OpFrame, OpWindow OpPick;

const
  NumPizzaToppings = 5;      {Number of items on pick list}
var
  PizzaTop : PickList;
  PickWindowOptions : LongInt;

  {$F+}
  procedure PizzaToppibg(Item : Word; Mode : pkMode;
                        var IType : pkItemType; var IString : String;
                        PickPtr : PickListPtr);
  {-Set item string and item options (if any)}
    begin
      case Item of
        1 : IString := 'Pepperoni';
        2 : IString := 'Sausage';
        3 : IString := 'Mushrooms';
        4 : IString := 'Anchovies';
        5 : IString := 'Onions';
      end;
   end;
   {$F-}

begin
  {Make a PickList with custom window options}
  PickWindowOptions := DefWindowOptions or wBordered;
  if not PizzaTop.InitCustom(35, 5, 45, 10,  {Initnal window coordinates}
                            DefaultColorSet, {ColorSet to use}
                            PickWindowOptions,{Window options}
                            11,               {Column width per item}
                            NumPizzaToppings, {Number of picklist items}
                            PizzaToping,      {Item string function}
                            PickVertical,     {Orientation procedure}
                            SingleChoice)     {Command handler}
  then  begin
    WriteLn('Failed to Init PickList, Status =', InitStatus);
    Halt;
  end;

  {Set some PickList and Frame features}
  PizzaTop.SetSearchMode(PickCharSearch);
  PizzaTop.EnableExplosions(20);
  withh PizzaTop.wFrame do begin
   AddShadow(shBR, shOverWrite);
   AddHeader(' PICK ', heTC);
  end;

  {Pick an item}
  PizzaTop.Process;
  PizzaTop.Erase;
  if PizzaTop.GetLastCommand = ccSelect then
    WriteLn('You chose item ', PizzaTop.GetLastChoice,
            '  -   ', PizzaTop.GetLastChoiceString)
  else
    WriteLn('No choice was made');
  PizzaTop.Done;
end.

    В примере вводится PickList, показывающий пять верхушек блюд -
PizzaTopping. Пользователь может перемещаться по списку,
используя клавиши управления курсором, или перескакивать к
конкретному элементу, вводя первую букву в имени элемента. При
нажатии клавиши <Enter> данный список осуществляет один выбор и
возвращает его к запрашиваемой прикладной программе.
    Процедура PizzaTopping демонстрирует наиболее важные новые
концепции по использованию системы PickList. Эта процедура
является примером того, что мы называем "определяемая
пользователем процедура обработки цепочек". PickList вызывает
рассматриваемую процедуру всякий раз, когда необходимо получить
имя одного из элементов списка, которые пронумерованы от 1 до
общего числа элементов. Параметр Item, передаваемый процедуре
обработки цепочек, определяет имя возвращаемого элемента.
Отсутствуют какие-либо ограничения на то, каким образом эта
процедура фактически получает имя каждого элемента: она может
использовать утверждение case, как показано в приведенном
примере, давать ссылку на массив цепочек; вычислять имя по
некоторому численному значению или считывает из файла на диске.
Единственное ограничение состоит в том, что процедура должна
работать быстро, так как PickList весьма часто ее вызывает.
    Из различных параметров, передаваемых определяемой
пользователем процедуре обработки цепочек, два из них должны
всегда использоваться. Item определяет номер элемента,
возвращаемого для цепочки символов, а IString - имя, которое
возвращает процедура. Процедура должа всегда выполнять
инициализацию значения IString. Другие параметры применяются в
более сложных прикладных программах; мы вернемся к ним позднее.
    Процедура обработки цепочек должна бытиь определена
корректным образом для компиляции без ошибок. Процедуре
предшествует директива {$F+}, таким образом, используется модель
FAR. Процедура не может быть вложена внутрь любой другой
процедуры или функции, а список параметров процедуры должен
точно соответствовать списку, приведенному в примере, независимо
от того, все или только часть параметров будут использоваться.
    В примере далее следует вызов PickList.InitCustom. Начальные
параметры этого конструктора подобны параметрам любого другого
окна, координаты активного окна; применяемые цвета и опции окна.
После них следуют параметры специфичные для PickList. Значение
11 определяет число столбцов экрана, реализуемых для каждого
элемента в списке, а NumPizzaToppings (равный 5) - общее число
элементов в списке. Отметим, что PickList будет размещать
столько полных столбцов элементов в окне, сколько поместится. В
случае, если ширина окна равна по крайней мере 22 столбцам
PickList автоматически разположит элементы в двух столбцах.
    Слещующий параметр - PizzaTopping - устанавливает
определяемую пользователем процедуру обработки цепочек. Эта
процедура должна удовлетворять вышеприведенным требованиям.
    PickVertical задает ориентацию списка. Этот вопрос является
не столь важным для короткого в одну колонку списка, такого как
в приведенном примере, но становится весьма актуальным при
перемещении по спискам. Мы вернемся к нему ниже.
    SingleChoice определяет, что список принимает только один
выбор в один момент времени. Вместо этого параметра можно задать
альтернативный - MultipleChoice. Приведенные идентификаторы
фактически являются именами процедур, взаимодействующими с
модулем OPPICK; конструктор вызывает поименованную процедуру,
которая затем инициализует соответствующий объект.
    В случае успешной работы конструктора, в примере происходит
настройка окна. Вначале делается доступным буквенно-цифровой
поиск, вызывая метод SetSearchMode. Опция PickCharSearch - это
одна из нескольких опций, предлагаемых OPPICK: PickCharSearch
означает, что при вводе буквенно-цифрового символа PickList
выполняет поиск для отыскания элемента, имя которого начинается
с этого символа. Кроме того, в примере добавляются к окну тени и
заголовок.
    Вызов PizzaTop.Process выводит на экран список выбора и
позволяет пользователю осуществить выбор. Процедура Erase
удаляет окно с экрана. В случае, если пользователь нажмет
клавишу <Enter> процедура GetLastCommand возвращает ccSelect,
GetLastChoice возвращает номер выбранного элемента и
GetLastChoiceString возвращает цепочку символов,
соответствующему элементу. В случае, если пользователь нажмет
<Esc>, то выбор не будет сделан.
    И наконец, PizzaTop.Done удаляет PickList и его
нижерасположенное окно.
    Данный пример затрагивает лишь малую часть того, что может
делать OPPICK. Ниже мы опишем другие его особенности и приведем
примеры использования. Демонстрационные программы-утилиты
MAKESCRN, MAKEMENU и ENTRY в значительном объеме используют
возможности , предоставляемые PickList.

    Команды списка выбора

    Метод Process OPPICK предоставляет соответсвующие команды
для перемещения по списку элементов и отметки выбора. В
приведенном ниже перечне они расположены по категориям. В любом
случае первая строка указывает имя команды, за которым следует
клавиши, которым она обычно присваивается. Вторая и следующие
строки дают краткое описание команды. Определение назначения
клавиш по умолчанию хранится в глобальной текстовой константе
PickKeySet (в OPPICK.ICD).

    Перемещение курсора

ccLeft           <Left>, <CtrlS>

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

ccRight          <Right>, <CtrlD>

    Выделить полосу справа от элемента.

ccHome           <Home>, <CtrlQ> <S>

    Выделить первый элемент.

ccEnd            <End>, <CtrlQ> <D>

    Выделить последний элемент.

ccUp             <Up>, <CtrlE>, <CtrlW>

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

ccDown           <Down>, <CtrlX>,<CtrlZ>

    Курсор перемещается на одну строку ниже с дейтсвием
загибания аналогично команде ccUp.

ccPageUp         <PgUp>, <CtrlR>

    Перенести изображение на одну страницу вверх. В случае, если
действует опция pkAlterPageRow, выделенная полоска всегда
перемещается в верхнюю строку окна после ввода рассматриваемой
команды. Если же опция pkAlterPageRow выключена, выделенная
полоска остается в той же строке относительно окна до тех пор,
пока нельзя будет более перемещаться по окну; в такой ситуации
выделение перемещается на первую строку.

ccPageDn         <PgDn>, <CtrlC>

    Перемещает изображение ниже на одну страницу. Действие опции
pkAlterPageRow для данной команды подобно ее действию для
команды ccPageUp.

    Селекция с кратным выбором

    Нижеприведенные команды интерпретируются только для
PickList с кратным выбором, который активизируется , передавая
MultipleChoice.CommandHandler в конструктор PickList. Выбранные
элементы становятся явными, используя цепочки маркера (например,
метки контроля или стрелки) или различные видеоатрибуты.

ccIns            <Ins>

    Отметить выбранный текущий элемент.

ccDel            <Del>,<->

    Отменить выбор текущего элемента.

ccToggle         <Space>, < + >

    В случае, если текущий элемент не выбран, то выбираем его, в
противном случае - отменить его выбор.

ccBlkToggle      <CtrlEnter>, <Ctrlf>

    В случае, если в рассматриваемый момент времени выбраны
какие-либо элементы, этот выбор отменяется. В случае, когда в
данный момент не выбраны никакие элементы, то отмечаются все
элементы как выбранные.

ccBlkBegin       <F7>, <CtrlK><B>

    Указывает, что выделенный в данный момент элемент является
первым в отмеченном блоке. До тех пор, пока не будет введена
команда ccBlkEnd операция с блоком не завершена (и не будет
никакой визуальной индикации блока).

ccBlkEnd         <F8>, <CtrlK><K>

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

ccRestore        <CtrlK><H>

    Отменить выбор всех элементов.

    Другие команды

ccSelect         <Enter>

    В случае PickList с одним выбором выбирает текущий элемент и
выходит из списка. В случае PickList с кратным выбором принимает
текущий набор селекций и выходит из списка.

ccMouseSel       <ClickLeft>

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

ccQuit           <Escape>,<ClickRight>

    Прекратить обработку списка без осуществления выбора.

ccHelp           <F1>, <ClickBoth>

    Помощь. В случае, если была задана определяемая
пользователем процедура обработки помощь через вызов
PickCommands.SetHelpProc, то нажатие клавиши <F1> обеспечивает
вызов названной процедуры; в противном случая эта команда ничего
не делает. PickList передает в команду помощи следующие три
параметра: ucPick, @Self и номер предмета помощи. При
функционировании pkUserItemForTopic номер предмета помощи
совпадает с номером индекса текущего элемента. В противном
случае предмет помощи - это величина, обозначенная как индекс
помощи окна (см. CommandWindow.SetHelpIndex), который по
умолчанию принимает значение 0.

    Определяемая пользователем процедура обработки цепочек
символов

    Как было указано выше, определяемая пользователем процедура
обработки цепочек является сердцевиной системы PickList. Без
этой процедуры PickList не имеет никаких представленй о том, что
выводить на экран дисплея. Вынуждая программиста разработать
такую програму, PickList сохраняет мамксмимально возможное
число общих черт. В случае, если PickList всегда использовал
массив цепочек символов для получения элементов списка, то стали
бы невозможными многие полезные способы его применения.
    В действительности для реализации таких цепочек существует
не один способ. Первый способ мы уже представили: передали
параметр процедуры в конструктор PickList. Следующий способ
использует преимущества виртуальных методов OOP. При подготовке
к выводу на экран элемента PickList вызывает виртуальный метод
ItemString, которые в свою очередь вызывает процедуру обработки
цепочки, задаваемую через параметр процедуры. Вместо
использования параметра процедуры вы можете создать новый тип
объекта - производный от PickList -и просто блокировать метод
ItemString. Такой новый метод может передавать каждую цепочку
элемента прямо без ссылки на указатели процедур.
    Второй вариант более подходит для методологии
объектно-ориентированного программирования. Он является
несколько более быстрым методом, так как исключает один уровень
перенаправления при каждом вызове для получения цепочки
элемента. Очень удобно создать такого рода объект - производный
от PickList- так как требуется блокировать фактически только
один метод (хотя, обычно, кроме того, целесообразно
предусмотреть специализированный метод конструктора).
    С тем , чтобы второй вариант стал более понятным, перепишем
приведенный в начале раздела пример программы PizzaTopping,
используя виртуальный метод вместо определяемой пользователем
процедуры .

program PizzaListExample;    {EXPICK2.PAS}

uses
  OpCrt, OpRoot, OpFrame, OpWindow;
type
  PizzaList =
    object(PickList)
      constructor Init(X1, Y1, X2, Y2 : Byte);
      procedure ItemString(Item : Word; Mode pkMode;
                          var IType : pkItemType;
                          var IString : String); virtual;
    end;

  constructor PizzaList.Init(X1, Y1, X2, Y2 : Byte);
  const NumPizzaToppings = 5;
  var   PickWindowOptions : LongInt;
  begin
    PickWindowOptions := DefWindowOptions or wBordered;
    if not PickList.InitAbstract(X1, Y1, X2, Y2,
                         DefaultColorSet,   {ColorSet to use}
                         PickWindowOptions, {Window options}
                         11,                {Column width per item}
                         NumPizzaToppings,  {Number of picklist items}
                         PickVertical,      {Orientation procedure}
                         SingleChoice)      {Command handler}
     then
       Fail;
  end;

procedure PizzaList.ItemString(Item : Word; Mode : pkMode;
                              var IType : pkItemType;
                              var IString : String);
begin
  case Item of
    1 : IString := ' Pepperoni';
    2 : IString := ' Sausage';
    3 : IString := ' Mushrooms';
    4 : IString := ' Anchovies';
    5 : IString := ' Onions';
  end;
end;

var
  PizzaTop : PizzaList;

begin
  {Make a PizzaList}
  if not PizzaTop.Init(35, 5, 45, 10) then begin
    WriteLn('Failed to Init PizzaList, Status =', InitStatus);
    Halt;
  end;

  {Set some PickList and Frame features}
  PizzaTop.SetSearchMode(PickCharSearch);
  PizzaTop.EnableExplosions(20);
  with PizzaTop.wFrame do begin
    AddShadow(shBR, shOverWrite);
    AddHeader(' PICK ', heTC);
  end;

  {Pick an item}
  PizzaTop.Process;
  PizzaTop.Erase;
  if PizzaTop.GetLastCommand = ccSelect then
    WriteLn('You chose item ', PizzaTop.GetLastChoice,
            '    -   ', PizzaTop.GetLastChoiceString)
  else
   WriteLn('No choice was made');
  PizzaTop.Done;
end.

    Здесь мы объявили новый объект - PizzaList - производный от
PickList. Его метод-конструктор содержит в себе все, что мы
знаем о PizzaList: имеется 5 элементов, каждый длиной 11
символов, в списке с одним выбором. Отметим, что конструктор
вызывает один из конструкторов PickList - InitAbstract, который
введен специально для использования производными объектами. Для
него не требуется параметр процедуры, так как он не
используется. Виртуальный метод ItemString делает то же самое,
что делала и прежняя процедура PizzaTopping. В главном блоке
примера вызывается упрощенный конструктор PizzaList и после
этого места программа совпадает с исходной.
    Почему мы все же поддерживаем способ с использованием
параметра процедуры? Для этого есть две причины. Первая причина
имеет исторические корни - в списках выбора Turbo Professional
был использован именно этот подход, и имело смысл сохранить
некоторую концептуальную преемственность. Вторая причина более
важная : с помощью параметра процедурв отдельный PickList-объект
может выводить на экран списки, формат которых меняется
динамически. Примером может служить объект DirList, который
выводит на экран директории DOS. Формат для каждого имени файла
должен быть весьма гибким - с или без даты и времени, с или без
размера файла и т.д. - и необходимо, чтобы его можно было
изменить при выполнении программы. Естественно, такая гибкость
может быть достигнута, если написать сложный метод ItemString с
множеством флагов и опций. Но такой подход вызывает значительные
затраты времени, а также памяти под программу. С помощью
параметров процедуры подсоединяются только фактически
используемые форматы и выполнение может сразу перескочить к
процедуре, формат которой используется в данным момент.
    Вы можете сами выбрать, какой из этих двух подходов
использовать. Однако, мы рекомендуем там, где это имеет смысл,
применять OOP подход и выводить ваши собственные
специализированные PickList типы. Мы так делаем во многих
демонстрационных программах ObjectProfessional: объекты Calender
(календарь) и PhoneBook (телефонная книга) в DESKPOP, а также
рамка, заголовки и символьные списки в MAKEMENU и MAKESCRN.
    После обсуждения этого общего вопроса мы теперь более
подробно рассмотрим, как использовать процедуру обработки
цепочек или виртуальный метод.
    Каждая определяемая пользователем процедура обработки
цепочек должна быть скомпилированна по FAR модели, она должна
быть глобальной процедурой и соответствовать объявлению типа
pkStringProc. Эти требования означают, что процедура должна
иметь точно такие же параметры, как указано ниже:

{$F+}
procedure MyStringProc(Item : Word;
                      Mode: pkMode;
                      var IType : pkItemType;
                      var IString : String;
                      PickPtr : PickListPtr);

    Объявления для виртуального метода отличаются незначительно:

procedure ItemString(Item : Word;
                    Mode : pkMode;
                    var IType : pkItemType;
                    var IString : String); virtual;


    Хотя создается впечатление, что виртуальный метод не
содержит последнего параметра PickPtr, в действительности это не
так: каждый метод передает адрес Self в качестве последнего
(скрытого) параметра. PickPtr играет ту же роль для
MyStringProc, позволяя процедуре ссылаться на все методы и поля
данных экземпляра PickList, для которого он строит имя элемента.
Например, если необходимо, что MyStringProc вызвала метод
GetDefaultChoice, будет использован следующий синтаксис
конструктора:

InitChoice := PickPtr^.GetDefaultChoice;

    Остальные параметры интерпретируются одинаково в обоих
случаях. Item - это последний номер элемента, для которого
процедура должна вернуть цепочку символов. Первый элемент имеет
номер 1, а остальные номера возрастают последовательно до общего
числа элементов.
    Mode определяет причину ,почему PickList вызывает процедуру
обработки цепочек. В зависимости от того, какое из
нижеприведенных значений принимает Mode, процедура может
опустить ряд шагов обработки.

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

pkSearch
    Возвращаемая цепочка символов будет использована для
буквенно-цифрового поиска. Для цепочки необходимо добавить
символы заполнения и управляющие символы.

pkGetType
    PickList вовсе не нужна цепочка символов. Требуется только
узнать, является ли заданный элемент нормальным или защищенным
от выбора. Для экономии времени процедура обработки цепочек
может инициализовать только IType параметр и сразу же прекращает
работу.

    IType возвращает категорию элемента, которая будет одной из
следующих: pkNormal, pkAlternate, pkProtected или pkPrivate.
PickList инициализует IType равный pkNormal перед вызовом
процедуры обработки цепочек, поэтому вам не требуется делать для
него присвоения, если элемент является нормальным. Элементы
pkAlternate рассматриваются подобно элементам pkNormal за
исключением того, что они используют другой набор
видеоатрибутов. Примеров элементов pkAlternate может служить имя
поддиректории в листинге директорий. Элементы pkProtected
выводятся на экран с еще другим набором видеоатрибутов;
дополнительно, полоска выделения никогда не перемещается на
такие элементы. Их можно использовать для создания заголовков
или пустых строк внутри PickList. pkPrivate - это категория,
зарезервированная для Turbo Power; вы не должны присваивать для
IType это значение.
    IString - это цепочка символов, которая возвращает имя
заданного элемента. За исключением случая, когда Mode равно
pkGetType, Вы должны всегда задавать значение для IString.
OPPICK не заботится о том, где Вы получили значение цепочки,
поэтому Вы можете допустить потерю созданного вами. Запомните
только - данная процедура вызывается весьма часто, поэтому
нежелательно делать что-либо, что занимает слишком много времени.
    OPPICK обрывает или дополняет возвращаемую цепочку символов
в случае, если ее визуальная длина (после удаления управляющих
символов для гибкой записи) не соответствует заданной ширине
столбца. Кроме того, OPPICK добавляет маркеры заполнения и
селекции к возвращаемой цепочке, если действуют соответствующие
опции.
    Вы возможно удивлены, почему процедура обработки цепочек
символов не является функцией, так как ее главное назначение
возвратить цепочку. Передавая цепочку как параметр var, а не как
результат функции, используется минимальный стек, особенно в
случае, когда цепочка передается через ряд вложенных процедур. В
типичной ситуации имеется по крайней мере три вложенных вызова:
процедура вывода на экран для PickList вызывает виртуальный
метод CompleteItemString (который возвращает цепочку с
добавлениями и маркерами); последний метод в свою очередь
вызывает виртуальный метод ItemString (который возвращает
цепочку без символов заполнения), а он вызывает определяемую
пользователем процедуру обработки цепочек. Подход с
использованием параметра var экономит по крайней мере 3*256
байтов объема стека и, возможно, несколько даже больше.
    OPPICK не дает никаких гарантий о последовательности или
числе вызовов процедуры обработки цепочек. Многие полагали (при
работе с Turbo Professional), что процедура обработки цепочек
вызывается по увеличению порядкового номера для каждого элемента
и что последний вызов для одной корректировки на экран - это
вызов для выделенного элемента. Это необязательно так.
Фактически OPPICK предпринимает специальные меры для минимизации
числа вызовов процедуры обработки цепочек , так как часто именно
эти обращения являются основным узким местов при выполнении
программы. Например, если необходимо переместиться по списку
выбора на одну строку, OPPICK осуществляет перемещение путем
прямого видеоперемещения и вызывает процедуру обработки цепочек
только для вывода на экран вновь появившейся строки.

    Ориентирование в спиская выбора

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

PickVertical    PickHorizontal      PickSnaking
 A   E    I       A   B   C           A   D   G
 B   F    J       D   E   F           B   E   H
 C   G    K       G   H   I           C   F   I

    Для PickVertical в вертикальных столбцах расположены элементы
по возрастанию их номера. Отметим, что элементы D и H находятся
ниже окна и не будут видны, пока окно не передвинется вверх.
    Для PickHorizontal элементы расположены по возрастанию
номера по строкам. Правый край первой строки сразу же
продолжается с левого края следующей строки. Перемещение окна
вверх на одну строку открывает два оставшихся элемента J и K.
    PickSnaking подобно PickVertical в том смысле, что элементы
расположены по столбцам. Однако, подобно PickHorizontal верх
каждого столбца является непосредственным продолжением низа
предыдущего столбца. Перенос окна примера влево на один столбец
сделает видимыми элементы J и K в правом столбце.
    Какой способ ориентации лучше зависит от его применения. Для
сортированных списков директорий мы предпочитаем ориентацию
PickSnaking, так как глаз естественным образом стремится
просматривать сверху вниз по столбцам и к тому же в отличие от
PickVertical не возникает никаких пропусков в последовательности
элементов.
    Отметим, что ориентация в списке не оказывает никакого
влияния на применение клавиш управления курсором в границах
списка. Например, нажимая на клавишу стрелки "вниз", всегда
перемещаем полосу выделения вниз на одну строку.
    Использование любой из трех ориентация осуществляется весьма
просто. Необходимо только указать имя ориентации - PickVertical,
PickHorizontal или PickSnaking - в параметре Orientation
конструктора PickList. Для изменения в приведенном вначале раздела
примере ориентации достаточно только изменить вызов конструктора
PizzaTop:

if not PizzaTop.InitCustom(35, 5, 45, 10,   {Initial window coordinates}
                          DefaultColorSet,  {ColorSet to use}
                          PickWindowOptions,{Window options}
                          11,               {Column width per item}
                          NumPizzaToppings, {Number of pickList items}
                          PizzaTopping,     {Item string function}
{-------->}               PickHorizontal,   {Orientation procedure}
                          SingleChoice)     {Command handler}
then begin
 ...

    Вы можете изменить ориентацию, когда PickList не является
активным, вызвав ChangeOrientation. Кроме того, можно в любой
момент проверить текущую ориентацию, вызвав процедуру
GetOrientation.
    Отметим, что все три ориентации фактически являются именами
процедур, взаимодействующими с OPPICK. Эти процедуры при вызове
их из PickList выполняют инициализацию необходимую для задания
клавиш перемещения курсора и логики работы дисплея. Каждая
дополнительная ориентация, используемая Вами в программе,
вызывает подсоединение Turbo Pascal к  более выполняемому коду.

    Изменение размеров окна для списков выбора

    OPPICK предоставляет ряд других методов помимо трех способов
ориентации для контроля , где в пределах списка показаны
заданные элементы и окно выбора отрегулировано в области
элемента. Далее мы коротко рассмотрим эти методы.
    Один из флагов опций PickList имеет имя pkMinHeight. В
случае, когда указанная опция включена, что предусмотрено по
умолчанию, все конструкторы PickList будут автоматически снижать
высоту окна выбора при условии, что элементы списка не
используют все строки окна. Например, предположим, что список
содержит 1 столбец; общее число элементов - 7. В случае, если
минимальная и максимальная Y координаты конструктора,
соответственно, равны 5 и 20,то остается свободным пространство
для 16 элементов. Конструктор перед вызовом CommandWindow
уменьшит максимальную Y координату до 11 и тем самым уберет
пустые строки. Ввиду того, что эта регулировка выполняется перед
реализацией окна, отсутствует фрагментация динамически
распределяемой памяти.
    Метод PickList с именем SetRowLimits воздействует на
минимальное и максимальное число элементов в каждом столбце
списка. Предположим, что мы выбрали пример A-K из рассмотренных
выше способ ориентации, используем PickVertical, а минимальный
предел строки равен 5. Тогда вначале мы увидим:

  A  F  K
  B  G
  C  H

    Отметим, что элементы D и E расположены ниже края окна,
также как и элементы I и J. Минимальный предел строки вызывает
задание 5 элементов в каждом столбце.
    Подобным же образом максимальный предел строки определяет
максимальное число элементов в каждом столбце. В отличие от
вышерассмотренной опции pkMinHeight максимальный предел строки
не оказывает влияния на высоту окна выбора. Этот параметр
контролирует только расположение элементов в пределах окна.
Обратимся вновь к примеру A-K. Если мы зададим масимальный
предел строки равный 2 (более ничего не изменяя), мы увидим:

  A  E  I
  B  F  J
  _  _  _

    Символы подчеркивания указывают пустые области внутри окна.
    Следующий метод с именем OptimizeSize полностью изменяет
конфигурацию окна выбора при изменении числа элементов, их
ширины или ориентации. Мы используем этот метод в окне
управляющей программы файлами DESKPOP при изменении режима
вывода изображения с компактного на режим полного изображения.
Метод регулирует координаты окна для возврата к первоначально
запрошенному размеру. Для этого метод задает максимальное число
столбцов элементов, делает минимальной неиспользуемую ширину и
высоту окна и одновременно остается в пределах окна RawWindow.
Более подробно данный вопрос рассмотрен в описании метода
OptimizeSize. Перед изучением материала следует
поэкспериментировать с окном управляющей программы файлами
DESKPOP, чтобы увидеть OptimizeSize в действии.

    Списки с кратным выбором

    Одно из наиболее популярных усилений , запрашиваемых для
Turbo Professional модуля списка выбора - возможность выбирать и
помечать за один раз более одного элемента. Хотя эта возможность
легко реализуется при использовании в полном объеме средств
определяемой пользователем процедуры обработки цепочек, многие,
по-видимому, предполагают, что модуль должен автоматически
обеспечивать эту возможность. Учитывая это, мы реализовали
кратный выбор в модуле OPPICK.
    Списки выбора с кратным выбором являются полезными во многих
приложениях. Мы использовали только одно из них, присущее для
ObjectProfessional: окно управляющей программы в DESKPOP. Это
окно позволяет применять заданную операцию работы с файлами -
удаление, переименование, копирование - для всего списка
отмеченных файлов. Другое общее требование - выбрать несколько
опций, по крайней мере, для программы инсталляции.
    Для обеспечения возможности кратного выбора объект PickList
работает совместно с другим типом объектов ObjectProfessional -
BitSet.Каждый бит в BitSet соответствует одному элементу в
списке; если элемент помечен, то бит установлен, и наоборот.
Учитывая высокую эффективность BitSet - они упаковывают по 8
битов в каждый байт - списки кратного выбора требуют весьма
небольших дополнительных расходов объема для данных. Размещение
и управление BitSet выполняется автоматически и PickList
предлагает группу методов, упрощающих определение, какие
элементы выбраны в данный момент.
    Кроме того, OPPICK предлагает методы для визуальной
идентификации выбранных элементов. Метод SetSelectMarker
определяет выводимую на экран дисплея цепочку по левой и правой
стороне каждого выбранного элемента. Обычно эти цепочки
используют символ "контрольного маркера" (#251) или некоторую
форму символа стрелки (например #16) для указания выбранного
элемента.
    В случае, когда опция кратного выбора является активной,
OPPICK делает активными новые команды в окне выбора. К ним
относятся команды создания блоков элементов, переключения
состояния выбора и очистки всего списка. Более подробную
информацию Вы найдете в разделе "Команды списка выбора".
    С тем, чтобы операции с кратным выбором стали активными, вам
необходимо только в любом конструкторе PickList для параметра
CommandHandler задать MultipleChoice.
    Ниже приведен пример, опять с использованием PizzaTopping,
списка выбора с кратным выбором. Как вы видите понадобились лишь
назначительные изменения.

program PizzaListExample; {EXPICK3.PAS}
uses
  OpCrt, OpRoot, OpCmd, OpFrame, OpWindow, OpPick;
type
  MultiPizzaList =
    object(PickList)
      constructor Init(X1, Y1, X2, Y2 : Byte);
      procedure ItemString(Item : Word; Mode : pkMode;
                          var IType : pkItemType;
                          var IString : String); virtual;
    end;

constructor MultiPizzaList.Init(X1, Y1, X2, Y2  : Byte);
const NumPizzaToppings = 5;
var   PickWindowOptions : LongInt;
begin
  PickWindowOptions := DefWindowOptions or wBordered;
  if not PickList.initAbstract(X1, Y1, X2, Y2,
                          DefaultColorSet,  {ColorSet to use}
                          PickWindowOptions,{Window options}
                          11,               {Column width per item}
                          NumPizzaToppings, {Number of pickList items}
                          PickVertical,     {Orientation procedure}
{--------->}              MultipleChoice)   {Command handler}
  then
    Fail;
  SetSelectMarker(#251, ' ');
end;

procedure MultiPizzaList.ItemString(Item : Word; Mode : pkMode;
                                   var IType : pkItemType;
                                   var IString : String);
begin
  case Item of
    1 : IString := 'Pepperoni';
    2 : IString := 'Sausage';
    3 : IString := 'Mushrooms';
    4 : IString := 'Anchovies';
    5 : IString := 'Onions';
  end;
end;

var
  PizzaTop : MultiPizzaList;
  SelectedItem : Word;

begin
  {Make a MultiPizzaList}
  if not PizzaTop.Init(35, 5, 45, 9) then begin
    WriteLn('Failed to Init MultiPizzaList, Status =', InitStatus);
    Halt;
  end;

  {Pick an item}
  PizzaTop.Process;
  PizzaTop.Erase;
  if PizzaTop.GetLastCommand = ccSelect then
    if PizzaTop.GetSelectedCount > 0 then begin
      WriteLn('You selected:');
      PizzaTop.InitSequence(SelectedItem);
      while PizzaTop.HaveSelected(SelectedItem) do begin
        WriteLn(PizzaTop.GetItemString(SelectedItem));
        PizzaTop.NextSelected(SelectedItem);
      end;
    end else
      WriteLn('No selections');
  PizzaTop.Done;
end.


    Отметим, что вызов PickList.InitAbstract устанавливает опцию
MultipleChoice. Вызов SetSelectMarker определяет, что
контрольный маркер в левом краю указывает на выбранный элемент.
В каждой верхушке теперь отсутсвует начальный пробел в цепочке
символов. Его место будет занимать односимвольный маркер выбора.
    После вызова PizzaTop.Erase Вы выполняете проверку, чтобы
увидеть , выбраны ли какие-нибудь элементы. Если были выбраны
элементы, то с помощью серии вызовов InitSequence, HaveSelected
и NextSelected просматриваются все выбранные элементы. Вы
выполняет обратное считывание каждого элемента , вызывая
GetItemString.
    Существуют ситуации, когда вам необходимо предварительно
выбрать ряд элементов. Это легко сделать, но для этого
требуется, чтобы вы знали еще один факт: PickList не размещает
своq BitSet до тех пор, пока в его работу вмешиваются, так как
число элементов может быть изменено после вызова конструктора.
(Это часто случается для списков директорий.) Следовательно, для
предварительного выбора ряда элементов Вы должны явно разместить
BitSet и затем пометить заданные элемнты. опробуйт добавить
слдущи строки к примеру в конце процедуры MultiPizzaList.Init :

AllocateSelectSet(NumPizzaToppings);
SelectItem(2);
SelectItem(5);

    Кроме того, размещение BitSet вызывает его очистку. Теперь
при первом выводе на экран дисплея Вы увидите, что выбраны
элементы 2 (Sausage) и 5(Onions).
    PickList имеет ряд других методов для управления списками с
кратным выбором. Обязательно прочтите описание следующих методов:

function GetItemString(Item : Word) : string;
  {-Return srecified item string in search format}
  {Возвратить цепочку символов для заданного элемента в формате
          поиск}

procedure SetSelectMarker(Left, Right : String);
  {-Define strings to mark selected items}
  {Определить цепочки символов для отметки выбранных элементов}

procedure AllocateSelectSet(MaxItems : Word};
  {-Allocate the select set   for the maximum items}
  {Разместить выбранный набор для максимальных элементов}

procedure ClearSelected;
  {-Clear selected items}
  {Очистить выбранные элементы}

procedure MarkAllSelected;
  {-Mark all items selected}
  {Отметить все выбранные элементы}


procedure SelectItem(Item : Word); virtual;
  {-Select an item}
  {Выбрать элемент}

procedure DeselectItem(Item : Word); virtual;
  {-Deselect an item}
  {Отменить выбор элемента}

Function ItemIsSelected(Item : Word) : bOOLEAN;
  {-Return True if item is selected}
  {Вернуть True если элемент выбран}

function GetSelectedCount : Word;
  {-Return number of items selected}
  {Вернуть число выбранных элементов}

procedure InitSequence(var Item : Word);
  {-Prepare to get first selected item}
  {Подготовить получение первого выбранного элемента}

function HaveSelected(Item : Word) : Boolean;
  {-Return True if there is a selected item}
  {Возвратить True в случае, если есть выбранный элемент}

procedure NextSelected(var Item : Word);
  {-Position at the next selected item}
  {Перейти к следующему выбранному элементу}

    Поиск по цепочкам символов

    Типичной характеристикой систем меню является возможность
выбора элемента по введенному первому символу имени элемента.
PickList поддерживает эту характеристику, а также ее обощает.
    Метод Process OPPICK вызывает виртуальный метод ItemSearch
как только обнаруживает команду ccChar. ItemSearch вызывает
определяемую пользователем функцию поиска, которая должна
соответствовать следующему определению прототипа:

{$F+}
function PpickSearch(P : PickListPtr) : Boolean;

    Функция может ссылать ся на поля данных и методы
PickList-объекта для определения, совпадает ли один из
элементов. В случае совпадения определяемая пользователем
функция должна установать текущий элемент списка. Если Метод
Process должен прекратить работу в результате достижения
совпадения, определяемая пользователем функция должна возвратить
True. При отсутствии совпадения или в случае, если Process
должен в любом случае остаться активным, функция должна
возвратить False.
    OPPICK уже обеспечивает ряд из указанных функций, поэтому,
вполне вероятно, что вам не понадобиться писать ее самим. Ниже
приведены предопределенные функции:

function PickNoSearck(P : PickListPtr) : Boolean;
  {-No searching mode}
  {Не задан режим поиска}

function PickStringSearch(P : PickListPtr) : Boolean;
  {-String searching mode}
  {Режим поиска цепочки символов}

function PickAltStringSearch(P : PickListOtr) : Boolean;
  {-Alternate string searching mode}
  {Альтернативный режим поиска цепочки символов}

function PickCharSearch(P : PickListPtr) : Boolean;
  {-Character searching  mode}
  {Режим поиска символа}

function PickCharExit(P : PickListPtr) : Boolean;
  {-Character searching with exit on match}
  {Режим поиска символа с выходом из при совпадении}

function PickAnyCharExin(P : PickListPtr) : Boolean;
  {-exit ln any alpha character. No highlight repositioning}
  {выход из программы по любому буквенному символу. Без
         выделения возврата в прежнее место}

    Вновь сконструированный PickList использует функцию
PickNoSearch. В этом режиме игнорируются буквенно-цифровые
символы. Выберите альтернативны режим поиска, вызвав метод
SetSearchMode с именем функции обработки цепочки в качестве
параметра, например:

PizzaTop.SetSearchMode(PickStringSearct);

    PickStringSearch выполняет пошаговый поиск , добавляя каждый
символ, совпадающий с внутренней цепочкой символов. Длина этой
цепочки определяется константой OPPICK с именем pkMaxSearchLen,
которая по умолчанию равна 15. Поиск начинается с текущего
выделенного элемента. Каждый раз при обнаружении нового
совпадения OPPICK добавляет текущий элемент к этому элементу.
Метод Process никогда не прекращает работу в результате
обнаружения совпадения (т.е. пользователь должен нажать клавишу
<Enter> для завершения выбора). При введении несовпадающего
символа очищатся внутренняя цепочка поиска и текущий элемент
остается без изменений.
    PickAltStringSearch отличается от PickStringSearch только в
ситуации обнаружения несовпадающего символа. В этом случае
иницилизуетя внутренняя цепочка поиска по последнему введенному
символу ( по несовпадающему символу) и предпринимается попытка
повторного поиска. В случае, если вторая попытка поиска дала
совпадение, выделяется новый совпавший элемент. В противном
случае цепочка поиска очищается.
    PickCharSearch осуществляет поиск только по одному символу.
поиск всегда начинатся с элемента, расположенного ниже текущего.
Таким образом , нажимая на один символ повторно, перемещаем
выделение по всем элементам, начинающихся с одного символа.
Пользователь для завершения выбора должен нажать <Enter>.
    PickCharExit осуществляет поиск одного символа, начиная с
текущего элемента. При обнаружении совпадения совпавший элемент
выделяется. Далее функция изменяет последнюю введенную команду с
ccChar на ccSelect и возвращает True с тем, чтобы метод Process
прекратил работу.
    PickAnyCharExit невыполняет никакого поиска на совпадение.
Она просто вызывает выход из метода Process при вводе любого
буквенно-цифрового символа. При возврате из метода Process метод
GetLastCommand возвращает ccChar. Применение этому режиму поиска
мы оставляем вашему воображению.
    Внутренний двигатель поиска использует одну и ту же
стратегию для всех режимов поиска. Защищенные элементы никогда
не дают совпадения. Поиск не зависит от случая. Каждая цепочка
элемента генерируется через вызов метода CompleteItemString,
используя режим pkSearch (это означает, что управляющие символы
гибкой записи и маркеры выбора не должны быть частью
возвращаемой цепочки символов). Ведущие белые пробелы
подгоняются для возвращаемой цепочки. Символы слева от
начального столбца поиска (задаваемого в методе SetSearchStart)
отбрасываются. И наконец, если Pos(SearchString,
AdjustedItemString) равно 1, совпадение есть. Если не 1, то
поиск продолжается для следующего элемента, загибаясь на начало
поиска при достижении его конца. Цикл поиска продолжается до
достижения исходного элемента.
    Как и в случае определяемой пользователем процедуры
обработки цепочек символов, функция поиска может быть
использована при блокировании метода ItemSearch в выведенном
типе или через вызов SetSearchMode с тем, чтобы объявить другой
указатель функции. Аргументы в пользу того или другого подходов
см. выше в разделе "Определяемая пользователем процедура
обработки цепочек символов".







          Поддержка мыши

    Поддержка мыши встроена в PickList-объект; Вам необходимо
только сделать ее активной. Для этого добавьте следующие строки
к примеру PizzaTopping после вызоваPizzaTop.Init:

if MouseInstalled then begin
  with DefaultColorSet do
    SoftMouseCursor($0000, (ColorMono(MouseColor, MouseMono) shl 8)+$04);
  PickCommands.cpOptionsOn(cpEnableMouse);
  PizzaTop.wFrame.AddScrollBar(frRR, 0, MaxLongInt, DefaultColorSet);
end;

    Рассматриваемый код вначале проверяет, установлена ли мышь.
В случае, если мышь установлена, определяются характеристики
курсора мыши. Этот шаг является необязательным, так как
программный курсор мыши задается по умолчанию, но, возможно, что
у вас появится желание установить его цвета, согласованные с
остальной частью вашего ColorSet. Для PickList-объекта Вы всегда
должны использовать программный (в противоположность
аппаратному) курсор мыши. Более подробную информацию об
определении курсора мыши Вы найдете в OPMOUSE.
    Вызов PickCommands.cpOptionsOn инициализует для поддержки
мыши PickList коммандный процессор. Более подробную информацию
Вы найдете в OPCMD, особенно если Вы используете ловушки заданий
фоновой обработки.
    И наконец, рассматриваемый код добавляет необязательную
полосу прокрутки . Вы можете выбрать элементы списка с помощью
мыши даже без полосы прокрутки, Вы можете иметь полосу прокрутки
без использования мыши. Отметим, что минимальный (0) и
максимальный (MaxLongInt0) пользовательские пределы являеются
произволными в этот момент; PickList корректирует их в
соответствии с фактической конфигурацией списка выбора. В данном
примере используется только полоса вертикальной прокрутки в
правом краю рамки. Кроме того, PickList поддерживает
горизонтальные полосы прокрутки. Полосы прокрутки действуют
точно так же, как мы этого ожидаем: слайд перемещается с
изменением текущего элемента; щелкание по полосе изменяет
выделенный элемент; щелкание по стрелке прибавления/уменьшения
передвигает список. В случае, если включена опция PickList с
именем pkMousePage стрелки при однократном нажатии переносят
список на целую страницу, если опция выключена - то на одну
строку (или столбец).

    Специализированные заголовки рамки

    Два существующих типа специализированных заголовков
обеспечивают улучшение визуального восприятия способов выбора.
Первый тип имеет название "заголовок продолжения" . Он обычно
используется с перемещаемыми списками выбора с тем, чтобы
показать , что за границами окна имеются еще другие элементы
списка. Заголовок является альтернативой полос перемещения в
приложениях, где не используется мышь. Добавьте заголовок
продолжения к главной рамке окна, вызвав процедуру AddModeHeader:

procedure AddModeHeader(PromptStr : String80;
                       Posn : HeaderPosType;
                       UpStr, DnStr, SepStr : String10;
                       UpPos, DnPos, SepPos : Byte);

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

PizzaTop.AddMoreHeader('   for more', heBR, #24, #25, '', 1, 2, 0);

    PickList заменяет первые два символа в PromptPtr стрелками
вверх (#24) и вниз (#25) в зависимости от того, какая часть
списка видна, а затем корректирует изображение заголовка. Более
подробно мы опишем параметры при рассмотрении процедуры
AddModeHeader.
    Второй специализированный заголовок - это заголовок поиска.
Используйте этот заголовок при задании одного из режимов поиска
PickList: PickAltStringSearch или PickStringSearch. Если Вы
хотите получить визуальное изображение цепочки символов
пошагового поиска, добавьте заголовок поиска, используя
следующий способ:

procedure AddSearchHeader(MaxLen : Byte; Posn : HeaderPosType);

    MaxLen определяет максимальное число показываемых символов
цепочки поиска. Лишние символы отбрасываются обычно из-за того,
чтобы заголовок не выходил за границу рамки или не перекрывал
другой заголовок. Нет никаких причин делать MaxLen больше, чем
pkMaxSearchLen(15), так как это самая длинная цепочка поиска,
используемая OPPICK.

    Применения гибкой записи FlexWrite для вывода изображения
                    элемента

    Элементы в приведенных нами выше примерах PickList
выводились на дисплей одним цветом. Кроме того, OPPICK имеет
возможность использовать несколько видео атрибутов для каждого
элемента списка. Это осуществляется с помощью процедуры
FlexWrite из OPCRT. Наиболее типичный случай использования этого
способа - выделить первый символ в каждом элементе, показывая
пользователю, что вводя символ, он выбирает элемент. Для
демонстрации рассматриваемого способа изменим пример
PizzaTopping еще раз:

program PizzaListExample;    [EXPICK4.PAS}
uses
  OpCrt, OpMouse, OpRoot, OpCmd, OpFrame, OpWindow, OpPick;
type PizzaList =
       object(PickList)
         constructor Init(X1, Y1, X2, Y2 : Byte);
         procedure ItemString(Item : Word; Mode : pkMode;
                             var IType : pkItemType;
                             var IString : String); virtual;
       end;

constructor PizzaList.Init(X1, Y1, X2, Y2 : Byte);
cont NumPizzaToppings = 5;
     ColorFlex : FlexAttrs = ($07, $0F, $01, $70);
     MonoFlex : FlexAttrs = ($07, $0F, $01, $70);
var  PickWindowOptions : LongInt;
begin
  PickWindowOptions := DefWindowOptions or wBordered;
  if not PickList.InitAbstrct(X1, Y1, X2, Y2,
                             DefaultColorSet,  {ColorSet to use}
                             PickWindowOptions,{Window options}
                             11,               {Column width per item}
                             NumPizzaToppings, {Number of pickList items}
                             PickVertical,     {Orientation procedure}
                             SingleChoice)     {Command handler}
then
  Fail;
  SetSearchMode(PickCharSearch);
  {Enable flexwriting}
  SetPickFlex(pkNormal, False, ColorFlex, MonoFlex);
end;

procedure MultiPizzaList.ItemString(Item : Word; Mode : pkMode;
                                   var IType : pkItemType;
                                   var IString : String);
begin
  case Item of
    1 : IString := 'Pepperoni';
    2 : IString := 'Sausage';
    3 : IString := 'Mushrooms';
    4 : IString := 'Anchovies';
    5 : IString := 'Onions';
  end;
  if Mode = pkDisplay then begin
    { Insert flexwriting control characters}
    Insert(^A, IString, 3);
    Insert(^A, Istring, 2);
  end;
end;

var
  PizzaTop : PizzaList;

begin
  {Make a PizzaList}
  if not PizzaTop.Init(35, 5, 45, 10) then behin
    WriteLn('Failed to Init PizzaList, Status =', InitStatus);
    Halt;
  end;

  {Pick an item}
  PizzaTop.Process;
  PizzaTop.Erase;
  if PizzaTop.GetLastCommand = ccSelect then
    WriteLn('You chose item ', PizzaTop.GetLastChoice,
            '    -   ', PizzaTop.GetLastChoiceString)
  else
   WriteLn('No choice was made');
  PizzaTop.Done;
end.

    Вызов процедуры SetPickFlex из Init делает допустимым гибкую
запись для рассматриваемого списка выбора. В данном случае мы
используем гибкую запись только для нормальных элементов
(pkNormal), которые в текущий момент не выбраны (False во втором
параметре). Мы определяем два массива видео атрибутов, первый
используется для цветного видеорежима, а второй для
монохроматического режима. Эти массивы интерпретируются подобно
вызову FlexWrite, описанной в OPCRT. Вы можете построить массивы
атрибутов из особых элементов ColorSet или можете явно их
определить, подобно тому, как мы сделали.
    Кроме того, Init делает возможным поиск символа. В
результате выделенные символы будут иметь опеределенное значение.
    Для подготовки гибкой записи необходимо изменить процедуру
ItemString. В случае, если для Mode задан pkDisplay (и только
тогда) , мы вставляем два дополнительных управляющих символа в
каждую цепочку элементов. Первый символ <CtrlA> сообщает
FlexWrite начать запись с его первого альтернативного атрибута,
а второй символ сообщает - закончить запись. Действие
рассматриваемой процедуры в данном примере заключается в записи
первого символа отличного от пробела каждого элемента с видео
атрибутов "ярко" (атрибут $0F).
    С помощью гибкой записи вы можете создавать различные
дополнительные эффекты. Каждый гибкий массив имеет три атрибута
помимо буквенного значений. Эти атрибуты делаются активными со
значениями <CtrlA>, <CtrlB>, <CtrlC>, подсоединяемыми к каждой
цепочке элементов. Более подробную информацию Вы найдете в
OPCRT.FlexWrite. Процедура StePickFlex выполняет гибкую запись
для нормальных, альтернативных и защищенных элементов в
выбранном и невыбранном состояниях. В случае, когда заданы все
комбинации PickList должна хранить 64 различных видео атрибута;
этого конечно достаточно для самых цветонасыщенных приложений!

    Защищенные элементы

    Списки выбора могут содержать элементы,которые не могут быть
выбраны. Такие элементы следует использовать в качестве
подзаголовков, пробулов или резделительных полос, которые
прокручиваются вместе со списком.
    Такие элементы создаются с помощью определяемой
пользователем процедуры обработки цепочек символов. Процедура
возвращает цепочку элемента как обычно, но она должна установить
параметр IType как pkProtected. В таком случае PickList знает
две вещи: рисовать цепочку с другим атрибутом (ProItemColor или
ProItemMono из ColorSet) и не допускать попадания полосы
выделения на защищенные элемент.
    В нашем примере PizzaTopping, если мы хотим защитить
'Onioins' от возможности выбора, нам достаточно только добавить
следующую строку к программе в конце процедуры обработки цепочек:

if Item = 5 then
  IType := pkProtected;

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

if ProtectedItems.BitIsSet(Item)then
  IType := pkProtected;

    Полезно описать, как OPPICK управляет движением курсора при
наличии защищенных элементов. Во-первых, отметим, что является
ошибкой программирования сделать защищенными все элементы в
списке. При обработке такого списка OPPICK не сможет выделить
никакой элемент и будет просто ждать , пока Вы не нажмете <Esc>.
В ситуациях, когда Вы можете гарантировать, что покрайней мере
один элемент является незащищенным, перед вызовом метода Process
Вы должны убедиться, что функция PickList с именем
NumSelectableItems возвращает ненулевое значение.
    В случае, если пользователь нажмет клавишу стрелки при
обработке списка п полученный элемент является защищенным,
OPPICK вводит специальный цикл поиска. Он повторно выполняет
только-что обработанную команду до тех пор, пока а) не достигнет
незащищенного элемента, б)элемент не изменился (например, если
элемент находится внизу столбца) или в) снова достигнет
исходного элемента. В случае, если в этом цикле не будет найден
незащищенный элемент, OPPICK просматривает весь список элементов
до его исчерпания (в направлении, совпадающем с последней
командой), пытаясь найти любой незащищенный элемент.
    Вы можете разработать вырожденный список выбора, для
которого такое эвристическое поведение, по-видимому, не имеет
особого смысла; даже если это так, способ дает логические
результаты почти во всех случаях. Один, вероятно нелогичный
случай возникает, когда последний элемент в списке является
защищенным, а пользователь с помощью мыши выбрал последнее
положение полосы перемещения по списку. OPPICK пытается выбрать
последний элемент и дает отказ; повторное движение вниз приводит
к первому элементу в списке.
    В случае, если Вы пытаетесь выбрать защищенный элемент с
помощью мыши , OPPICK просто игнорирует эту попытку. Подобным же
образом поиск по цепочке символов игнорирует защищенный элемент.

    Ловушка передвижения пользователя

    В ряде случаев у вас может возникнуть необходимость
выполнить заданное действие всякий раз, когда пользователь
изменяет выделенный элемент списка. Общеизвестный пример -
вывести на экран строку помощи или подробное описание каждого
элемента. "Ловушка перемещения пользователя" вызывает
специальную процедуру непосредственно перед вводом какой-либо
команды списка и тем самым Вы можете выполнить такое задание.
    Подобно другим ловушкам PickList Вы можете сделать ее
действующей либо блокируя вирутальный метод, либо используя
указатель в процедуру. Способ блокирования можно ввести
следующим образом:

procedure PreMove; virtual;
  {-Called just prior to getting each keyboard command}
  {Вызывается непосредственно перед вводом любой команды с
        клавиатуры}

    Процедура PreMove, используемая для PickList, вызывает
процедуру:

procedure SetMoveProc(MP : pkGenlProc);
  {-Specify user move procedure}
  {Определить процедуру перемещения пользователя}

    Определяемая по умолчанию процедура перемещения пользователя
не вызывает никаких действий. Альтернативная процедура
перемещения должна быть скомпиллирована по модели FAR, используя
директиву {$F+}; это должна быть глобальная процедура,
соответствующая следующему объявлению прототипа:

{$F+}
procedure MyMoveProc(P : PickListPtr);

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

CurrentItemNumber := P^.GetLastChoice;

    Процедура перемещения может выполнять любое заданное
действие, но с учетом следующего ограничения: активное окно при
выходе из процедуры должно быть таким же как при входе в нее, и
выбранный элемент нельзя изменять.
    В момент вызова PreMove внутренние переменные и изображение
списка выбора уже полностью скорректированы для объяснения
предыдущей команды. Курсор мыши, если он есть, убирается.
Следующая команда еще не получена с клавиатуры. Отсутствует
гарантия, что выбранный в текущий момент элемент отличается от
того, каким он был при предыдущем вызове PreMove, хотя обычно
именно так и обстоит дело.
    Ниже приведен пример процедуры перемещения, которая работает
с нашим примером PizzaTopping:

{$F+}
procedure ToppingSugestions(P : PickListPtr);
var
  S : String[39];
begin
  case P^.GetLastChoice of
     1 : S := 'A required topping';
     2 : S := 'Optional          ';
     3 : S := 'A little is OK    ';
     4 : S := 'If you must...    ';
     5 : S := 'Not recommended   ';
  end;
  FastWrite(S, ScreenHeight, 1, TextAtr);
end;
{$F-}
...
PizzaTop.SetMoveProc(ToppingSuggestions);
...

    Процедура перемещения записывает дополнительную информацию о
каждой верхушке блюда в последнюю строку экрана. Подпрограмма
активизируется через вызов SetMoveProc после реализации PizzaTop.

    Константы
pkStick            = $0001;    {Stick at edges of scrolling lists}
                               {Остановка на краях
                                прокручиваемых  списков}
pkExitAtEdges      = $0002;    {Exit picklist for cursor at extreme edges}
                               {Выход из списка выбора, если
                                курсор находится в крайних положениях}
pkAlterPageFow     = $0004;    {Alter screen row wgen paging}
                               {Изменить строку экрана при
                                разбиении на страницы}
pkMousePage        = $0008;    {Clicking on scroll bar scrolls by page}
                               {Щелкание по полосе прокрутки
                                вызывает постраничную прокрутку}
pkDrawActive       = $0010;    {Draw and Pick leave selected item visible
                                and frame status geaders showing}
                               {Draw и Pick оставляют выбранный
                                элемент видимым и показывают заголовки
                                статуса рамки}
pkMinHeight        = $0020;    {Minimize height depending on number of items}
                               {Минимизировать высоту в
                                зависимости от числа элементов}
pkSetDefault       = $0040;    {Store the default choice when entering Pick}
                               {Сохранить выбор по умолчанию при
                                вводе Pick}
pkOptFullExtent    = $0080;    {When optimizing size, account for full
                               extent of window, including shadows}
                               {При оптимизации размера учесть
                                всю протяженность окна, включая тени}
pkUseItemForTopic  = $0100;    {Use the current item number for help topic,
                                else use the code in the command window}
                               {Использовать номер текущего
                                элемента для предмета помощи или
                                использовать код в командном окне}


    Здесь перечислены опции, влияющие на характеристики
PickList.pkStick заставляет полосу выделения "упираться" в края
прокручиваемых списков. В случае, если эта опция отключена или
список польностью помещается вокне, полоса выделения переходит
на следующую строку или в следующий столбец.
    pkExitAtEdges контролирует поведение на краях списка: если
опция включена метод Process прекращает работу при нажатии
клавиши перемещения курсора, указывающей на движение за границы
окна. GetLastCommand возвращает одно из четырех специальных
значений: ccExitAtTop, ccExitAtBot, ccExitLeft, ccExitRight. Эту
опцию целесообразно использовать только в случае, когда
непрокручиваемый список выбора встроен в более крупную
структуру, такую как EntryScreen.
    pkAlterPageFow влияет на действие клавиш <PgUp>, <PgDn> (см.
"Команды списка выбора").
    В случае, если включена опция pkMousePage, щелкание по
стрелке приращения или убывания вертикальной полосы перемещения
трактуется подобно нажатию клавиш <PgUp>, <PgDn>. Если же опция
выключена, щелкание трактуется подобно нажатию клавиш <Up>,
<Down>.
    В случае, если действует pkDrawActive, выделяется текущий
элемент и после прекращения работы метода Process становятся
видимыми специализированные заголовки выбора. Если опция
выключена, то выделение и заголовки стираются.
    При установке pkMinHeight перед вызовом конструктора
PickList высота окна выбора будет уменьшена до полного
заполнения заданного числа элементов строк окна.
    pkSetDefault указывает, что метод Process должен сохранить
номер первоначально выбранного элемента во внутреннем поле
данных сразу же после входа в Process. Доступ к полю данных
обеспечивается методом GetDefaultChoice. Определяемая
пользователем процедура обработки цепочек может ссылаться на это
значение, по крайней мере, для выделения соответсвующего
элемента. В случае, если опция выключена, поле внутренних данных
можно изменить только с помощью метода SetDefaultChoice.
    В случае, когда включена опция pkOptFullExtent, метод
OptimizeSize при регулировании размера окна учитывает наличие
теней окна выбора. Не допускается увеличение размеров окна, если
требуется сжатие теней.
    В случае, если установлена опция pkUseItemForTopic метод
Process передает номер текущего элемента как номер предмета в
пользовательскую процедуру обработки помощи. При выключенной
опции pkUseItemForTopic предмет помощи - это значение,
обозначаемое как индекс помощи окна (см.
CommandWindow.SetHelpIndex), который по умолчанию равен 0).

DefPickOptions : Word = pkStick+pkAlterPageRow+pkDrawActive+
                        pkMinHeight+pkSetDesault+pkOptFullExtent;

    Опции по умолчанию для PickList.

BadPickOptions : Word = pkItemWrap+pkPickActive+pkBitSetAlloc+pkRedrawPage+
                        pkRedrawOne+pkFlexWrite+pkMultiChoice;

    Внутренние для PickList опции. Методы pkOptionsOn и
pkOptionsOff  не должны менять эти биты слова  опций PickList.

PickKeyMax = 160;
PickKeyID : string[11] = 'oppick keys';
PickKeySet : array[0..PickKeyMax] of Byte = (...);
PickCfgEnd : Byte = 0;

    PickKeyId - это ID цепочка символов, используемая для
отметки начала области данных о конфигурации для OPPICK;
PickCfgEnd отмечает конец области данных о конфигурации. Между
этими цепочками символов расположена таблица команд,
используемых PickCommand - PickKeySet. PickKeyMax - последний
допустимый индекс в таблице.

pkMaxSearcgLen = 15;

    Максимальная длина цепочки символов, используемой для
пошагового поиска. Увеличение этой величины вызывает увеличение
размера переменной экземпляра PickList. Размер имеет значение
только тогда, кода в качестве режима поиска заданы
PickStringSearch или PickAltStringSearch.

pkNormal    = 0;         {Normal items}
                         {Нормальные элементы}
pkAlternate = 1;         {Alternate items}
                         {Алтернативные элементы}
pkProtected = 2;         {Protected items}
                         {Защищенные элементы}
pkPrivate   = 3;         {Reserved for TurboPower}
                         {Зарезервировано для TurboPower}

    Здесь перечислены категории элементов списка выбора. Более
подробную информацию Вы найдете во введении к рассматриваемому
разделу.

pkNoOrient   = 0;
pkVertical   = 1;
pkHorizontal = 2;
pkSnaking    = 3;
    Величины, возвращаемые методом GetOrientation для указания
ориентации PickList.

    Типы

String10 = String[10];
String80 = String[80];
    Типы цепочек, используемые при задании "заголовка
продолжения".

    pkItemType       = pkNormal..pkPrivate;
    Допускаемый категории элементов (см. выше "Константы").

pkBaseColorArray = array[pkItemType, Boolean] of FlexAttrs; {unsel/selected}
pkColorArray     = array[Boolean] of pkBaseColorArray; {mono/color}
    Массивы , используемые для хранения в PickList видео
атрибутов. Отметим, что предлагается 64 независимых значений
цветов. В случае, если гибкая запись не разрешена, используется
максимум 16 значений цветов.

pkSearcyString   = String[pkMaxSearcgLen];
    Тип данных, используемых для хранения текущей цепочки
пошагового поиска.

pkMode      = (pkDisplay, pkSearcg, pkGetType);
    Режимы, передаваемые в определяемую пользователем процедуру
обработки цепочек символов. См. обсуждение во введении к разделу.

pkStringProc   = procedure (Item : Word; Mode : pkMode;
                           var IType : pkItemType; var IString : String;
                           PickPtr :  PickListPtr);
    Типы параметров определяемой пользователем процедуры
обработки цепочек.

pkGenProc    = procedure (P : PickListPtr);
    Типы параметров функции перемещения пользователя, а также
другиз переменных для процедур, используемых внутри PickList.

pkSearchFunc   = function (P : PickList Ptr) : Boolean;
    Тип параметров определяемой пользователем функции поиска.

MoreRec =
  record
   ...
  end;
    Тип записи, хранящей детали специализированного "заголовка
продолжения". Кроме того, этот тип используется OPHELP для
аналогичного типа заголовков. Вам не требуется ссылаться на поля
этой записи.

PickListPtr = ^PickList;
PickList =
  object(CommandWindow)
   ...
  end;
    PickList объект.

    Переменные

PickCommands : CommandProcessor;

    Принимаемый по умолчанию CommandProcessor для PickList. Эта
переменная инициализуется блоком инициализации OPPICK. Более
подробную информацию о назначении клавиш Вы найдете в OPPICK.ICD.









     AddMoreHeader

    Объявление

procedure  AddMoreHeader(PromptStr : String80;
                        Posn : HeaderPosType;
                        UpStr, DnStr, SepStr : String10;
                        UpPos, DnPos, SepPos : Byte);

    Функция

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

    Описание

    Данный заголовок является полезным в случае, когда списки
выбора имеют большее число элементов, чем может поместиться в
окно за один раз, и не предусмотрены полосы перемещения.
Заголовок задает в рамке окна PickList сообщение типа
"продолжение выше/ниже". Фактическое сообщение динамически
изменяется в зависимости от положения полосы выделения в
пределах списка.
     AddMoreHeader посылает вызов в wFrame.AddHeader после
инициализации внутренней структуры данных для хранения дорожки
заголовка продолжения. После этого PickList управляет
изменениями и выводом изображения заголовка.
    PickList одновременно может иметь только один из таких
заголовков. В случае, если добавлен другой заголовок, PickList
удаляет предыдущий заголовок прежде, чем добавит новый.
    Параметр Posn определяет положение заголовка относительно
рамки (heTL, heTC, heTR, heBL, heBC или heBR).
    Остальные цепочки символов и значений байтов определяют
составляющие заголовка, который состоит из четырех частей. Проще
всего их описать на примере.
    Предположим, что мы хотим прочитать в заголовке:

'Up/Down for More'

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

'xxxxxxx for More'

    Позиции xxxxxxx содержат произвольные символы, так как они
служат только для фиксации положения. Однако, целесообразно
использовать исходную цепочку символов для PromptStr.
    UpStr -'Up' в рассматриваемом примере - определяет цепочку
символов, вставляемую в PromptStr в случае, когда выше текущего
окна расположены некоторые элементы. UpPos определяет позицию, с
которой вставляется цепочка символов в PromptStr - 1 в
рассматриваемом примере.
    DnStr и DnPos определяются аналогичным образом и будут иметь
значения "Down" и 4 в приведенном примере. SetPtr выводится на
экран только тогда, когда показаны и UpStr и DnStr. В данном
случае SetPtr будет равно '/' ,а SetPos будет равно 3.
    В случае, когда позиция прокрутки списка такова, что одна из
рассматриваемых цепочек символов не подходит, ее позиция
заполняется пробелами. В случае, если не требуются динамические
цепочки символов (например, список весь целиком помещается в
окно выбора) заголовок не будет нарисован.
     AddMoreHeader проверяет различные ошибки, включая
неправильную позицию цепочки символов и недостаточный объем
памяти для размещения буферов цепочек.Эти ошибки можно
обнаружить,вызвав GetLastError.

    Пример

    PizzaTop.AddMoreHeader(' ..More', heBR, #24, #25, ' ', 2, 3, 0);

    Добавляем справа внизу заголовок продолжения к окну выбора.
Вместо точек в цепочке символов будут записаны символы UpStr и
DnStr (в рассматриваемом случае - стрелки вверх и вниз). Стрелка
вверх будет записана во второй позиции для символа в заголовке,
а стрелка вниз - в третьей позиции. В рассматриваемом заголовке
отсутствует цепочка разделителя.

    Дополнительно см.

Frame.AddHeader


    AddSearchHeader

    Объявление

procedure AddSearchHeader(MaxLen : Byte; Posn : HeaderPosType);

    Функция

    Добавить специальный заголовок цепочки поиска.

    Описание

    Рассматриваемый заголовок удобно использовать только в
случае, когда Вы предполагаете использовать режимы поиска
PickAltStringSearch и PickStringSearch. Заголовки будут
показывать текущее значение цепочки пошагового поиска.
    AddSearchHeader создает вызов в wFrame.AddHeader после
инициализации внтуренних структур данных. После этог PickList
управляет изменениями и изображением данного заголовка.
    MaxLen устанавливает максимальную длину для вывода на экран
дисплея. Нет причин делать MaxLen больше, чем pkMaxSearchLen,
так как последний параметр определяет максимальную длину цепочки
поиска символов в OPPICK.
    Posn устанавливает позицию заголовка относительно рамки
(heTL,  heTC, heTR, heBL, heBC или heBR).
    В случае, если не хватает памяти AddSearchHeader генерирует
ошибку epFatal+ecOutofMemory.

    Пример

PizzaTop.SetSearckMode(PickStringSearch);
PizzaTop.AddSearchHeader(20, heTL);

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

    Дополнительно см.

SetSearchMode

   AllocateSelectSet

    Объявление

procedure AllocateSelectSet(MaxItems : Word);

    Функция

    Разместить набор выбора для заданного числа элементов.

    Описание

    Этот метод вводится для списков кратного выбора. PickList
вызывает его автоматически, если Вы этого не сделаете. Имеются
две причины, почему Вы можете пожелать вызвать процедуру явно. В
случае, если число элементов в списке должно увеличиться, Вы
можете разместить больше, чем Вам потребуется в первоначальный
момент. Это позволит избежать фрагментации динамически
распределяемой памяти, если список позднее вырастет. Объект
списка директорий (полученный из PickList) использует именно
рассматриваемый метод, так как он не может знать заранее точное
число файлов, которыми он будет управлять.
    Другая ситуация, когда Вам необходимо вызвать
AllocateSelectSet - если Вы хотите пометить определенные
элементы, выбранные до вызова метода Process. Более подробную
информацию Вы найдете во вступительной части "списки с кратным
выбором".
    AllocateSelectSet размещает порядка (MaxItems + 8) div 8
байт динамически распределяемой памяти. Все эти биты
инициализуются в "чистом" состоянии. Если Вы затем вызовите
AllocateSelectSet, когда размещено меньшее число элементов,
AllocateSelectSet ничего не будет делать. Однако, если Вы
вызовите ее для большего числа элементов, процедура удаляет
старый BitSet и размещает новый. В этой ситуации будут потеряны
установки старого BitSet.

    Пример

    PizzaTop.AllocateSelectSet(5);

    Разместить выбранный набор, способный управлять 5 элементами.

    Дополнительно см.

Process

            ChangeCommandHandler

    Объявление

    procedure ChangeCommandHandler(CommandHandler : pkGenlProc);

    Функция

    Изменить режим выбора: единственный или кратный.

    Описание

    OPPICK имеет две процедуры, которые можно передавать как
параметры в рассматриваемую процедуру: SingleChoice и
MultipleChoice. Данный метод инициализует внутренние поля
данных, которые указывают Process, какие процедуры необходимо
использовать при следующем его вызове.

    Пример

PizzaTop.ChangeCommandHandler(MultipleChoice);
PizzaTop.SetSelectMarker('<','>');

    Изменить PizzaTop на применение обработки команд с кратным
выбором MultipleChoice.

    Дополнительно см.

Init


     ChangeItemWidth

    Объявление

procedure ChangeItemWidth(ItemWidth : Byte);

    Функция

    Изменить ширину элемента.

    Описание

    Данная процедура вызывается при изменении формата списка
выбора. Объект DirList , используемый для выбора из директорий
файлов DOS, предлагает ряд всевозможных форматов - только имя
файла, имя файла плюс его размер; имя файла плюс размер плюс
дата и время создания; и т.д. Этот объект должен вызывать
ChangeItemWidth всякий раз при изменении формата.
    Вызов ChangeItemWidth обычно сопровождается вызовом
ChangeStringProc, а за этими вызовами следует вызов OptimizeSize
и Draw.

    Пример

PizzaTop.ChangeItemWidth(10);
PizzaTop.OptimizeSize;
PizzaTop.Draw;

    Изменить PizzaTop - задать ширину элемента равной 10
символам; окно будет сжать до нового размера списка.

    Дополнительно см.

ChangeStringProc             OptimizeSize


     ChangeNumItems

    Объявление

procedure ChangeNumItems(NumItems : Word);

    Функция

    Изменить число элементов, выводимых на экран дисплея.

    Описание

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

    Примеры

{$F+}
procedure PizzaTopping(Item : Word; Mode : pkMode;
                       var IType : pkItemType; var IString ; String;
                       PickPtr : PickListPtr);
  {-Sets item string and item options (if any)}
begin
      case Item of
        1 : IString := 'Pepperoni';
        2 : IString := 'Sausage';
        3 : IString := 'Mushrooms';
        4 : IString := 'Anchovies';
        5 : IString := 'Onions';
      end;
   end;
   {$F-}
 ...
PizzaTop.ChangeNumItems(3);

    Уменьшить число элементов в PizzaTop до 3. Элементы номер 4
и 5 больше не будут выводится на экран в этом списке выбора.

PizzaTop.ChangeNumItems(6);

    Некорректно! Наша процедура работает только с пятью
элементами. В шестой позиции будет выведено на экран
произвольное значение или "мусор". Допускаемтся увеличивать
размер списка только в случае, когда процедура обработки ошибок
может обрабатывать это увеличение.

    Дополнительно см.

OptimizeSize


         ChangeOrientation

    Объявление

procedure ChangeOrientation(Orientation : pkGenlProc);

    Функция

    Изменить ориентацию.

    Описание

    Допускаемые значения для Orientation включают: PickVertical,
PickHorizontal и PickSnaking. ChangeOrientation вызывает
процедуру, определяемую как параметр ChangeOrientation, а эта
процедура изменяет ряд внутренних указателей в процедуры для
обеспечения поведения , соответствующего новой ориентации.
Изображение будет скорректировано при следующем вызове Draw или
Process.

    Пример

PizzaTop.ChangeOrientation(PickHorizontal);

    Изменить ориентацию PizzaTop на PickHorizontal.

    Дополнительно см.

GetOrientation

    ChangeStringProc

    Объявление

    procedure ChangeStringProc(StringProc : pkStringProc);

    Функция

    Изменить процедуру обработки цепочек символов.

    Описание

    Эта процедура делает какие-либо действия только в случае,
когда не блокировано действие процедуры ItemString. По умолчанию
ItemString вызывает процедуру , определяемую пользователем с
именем StringProc. StringProc - это определяемая пользователем
процедура, которую необходимо компиллировать по модели FAR с
помощью директивы {$F+}. Это должна быть глобальная процедура,
соответствующая следующему определению прототипа:

{$F+}
procedure MyStringProc(Item : Word;
                      Mode : pkMode;
                      var IType : pkItemType;
                      var IString : String;
                      PickPtr : PickListPtr);

    Более подробную информацию Вы найдете во введении к этому
разделу.

    Пример

PizzaTop.ChangeStringProc(OtherToppings);

    Заменить процедуру PizzaTop с именем StringProc на процедуру
с именем OtherToppings.

    Дополнительно см.

CompleteItemString        ItemString

                ClearSelected

    Объявление

procedure ClearSelected;

    Функция

    Очистить выбранные элементы.

    Описание

    Эта процедура имеет значение только для списков выбора с
кратным выбором. Отмечает все невыбранные элементы. Экран не
корректируется пока не вызваны методы Draw или Process.
    Выбранный набор должен быть размещен до вызова
рассматриваемого метода. В противном случае метод ничего не
делает. Отметим, что при первом размещении выбранный набор
автоматически очищается.

    Пример

PizzaTop.ClearSelected;

    Предполагая, что мы обрабытвает кратные выборы, приведенное
обращение очищает все текущие выборы.

    Дополнительно см.

AllocateSelectSet          MarkAllSelected


           CompleteItemString

    Объявление

procedure CompleteItemString(Item : Word;
                            Mode : pkMode;
                            var IType : pkItemType;
                            var IString : String); virtual;

    Функция

    Передает,  маркирует и заполняет цепочки элемента.

    Описание

    OPPICK вызывает данный виртуальный метод для генерации
каждой цепочки элемента с тем, что получить изображение элемета
или выполнить для него сравнение при поиске. CompleteItemString
в свою очередь вызывает виртуальный метод ItemString, который
вызывает определяемую пользователем процедуру. Для списков
кратного выбора CompleteItemString соединяет в ряд левый и
правый маркеры ( определяемые с помощью SetSElectMarker) в
случае, если элемент выбран, а если элемент не выбран, то
заполняет его символами фона окна.
    CompleteItemString затем заполняет строку символами фона,
указанными в методе SetPadSize.
    Дальнейшее рассмотрение параметров, передаваемых
CompleteItemString приведено в обсуждении "Определяемая
пользователем процедура обработки цепочек символов" в начале
раздела OPPICK.

    Дополнительно см.

ItemString          SetSelectedMarker
SetPadSize

          DeselectItem

    Объявление

procedure DeselectItem(Item : Word); virtual;

    Функция

    Отменить выбор элемента.

    Описание

    Процедура полезна для списков с кратным выбором. Этот метод
очищает бит набора выбора для элемента. Изображение списка
выбора будет скорректировано при следующем его рисовании.
    Рассматриваемый метод является виртуальным, поэтому
производные объекты (например, DirList) могут игнорировать
попытки отменить выбор или выбрать некоторые элементы.

    Пример

repeat
  PizzaTop.Process;
  case PizzaTop.GetLastCommand of
    ccUser0 :
      for I := 1 to PizzaTop.GetNumItems do
        if PizzaTop.ItemIsSelectel(I) then
          PizzaTop.DeselectItem(I)
        else
          PizzaTop.SelectItem(I);
     {other exit commands}
  end;
until Finished;

    Как только нажата клавиша, соответствующая ccUser0, для всех
выбранных элементов отменяется выбор.

    Дополнительно см.

ClearSelectel       SelectedItem



      Done

    Объявление

destructor Done; virtual;

    Функция

    Удалить PickList.

    Описание

    В случае, если набор выборов был размещен для списка
кратного выбора, он удаляется. При добавлении заголовка
продолжения будет очищена память, отведенная под хранение
внутренней цепочки заголовка. После этого вызывается деструктор-
предок PickList - CommandWindow.Done.

    Пример

PizzaTop.Done;

    Удалить весь объем динамически распределяемой памяти,
используемой PizzaTop.

    Дополнительно см.

CommandWindow.Done

             GetDefaultChoice

    Объявление

function GetDefaultChoice : Word;

    Функция

    Возвратить номер выбора по умолчанию.

    Описание

    В случае, если действует опция pkSetDefault, функция
GetDefaultChoice возвращает номер элемента, являвшегося текущим
в начале наиболее частого вызова Process. В противному случае,
функция возвращает значение, определяемое последним вызовом
SetDefaultChoice или 1 - по умолчанию.
    Рассматриваемый метод полезен главным образом внутри
определяемой пользователем процедуры обработки цепочек , в
которой Вы можете выделить выбор по умолчанию, чтобы
пользователь мог без труда в нему вернуться. Кроме того, у Вас
может возникнуть желание использовать GetDefaultChoice в
сочетании с SetInitialChoice для восстановления текущего
элемента в предыдущее состояние по умолчанию при выходе
пользователя из Process по команде ccQuit.
    Отметим, что GetDefaultChoice и GetLastChoice часто
возвращают различные значения. GetLastChoice всегда возвращает
последний элемент, на котором была полоса выделения.

    Пример

procedure PizzaList.ItemString(Item : Word;
                              Mode : pkMode;
                              var IType : pkItemType;
                              var IString : String);
begin
      case Item of
        1 : IString := 'Pepperoni';
        2 : IString := 'Sausage';
        3 : IString := 'Mushrooms';
        4 : IString := 'Anchovies';
        5 : IString := 'Onions';
      end;
      if Item = GetDefaultChoice then
       IType := pkAlternate;
end;

    Элемент по умолчанию будет показан с альтернативным видео
атрибутом.

    Дополнительно см.

GetLastChoice            SetInitialChoice
SetDefaultChoice

     GetItemCols

    Объявление

function GetItemCols : Byte;

    Функция

    Возвратить число видимых столбцов элементов.

    Описание

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

    Пример

WriteLn('This window will hold', PizzaTop.GetItemCols, 'columns');

    Вывести на экран число столбцов элементовв списке выбора.

    Дополнительно см.

Init

       GetItemString

    Объявление

function GetItemString(Item : Word) : string;

    Функция

    Возвратить цепочку заданного элемента в формате поиска.

    Описание

    GetItemString вызывает виртуальный метод CompleteItemString
для получения имени заданного элемента Item. После выполнения
этого функция задает режим pkSearch, которая не допускает
добавления к цепочке символов маркеров выбора или символов
заполнения, выполняемого методом CompleteItemString по умолчанию.
    Правильно разработанная определяемая пользователем процедура
обработки цепочек не будет вставлять символы управления гибкой
записью в возвращаему цепочку при задании режиме pkSearch.

    Пример

WriteLn('The name of the first item is', PizzaTop.GetItemString(1)));

    Записать имя первого элемента выбора.

    Дополнительно см.

CompleteItemString      GetLastChoiceString


     GetLastChoice

    Объявление

function GetLastChoice : Word;

    Функция

    Возвратить номер элемента, выбранного в последний раз.

    Описание

    Метод всегда возвращает номер элемента, на котором наиболее
часто останавливается полоса выделения. Результат функции
является допустимым в любой момент времени при его вызове -
внутри определяемой пользователем процедуры обработки цепочек,
процедуры перемещений, функции поиска цепочки и после возврата
вызова Process.
    Отметим, что GetLastChoice возвращает наиболее часто
выделяемый элемент, даже если пользователь нажмет клавишу <Esc>
для выхода из Process. Поэтому важно проверить значение
GetLastCommand перед обработкой GetLastChoice.

    Пример

    См. пример программы в началае рассматриваемого раздела.

    Дополнительно см.

CommandWindow.GetLastCommand       GetDefaultChoice

              GetLastChoiceString

    Объявление

function GetLastChoiceString : string;

    Функция

    Возвратить последнюю выбранную цепочку  в формате поиска.

    Описание

    GetLastChoiceString вызывает GetItemString с параметром
GetLastChoice.

    Пример

PizzaTop.Process;
if PizzaTop.GetLastCommad = ccSelect then
  WriteLn('You chose item ', PizzaTop.GetLastChoice,
         ' - ', PizzaTop.GetLastChoiceString);

    Выводит на экран номер и цепочку символов для выбранного
элемента.

    Дополнительно см.

GetItemString

     GetNumItems

    Объявление

function GetNumItems : Word;

    Функция

    Вернуть число элементов выбора.

    Описание

    Число элементов задается при начальном вызове конструктора
PickList или при последующем вызове ChangeNumItems.

    Пример

 WriteLn('This pick list has ', PizzaTop.GetNumItems, 'items');

    Выводит на экран число элементов в списке выбора.

    Дополнительно см.

ChangeNumItems         Init

       GetOrientation

    Объявление

    function GetOrientation : Byte;

    Функция

    Возвратить код ориентации.

    Описание

    Ориентация PickList определяется при начальном вызове
конструктора или при последующем вызове ChangeOrientation.
GetOrientation возвращает одно из значений pkNoOrient,
pkVertical, pkHorizontal или pkSnaking.pkNoOrient используется
внутри и указывает, что задана недопустимая процедура
ориентации. Вы не получите этого значения, если действует
соответствующая обработка ошибок.

    Пример

case PizzaTop.GetOrientationh of
  pkVertical       : {do something};
  pkHorizontal     : {do something};
  pkSnaking        : {do something};
end;

    Выполняет некоторые действия с учетом текущей ориентации
списка выбора.

    Дополнительно см.

ChangeOrientation          Init

       GetSelectedCount

    Объявление

function GetSelectedCount : Word;

    Функция

    Возвратить  номер выбранного элемента.

    Описание

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

    Пример

PizzaTop.Process;
if PizzaTop.GetLastCommang = ccSelect then
  if PizzaTop.GetSekectedCount > 0 then begin
    WriteLn('You sekectel:');
    PizzaTop.InitSequence(SekectedItem);
    while PizzaTop.HaveSelected(SelecteItem) do begin
      WriteLn(PizzaTop.GetItemString(SelecteItem));
      PizzaTop.NextSelected(SelectedItem);
    end;
  end else
    WriteLn('Nosekections');

    После вызова Process проверяет выбор ряда элементов прежде,
чем выполнить действия со всеми такими элементами.

    Дополнительно см.

AllocateSelectSet          ClearSelected


     HaveSelected

    Объявление

function HaveSelected(Item : Word) : Boolean;

    Функция

    Возвратить True в случае, если есть выбранный элемент.

    Описание

    Этот метод используется в сочетании с методами InitSequence
и NextSelected для просмотра всех выбранных элементов в списке с
кратным выбором. HaveSelected возвращает True всякий раз, когда
Item меньше или равно числу элементов (GetNumItems), поэтому
сама по себе функция мало используется.

    Пример

var
  N : Word;
...
PizzaEop.InitSequence(N);
while PizzaTop.HaveSelected(N) do begin
  WriteLn('Selected item number ', N);
  PizzaTop.NextSelected(N);
end;

    Показывает правильную последовательность для отыскания
выбранных элементов из списка выбора.

    Дополнительно см.

InitSequence      NextSelected


     Init

    Объявление

constructor Init(X1, Y1, X2, Y2 : Byte;
                ItemWidth : Byte;
                NumhItems : Word;
                StringProc : pkStringProc;
                Orientation : pkGenlProc;
                CommandHandler : pkgenlProc);

    Функция

    Инициализация окна выбора.

    Описание

    Рассматриваемый конструктор инициализует PickList ,
используя опции по умолчанию (DefWindowOptions), набор цветов
окна по умолчанию (DefaultColorSet) и опции выбора по умолчанию
(DefPickOptions). Более подробную информацию Вы найдете в
InitDeluxe.

    Пример

if not PizzaTop.Init(35, 5, 45, 10,  {Initnal window coordinates}
                   20,               {Column width per item}
                   NumPizzaToppings, {Number of picklist items}
                   PizzaToping,      {User string procedure}
                   PickVertical,     {Orientation procedure}
                   SingleChoice)     {Command handler}
  then  begin
    WriteLn('Failed to Init PickList, Status =', InitStatus);
    Halt;
  end;

    Реализует PizzaTop, используя цвета и опции окна по
умолчанию. Список выбора будет иметь вертакальную ориентацию, в
качестве функции обработки цепочек использует PizzaTopping и
возвращает единственный выбор.

    Дополнительно см.

InitAbstract         InitDeluxe
InitCustom

      InitAbstract

    Объявление

constructor InitAbstract(X1, Y1, X2, Y2 : Byte;
                        var Colors : ColorSet;
                        Options : LonInt;
                        ItemWidth : Byte;
                        NumItems : Word;
                        Orientation : pkGenlProc;
                        CommandHandler : pkGenlProc);

    Функция

    Конструктор вызывается для выводта типов, блокирующих метод
ItemString.

    Описание

    Рассматриваемый конструктор работает подобно InitCustom за
исключением того, что не передается определяемая пользователем
процедура обработки цепочек. Вызывающая процедура должна
блокировать методы ItemString и/или CompleteItemString объекта
PickList, поэтому ItemString больше не генерирует вызова в
определяемую пользователем процедуру обработки цепочек. В
противном случае при первом вызове ItemString в процессе
прогонки программы генерируется ошибка (код ошибк 211).

    Пример

    См. обсуждение "Определяемая пользователем процедура
обработки цепочек" в начале рассматриваемого раздела, где
приведен полный пример использования конструктора InitAbstract.

    Дополнительно см.

InitDeluxe

       InitAbstractDeluxe

    Объявление

constructor InitAbstractDeluxe(X1, Y1, X2, Y2 : Byte;
                        var Colors : ColorSet;
                        Options : LonInt;
                        ItemWidth : Byte;
                        NumItems : Word;
                        Orientation : pkGenlProc;
                        CommandHandler : pkGenlProc;
                        PickOptions : Word);

    Функция

    Конструктор вызывается производными типами, которые блокируют
метод ItemString. Задаются заказные опции выбора.

    Описание

    Рассматриваемый конструктор работает подобно InitDeluxe за
исключением того, что в момент вызова могут быть определены
заказные опции выбора (опции отличные от DefPickOptions).

    Пример


if not PickList.InitAbstractDeluxe(X1, Y1, X2, Y2,
                                  DefaultColorSet,
                                  PickWindowOptions,
                                  11,
                                  NumPizzaToppings,
                                  PickVertical,
                                  SingleChoice,
                                  pkStick+pkMousePage+pkSetDefault)
then
   Fail;

    Конструктор производного типа вызывает конструктор его
предка с заказными опциями списка выбора
pkStick+pkMousePage+pkSetDefault.

    Дополнительно см.

InitDeluxe

       InitCustom

    Объявление

  constructor InitCustom(X1, Y1, X2, Y2 : Byte;
                        var Colors : ColorSet;
                        Options : LongInt;
                        ItemWidth : Byte;
                        NumItems : Word;
                        StringProc : pkStringProc;
                        Orientation : pkGenlProc;
                        CommandHandler : pkGenlProc);

    Функция

    Инициализация окна выбора с заказными опциями окна.

    Описание

    Рассматриваемый конструктор реализует PickList , используя
заданные опции окна Options, заданные цвета Colors и опции
выбора по умолчанию (DefPickOptions). Более подробную информацию
Вы найдете в InitDeluxe.

    Пример

PickWindowOptions := DefWindowOptions or wBordered;
if not PizzaTop.InitCustom(35, 5, 45, 10,  {Initial window coordinates}
                          DefaultColorSet, {ColorSet to use}
                          PickWindowOptions,{Window options}
                          20,               {Column width per item}
                          NumPizzaToppings, {Number of picklist items}
                          PizzaToping,      {Item string function}
                          PickVertical,     {Orientation procedure}
                          SingleChoice)     {Command handler}
then  begin
    WriteLn('Failed to Init PickList, Status =', InitStatus);
    Halt;
end;

    Реализует PickList с цветами окна по умолчанию, но использую
заказные опции окна для создания окна с рамкой.

    Дополнительно см.

RawWindow.InitCustom

       InitDeluxe

    Объявление

  constructor InitDeluxe(X1, Y1, X2, Y2 : Byte;
                        var Colors : ColorSet;
                        Options : LongInt;
                        ItemWidth : Byte;
                        NumItems : Word;
                        StringProc : pkStringProc;
                        Orientation : pkGenlProc;
                        CommandHandler : pkGenlProc;
                        PickOptions : Word);

    Функция

    Инициализация окна выбора с заказным окном и опциями выбора.

    Описание

    Это наиболее общий конструктор для окна выбора. Все
остальные конструкторы PickList посылают специальный вызовы к
нему.
    X1, Y1, X2, Y2 определяют координаты активного окна , внутри
которого будет выведен список выбора.
    InitDeluxe выдергивает определенные поля из заданного
ColorSet для использования при рисовании списка выбора. Помимо
полей, используемых в окне в общем случае, конструктор
InitDeluxe сохряняет внутри экземпляра PickList следующие поля:

TexeColor, TextMono             - pkNormal невыбранные элементы
SelItemColor, SelItemMono       - pkNormal выбранные элементы
AltItemColor, AltItemMono -       pkAlternate невыбранные элементы
AltSelItemColor, AltSelItemMono - pkAlternate выбранные элементы
ProItemColor, ProItemMono -       pkProtected элементы (нельзя выбирать)

    Отметим, что "выбранный" обозначает элемент , на котором в
текущий момент находится в текущий момент полоса выбора, а не
помеченный элемент в списке кратного выбора. Кроме того,
отметим, что по умолчанию элементы выводятся на экран одним
цветом - гибкая запись не действует.
    Options - это преобразованная в биты опция, такая как
wBordered, которая применима ко всем объектам производным
RawWindow. Более подробную информацию Вы найдете в разделе
"Константы RawWindowр. InitDeluxe включает флаг wUserContents ,
так как PickList имеет метод UpdateContents, который позволяет
воспроизводить содержимое окна при запросе.
    ItemWidth - число столбцов экрана, используемое каждым
элементом. Убедитесь, что Вы зарезервировали память для самой
длинной цепочки символов элемента, для символа заполнения,
определяемого SetPadSize и для маркеров кратного выбора,
задаваемых SetSelectMarker. InitDeluxe определяет число столбцов
для показа элементов в окне выбора, разделив ширину окна на
ItemWidth. При выводе на экран изображения какого-либо элемента
он обрезается или дополняется до ItemWidth.
    NumItems - это общее число элементов, управляемых PickList.
Определяемая пользователем процедура обработки цепочек должна
иметь возможность возврата имени элемента для каждого номера
элемента в диапазоне от 1 до NumItem.
    StringProc передает имя определяемой пользователем процедуры
обработки цепочек. Это процедура должна быть скомпилирована по
модели FAR. Она должна быть глобальной и иметь параметры,
соответствующие следующему прототипу:

procedure MyStringProc(Item : Word;
                       Mode : pkMode;
                       var IType : pkItemType;
                       var IString : String;
                       PickPtr : PickListPtr);

    Более подробную информацию Вы найдете в обсуждении
"Определяемая пользователем процедура обработки цепочек" в
начале раздела.
    Orientation определяет ориентацию списка. Данный параметр
может принимать одно из значений pkVertical, pkHorizontal или
pkSnaking. Более подробную информацию Вы найдете в "Ориентации
списка выбора" во введении к разделу.
    CommandHandler определяет список с единственным выбором
(SingleChoice) или с кратным выбором (MultipleChoice) . Более
подробную информацию Вы найдете в "Списки с кратным выбором".
Будьте внимательны и не переставьте местами параметры
Orientation и CommandHandler. Компилятор позволяет вам это
делать, но Вы получите ошибку в конструкторе при прогоне
программы (epFatal+ecBadPickOrient).
    PickOptions определяет опции, специфичные для списка выбора.
Более подробную информацию Вы найдете в разделе "Объявление
констант".
    Конструктор рассчитывает конфигурацию списка выбора - число
столбцов, элементы к каждой строке и т.д. - с учетом ширины
элемента, ширины окна, числа элементов и ориентации списка. В
случае, если действует опция pkMinHeight, конструктор InitDeluxe
уменьшит высоту окна, когда она превышает число строк с
элементами.
    Для PickList объявляется командный процессор с именем
PickCommands. Списку присваивается код устройства ucPick (с
целью идентификации его для программ обработки ошибок и помощи).
Курсор аппаратных средств задается с режимом по умолчанию -
ccHidden.
    InitDeluxe не размещает никакой динамически распределяемой
памяти, помимо затребованной его конструктором-предком -
CommandWindow.InitCustom. Особенно подчеркнем, что InitDeluxe не
размещает BitSet, требуемый для управления списками выбора с
кратным выбором. Названный BitSet не будет размещен, пока не
вызваны AllocateSelectSet, Process или UpdateContents.
    В случае отказа конструктора проверьте переменную
InitStatus, содержащую подробный код ошибки.

    Пример

var
  PickWindowOptions : LongInt;
  PickListOptions : Word;
...
PickWindowOptions := DefWindowOptions or wBordered;
PickListOptions := DefPiclOptions and not pkMinHeight;
if not PizzaTop.InitDeluxe(35, 5, 45, 10,   {Initial window coordinates}
                          DefaultColorSet,  {ColorSet to use}
                          PickWindowOptions,{Window options}
                          20,               {Column width per item}
                          NumPizzaToppings, {Number of picklist items}
                          PizzaTopping,     {Item string procedure}
                          PickVertical,     {Orientation procedure}
                          SingleChoice,     {Command handler}
                          PickListOptions)  {List options}
then  begin
    WriteLn('Failed to Init PickList, Status =', InitStatus);
    Halt;
end;

    Реализует PizzaTop с опциями списка, которые не разрешают
конструктору изменять размер окна. В нашем примере заданы 5
PizzaTopping, высота окна равна 11 (5..15), ниже списка будут
пустые строки.

    Дополнительно см.

ChangeCommandHandler               CommandWindow.Init
ChangeItemWidth                    RawWindow.Init
ChangeNumItems                     SetPadSize
ChangeOrientation                  SetPickFlex
ChangeStringProc                   SetSelectMarker

      InitSequence

    Объявление

procedure InitSequence(var Item : Word);

    Функция

    Подготовка к получению первого выбранного элемента.

    Описание

    Рассматриваемый метод используется в сочетании с методами
HaveSelected и NextSelected для просмотра всех выбранных
элементов в списке с кратным выбором. InitSequence инициализует
Item равным индексу первого выбранного элемента. В случае, если
нет выбранных элементов, процедура устанавливает Item на единицу
больше, чем число элементов в списке.

    Пример

var
  N : Word;
...
PizzaTop.InitSequence(N);
while PizzaTop.HaveSelected(N) do begin
  WriteLn('Selected item number ', N);
  PizzaTop.NextSelected(N);
end;

    Показывает правильную последовательность для отыскания
выбранных элементов из списка выбора. Полный пример программы
приведен во вступительной части "Списки с кратным выбором".

    Дополнительно см.

HaveSelected                      NextSelected

     IsProtected

    Объявление

function IsProtected(Item : Word) : Boolean;

    Функция

    Возвращает True в случае, если Item защищен от выбора.

    Описание

     IsProtected вызывает CompleteItemString в режиме pkGetType
(которая информирует процедуру обработки цепочек символов, что
требуется только этот тип элемента). В случае, если процедура
обработки цепочек возвращает тип pkProtected, функция
IsProtected возвращает True. Не допускается нахождение полосы
выбора из списка на защищенном элементе.
    Рассматриваемый метод используется главным образом
собственными методами PickList. Предположительно ваши прикладные
программы уже знают, какие элементы являются защищенными, так
как именно ваша процедура обработки цепочек символов задает, что
элемент является защищенным. Однако, в случае, если пользователь
прикладных программ может каким-либо образом защитить элемент,
Вам требуется вызвать этот метод самим.

    Дополнительно см.

NumSelectableItems

     ItemSelected

    Объявление

 function ItemSelected(Item : Word) : Boolean;

    Функция

    Возвращает True ,если элемент выбран.

    Описание

    Рассматриваемый метод применяется только для списков с
кратным выбором.

    Пример

repeat
  PizzaTop.Process;
  case PizzaTop.GetLastCommand of
    ccUser0 :
      for I := 1 to PizzaTop.GetNumItems do
        if PizzaTop.ItemIsSelected(I) then Pizzatop.DeselectItem(I)
        else PizzaTop.Selected(I);
   {... other exit commands...}
  end;
until Finished;

    Всякий раз при нажатии на клавишу, связанную с командой
ccUser0, для всех выбранных элементов выбор будет отмечен.

    Дополнительно см.

DeselectItem          SelectItem



      ItemSearch

    Объявление

function ItemSearch : Boolean; virtual;

    Функция

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

    Описание

    Метод Process для PickList вызывает данный виртуальный метод
для поиска по списку элемент на совпадение с буквенноцифровым
символом. ItemSearch в свою очередь вызывает функцию поиска,
заданную с помощью метода SetSearchMode.
    Более подробную информацию Вы найдете в обсуждении "Поиск
цепочки символов" в начале данного раздела.

    Дополнительно см.

SetSearchMode


     ItemString

    Объявление

procedure ItemString(Item : Word; Mode :pkMode; var IType : pkItemType;
                     var IString : String); virtual;

    Функция

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

    Описание

    Рассматриваемый виртуальный метод можно блокировать
производными типами для применения специального вида списка.
Использование в PickList процедуры ItemString просто вызывает
передачу вызова в другую определяемую пользователем процедуру
обработки цепочек.
    Более подробную информацию и законченные примеры Вы найдете
в начале раздела в обсуждении "Определяемая пользователем
процедура обработки цепочек".

    Дополнительно см.

ChangeStringProc      InitDeluxe
CompleteItemString

       Load

    Объявление

comstructor Load(var S : IdStream);

    Функция

    Загрузить упакованное окно из потока.

    Описание

    S - это соответствующим образом инициализированный объект
типа потока (например, файлы типа потока, открытые для чтения).
Отметим, что S может быть любым наследником типа IdStream,
включая DosIdStream, BufIdStream, MemIdStream.
    Load считывает следующую последовательность байтов из потока
S. Эти байты должны быть записаны в предыдущем обращении к
PickList.Store. Load вначале вызывает CommandWindow.Load для
считывания ниже лежащего CommandWindow. Затем она считывает
данные специфичные для PickList.
    Процедура регистрации потока для CommandWindow имеет имя
CommandWindow.Stream.
    Кроме того, имеется ряд указателей в процедуры, которые
должны быть зарегистрированы независимо. Как это сделать
показано в приведенном ниже примере программы. Более подробную
информацию Вы найдете в Store.

    Пример

    {... same ae introductory example...}
var
  S : BufIdStream;
begin
  {Load PizzaTop from a stream}
  S.Init('PIZZA.STM', SOpen, 1024);
  S.RegisterHier(PickListStream);
  S.RegisterPointer(ptPickVertical,@PickVertical);
  S.RegisterPointer(ptPickSingleChoice, @SingleChoic
  S.RegisterPointer(ptPickCharSearch, @PickCharSearc
  S.RegisterPointer(1000, @PizzaTopping);
  S.Get(PizzaTop);
  S.Done;

  {Pick an item}
  PizzaTop.Process;
  PizzaTop.Erase;
  if PizzaTop.GetLastCommand = ccSelect then
    WriteLn('You chose item ', PizzaTop.GetLastChoice,
           ' - ', PizzaTop.GetLastChoiceString)
  else
    WriteLn('No choice was made');
  PizzaTop.Done;
end.

    Реализует PizzaTop из потока , созданного в примере Store.
Более подробную информацию о регистрации типовВы найдете в Store.
    Правила обработки ошибок при использовании потоков приведены
в BufIdStream (в OPROOT).

    Дополнительно см.

CommandWindow.Load         Store


      MarkAllSelected

    Объявление

procedure MarkAllSelected;

    Функция

    Отметить все выбранные элементы.

    Описание

    Применяется только для списков с кратным выбором. Будьте
внимательны и гарантируйте, что BitSet выбора размещен до вызова
MarkAllSelected. Более подробную информацию Вы найдете в
AllocateSelectSet.

    Пример

PizzaTop.AllocateSelectSet(5);
PizzaTop.SetSelectMarker('<','>');
PizzaTop.MarkAllSelected;
PizzaTop.Process;

    PizzaTop запускается со всех выбранных элементов.

    Дополнительно см.

AllocateSelectSet          SelectItem
ClearSelected


      NextSelected

    Объявление

procedure NextSelected(var Item : Word);

    Функция

    Установить Item на следующий выбранный элемент ниже
начального значения.

    Описание

    Рассматриваемый метод используется в сочетании с методами
InitSequence и HaveSelected для просмотра всех выбранных
элементов в списке с кратным выбором. NextSelected просматривает
набор выборов , начиная с элемента ниже Item, для нахождения
следующего выбранного элемента. В случае, если нет другого
выбранного элемента, процедура установит Item на единицу больше,
чем число элементов в списке.

    Пример

var
  N : Word;
...
PizzaTop.InitSequence(N);
while PizzaTop.HaveSelected(N) do begin
  WriteLn('Selected item number ', N);
  PizzaTop.NextSelected(N);
end;

    Показывает правильноую последовательность для отыскания
выбранных элементов из списка выбора.
    Законченный пример программы приведен в разделе "Списки с
кратным выбором" в начале рассматриваемого раздела.

    Дополнительно см.

HaveSelected       InitSequence


      NumSelectableItems

    Объявление

function NumSelectableItems : Word;

    Функция

    Возвратить число элементов, не являющихся защищенными.

    Описание

    Рассматриваемая функция вызывает IsProtected для каждого
элемента в списке и подсчитывает число возвращаемых значений
False. Для списков без защищенных элементов NumSelectableItems
будет равна GetNumItems.
    Для большинства программ заранее известно сколько элементов
защищено и сколько элементов можно выбирать. Однако, в ряде
прикладных программ пользователь или какой-либо другой внешний
фактор могут иметь возможность контролировать защищенные
элементы. Если это так, важно убедиться, что NumSelectableItems
возвращает ненулевое значение прежде, чем вызвать метод Process
для PickList.
    Более подробную информацию Вы найдете во введении в
обсуждении "Защищенные элементы".

    Пример

if PizzaTop.NumSelectableItems > 0 then begin
  PizzaTop.Process;
...
end else
  WriteLn('All items are protected');

    Дополнительно см.

IsProtected        Process

      OptimizeSize

    Объявление

{$IFDEF UseAdjustableWindows}
procedure OptimizeSize;

    Функция

    Изменить размер окна в соответствии со списком элементов.

    Описание

    OptimizeSize регулирует ширину и высоту окна выбора с тем,
чтобы наилучшим образом оно "подходило" к списку. Процедура
учитывает текущее число элементов, ширину элементов,
первоначально запрошенный размер окна и пределы регулирования
окна. В процедуре используется эвристический алгоритм
определения нового размера. Отметим, что верхний левый угол окна
всегда остается фиксированным; изменяются только высота и ширина
окна.
    Целесообразно вызывать эту процедуру после изменения числа
элементов в списке или после изменения ширины списка.
    Вначале ширина увеличивается так, чтобы помещалось полное
число столбцов элементов, насколько это возможно, без
превышения: а) начальной ширины, заданной при конструировании
PickList; б) предела активного размера окна; в) максимальной
координаты по x рамки или г)предела максимального размера рамки.
Если возможно, то ширина устанавливается в точности равной
значению, соответствующему  целому числу столбцов.
    После этого регулируется высота в соответствии с числом
строк с элементами, по возможности плотнее. И в этом случае,
регулирование ограничено активными пределами размеров окна,
пределами координат рамки и пределами размеров рамки.
    При оптимизации тени окна учитываются только в случае, когда
установлен флаг pkOptFullExtent. При действии этой опции Вы
можете запретить OptimizeSize выталкивать тени наружу за
ограничивающий прямоугольник рамки.
    И наконец, OptimizeSize вызывает метод
StackWindow.ResizeWindow для регулировки окна. В случае, если
окно является текущим, изменения будут показаны сразу же. В
случае, если окно не является активным, изменения будут показаны
при следующем рисовании окна. Помните, что для виртуального
экрана могут потребоваться временные буферы динамически
распределяемой памяти и что при изменении размеров окна может
произойти фрагментация динамически распределяемой памяти.
    OPPICK не изменяет текущее число элементов в ходе процесса
оптимизации.
    Окно должно иметь флаг возможностир изменения размеров
(wResizeable) и не может распахиваться. В случае, если это
необходимое условие не выполнено OptimizeSize сразу же
прекращает работу. (Процедура не генерирует ошибку.) Окно должно
быть либо неактивным, либо, если оно активное - текущим. В
противном случае ResizeWindow генерирует ошибку.

    Пример

PizzaTop.InitCustom(35, 5, 45, 10,
                   DefaultColorSet,
                   PickWindowOptions or wBordered,
                   11,
                   NumPizzaToppings,
                   PizzaToping,
                   PickVertical,
                   SingleChoice);
...
ChangeNumItems(10);
OptimizeSize;
Process;
...

    После увеличения числа элементов с NumPizzaTopping(5) до 10
мы вызвали OptimizeSize. Вызванная процедура увеличивает высоту
окна с тем, чтобы сделать все элементы видимыми. В случае, если
мы первоначально сделали окно шире, чем требуется (изменив
параметр X2 , например, с 45 на 50), процедура OptimizeSize
уменьшит эту координату. В итоге окно будет точно
соответствовать списку элементов.

    Дополнительно см.

ChangeItemWidth               StackWindow.ResizeWindow
ChangeNumItems


     pkOptionsAreOn

    Объявление

function pkOptionsAreOn(OptionFlags : Word) : Boolean;

    Функция

    Возвращает True , если все заданные включены.

    Описание

    Данная функция тестирует опции списка выбора, которые
описаны в объявлениях констант в начале рассматриваемого раздела.

    Пример

if PizzaTop.pkOptionsAreaOn(pkUseItemForTopic) then
  HelpWindow.SetTopic(HelpIndex+100)
else
  Exit;

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

     pkOptionsOff

    Объявление

procedure pkOptionsOff (OptionFlags : Word);

    Функция

    Дезактивация кратных опций.

    Описание

    Рассматриваемый метод дезактивирует заданные опции, исключая
опции, отмеченные как BadPickOptions (см. выше раздел
"Константы").

    Пример

    PizzaTop.pkOptionsOff(pkMinHeight+pkSetDefault);

    Отключаем опции минимизации высоты и автоматического
сохранения для элемента по умолчанию.


    pkOptionsOn

    Объявление

procedure pkOptionsOn(OptionFlags : Word);

    Функция

    Активизировать кратные опции.

    Описание

    Данный метод активизирует кратные опции, исключая опции,
отмеченные как BadPickOptions (см. выше раздел "Константы").

    Пример

PizzaTop.pkOptionsOn(pkMinHeight+pkSetDefault);

    Подключаем опции минимизации высоты и автоматического
сохранения для элемента по умолчанию.



    PreMove

    Объявление

procedure PreMove; virtual;

    Функция

    Вызывается непосредственно перед получением каждой команды с
клавиатуры.

    Описание

    Данный виртуальный метод может блокироваться производными
типами для выполнения некоторых действий перед каждой командой.
Использование PickList процедуры PreMove просто вызывает
передачу вызова в определяемую пользователем процедуру обработки
цепочек. Вы можете объясить конкретную процедуру, используя
метод SetMoveProc. Более подробную информацию и законченный
пример Вы найдете в начале раздела в обсуждении "Ловушка
перемещения пользователя".

    Дополнительно см.

SetMoveProc

    Process

    Объявление

procedure Process; virtual;

    Функция

    Обработка команд списка выбора, осуществляющие выбор.

    Описание

    Метод Process для PickList следует общей модели, описанной
выше для CommandWindow.Process со следующими дополнениями и
исключениями: он обрабатывает команты, описанные в разделе
"Команды списка выбора" в начале данного раздела.
    В случае, если нет выбранных элементов (GetNumItems
возвращает ноль) Process очищает окно выбора и прекращает работу
с предупреждением ecWarning+ecNoPickItems.
    В случае, если список предназначен для обработки кратных
выборов, а BitSet селекции еще не размещен, Process размещает
набор достаточно большой для сохранения в нем текущего числа
выбранных элементов. Если не хватает динамически распределяемой
памяти , Process прекращает работу и генерирует ошибку
epFatak+ecInsufficientMemory. Process делает перерасчет
конфигурации списка ( числа столбцов, числа элементов в каждом
столбце и т.д.) в случае изменения размеров окна или если
изменен ряд других параметров списка после того, как список был
инициализован.
    В случае, если действует опция pkSetDefault , Process
сохраняет текущий выбранный элемент в поле данных экземпляра, из
которого он может его получить с помощью метода
GetDefaultChoice.
    Является ошибкой программирования вызывать Process , когда
все элементы списка являются защищенными, но Process все же в
это случае реагирует на команды выхода.
    Process вызывает, по крайней мере одну, а возможно -
несколько определяемых пользователем процедур обработки цепочек.
Процедура обработки цепочек символов, процедура Premove и
функция поиска по цепочке символов являются специфическими для
PickList. Процедура обработки ошибок берется из CommandWindow, а
процедура фоновой обработки команд с клавиатуры и контекстуально-
зависимой помощи - из CommandProcessor.

    Пример

    Полный пример приведен в начале рассматриваемого раздела.

    Дополнительно см.

CommandWindow.Process       GetLastChoice


      SelectItem

    Объявление

procedure SelectItem(Item : Word); virtual;

    Функция

    Выбрать элемент.

    Описание

    Функция полезна только для списков с кратным выбором.
Рассматриваемый метод позволяет выбрать заданный элемент.
Изображение списка выбора будет скорректировано при следующем
его рисовании.
    Данный метод является виртуальным, поэтому производные
объекты (например, DirList) могут игнорировать попытки выбрать
определенные элементы.

    Пример

repeat
  PizzaTop.Process;
  case PizzaTop.GetLastCommand of
    ccUser0 :
      for I := 1 to PizzaTop.GetNumItems do
       if PizzaTop.ItemIsSelected(I) then
         PizzaTop.DeselectedItem(I)
       else
         PizzaTop.SelectItem(I);
     {other exit commands}
   end;
until Finished;

    Как только нажата клавиша, связанная с командой ccUser0, для
всех выбранных элементов выбор будет отменен.

    Дополнительно см.

DeselectItem        MarkAllSelected


    SetChoice

    Объявление

procedure  SetChoice(Choice, FirstChoice : Word);

    Функция

    Установить первоначальный выбор с помощью управления
прокруткой.

    Описание

    Как только определена конфигурация конкретного списка,
PickList использует два параметра для решения, как нарисовать
окно выбора. Один из названных параметро - Choice - индекс
элемента, выделяемого как текущий элемент. Другой параметр -
FirstChoice - задает индекс элемент, появляющегося в левом
верхнем угле окна. При передвижении пользователя по окну с
помощью клавиш управления курсором Choice изменяется, а
FirstChoice остается неподвижным пока список будет
прокручиваться.
    При инициализации PickList оба параметра Choice и
FirstChoice устанавливаются равными 1. SetChoice предлагает вам
способ установки первоначально выбранного элемента и
одновременно способ контроля за прокруткой окна.
    В случае, если Choice и FirstChoice разделены большим числом
элементов, чем может поместиться в одно окно, PickList
отрегулирует значение FirstChoice так, чтобы Choice мог
появиться внутри окна.
    В случае, если Choice равен нулю или больше числа элементов
в списке, или елси элемент, на который ссылается Choice,
является защищенным, SetChoice сразу же прекращает работу.

    Пример

PizzaTop.SetChoice(4,3);
PizzaTop.Process;

    Установить элемент 4 в качестве начального выбора и выбрать
элемент 3 в качестве первого видимого элемента в окне.

    Дополнительно см.

SetInitialChoice

     SetDefaultChoice

    Объявление

procedure SetDefaultChoice(Choice : Word);

    Функция

    Установить номер выбранного элемента по умолчанию.

    Описание

    Рассматриваемый метод просто записывает заданный номер
элемента Choice во внутреннюю переменную экземпляра, на которую
может ссылаться метод GetDefaultChoice. Это полезно в случае,
когда процедура обработки цепочек символов списка должна
выделять конкретный элемент в качестве предпочтительного выбора
или выбора по умолчанию.
    В случае, если действует опция pkSetDefault, метод Process
будет каждый раз перезаписывать ту же внутреннюю переменную.
    Не путайте этот метод с методом SetChoice или
SetInitialChoice, которые фактически задают текущий элемент.

    Пример

PizzaTop.pkOptionsOff(pkSetDefault);
PizzaTop.SetDefaultChoice(5);

    Убедитесь, что Process будет правильно обеспечивать выбор по
умолчанию, а затем установить выбор по умолчанию для элемента
номер 5. В случае, когда процедура обработки цепочек
PizzaTopping, заканчивается следующей строкой:

if PiclPtr^.GetDefaultChoice = Item then
  IType := pkAlternate;

то метод Process нарисует пятый элемент с альтернативным
видеоатрибутом.

    Дополнительно см.

         GetDefaultChoice


       SetInitialChoice

    Объявление

procedure SetInitialChoice(Choice : Word);

    Функция

    Установить начальный выбор по возможности без прокрутки.

    Описание

    Работает подобно SetChoice за исключением того, что
рассматриваемый метод не изменяет значнеия FirstChoice. Когда
это возможно новый Choice будет выделен без прокрутки окна
выбора. Новый Choice станет видимым при следующем вызове методов
Draw или Process.

    Пример

PizzaTop.SetInitialChoice(4);
PizzaTop.Process;

    Установить начальный выбор непосредственно перед вызовом
Process. Когда список выбора нарисован, четвертый элемент выбора
будет уже выбранным.

    Дополнительно см.

SetChoice


       SetMoveProc

    Объявление

procedure SetMoveProc(MP : pkGenlProc);

    Функция

    Установить процедуру перемещения пользователя.

    Описание

    Записывает адрес указанной процедуры во внутреннее поле
данных. Процедура перемещения будет использована при следующем
вызове Process.
    Отметим6 что OPPICK взаимодействует с правильно объявленной
процедурой NoMoveAction, которую Вы можете передать в
SetMoveProc с тем, чтобы дезактивировать ранее активную
процедуру передвижения.
    Более подробную информацию Вы найдете в обсуждении "Ловушка
перемещения пользователя" во введении к данной части.

    Пример

PizzaTop.SetMoveProc(Suggestions);

    Записывает адрес процедуры Suggestions, на которую будет
ссылаться метод Process.

    Дополнительно см.

PreMove


            SetPadSize

    Объявление

procedure SetPadSize(LeftPad, RightPad : Byte);

    Функция

    Установить число символов для заполнения элементов выбора.

    Описание

    После того, как цепочка символов элемента возвращена
определяемой пользователем процедурой обработки цепочек , метод
CompleteItemString вначале добавляет маркеры выбора к обоим
концам цепочки (только для списков с кратным выбором). Затем он
добавляет символы фона окна с каждой сторны: LeftPad символов -
с левой стороны и RightPad символов - с правой стороны.
    Для вновь инициализованного PickList параметры LeftPad и
RightPad равны нулю.
    Длина рассматриваемых символов заполнения должна быть учтена
в общей ширине элемента, передаваемой в конструкторы PickList и
в метод ChangeItemWidth.

    Пример

PizzaTop.SetPadSize(5, 5);

    Добавить по пять пробелов слева и справа от цепочки символов
элемента.

    Дополнительно см.

ChangeItemWidth           SetSelectMarker
RawWindow.SetBackChar

            SetPickAttr

    Объявление

    procedure SetPickAttr(ItemType : pkItemType; Selected : Boolean;
                      var Color, Mono : Byte);

    Функция

    Установить одну группу цветов - фактически отменить гибкую
запись.

    Описание

    ItemType , определяющий категорию элемента, которому задают
рассматриваемые атрибуты, имеет одно из значений pkNormal,
pkAlternate или pkProtected. В случае, если Selected равно True,
атрибуты будут использоваться, когда полоса выбора находится на
элементе, в противном случае атрибуты используются, если элемент
не является текущим. Отметим, что сочетание ItemType =
pkProtected и Selected = True невозможно. Color и Mono - это
видео атрибуты для использования в цветовом и монохроматическом
видеорежимах, соответственно.
    Для поддержки гибкой записи различные сочетания ItemType,
Selected и Color/Mono могут содержать вплоть до четырех
видеоатрибутов. SetPickAttr инициализует каждый из четырех
байтов равными одному значению, в результате для
рассматриваемого типа элемента гибкая запись фактически
отменяется. Однако, отметим, что SetPickAttr не восстанавливает
внутренний флаг, который используется PickList для решения,
какой из методов записи на экран выбрать: FastWrite или
FlexWrite.

    Пример

PizzaTop.SetPickAttr(pkNormal, True, $02, $70);
PizzaTop.SetPickAttr(pkNormal, False, $03, $07);

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

    Дополнительно см.

SetPickFlex



           SetPickFlex

    Объявление

procedure SetPickFlex(ItemType : pkItenType;
                     Selected : Boolean;
                     var  Color, Mono : FlexAttrs);

    Функция

    Задать одну группу цветов для гибкой записи.

    Описание

    SetPickFlex работает подобно процедуре SetPickAttr за
исключением того, что рассматриваемая процедура передает все
четыре уникальных байта, заданных массивом FlexAttrs , во
внутреннюю память PickList. Кроме того, она устанавливает
внутренний флаг, который заставляет PickList использовать
FlexWrite вместо FastWrite при записи на экран. Когда этот флаг
установлен, символы <CtrlA>, <CtrlB>, <CtrlC> интерпретируются
как команды активации гибких атрибутов и не могут быть записаны
буквально.

    Пример

uses
   OpCrt, OpRoot, OpCmd, OpFrame, OpWindow, OpPick;
const
  NumPizzaToppings = 5;
  SetColorFlex : FlexAttrs = ($1E, $1F, $07, $07);
  SetMonoFlex : FlexAttrs  = ($07, $70, $07, $07);
  UnsColorFlex : FlexAttrs = ($01, $03, $07, $07);
  UnsMonoFlex : FlexAttrs  = ($70, $07, $07, $07);
var
  PizzaTop : PickList;

{$F+}
procedure PizzaTopping(Item : Word; Mode : pkMode;
                       var IType : pkItemType;
                       var IString : String;
                       PickPtr : PickListPtr);
  {-Set item string and item options (if any)}
begin
  case Item of
    1 : IString := ' '^A'P'^A'epperoni';
    2 : IString := ' '^A'S'^A'ausage  ';
    3 : IString := ' '^A'M'^A'ushrooms';
    4 : IString := ' '^A'A'^A'nchovies';
    5 : IString := ' '^A'O'^A'nions   ';
  end;
end;

begin
PizzaTop.InitCustom(20, 5, 60, 10,
                   DefaultColorSet,
                   PickWindowOptions or wBordered,
                   15,
                   NumPizzaToppings,
                   PizzaToping,
                   PickVertical,
                   SingleChoice);
PizzaTop.SetPickFlex(pkNormal, True, SelColorFlex, SelMonoFles);
PizzaTop.SetPickFlex(pkNormal, False, UnsColorFlex, UnsMonoFles);
PizzaTop.Process;
PizzaTop.Done;
end.

    Здесь приведен пример законченной программы, показывающей
как гибкая запись повзоляет улучшить визуальное восприятие
списка выбора. Для цветных мониторов мы используем голубой на
темном для невыбранных элементов, но первая буква показана
зеленовато-голубой . Выбранные элементы изображаются желтыми на
голубом, а первая их буква - белая на голубом. Отметим6 что мы
используем символв <CtrlA> в цепочках символов элементов для
активизации первого специального атрибута гибкой записи.

    Дополнительно см.

FlexWrite(OPCRT)        SetPickAttr

      SetRowLimits

    Объявление

procedure SetRowLimits(MinRows, MaxRows : Word);

    Функция

    Установить значения для минимальной и максимальной строки.

    Описание

    Рассматриваемый метод целесообразно пременять только для
списков с несколькими столбцами. MinRows определяет минимальное
число элементов в каждом столбце,а MaxRows - максимальное число.
Эти значения не влияют на размер окна выбора; они лишь
контролируюют конфигурацию списка внутри окна.
    Более подробную информацию и пример Вы найдете в обсуждении
"Изменение размеров окна для списков выбора".

    SetSearchMode

    Объявление

procedure SetSearchMode(SF : pkSearchFunc);

    Функция

    Установить новый режим поиска.

    Описание

    Адрес функции SF храниться во внутреннем поле данных. При
следующем вызове метода Process и вводе буквенно-цифрового
символа, Process посылает вызов в указанную подпрограмму для
поиска совпадающего с символом элемента. При выполнении поиска
OPPICK взаимодействует с различными подпрограммами. В случае,
если Вы вызвали SetSearchMode, Вы можете задать: PickNoSearch,
PickStringSearch, PickAltStringSearch, PickCharSearch,
PickCharExit или PickAnyCharExit. Вновь инициализованный
PickList использует функцию PickNoSearch, которая не выполняет
никакого поиска.
    Более подробную информацию Вы найдете в обсуждении "Поиск
цепочки символов" во введении.

    Пример

PizzaTop.SetSearchMode(PickCharExit);

    Установить для PizzaTop выбор элемента и прекращении работы
в случае, если нажата клавиша, совпадающая с первой буквой
элемента.


    SetSearchStart

    Объявление

procedure SetSearchStart(SStart : Byte);

    Функция

    Установить начальное ответвление для поиска цепочки символов.

    Описание

    В случае, если действует буквенно-цифровой поиск цепочки
символов, двигатель поиска не обязательно начинает с просмотра
первого символа каждой цепочки символов элементов. Это он делает
по умолчанию, но Вы можете вызвать SetSearchStart для выполнения
поиска символа из другого места в списке. Данный способ полезен,
например, когда все цепочки символов начинаются с одного
префикса.
    Более подробную информацию Вы найдете в обсуждении "Поиск
цепочки символов" во введении.

    Пример

PizzaTop.SetSearchStart(2);

    Задаем для PizzaTop начало поиска со второго символа в
каждом предмете.


          SetSelectMarker

    Объявление

procedure SetSelectMarker(Left, Right : String);

    Функция

    Определить цепочку символов для отметки выбранных элементов.

    Описание

    Метод пригоден только для способов с кратным выбором.
Заданные цепочки символов Left и Right подсоединяются к цепочке
символов каждого выбранного элемента, возвращаемой определяемой
пользователем процедуры обработки цепочек.
    Для вновь инициализованного PickList параметры Left и Right -
пустые цепочки символов. Следовательно, Вы не можете обнаружить
выбранные элементы в списке с кратным выбором , если Вы не
вызовите метод SetSelectMarker (или же выполните некоторые шаги
для вывода на дисплей выбранных элементов с альтернативным
видеоатрибутом).
    Длина рассматриваемых символов заполнения должна быть учтена
в общей ширине элемента, передаваемой в конструкторы PickList и
в метод ChangeItemWidth.

    Пример

PizzaTop.SetSelectMarker('<', '>');

    При использовании программы обработки команд MultipleChoice
выбирает элементы, заключенные в угловые скобки <>.

    Дополнительно см.

CompleteItemString

         Store

    Объявление

procedure Store(var S : IdStream);

    Функция

    Записать список в поток.

    Описание

    S - это соответствующим образом инициализированный объект
типа потока (например, файлы типа потока, открытые для чтения).
Отметим, что S может быть любым наследником типа IdStream,
включая DosIdStream, BufIdStream, MemIdStream (Хотя, обычно вы не
будете записывать в MemIdStream).
    Store записывает образ PickList в поток S. Процедура
начинает работу с вызова CommandWindow.Store, затем записывает
данные спицифичные для PickList.
    Для проверки и обработки ошибок, которые могут возникнуть в
ходе выполнения Store, вызовите функцию GetStatus для потока.
    Процедура регистрации потока для PickList имеет имя
PickList.Stream. Кроме того, имеется ряд указателей в процедуры,
которые должны быть зарегистрированы независимо. В приведенном
ниже примере программы показано, как это надо делать. Вызовы
процедур регистрации предполагают небольшое усилие со стороны
пользователя, но , в свою очередь, мощная программа
подсоединения Turbo позволяет не подсоединять части кода OPPICK-
альтернативные ориентации, процедура буквенно-цифрового поиска и
т.д. - которые ваша программа фактически не использует. В
случае, если Вы зарегистрируете все эти процедуры для Вашего
применения, программа подсоединения всех их получит и
подсоединит к Вашей прикладной программе.
    Должна быть зарегистрирована процедура ориентации списка
(PickVertical, PickHorizontal или PickSnaking). Если Вы этого не
сделаете , то при загрузке потока будет выдана ошибка
epFatal+ecBadPickOrient.
    Кроме того, должна быть зарегистрирована программа обработки
команд списка (SingleChoice или MultipleChoice). Если Вы этого не
сделаете , то при загрузке потока будет выдана ошибка
epFatal+ecBadPickHandler.
    В случае, если для списка используется определяемая
пользователем процедура обработки цепочек ( которая должна
блокировать виртуальный метод ItemString),названную процедуру
также необходимо зарегистрировать. В противном сдлучае при
использовании списка вы получите ошибку выполнения 211 (попытка
выполнить абстрактную процедуру).
    Если для списка задана определяемая пользователем процедура
перемещения, ее необходимо зарегистрировать , иначе процедура
перемещения не будет активной при перезагрузке списка.
    В случае, когда действует буквенно-цифровой поиск, функция
поиска (PickStringSearch, PickAltStringSearch, PickCharSearch,
PickCharExit или PickAnyCharExit) должны быть зарегистрированы.
В противном случае при загрузке потока поиск не будет
действовать.
    При использовании в списке выбора PickList какого-либо
командного процессора, а не CommandProcessor по умолчанию
(PickCommands), Вам необходимо зарегистрировать этот объект.
Пример приведен в CommandWindow.Store.

    Пример

uses
  OpCrt, OpRoot, OpCmd, OpFrame, OpWindow, OpPick;
const NumPizzaToppings = 5;
var PizzaTop : PickList;
    S : BufIdStream;

{$F+}
procedure PizzaTopping(Item : Word; Mode : pkMode;
                       var IType : pkItemType;
                       var IString : String;
                       PickPtr : PickListPtr);
  {-Set item string and item options (if any)}
begin
  case Item of
    1 : IString := ' Pepperoni';
    2 : IString := ' Sausage  ';
    3 : IString := ' Mushrooms';
    4 : IString := ' Anchovies';
    5 : IString := ' Onions   ';
    end;
  end;
{$F-}
begin
PizzaTop.InitCustom(35, 5, 45, 10,
                   DefaultColorSet,
                   DefWindowOptions or wBordered,
                   20,
                   NumPizzaToppings,
                   PizzaToping,
                   PickVertical,
                   SingleChoice);
PizzaTop.SetSearchMode(PickCharSearch);
PizzaTop.wFrame.AddShadow(shBR, shOverWrite);
PizzaTop.wFrame.AddHeader(' PICK ', heTC);

   {Store PizzaTop to a stream}
  S.Init('PIZZA.STM', SCreate, 1024);
  S.RegisterHier(PickListStream);
  S.RegisterPointer(ptPickVertical,@PickVertical);
  S.RegisterPointer(ptPickSingleChoice, @SingleChoice);
  S.RegisterPointer(ptPickCharSearch, @PickCharSearch);
  S.RegisterPointer(1000, @PizzaTopping);
  S.Put(PizzaTop);
  S.Done;
  PizzaTop.Done;
end.

    Реализуем PizzaTop, добавляем ряд характеристик, затем
записываем PizzaTop в поток. В примере регистрируеются адреса
процедуры ориентации списка (PickVertical), процедуры обработки
команд (SingleChoice), функции поиска (PickCharSearc) и
процедуры обработки цепочек символов (PizzaTopping). Отметим,
что мы используем оператор '@' для возврата указателя в каждую
поименованную процедуру или функцию. Каждая стандартная
процедура поддержки, предлагаемая OPPICK, имеет предопределенный
код регистрации. Этот код необходимо использовать , чтобы
избежать конфликтов.

Процедура или функция  Код регистрации указателя   Категория

PickNoSearch             ptPickNoSearch            поиск цепочки
PiclStringSearch         ptPiclStringSearch        "
PickAltStringSearch      ptPickAltStringSearch     "
PickCharSearch           ptPickCharSearch          "
"PickCharExit            ptPickCharExit            "
PickAnyCharExit          ptPickAnyCharExit         "
PickVertical             ptPickVertical            ориентация списка
PickHorizontal           ptPickHorizontal          "
PickSnaking              ptPickSnaking             "
SingleChoice             ptSingleChoice            обработка команд
MultipleChoice           ptMultipleChoice          "
NoMoveAction             ptNoMoveAction            процедура перемещения
NoPickString             ptNoPickString            процедура обработки
                                                   цепочек

    Мы зарегистрировали процедуру обработки цепочек символов
(PizzaTopping) с кодом 1000. Можно использовать любое значение
равное 1000 или более, являющееся уникальным для
рассматриваемого потока. Программа , загружающая данный поток,
должна использовать тот же код.
    Пример программы загрузки потока приведен в Load.
    Правила обработки ошибок при использовании потока приведены
в BufIdStream  (OPROOT).

    Дополнительно см.

CommandWindow.Store              Load

     UpdateContents

    Объявление

procedure UpdateContents; virtual;

    Функция

    Перерисовать законченное окно выбора.

    Описание

    Вам не требуется прямого вызова UpdateContents . Вместо
этого вызовите Draw.
    UpdateContents выполняет следующие операции:
    Размещает BitSet выбора для списков выбора с кратным
выбором, если он еще не был размещен.
    В случае, если список выбора не содержит элементов ,
UpdateContents очищает окно и прекращаетработу.
    Процедура UpdateContents выполняет перерасчет конфигурации
списка при изменении после последнего вызова числа элементов,
ширины элементов , ориентации списка и т.д. Для экономии времени
UpdateContents пропускает этот шаг, когда установлено внутренний
флаг , чтобы показать, что метод Process является активным.
(Конфигурацию списка нельзя изменять , если метод Process
является активным.)
    UpdateContents полностью перерисовывает элементы, которые в
текущий момент времени видны в окне, и выделяет выбранный в
текущий момент элемент.
    UpdateContents перерисовывает заголовок продолжения, если он
есть, и корректирует полусы прокрутки.

    Дополнительно см.

RawWindow.Draw       StackWindow.Draw

        WhereSelect

    Объявление

procedure WhereSelect(var X, Y : Byte);

    Функция

    Возвращает для выбранного элемента координаты относительно
окна.

    Описание

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

    Пример

PizzaTop.Process;
PizzaTop.WhereSelect(X,Y);
PizzaTop.wChangeAttribute(20, Y, X, $02);
Delay(1000);
PizzaTop.Erase;

    Изменяет одну секунду атрибут выбранного элемента, а затем
стирает окно.


     WhereSelectsAbs

    Объявление

procedure WhereSelectsAbs(var X, Y : Byte);

    Функция

    Возвратить абсолютные координаты выбранного элемента.

    Описание

    Работает подобно WhereSelects, но возвращает абсолютные
координаты, а не координаты относительно окна.
