F.OPMENU - Системы меню

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

Меню выходят  в различных стилях.Спускающиеся меню (Borland's) опре-
деляют один , обычно используемый стиль.Линейное,горизонтально раск-
ручивающееся меню (Lotus'), является другим стилем.OPMENU легко под-
ражает любому из этих стилей,и дает вам возможность определить  дру-
гие  стили  ,которые  соответствуют  вашему воображению.OPMENU также
обеспечивает  общую  поддержку   для   более   поздних   технических
средств:многоуровневых гнездовых меню,отраженных кадров,покомпанент-
ных подменю,меню горячих ключей,и поддержка мыши.

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

     [Root]
       [DoubleListNode]
         MenuItemNode
       [DoubleList]
         [CircularList]
          MenuItemList
       [AbstractWindow]
         [RawWindow]
          SubMenu
          [StackWindow]
              [CommandWindow]
                  Menu

Menu обьект является только одним из четырех ,которые вам будут
обычно нужны ,чтобы обьявить и использовать.Также мы документируем
некоторые черты обьектов нижнего уровня ,которые могут быть полез-
ными для уникальных случаев.

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

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

Одним из полей данных обьекта Menu является MenuItemList,который
является специализированной формой ссылочного списка,элементы ко-
торого являются типом MenuItemNode.Каждый элемент данных ,который
вы видите на одном уровне меню системы , является
MenuItemNode.MenuItemNode имеет поля данных ,которые описывают
следующие черты элемента данных:
.
-    отображаемое имя элемента данных
-    уникальный идентифиционный номер," item key"
-    необязательная строка помощи
-    смещение на экране от конца списка элемента данных
-    смещение внутри имени элемента данных необязательного выделенного
     выбранного символа
-    флаг защиты
-    указатель к подменю (SubMenu)

Когда указатель к подменю не пустой,то это  означает,что  прикрепля-
ется  другой  список  элементов  меню.Обьект  SubMenu является точно
RawWindow с дополнительным полем данных из MenuItemList и нескольки-
ми  отмененными  методами.Конечно  же  ,MenuItemList в SubMenu имеет
MenuItemNodes,которые   сами   могут   определить    соответствующие
SubMenus (подменю).  Эта  многоуровневая  структура  дерева разрешает
произвольно сложные меню систем.

Некоторые из полей данных MenuItemNode заслуживают дальнейшего  ком-
ментария,  поскольку  многие черты OPMENU вращаются вокруг них.Таким
полем является "уникальный номер  идентифицирования",к  которому  по
историческим  причинам  мы  ссылаемся  ,  как  к ключу элемента дан-
ных.Каждому  элементу  данныхв  меню  системы   ,независимо   оттого
насколько  сложна система,  должен быть назначен уникальный номер во
время построения системы.  Чтобы выделить в  меню  ,используемый  по
умолчанию элемент данных,вы должны определить его ключ.Когда пользо-
ватель выбирает элемент данных (через метод Process),OPMENU  возвра-
щает его уникальный ключ.В большинстве меню базовые прикладные прог-
раммы должны использовать оператор выбора прямо осуществляющий обра-
щение  к Menu Process;каждая выбранная метка должна быть ключом эле-
мента данных и отмеченный оператор будет совершать действия  ,специ-
фичные для этого элемента данных.

Тип данных  ключа элемента данных -LongInt(длинное целое),так что вы
можете не опасаться выхода за пределы кодов.Ключи  элементов  данных
обычно  назначаются  в  возрастающем цифровом порядке,начиная с 1,но
нет требования для ключей быть последовательными.Однако  ,держите  в
голове следующее потенциальное значение. Многие прикладные программы
обеспечивают контекстно зависимую помощь для каждого элемента данных
меню.Если  вы используете OPHELP,чтобы показать эту помощь ,вы веро-
ятно хотите помощь OPHELP в получении номера  темы  ,который  должен
быть тем же самым ,что и как ключ элемента данных в меню. Допустимые
номера  тем  для  OPHELP  ограничены  диапазоном  1..65535.  Так-
же,OPHELP использует память более эффективно ,когда нет неиспользуе-
мых номеров тем между 1  и  наибольщим  номером.Конечно  ,достаточно
легко   обеспечить   промежуточный   ,устанавливающий  соотвеетствие
массив(ключ элемента данных к номеру темы),тогда даже  использование
OPHELP не предполагает фундаментальных ограничений на меню системы.

ПОСТРОЕНИЕ СИСТЕМЫ МЕНЮ
.
Как индивидуальная система меню инициализируется? В Object Professional
имеется два пути:вы можете инициализировать систему ,используя серию
операторов источника,которая начинает с конструктора вызова для обь-
екта меню и продолжает операторами,которые добавляют каждое  подменю
и меню элемента данных ;или вы можете читать меню из абсолютной биб-
лиотеки ,используя один оператор(плюс еще несколько,чтобы открыть  и
закрыть библиотечныый файл).
..
Библиотечное приближение  имеет  преимущество  в  поддержке простого
исходного текста.Для сложных систем меню размер выполняемой програм-
мы  будет  значительно  меньше.К недостаткам относится потребность в
отдельном библиотечном файле  или  отдельном  шаге  компиляции,чтобы
построить  библиотечный загрузочный модуль EXE ;и исходный текст,ко-
торый не является сам документом.
.
Какой бы  путь  вы  не   выбрали,поддерживающая   утилита   MAKEMENU
(описаннная  в  секции  H  этой части) спасет вас от большой работы.
MAKEMENU дает вам дизайн системы  меню видимо  и  интерактивно;затем
записывает  меню  в  форме исходного текста,библиотечной форме или в
той и другой.Вы вероятно будете использовать MAKEMENU для построения
вашего меню для всех систем , пока оно освобождает вас от черной ра-
боты по координации компьютерного окна,положениях  элемента  данных,
по  выбору величин видио аттрибутов и других мелких деталей.MAKEMENU
также легко модифицирует ваше системное меню  ,как  только  оно  вы-
растет и созреет.

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

 program MenuExaample;   (EXMENU1.PAS)
 uses
   Dos,OpInline,OpString,OpRoot,OpCrt,OpFrame,OpCmd,OpWindow,OpMenu;
 (Константы меню Item)
   miFirst       =1;
   miAlpha       =3;
   miBeta        =4;
   miSecgnd      =2;
   miGamma       =5;
   miDelta       =6;
 function IniMenu(var M : Menu) : Word;
   ( Инициализирование меню системы,сгенерированной MAKEMENU)
 const
   (Frame constans)
   Frame1 = '===||';
   Frame2 = '===||';
 begin
   with M do begin
 if not initCustom(2,2,16,2,DefaultColorSet,
                   wBordered+wClear+wUserContents,
                   Horizontal) then begin
  IniMenu := IniStatus ;
  Exit;
  end;
  mnOptionsOn(mnAlphMatch+mnSelectOnMatch+mnArrowSelect+mnAllHotSpots);
  mnOptionsOff(mnAllowPending+mnPopOnSelect+mnUseItemForTopic+
  mnSelectOnClick);
  wFrame,SetFrameType(Frame1);
  AddItem( 'First',2,1,miFirst);
    AddFramedSubMenu(3,4,9,5,Vertical,Frame2);
    AddItem('Alpha',1,1,miAlpha);
    AddItem('Beta',2,1,miBeta);
    ItemsDone;
  AddItem('Second',9,1,miSecond);
    AddFramedSubMenu(9,4,15,5,Vertical,Frame2);
    AddItem('Gamma',1,1,miGamma);
    AddItem('Delta',2,1,miDelta);
    ItemsDone;
  ItemsDone;
  IniMenu :=GetLastError;
  end;
 end;
 var
   Status : Word;
   M      : Menu;

 begin
   Status :=InitMenu(M);
   If Status <> 0 then begin
     WriteLn('Error Initializing menu: ',Status);
     Halt(1);
   end;

   M.Drow;
   M.Process;

(Структура управления выбором меню )
If M,GetLastCommand = ccSelect then
   case M.MenuChoice of
     miAlpha : (do somesing);
     miBeta  : (");
     miGamma : (");
     miDelta : (");
 end;

M.Erase;
WriteLn(('Item',M.MenuChoice);
WriteLn(('Command', M.GetLastCommand);
M.Done;
end.
.
Эта программа является слегка  упрощенной  версией  ,сгенерированной
MAKEMENU.Вы  должны  заметить ,что она начинается со списка констант
элементов данных меню - ключи элементов ссылаются к предидущей  сек-
ции.Мы рекомендуем,чтобы вы всегда ссылались к этим ключам по симво-
лическому имени нежели непосредственно по номеру.Делая  так,  стано-
вится  намного  легче расширять и поддерживать меню системы.MAKEMENU
автоматически генерирует такие символические имена для вас или  поз-
воляет вам назначать ваши собственные имена,
.
InitMenu-функция строит систему меню путем инициализации переменно-
го параметра M.(MAKEMENU генерирует функцию InitMenu потому,что  не
знает какое  имя  вы  хотите  дать  вашей актуальной переменной ме-
ню(Menu).InitMenu инициализирует  все  те  переменные  меню,которые
проходят,как ее параметры).Вызов конструктора InitCustom определяет
координаты окна меню верхнего уровня,его цвета и опции и ориентацию
списка верхнего уровня элемента данных -горизонтальную и вертикаль-
ную.Если конструктор завершился аварийно (выход из  памяти,недопус-
тимыые координаты и т.д.),InitMenu возвращает код статуса.
.
Обращение к  mnOptionsOn и mnOptionsOff определяют другие детали по-
ведения системного меню.Мы  опишем  эти  опции  в  секции  Constants
(константы)  ниже.SetFrameType  определяет символы ,используемые для
обрамления меню верхнего уровня.Обращение к другим методам,  унасле-
дованое  от RawWindow или Frame,  могут использоваться здесь также ,
чтобы добавить заголовки,тени,компаненты и т.д.
.
Таким образом,инициализация меню точно подобна инициализации  любого
другого  окна,обращение  к  AddItem  обеспечивает  вход  в новую об-
ласть.AddItem является текущим  состоянием  обьекта  MenuItemNode  и
связывает  его с верхним уровнем меню MenuItemList.Этот особый вызов
добавляет в меню элемент  данных,названный  'First'(первый),смещение
которого  (колонка  от  левого  края окна) равно 2,выделение символа
имеет смещение  1  в  имени('F'),и  ключ  элемента  данных  является
miFirst (который равен 1).
.
Элемент данных 'First' (первый) имеет подменю,соответствующее  ему.
Мы показываем это обращением к AddFramedSubMenu.Этот вызов являет-
ся текущим состоянием обьекта SubMenu и связывает его с  указателем
поля подменю  First(первый).Параметры  AddFramedSubMenu  определяют
новые координаты окна подменю,ориентацию списка его элементов
и символов,используемых для его обрамления.
.
Слеедующее обращение к AddItem применяют к подменю,но не к верхнему
уровню меню MAKEMENU выделяет исходный текст ,генерирует  по порядку,
чтобы сделать  это отношение ясным.Элементы данных продолжают при-
соединяться к гнездовому подменю до тех пор,  пока  элементы  данных
Done вызываются,после  которого применяют  AddItem к предварительно
активизированному подменю(в этом случае верхний уровень меню).
Пример добавляет  элемент  данных 'Second' (второй) к верхнему уровню
меню,подвешивает подменю на этот элемент данных и продолжает в  том
же духе пока вызывается ItemsDone для верхнего уровня меню.
.
Функция InitMenu     заканчивает    работу ,  возвращая    величину
GetLastError,которая возвратит нуль,если нет ошибок произошедших  в
течение инициализации.
.
В примере блок программы main стартует вызывая InitMenu,чтобы прои-
нициализировать переменную M в разделе Menu.Будучи уверенным в том,
что InitMenu завершилось успешно,вызывают специальную версию Menu -
Draw метод.Поскольку меню прежде не отображалось ,Draw просто рису-
ет верхний уровень меню и выделяет элемент данных по умолчанию(кото-
рый является первым элементом данных  ,если  вы  не  определили  по
другому).
.
Вызывающая программа Process передает управление клавиатурой пользо-
вателю,  который  может  просматривать  меню  системы с помощью клю-
чей:<Enter> и <Esc>.Когда пользователь нажимает <Enter> ,  в то вре-
мя,как  выделенная  линейка  находится на элементе данных без подме-
ню,программа Process  завершается.Также  ,  как  другие  производные
CommandWindow  ,  последняя  команда выбирается GetLastCommand,путем
проверки этой величины она убеждается,что пользователь  не  нажимает
<Esc>  (на верхнем уровне меню) или какой-нибудь другой команды exit
(выход).
.
Меню MenuChoice возвращает ключ выбранного элемента .Мы  ис-
пользуем условный оператор ,чтобы осуществить выбор среди различных
ключей,таким образом совершаем некоторое действие  специфичное  для
этого элемента данных .Заметьте,что ключи miFirst и miSecond не на-
ходятся в условном операторе.Это потому ,что те элементы данных име-
ют подменю и поэтому никогда не завершат Process командой ccSelect.
(В специальных случаях они могут осуществить exit различными коман-
дами). Пример  завершается  удалением системы меню и избавлением от
него .(Мenu.Erase отменяет обычное окно метода Erase и  удаляет  все
активные подменю ,но только не верхнего уровня).
.
В спедующих   секциях  мы  описываем  много  путей  ,  чтобы
рассмотреть эти базовые возможности.
.
НАСТРОЙКА МЕНЮ
.
Предидущий пример показал нам,как делать прекрасное спускающееся
системы меню.OPMENU обеспечивает множество путей для создания меню для
знатоков.В этой секции мы суммируем многие технологии настройки  по-
явления меню системы .Вы можете ссылаться к описаниям метода позднее
в главе для деталей использования каждой технологии,если MAKEMENU не
определено  другим  образом,MAKEMENU позволяет регулировать эти воз-
можности и генерирует соответствующий исходный текст

Во первых  ,запомните что обьект MENU перемещается из CommandWindow
и ,таким образом, наследует все возможности этого обьекта.Если вы  не
найдете того ,что хотите посмотреть в обсуждении  ,  которое
следует,то посмотрете назад в CommandWindow,RawWindow и Frame обьекты.

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

AddItemPtr ,не похожа на  AddItem,не  располагает  динамической  па-
мятью, чтобы запоминать имя строки элемента данных .Вместо этого она
просто запоминает адрес строки ,введенной в нее.Такой подход  сохра-
няет  память,поскольку  позволяет создать дубликат копии имени.(Сим-
вольную строку вы вводите в AddItem и запоминаете в  текстовом  сег-
менте;AddItem  делает дубликат этой строки.)AddItemPtr требует,чтобы
вы обьявили имена строк элемента данных ,как  типизованные  констан-
ты.(Компилятор  не  может  дать  нам  использовать адрес литеральной
строки в выполняемом разделе программы).Типизованные константы  соз-
дают  менее  удобочитаемый  исходный текст,но они могут найти ценное
AddItemPtr,если память полна и вы имеете большое меню системы.
.
AddItemHelp требует дополнительный параметр,строку помощи.OPMENU ни-
чего  не  делает  с  этой строкой ,но запоминает и возвращает ее.Еще
также,строка может быть полезна в комбинации  с  "текущим  элементом
данных"  (current  item hook).В секции ,описывающей этот элемент ,мы
покажем,как изобразить непрерывно обновляемое окно контекстнозависи-
мой помощи,используя каждую строку помощи элемента данных.
.
AddItemHelpPtr комбинирует  возможности  AddItemPtr и AddItemHelp.Ни
имя строки ни строка помощи не запоминаются в динамической  области,
таким  образом,исключая дублирование памяти.  AddSeparator добавляет
специальный сорт данных:линейку,которая обьединяет окно меню и отде-
ляет  одну  группу элементов данных от следующей Конечно ,OPMENU ни-
когда не даст выбор  выделенной  области  на  отделенной  линейке  В
действительности,Если  вы заглянете за место действия,вы найдете,что
AddSeparator не добавляет элемент данных в меню вообще,вместо  этого
добавляет  пространство  заголовка (cмотри Frame обьект).Но вы вызы-
вайте его также,как любой  другой  метод  AddItem,так  мы  ссылаемся
здесь.
.
AddSeparatorColor подобна AddSeparator,но вы можете определять цвета
не по умолчанию.
.
Обычно , имеются вариации при вызове  AddFramedSubMenu,чтобы  добавить
подменю. AddSubMenu присоединяет необрамленное подменю  соответствую-
щее меню системы для Lotus-стиля).AddSubMenuCustom принимает  допол-
нительные   параметры,которые  позволяют  вам  определить  настройку
ColorSet и настройку опций окна для подменю.
.
Переменная в программе ItemDone,ItemDoneCustom принимает  два  пара-
метра.  Если  первый  параметр  ,OptimizeSize,является  истинным  (и
UseAdjustabie является активным),ItemsDoneCustom ,автоматически фор-
матиряет окно , соответствующее подменю точно вокруг элементов .Вто-
рой параметр ,DefaultKey,  определяет,какой  элемент  данных  должен
быть  начальным по умолчанию,  когда меню активизируется.MAKEMENU не
должно гунерировать  вызовы  к  ItemsDoneCustom;если  вы  нуждаетесь
установить  элемент данных по умолчанию между первых в каждом списке
,вы должны изменить текст MAKEMENU ,чтобы вызвать ItemsDoneCustom или
использовать другой метод ,DefaultItem,описанный позже.
.
Следующей группой методов мы  подитоживаем изменение характеристик те-
кущего подменю или списка элементов данных ,хотя меню системы уже
построено.Вызовы этих  методов  включены  во фрагмент ,показанный в
следующем текстовом куске
.
     with M begin
       if not InitCustom{ ... } then begin
         InitMenu := InitStatus;
         Exit;
    end;
    wFrame.SetFrameType{Frame1};
--> включить настройки здесь
    AddItem{'First', 2, 1, miFirst};
      AddFramedSubMenu{3, 4, 9, 5, Vertical, Frame2};
--> включить настройки здесь
    AddItem{ 'Alpha', 1, 1, miAlpha};
.
Настройки,включенные в   первое  отмеченное  положение  применяются
только для верхнего уровня меню.То,что включено во второе положение
применяется к подменю,относящемуся к элементу данных 'First'.
.
Несколько методов      -SetNormAttr,SetSelectAttr,SetHighAttr      И
SetProtectAttr-используются,чтобы  определить изображение цвета эле-
ментов данных.Нормой являются невыделенные символы невыбранных  эле-
ментов  данных.  Выбранным  является  цвет выбранной линейки,которая
двигается с курсором.Сильное выделение условного  символа  использу-
ются  ,чтобы выбрать элемент данныхтекстуально,метод Protect применяется
к    защищенным    элементам     данных.SetFrameAttr,SetHeaderAttr,и
SetShadowAttr  определяют  цвета для порций подменю ,которые отлича-
ются от меню верхнего уровня.
.
SetLeftPad определяет число фоновых символов окна,добавляемых к ле-
вой стороне каждого элемента данных.Эта опция применяется только  к
вертикальным спискам.
.
SetSelectMarker определяет  строки ,которые конкатенируются слева и
справа текущего выбранного элемента данных,увеличивая выыбранную
линейку.
.
Поскольку каждое подменю перемещается из обьекта RawWindow,оно может
иметь  заголовки ,тени и процедуры открытия/закрытия для специальных
эффектов ,подобным взрывам (мгновенная смена окон) .Обьект  Menu  отме-
няет  некоторые методы RawWindow и Frame для того ,чтобы сделать эти
возможности более доступными.
.
Версии Menu работают подобно оригиналам за исключением того,что  ав-
томатически применяются к главной системе(wFrame) текущего подменю и
они проверяют переменную ошибки Menu ,прежде,чем они начнут действо-
вать.Эта  ошибка проверяет основное соглашение ,поэтому вам не нужно
проверять ошибки после каждого шага при построении меню.Меню обеспе-
чивает     версии     следующих    методов:AddHeader,AddHeaderColor,
AddCustomHeader,  AddShadow,  AddShadowColor,  EnableExplosions,   и
EnablNormalOpen.
.
Другая группа методов настройки используются ,чтобы модифицировать
вид всего меню системы.Вместо работающих  на простом подменю,эти методы
автоматически изменяют каждое подменю также,как основное меню.
Вы можете сделать вызовы к этим методам в любое время после того ,как
будет завершена инициализация меню системы (в конце InitMenu
или после возврата из него),
.
Следующие методы  модифицируют  настройки  цвета : SetAllNormAttr,
SetAllSelectAttr,SetAllhhhhHighAttr,SetAllProtectAttr,SetAllFrameA-
ttr,SetAllHeaderAttr,SetAllShadowAttr и SetHelpAttr  .Дополнительные
методы модифицируют           другие           свойства          ок-
на:AddShadows,EnableAllExplosions,EnableAllAlternateOpen,EnableAllN-
ormalOpen  и SetAllSelectMarker.
.
MAKEMENU не  генерирует  вызовы  к  этим "глобальным' программам.Оно
производит те же результаты путем построения меню системы с  коррек-
тирующими свойствами  на первом месте,Основное применение этих прог-
рамм - это построение пользовательских конфигурированных программ:
для примера ,  пользователь может иметь или не иметь возможность от-
тенков или взрввов (мгновенную смену окон) в меню системы.
.
Чтобы лучше прочуствовать эти опции  давайте  возьмем  показательный
пример программы и добавим несколько фантазируемых черт в нее (исполь-
зуя MAKEMENU),затем смотрите на программу InitMenu.
.


    function InitMenu(var M : Menu) : Word;
      (-инициализация меню системы ,сгенерированного MAKEMENU)
    const
      (константы системы)
      Frame1 = '===||';
      Frame2 = '===||';
    begin
      with M do begin
        if not InitCustom(2, 2, 16, 2, MenuColors,
                          wBordered+wClear+wUserContents,
                          Horizontal}then begin
           InitMenu := InitStatus;
           Exit;
         end;
 mn OPtionsOn(mnAlphaMatch+mnSelectOnMatch+mnArrowSelect+mnAllHotSpots);
 mn OptionsOff{mnAllowPending+mnPopOnSelect+mnUseItemForTopic+
            mnSelectOnClick};
         wFrame.SetFrameType{Frame1};
         AddHeader{'Top level',heTC};                           {***}
         AddItem('First', 2, 1, miFirst);
            AddFramedSubMenu{ 3, 4, 11, 6, Vertical, Frame2};
            AddSeparator{'|', '=', '|', 2};                     {***}
            SetSelectMarker{ '<', '>'};                         {***}
            AddItem{'Alpha', 1,1, miAlpha};
            AddItem{'Beta', 3, 1, miBeta};
            ItemsDone;
         AddItem{'Second', 9, 1, miSecond};
            AddFramedSubMenu{9, 4, 15, 5, Vertical< fram2|;
            SetNormAttr{LtCyanOnBlue, LtGrayOnBlack};           {***}
            SetSelectAttr{BlackOnLtGray, BlackOnLtGray};        {***}
            SetHighAttr{{LtRedOnBlue< WhiteOnBlack};            {***}
            EnAbleExplosions{15};                               {***}
            AddShadow{shBR, shOverWrite};                       {***}
            AddItem{'Gamma', 1, 1, migamma};
            AddItem{'Delta', 2, 1, miDelta};
            ItemsDone;
          ItemsDone;InitMenu := GetlastError;
        end;
      end;

Строки ,добавленные в этот раз , выделены комментарием {***}.Мы до-
бавили заголовок,'Top level'(Верхний уровень),к меню верхнего уровня.
Подменю 'First" имеет отдельную линейку между элементами данных
'Alpha' и 'Beta'.Выбранный элемент данных в этом подменю заключается
в угловые скобки ,т.е. '>Alpha<'.Подменю 'Second' обеспечивает специ-
альный взрывной эффект (мгновенная смена окон),когда оно открывается
или закрывается , и также имеет средство настройки оттенков.
Оно использует настройку цветов для нормальных и выбранных
элементов данных и для выделенного символа.

Мы закрываем  эту секцию с кратким упоминанием трех других методов ,
которые  могут  быть  полезными  приоритетным  пользователям  Object
Professional  (Профессиональный  обьект).Мы используем эти результа-
ты,чтобы реализовать специальные черты в MAKEMENU и написать  другие
методы в самом обьекте меню.VisitAllItems совершает глубинный первый
обход всего меню системы .Для каждого элемента данных он  встречает,
вызывает,записанные  пользователем  процедуры,и подводит указатель к
MenuItemNode,указатель к меню системы,и к нетипизованному переменно-
му параметру (var) содержащему ,  определенные пользователем данные.
VisitAllWindows и VisitAllItemList  совершают  подобные  обходы  для
каждого оконного обьекта и каждой MenuItemList в меню системы.Смотри
метод , описаний с большими подробностями.

КОМАНДЫ МЕНЮ

Метод Process меню(Menu's Process)предлагает соответствующие коман-
ды для управления элементами данных и подменю.Список ниже  распола-
гает их по категориям.В каждом случае первая строка дает имя коман-
ды ,следуемой за ключом,которому она назначена.Вторая  и  следующие
строки дают   глубокое описание команды.Назвапие ключа по умолчанию
запоминается в   типизованной  глобальной  константе   MenuKeySet(в
OPMENU.ICD)

Движение курсора

ccLeft             <Left>,<CtrlS>

Выделенная линейка двигает влево один элемент  данных  на  горизон-
тальном подменю.Если линейка находится в самом левом положении эле-
мента подменю,то из него она перемещается в  самый  правый  элемент
данных. Если  а)  активное подменю имеет вертикальную ориентацию,б)
опция mnArrow является возможной ,с)  подменю родительского подменю
имеет горизонтальную ориентацию и d) родительское подменю имеет до-
полнительные незащищенные элементы данных  ,тогда  текущее  подменю
удаляется и   родительский  выделенная линейка перемещается влево к
следующему элементу данных Если этот элемент данных имеет подменю ,
подменю выбирается и он по умолчанию становится активным.Если роди-
тельский элемент не имеет подменю и опция mnAllow является  возмож-
ной ,OPMENU   устанавливает  внутренний флаг ,который напоминает ей
выбрать следующее  доступное  подменю  ,если  команды  ccLeft  (или
ccRight, ccHome, или ccEnd)выполняются опять.

ccRight            <Right>,<CtrlD>

Выделенная линейка двигает вправо элемент данных на  горизонтальном
подменю.Дополнительное поведение является аналогичным ccLeft(справа
смещаясь влево).

ccHome             <Home>,<CtrlQ> <S>

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

ccEnd              <End>,<CtrlQ> <D>

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

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

Выделенный участок  движется  вверх  по  ряду на вертикальном подме-
ню.Дополнительное поведение  аналогично  ccLeft(со  смещением  влево
вверхи смещением горизонтали по вертикали).

ccDown             <Down>,<CtrlX>,<ctrlZ>

Выделенный участок движется вниз по ряду на вертикальном подменю.До-
полнительное поведение аналогично ccLeft(со смещением влево вниз и
вертикальным смещением горизонтали).

Другие

ccSelect           <Enter>

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

ccMouseSet          <ClickLeft>

Процесс сканирует стэк активных подменю (от недавно выбранных подме-
ню  по  направлению  к  верхнему  уровню меню),если положение "мыши"
соответствует горячему участку меню(смотри OPFRAME) текущего подменю
или горячему участку другого активного подменю и опция mnAllHotSpots
возможна.Процесс заканчивается,оставляя последнюю команду  ,установ-
ленной в ccMouseSel,если положение "мыши" соответствует незащищенно-
му элементу в текущем подменю  ,выделенная  линейка  перемещается  к
этому  элементу данных.Если элемент данных был уже выделен или ,если
опция mnSelectOnClick  возможна  ,Process  изменяет  код  команды  в
ссSelect и завершается.  Если положение "мыши" соответствует незащи-
щенному элементу в другом активном подменю ,все подменю удаляются до
тех пор , пока индицируемый элемент в подменю является текущим. Если
опция mnSelectOnClick включена ,  Process  изменяет  код  команды  в
ccSelect  и  завершается.  Осознано или нет,это поведение совершенно
интуитивно,когда вы делаете попытки вместо чтения о них.Эта  команда
доступна  только  тогда  ,если  активизировано  условное определение
UseMause.

ccQuit               <Esc>,<ClickRight>

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

ccHelp                <F1>,<ClickBoth>

Помощь. Если  записанная пользователем программа помощи установлена
вызовом MenuCommandsSetHelpProc,то нажимая <F1>, вызываем эту прог-
рамму;иначе эта команда ничего не значит.Меню осуществляет процеду-
ры помощи следующими тремя параметрами :  ucMenu,@Self и помощь  по
предметному номеру.Если  опция mnUseItemForTopic является возможной
,то номер предметной помощи является тем  же  самым,что  и  текущий
ключ элемента.Иначе   ,предметная помощь является величиной ,оформ-
ленной как оконная помощь (смотри CommandWindowSetHelpIndex) ,кото-
рая равна нулю по умолчанию.

ccChar                любой алфавитно-цифровой символ

Если опция mnAlphaMatch возможна,  текущий список элементов ищется
по элементу  ,   который по результату метода SelectChar ,  находит
парный символ (условно-независимый).Поиск начинается  на  следующем
элементе за   пределами текущего.Если пара найдена,то выбранная ли-
нейка движется к этому элементу.Если спаренный элемент имеет подме-
ню, подменю изображается.Если опция mnSelectOnMatch возможна,и эле-
мент не имеет подменю ,Process изменяет код команды  в  ccSelect  и
завершается.

ПОДДЕРЖКА "МЫШИ"

Поддержка мыши встроена в Menu обьект;всем вам необходимо  активизи-
ровать ее.Попытайтесь добавить  следующие строки к вводному примеру и
именно после вызов InitMenu успешно завершится.

         if MouseInstalled then begin
           with DefaultColorSet do
             SoftMouseCursor($0000, (ColorMono{MouseColor,MauseMono)
             shl 8)+$04);
           MenuCommands.cpOptionsOn(cpEnableMause);
        end;

Эти коды  уверяют,что  "мышь" установлена.Если так ,определим пара-
метры курсора "мыши".Этот шаг является необязательным до  тех  пор,
пока программный   курсор "мыши" является текущим,но вам желательно
установить его цвета в соответствии с вашим  ColorSet.   Вы  всегда
должны использовать   программный  курсор мыши (в противоположность
аппаратному) в  обьекте Menu.Смотри OPMOUSE для более подробной ин-
формации об определении курсора "мыши".

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

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

РИСОВАНИЕ И СТИРАНИЕ СИСТЕМ МЕНЮ

Обьект Menu ,подобно всем другим окнам производится в Object
Proffesional,поддерживает методы Draw (рисование) и Erase(стира-
ние).Поскольку система меню есть собрание связанных окон ,а  не  что
то единственное,поведение  Draw и Erase методов соответственно моди-
фицируются.Несколько дополнительных программ также доступны для
контроля появления меню.

Когда вы вызываете Draw впервые , изображается верхний уровень сис-
темы меню(граница,тени,заголовки),тогда   выводится список его эле-
ментов .Если опция mnMainSelect возможна,текущий элемент помечается
видео аттрибутом "select"(выбран) и маркером выбора ,если возможно.
Если возможна опция mnMainHighlight ,выделяются  поисковые  символы
альфа каждого  элемента .Доступность этих опций позволяет вам изоб-
разить верхний уровень системы меню в "dormant"(остановленном)  по-
ложении, пока пользователь ищет доступа к ней.
.
Когда вы  вызываете метод Menu's Process,  маркируется текущий эле-
мент и выделяются поисковые символы альфа ,  а  затем  пользователь
может просматривать систему и выбирать элемент.Когда Process завер-
шается ,  он не удаляет меню системы (при одном возможном  исключе-
нии: если  возможна олция mnPopOnSelect,подменю выбранного элемента
удаляется автоматически).Это ваша ответственность решать удалять ли
систему меню  ,когда  Process  возвращается.Обьект Menu предлагает
несколько путей для удаления.

Метод Erase передвигает все меню системы с экрана.  Однако Menu ос-
тается во  внутреннем стэке подменю.которое является активным.Когда
вы вызываете Draw или Process опять,все прежде активные подменю пе-
ресоздаются.

EraseClear также удаляет внутреннее меню системы.Поскольку внутрен-
ний стэк очищается ,  следующий вызов  Draw  или  Process  нарисует
только верхний уровень меню.

EraseAllSubMenus удаляет все ,  кроме верхнего уровня меню.Этот ме-
тод принимает также два параметра,ShowSelect и  ShowHighlight,кото-
рые дают  вам специфичные возможности - выбор линейки и альфа поис-
ковые выделения остаются видимыми.

Итак,EraseCurrentSubMenu удаляет только подменю ,которое было недав-
но активным.Он не удаляет верхний уровень меню.

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

В зависимости оттого находится ли меню системы уже  на  экране  или
нет ,вы   можете  обновить  вид меню используя другие методы ,чтобы
выбрать различные элементы.SelectItem перерисовывает меню системы ,
чтобы сделать   определенный  элемент  (где-нибудь  в системе)теку-
щим.SelectSubMenu перерисовывает меню системы ,чтобы  сделать  эле-
мент определенного  подменю текущим по умолчанию.(Эта программа яв-
ляется полезной   для  меню  системы   ,подражающей   интегральному
развитию среды  Borland's.Если вы нажмете ключ <AltF> в этой среде,
подменю Files(файлы)  будет изображено с самым недавним выбранным и
выделенным элементом  данных).SelectItemByPos выбирает элемент дан-
ных ,на определенную позицию экрана,этот метод  полезен,когда  раз-
личные окна(не  меню)являются текущими и пользователь "мыши" на ли-
нейке меню ,которая видима на другой части экрана.

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

МЕТОДЫ ДОСТУПА

Menu обеспечивает непосредственный доступ ко многим методам  обьек-
тов, которые    зависят  от  -  Frame,   RawWindow,   MenuItemNote,
MenuItemLast, SubMenu  и т.д.  - отменяя согласование имен метода и
выполняя согласование поля данных ссылки ,указателя ссылки и др.Это
достижение депает легче для вас читать и настраивать коды  ,которые
генерирует MAKEMENU.

Однако ,мы не можем делать те же самые вещи для каждого метода без
распухания обьекта Menu ,без особых причин.Вместо этого Menu пред-
лагает несколько "методов доступа".

       function ActiveWinPtr : RawWindowPtr;
           {возвращение указателя к активному необработанному окну}
      function ActiveListPtr : MenuItemListPtr;
           {возвращение указателя к активному списку элементов}
      function ActiveSubPtr : SubMenuPtr;
           {возвращение указателя к активному подменю}
      function ActiveItemPtr : MenuItemNodePtr;
           {возвращение указателя к активному элементу}
      function FindItem{Key : LongInt} : MenuItemNodePtr;
           {возвращение указателя к определенному типу элемента}

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

    M.ActiveWinPtr.ChangeHeader{HdrNum,NewHdrStr};

где М является переменнойMenu.ChangeHeader является методом обьек-
та RawWindow,а HdrNum и NewHdrStr согласуются с переменными или
константами в вашей программе.
Другой пример:предположим вы хотите отобрать строку помощи актив-
ного элемента.Следующий оператор такой:

    HelpStr : = M.ActiveItemPtr .HelpString;

Финальный метод доступа ,FindItem,ищет меню системы ,чтобы найти
ключ определенного элементаи возвращает указатель в
MenuItemNode.Используя указатель ,вы можете вызвать любой из мето-
дов MenuItemNode.Например:

    var
      IPtr : MenuItemNodePtr;
..
      IPtr :=M.FindItem{10};
      if IPtr .SubPtr <> nil then
         {Элемент 10 имеет подменю };
Если не найдены данные по определенному ключу,FindItem возвращает
нуль.

ЗАЩИЩЕННЫЕ  ЭЛЕМЕНТЫ  МЕНЮ

Защищенный элемент  данных меню рисуется в отдельный видео аттрибут
и пользователь не может перемещать линейку выбора к нему.Такие эле-
менты данных   полезны,по  крайней  мере ,в двух ситуациях.В первом
случае элементы данных должны быть защищены и не  защищены  динами-
чески.Например:не надо   ничего делать,чтобы сохранить файл,когда в
него ничего не загружено,или удалить  запись,когда  еще  ничего  не
выбрано.MAKEMENU и MAKESCRN широко используют эти возможности, что-
бы сделать не нужными специальные команды ,когда  они  не  примени-
мы.Во второй ситуации,элементы данных защищены статически,  т.е.че-
рез полное     управление   их    применением.Например,вы    можете
использовать определенные  элементы данных в меню,как информативные
подзаголовки никогда не выбираемые.  OPMENU имеет несколько методов
поддерживать эти возможности.Во первых,обьект Menu предлагает мето-
ды ProtectItem и UnprotectItem.Данным ключом определенного элемента
данных,эти методы  находят указатель элемента данных MenuItemNode и
затем устанавливают или очищают их  флаги  защиты.Нет  немедленного
обновления экрана (вы можете изменить более,чем один элемент),но вы
можете вызвать меню Redraw (перерисовать)  обновить экран  меню,уже
видимого.ProtectItem также проверяет защищен ли текущий элемент лю-
бого подменю,если так,то ProtectItem пытается выбрать рядом незащи-
щенный элемент данных.

Посмотрим быстрый  пример  защищенног  элемента,добавим  следующую
строку к  вводному   примеру   программы,но   только   до   вызова
M.Draw.Когда вы запустите программу,вы увидите,что элемент'Delta'
не может быть длиннее выбранного.

    M.ProtectItem{miDelta};

Для тех случаев,когда много элементов защищено и не защищено после-
довательно ,чрезмерность  каждого заголовка поискового дерева меню
может затруднить поиск каждого элемента.Поэтому было условие в
MAKEMENU и MAKESCRN.Чтобы избежать чрезмерности  в  заголовке  ,мы
запомнили указатель к каждому MenuItemNode и указатели к элемен-
там данных.Один  путь  - это использовать метод FindItem,только что
обсужденный в предидущей секции.Другой путь -это присвоить элемен-
ту данных указатель,когда меню строится.Например,чтобы запомнить
указатель элемента  данных  'Delta',мы  должны  добавить следующую
строку к функции InitMenu:

    AddItem{'Delta', 2, 1, miDelta};
--->DeltaPtr := ActiveItemPtr;
Этот подход не требует поиска.

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

     {установить указатели в меню элементов данных для более быст-
      рой возможности защиты}
     MAINMenu>VisitAllItems{SetItemPointers,Dummy};
в MMMAIN.INI для завершения примера.

ПРОЦЕДУРА НАСТРОЙКИ СТРОКИ

Многие меню включают не только элементы для поиска ,но также и ста-
тусы для этих элементов.Например,выбор меню может переключать слово
-свертку (word-wrap)  в текстовый редактор ,если вы хотите показать
пользователю было   ли  значение  слова-свертки  ON(включить)   или
OFF(выключить),и лучшим местом для этого будет рядом с меню элемен-
та.

OPMENU позволяет  для  этой  возможности ,вызывая пользовательскую
программу .подготовить каждый элемент для показа.По умолчанию  оно
вызывает программу  ,которая ничего не делает(NoCustomization,свя-
занную с OPMENU).Вы можете иметь программу вашего собственного вы-
зова метода Menu SetCustomStringProc:

   procedure Menu.SetCustomStringProc{CP : mnCustomProc};
     {установить процедуру  настройки  элементов  данных для всего
      меню системы}

Параметр,введенный в SetCustomStringProc должен быть глобальной про-
цедурой,которая  скомпилирована моделью FAR(использующей управляющий
компилятор {SF+}) ,  и соответствует следующему прототипу  опрелеле-
ния:

   {SF+}
   procedure CustomStringProc(var Name : String;Key : LongInt;
                              Selected,HighLighted : Boolean;
                              WPtr : RawWindowPtr);

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

Прежде,чем вызвать процедуру настройки строки , OPMENU инициализиру-
ет параметр Name с фиксированным именем строки элемента  данных,кон-
катенирует выбранные маркеры (если есть)и ожидает левые дополнитель-
ные символы(если есть).Если  обьединенный  список  элементов  данных
вертикально  ориентирован,OPMENU дополняет 'имя'полной шириной окна.
OPMENU выводит 'ключ' элемента данных в строковую  процедуру  ,чтобы
идентифицировать  ее для соответствующей настройки.Если элемент дан-
ных промаркирован с  линейкой  выбора,выбор  является  истинным.Если
альфа поисковый выделенный элемент является активным,выделение явля-
ется истинным.OPMENU выводит также адрес ассоциативного окна  ,прог-
рамма  может использовать этот указатель,чтобы определить ширину ок-
на,положение  или  любую  другую  необходимую  иннформацию.Процедура
настройки  строки  служит для модификации параметра Name(имя) ,чтобы
обеспечить статус информации.Для вертикально ориентированного списка
элементов  данных ,она не должна модифицировать длину параметра Name
(имя);вместо этого она должна переписать существующие дополнительные
символы  внутри строки.Строка настройки обычно не выполняется на го-
ризонтальных списках данных,но если вы желаете сделать так,вы должны
добавить информацию в начале строки Name(имя).

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

program MenuExample;  {EXMENU2.PAS}
uses
  Dos, OpInLine,  OpString,  OpRoot, OpCrt, OpFrame, OpCmd, OpWindow,
  OpMenu;
{Константы элементов данных Menu}
const
  mi First    =1;
  mi Alpha    =3;
  miBeta      =4;
  miSecond    =2;
  miGamma     =5;
  miDelta     =6;

var
AlphaOn : Boolean;
BetaOn : Boolean;
GammaOn : Boolean;
DeltaOn : Boolean;

{SF+}
procedure CustomStringProc{var Name : String;Key : LongInt;
                           Selected,HighLighted : Boolean;
                           WPtr : RawWindowPtr};
const OffOn : Boolean;
begin
  case Key of
    miAlpha : On :=AlphaOn;
    miBeta : On:=BetaOn;
    miGamma : On:=GammaOn;
    miDelta : On:=DeltaOn;
{не настраивать остальные элементы данных}
else   Exit;
end;
Move{OffOn[On] [1],Name[Length{Name}-2], 3};
end;
{SF+};

function InitMenu{var M :Menu} : Word;
  {-Initialize menu system generated by MAKEMENU}
  {инициализировать меню системы сгенерированной MAKEMENU}
const
  {константы системы}
Frame! = '===||';
Frame2 = '===||';
begin
  with M do begin
    if not InitCustom{2, 2, 16, 2, DefaultColorSet,
                      wBordered+wClear+wUserContents,
                      Horizontal} then begin
      InitMenu := InitStatus;
      Exit;
    end;
mnOptionsOn{mnAlphaMatch+mnSelectOnMatch+mnArrowSelect+mnAllHotSpots};
mn OptionsOff{mnAllowPending+mn PopOnSelect+mn Use ItemForTopic+
  mnSelect On Click};
wFrame.SetFrameType{Frame1};
AddItem{'First', 2, 1, miFirst};
  AddFramedSubMenu{3, 4, 13, 5, Vertical, Frame2};
  AddItem{'Alpha', 1, 1, miAlpha};
  AddItem{'Beta', 2, 1, miBeta};
  ItemsDone;
  Additem{'Second', 9, 1, miSecond};
    AddFramedSubMenu{5, 4, 15, 5, Vertical, Frame2};
    AddItem{'Gamma', 1,1, miGamma};
    AddItem{'Delta', 2, 1, miDelta};
    ItemsDone;
  ItemsDone;
  InitMenu := GetLastError;
end;

var
 Status : Word;
 M      : Menu;

begin
  Status := InitMenu{M};
  if Status <> 0 then begin
   Writeln{'Error initializing menu: ' Status};
   Haolt{1};
  end;

{инициализировать статические переменные}
AlphaOn := False;
BetaOn := False;
GammaOn := False;
DeltaOn := False;

{     строковая процедура}
M.SetCustomStringProc{CustomStringProc};

repeat
  M.Process;
  If M.GetLastCommand = ccSelect then
    case M.MenuChoice of
     miAlpha : AlphaOn := not AlphaOn;
     mi Beta : BetaOn := not Beta On;
     miGamma : GammaOn := not GammaOn;
     miDelta : DeltaOn := not DeltaOn;
    end;
until M.GetLaastCommand = ccQuit;

M.Erase;
M.Done;
end.

Этот пример является  инструктивным  по  нескольким  причпна,давайте
пройдем  через все различия от начала версии .Во-первых,мы обьявляем
четыре булевские переменные,AlpfaOn и еще три.Эти  переменные  явля-
ются  случайными для этого примера,мы просто переключаем им "истину"
или'ложь",когда каждый подключенный элемент данных является  выбран-
ным.В   реальных   программах   AlphaOn   может   быть   аналогичной
WordWrapOn,BetaOn,AutoIndentOn,  и  так  далее.  Реальная  процедура
настройки  строки может делаться с любым видом статуса переменных,не
только булевскими.Все мы нуждаемся в конвертировании  статуса  пере-
менной к изображаемой строке.

Следующее дополнение  является самой CustomStringProc.Она использует
условный оператор,чтобы различать отличные элементы данных.Некоторые
элементы данных не настраиваются,для других мы используем подходящую
булевскую переменную,чтобы слить строки 'Off' или 'On' в "имя".  За-
метим,что  используется  процедура  Move  ,чтобы копировать строку в
последние три символа строки "имени".

Эта простая программа достаточно ограничена.Если  вам  хотелось  бы
посмотреть реальные  примеры возьмите и посмотрите сразу в MAKEMENU
и MAKESCRN.Они покажут ,  как слить не только  булевские  выражения
,но также   числа,нечисловые  типы,символы  и  другие типы данных в
строку "имени". Следующие изменения происходят с InitMenu.Оба Вызо-
ва AddFramedSubMen   имеют  Х-координаты ,приспособленные оставлять
пространство для четырех экстра символов (отдельный  интервал  плюс
'Off') необходимый для статуса.

Основной блок программы инициализирует булевский статус величин,за-
тем возможна настройка строковой процедуры.Для того ,чтобы дать вам
величины переключателя статуса повторно ,  Process вызывается в се-
ти, пока  вы нажимаете <Esc> на верхнем уровне меню.Каждой командой
ccSelect переключается соответствующая булевская величина.

ПРОЦЕДУРА ТЕКУЩЕГО ЭЛЕМЕНТА ДАННЫХ

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

По умолчанию OPMENU вызывает  программу  ,которая  ничего  не  дела-
ет (NoCurrItemAction  стыкуется  с  OPMENU).Вы  можете задействовать
свою собственную программу ,вызывая Menu.SetCurrentItemProc:

   procedure  SetCurrentItemProc(IP : mnCurrentItemProc);
(Устанавливать вызванную процедуру всякий раз,когда текущий  элемент
нарисован)

Параметр ,передаваемый SetCurrentItemProc должен быть процедурой,ко-
торая компилируется  FAR моделью (используя {SF+} управляющий компи-
лятор),является глобальной,и соответствует следующему прототипу  оп-
ределения:
  {SF+}
  procedure CurrentItemProc(CurrentItemPtr :  MenuItemNodePtr;  NPtr
  :MenuPtr);
Подобно многим  другим  пользователям  этого   средства   в   OBJECT
Professional,текущая процедура  элемента  вызывается из виртуального
метода ,  CurrentItem.Вы можете получить тот же эффект ,выводя новый
элемент из Menu и отменяя этот метод.Текущей процедурой элемента пе-
редается указатель к элементу,который,который точно  делается  теку-
щим и указатель к меню системы.Он может иметь доступ к методам и по-
лям данных ссылочных обьектов,чтобы выполнить их задачи.Процедура те-
кущего элемента  данных  может  выполнять любое желаемое действие со
следующими ограничениями:Активное окно должно быть тем же  самым  на
выходе ,что и на входе;выбранное меню элемента не может быть измене-
но.

Давайте возвратимся  еще  раз  к  вводному примеру и добавим одну из
этих процедур.В этом случае мы просто напишем  строку  к  последнему
ряду экрана  ,показывая которую ключ элемента является текущим.Доба-
вим следующую глобальную процедуру к примеру:
   {SF+}
   procedure CurrentitemProc(CurrentItemPtr  :  MenuItemNodePtr;   Mptr
   : MenuPtr);
   begin
   FastWrite(Long2Str(CurrentItemPtr .  ItemKey+" является текущим клю-
          чом эпемента', ScreenHeight, 1, TExtAttr);
   end;

И активизирует эту программу добавлением спедующего кода к основному
блоку:

   {Активизировать текущую процедуру элемента данных}
   M.SetCurrentItemProc(CurrentItemProc);

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

1.ОБЬЕКТЫ НИЖНЕГО  УРОВЕНЯ

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

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

Мы описываем  только  методы  MenuItemNode ,которые в целом необходи-
мы.MenuItemList и SubMenu не обеспечивают методы,которые  вам  могут
потребоваться,поскольку а)большинство из этих методов доступны через
методы обьекта Menu,или б) методы отменяют унаследованные методы с
незначительными отличиями.Ссылайтесь к OPMENU.PAS ,  если вам требу-
ется дополнительная информация.

К о н с т а н т ы

   inprotected     = ^$01;
Этот бит устанавливается в байте опции MenuItemNode , чтобы показать
что элемент защищен.

   DefItemOptions  : Byte = 0;

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

   inAllocConsPtr  : Boolean = False;

Когда эта константа истинна ,  MenuItemNode.Load распределяет прост-
ранство для  дополнительной  строки  ,  "имя константы" элемента.Эта
строка читается и записывается MAKEMENU,и используется ,чтобы  гене-
рировать выбранные  пользователем  имена  констант  в  исходном  ко-
де.MAKEMENU устанавливает истинность;вы не должны делать этого.

Т и п ы
    MenuItemItemNodePtr   = ^MenuItemNode;
    MenuItemNode          =
         object{DoubleListNode}
             ...
         end;
MenuItemNode обьект.
    MenuItemListPtr       = ^MenuItemList;
    MenuItemList          =
         object{CircularList}
    ...
         end;

MenuItemList обьект.Методы   этого   обьекта   не    документированы
здесь.Смотри листинг OPMENU.

    SubMenuPtr            = ^SubMenu;
    SubMenu               =
         object{RawWindow}
             ...
         end;

SubMenu обьект. Методы этого обьекта не документированы здесь.Смотри
листинг OPMENU.PAS.

--------------------------------------------------==================
C h a n g e D i s p l a y P o s
--------------------------------------------------------------------

О б ь я в л е н и е
  procedure ChangeDisplayPos{DisplayPos : Byte};

Н а з н а ч е н и е
  Изменить смещение изображения.

О п и с а н и е
  Изображение смещения - это есть расстояние от левого/верхнего края
  обьединенного окна MenuItemList до начала  (вспомогательного  эле-
  мента,для горизонтальных/вертикальных списков соответственно.Пози-
  ция 1 находится вдали от левого /верхнего прямоугольника активного
  окна.

  ChangeDisplayPos не закрепляет определенную  позицию.Если  позиция
  ставит элемент  "вне  порядка"  по  отношению к последовательности в
  связанном списке эпементов ,  в результате получается странное пове-
  дение.

П р и м е р

  IPtr := M.FindItem(10);
  IPtr^.ChangeDisplayPos(1);

  Изменение изображения позиции меню элемента равно  10  к  первона-
  чальному  ряду  или  колонке  (для вертикальной или горизонтальной
  ориентации,относительно).

С м о т р и  т а к ж е
  GetDisplayPos                     MenuAddItem

  ------------------------------------------------------------------
C h a n g e H e l p
---------------------------------------------------------------------

О б ь я в л е н и е
  function ChangeHelp(Help : String) : Boolen;

Н а з н а ч е н и е
  Изменить строку помощи.

О п и с а н и е
  Эта функция  работает  только тогда,когда строка помощи была изна-
  чально распределена   в   динамической   памяти   (путем    вызова
  AddItemHelp  или  путем загрузки меню системы).Иначе она возвращает
  "ложь".Если строка помощи запоминается в типизованной  константе,
  изменяйте прямо типизованную константу.

  Если длина  новой  строки  помощи  отличается  от  старой   ,   то
  ChangeHelp  удаляет  старое  распределение  динамического  блока и
  распределяет новый блок ,  длина которого равна той,которая содер-
  жится  в  параметре  Help.Если  динамической памяти недостаточно ,
  ChangeHelp завершается, возвращая "ложь'.Иначе, она запоминает но-
  вую строку помощи и возвращает 'истину'.

П р и м е р
  IPtr := M.FindItem(10);
  if not  IPtr^.ChangeHelp('Copy  files  to  a different directory')
     then (error);
  Изменения строки помощи связываются с меню элемента 10.

С м о т р и  т а к ж е
  HelpString                          MenuAddItemHelp

--------------------------------------------------------------------
  C h a n g e K e y
--------------------------------------------------------------------

О б ь я в л е н и е
  procedure ChangeKey{Key : Longint};

Н а з н а ч е н и е
  Изменить ключ элемента.

О п и с а н и е
  Ключ элемента является уникальной характеристикой ,которая
  идентифицирует MenuItemNode.ChangeKey  не  закрепляет определенный
  ключ для неуникальных элементов.

П р и м е р
     M.ActiveItemPtr^.ChangeKet(100);
  Изменение ключа текущего  меню элемента до 100.

С м о т р и  т а к ж е
    ItemKey                    MenuAddItem

--------------------------------------------------------------------

  C a n g e N a m e
--------------------------------------------------------------------

О б ь я в л е н и е
   function ChangeName(Name : String) : Boolean;

Н а з н а ч е н и е
  Изменить имя элемента.

О п и с а н и е
  Эта функция работает только тогда,если имя элемента было изнаяально
  распределено в динамической памяти (Вызовом AddItem,AddItemHel или
  загрузкой меню системы).Иначе,она возвращает 'ложь'.Если имя запоми
  нается в типизованной константе,модифицируйте прямо типизован-
  ную константу.

  Если длина новой строки имени  отличается от старой ,  то ChangeName
  удаляет старое распределение динамического блока и распределяет  но-
  вый блок.Если динамической памяти недостаточно , ChangeName  заверша-
  ется, возвращая "ложь'.Иначе, она запоминает новое имя и возвращает
  'истину'.

П р и м е р
  if not M.ActiveItemPtr^.ChangeName('Copy') then (error);

С м о т р и  т а к ж е
    DisplayInfo                         MenuAddItem

--------------------------------------------------------------------
C h a n g e S e l e c t P o s
-- -----------------------------------------------------------------

О б ь я в л е н и е
  procedure ChangeSelectPos(SelectPos : Byte);

Н а з н а ч е н и е
  Изменить смещение выбранного символа.

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

П р и м е р
      IPtr := M.FindItem(10);
      IPtr ^.ChangeSelectPos(2);
Изменение выбранной позиции элемента меню 10 во втором символе имени

С м о т р и  т а к ж е
        MenuAddItem                 SelectChar

-- -----------------------------------------------------------------
C h a n g e S u b P t r
---------------------------------------------------------------------

О б ь я в л е н и е
  procedure ChangeSubPtr(Sptr : SubMenuPtr);

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

О п и с а н и е
  Метод меню  AddSubMenu  вызывает  ChangeSubPtr  ,чтобы обьединить
  вновь созданное подменю (SubMenu) в текущем элементе.Вы можете поль-
  зоваться либо  динамически  измененным  присоединенным подменю или
  иметь то же самое подменю ,чтобы присоединить более,чем один  эле-
  мент (следовательно сохраняя память).

П р и м е р ы
       IPtr :=M>FindItem(10);
       IPtr^.ChangeSubPtr(OtherSubMenuPtr);
  Изменения подменю ассоциировано с меню элемента 10 к  подменю  ,ука-
  занному,как OtherSubMenuPtr.

       var
          SM : SubMenuPtr;
       ...
       with M do begin
         ...
         AddItem('First', 2, 1, miFirst);
            AddFrameedSubMenu (3, 4, 9, 5, Vertical, Frame2);
            SM := ActiveSubPtr;
            AddItem('Alpha', 1, 1, miAlpha);
            AddItem('Beta', 2, 1, miBeta);
            ItemsDone;
        end;
  Сохраненяется  SubMenuPtr ,меню присоединенного к 'First',затем
  присоединяется то же самое меню к подменю 'Second'.Заметим,что
  положение меню  не регулируется автоматически.

С м о т р и  т а к ж е
    MenuAddSubMenu

--------------------------------------------------------------------
D i s p l a y I n f o
-------------------------------------------------------------------

О б ь я в л е н и е
  procedure DisplayInfo(var DisplayPos, SelectPos : Byte; var S : String);

Н а з н а ч е н и е
  Возвращение строки и показ смещений для элемента.

О п и с а н и е
  Menu{temList вызывает этот метод ,когда рисуется каждый элемент.Он
  возвращает изображение  смещения  .выбpанный  символ смещения и имя
  строки ,предварительно запомненнoй для элемента.

П р и м е р
     IPtr := M.FindItem(10);
     IPtr^.DisplayInfo(DPos, Spos, Name);
Возвращает показываемую позицию и имя меню элемента с ключом 10.

С м о т р и  т а к ж е
     GetDisplayPos              HelpString

  --------------------------------------------------------------------
G e t D i s p l a y P o s
--------------------------------------------------------------------

О б ь я в л е н и е
  function GetDisplayPos : Byte;

Н а з н а ч е н и е
  Возвращает точно показанное смещение

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

П р и м е р
     IPtr := M.FindItem(10);
     DPos:=IPtr^.GetDisplayPos;

С м о т р и  т а к ж е
ChangeDisPlayPos               DisplayInfo

--------------------------------------------------------------------
  H e l p S t r i n g
--------------------------------------------------------------------

О б ь я в л е н и е
  function HelpString : String;

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

О п и с а н и е
  Если строка помощи не  запоминалась,  HelpString  возвращает  пустую
  строку.Иначе она    возвращает    строку    помощи    ,сохраненную
  AddItemHelp,AdditemHelpPtr или ChangeHelp.

П р и м е р
     {SF+}
     procedure MyItemAction(CurrentItem   :   MenuItemNodePtr;   MPtr   :
                            MenuPtr);
     begin

     FastWrite(Pad(CurrentItem^.HelpString, ScreenWidth), ScreenHight, 1,
               TextAttr);
     end;

  Эта процедура помощи  (активизированная  SetCurrentItemProc),которая
  использует метод HelpString,чтобы изобразить строку помощи,ассоцииро-
  ванную с текущьм меню элементом.

 С м о т р и  т а к ж е
    ChangeHelp                       MenuAddItemHelp

--------------------------------------------------------------------
 I s P r o t e c t e d
--------------------------------------------------------------------

О б ь я в л е н и е
 function IsProtected : Boolean;

Н а з н а ч е н и е
Возвратить "истину",если элемент защищен.

О п и с а н и е
  Вновь созданные  элементы  не  защищены.Изменить  защиту  ,вызывая
  Protect,  Unprotect  или  (для  высшего  уровня)  ProtectItem  или
  UnprotectItem.

П р и м е р
     IPtr := M.FindItem(10);
     if IPtr^.IsProtected then  {do something};
  Осуществите какие-нибудь действия,если элемент 10 защищен.

С м о т р и  т а к ж е
     MenuProtectItWin.ScrollVert(1);   {Стрелка вниз}
           $011B : Finished := True;    {Выход}
         end;
       until Finished;
       Win.Done;
     end.

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


     ScrollVert
     ----------
     Объявление
     procedure ScrollVert(Rows : Integer); virtual;

     Назначение
     Прокручивает содержимое окна в вертикальном направлении.

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

     Пример

     См. процедуру ScrollHoriz



     SetBackChar
     -----------
     Объявление
     procedure SetBackChar(BackChar : Char); virtual;

     Назначение
     Устанавливает символ фона.

     Описание
     Сохраняет заданный символ в  поле  данных  объекта.  Этот
символ будет использоваться при очищении или прокрутке окна.

     Пример

     Win.SetBackChar(#178);

     В качестве   стандартного   фона  текста  устанавливается
"основной" заполняющий символ.

     См.также
     SetTextAttr


     SetCursor
     ---------
     Объявление
     procedure SetCursor(CT : CursorType);

     Назначение
     Устанавливает форму курсора.

     Описание
     Параметр CT  -  это  логическая  форма курсора (cuNormal,
cuBlock,  cuHidden и т.д.),  а не физические строки  развертки
экрана.  Если  на момент вызова данной процедуры окно является
текущим,  то форма фактического курсора изменяется сразу же; в
противном  случае обновляется соответствующее поле данных объ-
екта,  которое будет использоваться,  когда окно снова  станет
текущим.

     Примеры

     Win.SetCursor(cuBlock);

     Устанавливается прямоугольный курсор.

     Win.SetCursor(cuHidden);

     Курсор становится невидимым.

     См.также
     CursorType(OPCRT)               SetCursor


     SetFrameLimits
     --------------
     Объявление
     {$IFDEF UseAdjustableWindows}
     procedure SetFrameLimits(MinW, MinH, MaxW, MaxH : Byte);

     Назначение
     Устанавливает границы для задания размеров рамки.

     Описание
     Параметры MinW  и MinH устанавливают минимальные ширину и
высоту рамки, а параметры MaxW и MaxH - максимальные. Эти гра-
ницы относятся как к основной,  так и к подменяющей рамке. По-
пытки изменить размеры окна с нарушением этих границ не  увен-
чаются  успехом.  Если на момент вызова данной процедуры рамка
выходит за устанавливаемые границы,  то ошибка не  обнаружива-
ется.
     Наиболее общее применение этой  процедуры  заключается  в
изменении минимальной ширины таким образом, чтобы строка заго-
ловка полностью помещалась в рамке.
     Доступ к   границам   существующей  рамки  осуществляется
посредством обращения к полям данных frMinW,  frMinH, frMaxW и
frMaxH, содержащимся в поле wFrame окна.

     Примеры

     Win.SetFrameLimits(10, 5, ScreenWidth, ScreenHeight);

     Устанавливаются минимальные границы (для изменения разме-
ра рамки), составляющие 10 столбцов и 5 строк. Устанавливаются
максимальные границы, равные размеру полного экрана.

     Win.SetFrameLimits(10, Win.wFrame.frMinH,
                        Win.wFrame.frMaxW, Win.wFrame.frMaxH);

     Минимальная ширина рамки изменяется  до  10  столбцов,  а
остальные границы остаются неизменными.


     SetPosLimits
     ------------
     Объявление
     {$IFDEF UseAdjustbleWindows}
     procedure SetPosLimits(MinX, MinY, MaxX, MaxY : Byte);

     Назначение
     Устанавливает границы  для перемещения и изображения окна
(как правило, совпадающие с границами рамки).

     Описание
     Заданные координаты образуют новый прямоугольник, ограни-
чивающий положение рамки (см. введение к данному разделу). По-
пытки  переместить  или изменить размеры окна окончатся неуда-
чей,  если рамка - за исключением теней - будет превышать гра-
ницы этого прямоугольника. Если на момент вызова данной проце-
дуры рамка выходит за устанавливаемые границы,  то  ошибка  не
обнаруживается.
     Наиболее общее использование этой процедуры заключается в
том,  чтобы предотвратить перемещение окна в какой-либо другой
элемент экрана, например, в меню или строку состояния.
     Доступ к существующим границам осуществляется посредством
обращения к полям данных wMinXL, wMinYL, wMaxXH и wMaxYH окна.

     Пример

     Win.SetPosLimits(1, 2, ScreenWidth, ScreenHeight - 1);

     Верхняя и нижняя строки экрана защищаются от наложения на
них окна.

     См.также
     SetSizeLimits


     SetSizeLimits
     -------------
     Объявление
     {$IFDEF UseAdjustableWindows}
     procedure SetSizeLimits(MinW, MinH, MaxW, MaxH : Byte);

     Назначение
     Устанавливает границы для задания размеров активного  ок-
на.

     Описание
     Параметры MinW и MinH устанавливают минимальные ширину  и
высоту активного окна, а параметры MaxW и MaxH - максимальные.
Попытки изменить размеры окна  с  нарушением  этих  границ  не
увенчаются  успехом.  Если  на  момент вызова данной процедуры
размеры активного окна уже превышают устанавливаемые  границы,
то ошибка не обнаруживается.
     Наиболее распространенное  использование  этой  процедуры
заключается  в  изменении  минимального размера таким образом,
чтобы окно вмещало определенное содержимое.
     Доступ к  границам существующего окна возможен только при
обращении к полям данных wMinW, wMinH, wMaxW и wMaxH окна.

     Пример

     Win.SetSizeLimits(10, 5, ScreenWidth, ScreenHeight);

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

     См.также
     SetFrameLimits              SetPosLimits


     SetTextAttr
     -----------
     Объявление
     procedure SetTextAttr(Color, Mono : Byte); virtual;

     Назначение
     Устанавливает атрибуты для текста обычного окна.

     Описание
     Сохраняет заданные видеоатрибуты в полях данных  объекта.
Соответствующий  видеоатрибут  ( в зависимости от видеорежима)
будет использоваться при очищении или прокрутке окна  и  будет
назначен  константе  TextAttr модуля OPCRT,  когда окно станет
текущим.

     Пример

     Win.SetTextAttr($02, $70);

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

     См.также
     SetBackChar


     Store
     -----
     Объявление
     procedure Store(var S : IdStream);

     Назначение
     Сохраняет объект RawWindow в абстрактный последовательный
файл.

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

     Примеры

     uses
       OpCrt, OpRoot, OpFrame, OpWindow;
     var
       Win : RawWindow;
       S : BufIdStream;
       WinOpts : LongInt;
       I : Word;
     begin
       WinOpts := wBordered+wClear+wSaveContents+
                                              +wStoreContents;
       Win.InitCustom(30,    5,   50,   15,   DefaultColorSet,
       WinOpts);    Win.wFrame.AddHeader('Standard    Header',
       heTC);      Win.wFrame.AddScrollBar(frRR,     1,     9,
       DefaultColorSet); Win.Draw; for I := 2 to 10 do
         Win.wFastText('Hello Mars',  1, 5);
       Win.Erase;

       {Окно записывается в абстрактный последовательный файл}
       S.Init('RAWWIN.STM', SCreate, 1024);
       S.RegisterHier(RawWindowStream);
       S.Put(Win);
       S.Done;
       Win.Done;
     end.

     Создается объект  RawWindow,  добавляются  его  свойства,
объект заполняется текстом,  окно стирается, затем осуществля-
ется запись его в абстрактный последовательный файл, используя
метод  Put,  который косвенно вызывает процедуру Store объекта
RawWindow.  В пример включена  опция  wStoreContents,  поэтому
процедура Store будет производить запись содержимого окна Win.
     Для правильного осуществления проверки ошибок при исполь-
зовании абстрактных последовательных файлов следует обратиться
к описанию типа BufIdStream (в разделе OPROOT).

     begin
       WinOpts := wBordered+wClear+wSaveContents+
                                               +wStoreContents;
       Win.InitCustom(30, 5, 50, 15, DefaultColorSet, WinOpts);
       Win.Draw;
       for I := 2 to 10 do
         Win.wFastText('Hello Mars', I, 5);
       S.Init('RAWWIN.STM', SCreate, 1024);
       S.RegisterHier(RawWindowStream);
       S.Put(Win);
       ...
     end.

     Данный пример,  вероятно,  не даст ожидаемых результатов.
Опция wStoreContents включена, но содержимое окна не будет за-
писываться в абстрактный последовательный файл. Текст, находя-
щийся в окне,  ни разу не был скопирован в содержимое  объекта
ScreenRect. Нужно добавить обращение к процедуре Erase объекта
Win или перед записью в абстрактный последовательный файл  до-
бавить следующее:

     Win.StoreContents;

     См.также
     Frame.Store                ScreenRect.Store
     Load


     TweakSlider
     -----------
     Объявление
     {$IFDEF UseScrollBar}
     function TweakSlider(Posn : FrameEdgeType;
                                              0MousePosn : Byte;
                          UserVal : LongInt; Step : LongInt) :
                          LongInt;

     Назначение
     Корректирует пользовательскую величину до тех  пор,  пока
слайдер не совпадет с положением мыши.

     Описание
     В идеальном случае высокая разрешающая спо= mnSubPending;

Опции, используемые объектом Menu как внутренние. Методы mnOptionsOn
и mnOptionsOff не будут изменять эти биты из слова опций Menu.

   MenuKeyMax = 110;
   MenuKeyID  : string[16] = 'opmenu key array';
   MenuKeySet : array[0..Menu] of Byte = (...);
   MenuCfgEnd : Byte = 0;

MenuKeyID представляет собой строку ID, которая используется для то-
го, чтобы отметить начало области конфигурации  данных  для  OPMENU;
MenuCfgEnd  отмечает  конец  области конфигурации данных. Между ними
помещается MenuKeySet, таблица команд, используемая в  MenuCommands.
MenuKeyMax является последним допустимым индексом в таблице.

   MenuDepth  : Word = 8;

Начальное число объектов PointerStack, размещаемых объектом Menu для
того,  чтобы управлять вложенными подменю. Если одновременно активи-
зировано больше уровней, чем указано здесь, объекты PointerStack бу-
дут сами автоматически изменять это значение (наращивая его с  коэф-
фициентом 2), но будут фрагментарно использовать динамически распре-
деляемую область. Объект Menu предполагает 8 байт пространства дина-
мически распределяемой области для каждого приращения в MenuDepth.

   mnNotAKey           = $FFFFFFFF;

Это значение ключа элемента, которое эквивалентно "-1", резервирует-
ся модулем OPMENU для обозначения отсутствия "какого-либо конкретно-
го ключа". Если вы передаете это значение методу ItemsDoneCustom, то
OPMENU будет выбирать первый элемент подменю как элемент, выбираемый
по  умолчанию. Если вы перед тем, как вызвать Process, вызываете ме-
тод MenuChoice, то он будет возвращать значение mnNotAKey.

ПЫ

   mnCustomProc    = procedure (var Name : String; Key : LongInt;
                                Selected, Highlighted : Boolean;
                                WPtr : RawWindowPtr);

Процедурный тип, который определяет параметры процедуры строки наст-
ройки, задаваемой пользователем. Для получения более  детальной  ин-
формации  обратитесь  к разделу "Процедура настройки строки", приве-
денному выше.

   mnCurrentItemProc = procedure (CurrentItem : MenuItemNodePtr;
                                  MPtr : MenuPtr);

Процедурный тип, который  определяет  параметры  процедуры  текущего
элемента,  задаваемой  пользователем.  Для получения более детальной
информации обратитесь к разделу "Процедура текущего элемента",  при-
веденному выше.

   mnOrientation     = (Vertical, Horisontal, NoOrient);

Возможные виды ориентации MenuItemList. Значение "NoOrient" указыва-
ет на неправильно инициализированный список.

   mnItemProc        = procedure (IPtr : MenuItemNodePtr; var D;
                                  MPtr : MenuPtr);
   mnWindowProc      = procedure (WPtr : RawWindowPtr; var D;
                                  MPtr : MenuPtr);
   mnListProc        = procedure (LPtr : MenuItemListPtr; var D;
                                  MPtr : MenuPtr);
Процедурные типы  для  подпрограмм,  вызываемых соответственно с по-
мощью методов  VisitAllItems,  VisitAllWindows  и  VisitAllItemList.
Первый  параметр  определяет соответственно текущий элемент, текущее
окно или текущий список элементов. Второй,  нетипизованный  параметр
используется  для  того, чтобы передавать в каждую подпрограмму ука-
занные пользователем данные. Третий параметр всегда является адресом
системы меню.

   MenuPtr = ^Menu;
   Menu =
     object(CommandWindow)
       ...
     end;

Объект Menu.

ПЕРЕМЕННЫЕ

     MenuCommands : CommandProcessor;

  Принимаемое по умолчанию значение CommandProcessor для Menu. Эта пе-
  ременная инициализируется блоком инициализации модуля OPMENU.

______________________________________________________________________

A c t i v e I t e m P t r
______________________________________________________________________

О б ъ я в л е н и е
  function ActiveItemPtr : MenuItemNodePtr;

Н а з н а ч е н и е
  Возвратить указатель на текущий активный элемент.

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

П р и м е р
     HelpStr := M.ActiveItemPtr^.HelpString;

  Сохраняет строку помощи активного элемента.

С м о т р и   т а к ж е
  ActiveWinPtr
______________________________________________________________________

A c t i v e L i s t P t r
______________________________________________________________________

О б ъ я в л е н и е
  function  ActiveListPtr : MenuItemListPtr;

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

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

П р и м е р
    if ActiveListPtr^.Orientation = Vertical then
       {выполнить некоторое действие} ;

  Определяет, является  ли  активный список элементов вертикальным или
  горизонтальным.

С м о т р и   т а к ж е
  ActiveWinPtr
______________________________________________________________________

A c t i v e S u b P t r
______________________________________________________________________

О б ъ я в л е н и е
  function ActiveSubPtr : SubMenuPtr;

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

О п и с а н и е
  Если никакое  подменю  не  является  активным, то метод ActiveSubPtr
  возвращает "пустое" ("nil") значение. В противном случае он  возвра-
  щает  адрес того SubMenu, которое было самым последним отображено на
  экране или  добавлено с помощью AddSubMen.

С м о т р и   т а к ж е
  MenuItemNode.ChangeSubPtr
______________________________________________________________________

A c t i v e W i n P t r
______________________________________________________________________

О б ъ я в л е н и е
  function ActiveWinPtr : RawWindowPtr;

Н а з н а ч е н и е
  Возвратить указатель на активный объект RawWindow.
О п и с а н и е
  Если инициализируется  система меню (при этом все еще необходимо вы-
  зывать ItemsDone), то ActiveWinPtr возвращает  адрес  того  подменю,
  которое было последним добавлено в меню системы. (Этим адресом явля-
  ется адрес самого Menu, если никакие подменю еще не были добавлены.)
  Если система меню уже полностью инициализирована, но еще не выведена
  на  экран, то метод ActiveWinPtr также возвращает адрес самого меню.
  В противном случае он возвращает адрес активного  подменю.  Отметим,
  что  SubMenu и Menu получены прямо и косвенно из RawWindow, следова-
  тельно, они оба могут обрабатываться так же, как RawWindow, и  обес-
  печивается доступ ко всем методам и данным объекта RawWindow.

П р и м е р
    M.ActiveWinPtr^.ChangeHeader(HdrNum, NewHdrStr);

  Изменяет заголовок, относящийся к активному окну. Отметим, что к лю-
  бому  другому  методу объекта RawWindow (или Frame) можно обратиться
  подобным же образом.

С м о т р и   т а к ж е
  ActiveItemPtr
______________________________________________________________________

A d d F r a m e d S u b M e n u
______________________________________________________________________

О б ъ я в л е н и е
  procedure AddFramedSubMenu(X1, Y1, X2, Y2 : Byte;
                             Orient : mnOrientation;
                             FA : FrameArray);
Н а з н а ч е н и е
  Добавить обрамленное подменю с опциями и атрибутами цвета, заимство-
  ванными из основного меню.

О п и с а н и е
  К текущему  элементу  присоединяется  обрамленное подменю. Аргументы
  X1, Y1, X2 или Y2 указывают активные координаты  подменю  без  учета
  границ.  Аргумент  Orient  подменю  может  иметь значение "Vertical"
  (вертикальный) или "Horisontal" (горизонтальный), определяя ориента-
  цию списка элементов. Аргумент FA указывает массив символов, образу-
  ющих границу  окна.  Опции  окна,  относящегося  к  подменю  объекта
  RawWindow, будут соответствовать тем же опциям меню верхнего уровня.
  Цвета, используемые объектом SubMenu и его методом MenuItemList, бу-
  дут соответствовать атрибутам цвета меню верхнего уровня.

  Если на входе в метод AddFramedSubMenu обнаруживается  ошибка  Menu,
  то выполнение этого метода немедленно прекращается.

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

П р и м е р
    M.AddFramedSubMenu(4, 4, 20, 10, Vertical, DefWindowFrame);

  Добавляет обрамленное подменю к текущему элементу меню (т.е. к само-
  му последнему добавленному в меню элементу). Эта рамка будет  состо-
  ять  только  из  одного  ряда и одной колонки за пределами координат
  подменю: абсолютное размещение экрана соответствует координатам  (3,
  3)  для верхнего левого угла рамки и (21, 11) для ее нижнего правого
  угла. Элементы в этом подменю будут располагаться вертикально.

С м о т р и   т а к ж е
  AddSubMenu                            AddSubMenuCustom
______________________________________________________________________

A d d I t e m
______________________________________________________________________

О б ъ я в л е н и е
  procedure AddItem(Name : String; DisplayPos, SelectPos : Byte;
                    Key : LongInt);

Н а з н а ч е н и е
  Добавить элемент  к текущему списку элементов, помещая в динамически
  распределяемую область строку пробелов.

О п и с а н и е
  Элемент с указанными значениями Name ("Имя") и Key ("Ключ") добавля-
  ется в конец текущего списка элементов. Новый элемент становится те-
  кущим  элементом.  Аргумент DisplayPos указывает координаты элемента
  относительно левого или верхнего края окна, в зависимости  от  того,
  какую ориентацию имеет окно - горизонтальную или вертикальную. Аргу-
  мент SelectPos указывает, какой символ из аргумента Name должен быть
  выделен  как  алфавитно-цифровой символ, позволяющий осуществить вы-
  бор этого элемента. Если SelectPos имеет нулевое значение,  то  воз-
  можность  такого выбора исключена. Аргумент Key устанавливает значе-
  ние переменной типа  LongInt  (длинное  целое),  которое  однозначно
  идентифицирует этот элемент меню.

  Копия строки Name хранится в динамически распределяемой области. Ес-
  ли в этой области недостаточно места, то AddItem  генерирует  ошибку
  (epFatal+ecOutOfMemory).

  Если на входе в метод AddItem обнаруживается ошибка Menu, то  выпол-
  нение этого метода немедленно прекращается.

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

П р и м е р ы
    M.AddItem('File', 4, 1, 1);

  Добавляет элемент  с именем "File" в текущий уровень меню. При усло-
  вии, что текущее меню использует горизонтальную  ориентацию,  строка
  "File"  будет  отображаться  на расстоянии четырех колонок от левого
  края окна. Первая позиция строки ("F") будет  служить  символом  для
  выбора этого элемента. Ключом элемента является 1.

    M.AddFramedSubMenu(4, 4, 20, 10, Vertical, DefWindowFrame);
      M.AddItem('New', 1, 1, 2);
      M.AddItem('Save', 2, 1, 3);
      M.ItemDone;
  Создает подменю с двумя элементами: "New" и  "Save".  Элемент  "New"
  будет  расположен  в первом (верхнем) ряду окна и будет использовать
  первый символ ("N") в качестве символа для  выбора  этого  элемента.
  Элемент  "Save"  будет  расположен во втором ряду окна и также будет
  использовать свой первый символ в качестве символа выбора. Эти  эле-
  менты будут иметь соответственно ключи 2 и 3.

С м о т р и   т а к ж е
  AddItemPtr
______________________________________________________________________

A d d I t e m H e l p
______________________________________________________________________

О б ъ я в л е н и е
  procedure AddItemHelp(Name : String;
                        DisplayPos, SelectPos : Byte;
                        Key : LongInt; Help : String);

Н а з н а ч е н и е
  Добавить элемент к текущему списку элементов, помещая строки  "Name"
  и "Help" в динамически распределяемую область.

О п и с а н и е
  Работает совершенно так же, как AddItem, за исключением того, что  в
  динамически распределяемой области хранится также копия строки Help.
  К    этой    строке    помощи    можно    обращаться    с    помощью
  MenuItemNode.HelpString из процедуры текущего  элемента.  OPMENU  не
  делает  ничего со строкой помощи, за исключением того, что сохраняет
  и отыскивает ее для вас.

П р и м е р
    M.AddItemHelp('File', 4, 1, 1, 'Process files');

  Добавляет элемент с именем "File" к текущему уровню меню. Строка по-
  мощи "Process files" будет храниться  в  динамически  распределяемой
  области  и  может быть вызвана с помощью подпрограммы отображения на
  экране помощи.

С м о т р и   т а к ж е
  AddItemHelpPtr                     SetCurrentItemProc
______________________________________________________________________

A d d I t e m H e l p P t r
______________________________________________________________________

О б ъ я в л е н и е
  procedure AddItemHelpPtr(var Name : String;
                           DisplayPos, SelectPos : Byte;
                           Key : LongInt; var Help : String);

Н а з н а ч е н и е
  Добавить элемент  к  текущему  списку  элементов,  не помещая строки
  "Name" и "Help" в динамически распределяемую область.

О п и с а н и е
  Работает совершенно так же, как AddItemPtr, за исключением того, что
  хранится также адрес строки "Help". К этой строке помощи можно обра-
  щаться посредством метода MenuItemNode.HelpString из процедуры теку-
  щего элемента. OPMENU не делает ничего со строкой помощи, за  исклю-
  чением того, что сохраняет и отыскивает ее для вас.

П р и м е р ы
    const
      FileStr : String[4] = 'File';
      FileHelpStr : String[13] = 'Process files';
    begin
      ...
      M.AddItemHelpPtr(Filestr, 4, 1, 1, FileHelpStr);

  Добавляет элемент,  названный "File", к текущему уровню меню. Содер-
  жимое  строки  FileHelpStr  будет  возвращено   с   помощью   метода
  HelpString.

    var
      ItemStr : String;
      ItemHelpStr : String;
    begin
      ...
      ItemStr := 'File';
      ItemHelpStr := 'Process files';
      M.AddItemHelpPtr(Itemstr, 4, 1, 1, ItemHelpStr);
      ItemStr := 'Save';
      ItemHelpStr := 'Save the current file';
      M.AddItemHelpPtr(Itemstr, 5, 1, 2, ItemHelpStr);

  НЕВЕРНО! AddItemHelpPtr  сохраняет  адрес   переменных   Itemstr   и
  ItemHelpStr,  но  не их значения. Если вы изменяете их значения,  вы
  изменяете отображение меню на экране. Этот пример приведет к  выводу
  на  экран строки "Save" в том месте, где вы ожидаете увидеть "File".
  Вообще говоря, вы должны использовать только типизованные  константы
  в качестве аргументов для AddItemHelpPtr.

С м о т р и   т а к ж е
  AddItemHelp                            AddItemPtr
______________________________________________________________________

A d d I t e m P t r
______________________________________________________________________

О б ъ я в л е н и е
  procedure AddItemPtr(var Name : String;
                       DisplayPos, SelectPos : Byte;
                       Key : LongInt);

Н а з н а ч е н и е
  Добавить элемент к текущему  списку  элементов,  не  помещая  строку
  "Name" в динамически распределяемую область.

О п и с а н и е
  Работает так  же,  как  AddItem,  за  исключением  того,  что  метод
  AddItemPtr не размещает динамически распределяемую область для стро-
  ки "Name". Вместо этого он предполагает, что переменная,  переданная
  в позицию "Name", сохраняет свое значение на протяжении всего сущес-
  твования системы меню. Обычно это означает, что в "Name" должна быть
  передана типизованная константа. Метод AddItemPtr является более эф-
  фективным  методом  по  сравнению с методом AddItem вследствие того,
  что он исключает создание дублирующих копий каждого элемента "Name".
  Однако на вас возлагается обязанность обеспечить, чтобы строки,  со-
  держащие  имена элементов, оставались правильными все то время, пока
  используется система меню. Отметим, что MAKEMENU будет  генерировать
  соответствующие  типизованные  константы и вызовы метода AddItemPtr,
  если вы указываете опцию "строковые константы ".

  Обратите внимание  на  то,  что  типизованные константы Turbo Pascal
  хранятся в сегменте данных. Преимущество их хранения в сегменте дан-
  ных состоит в том, что константы никогда не будут перекрыты  модулем
  OVERLAY,  используемым  в Turbo Pascal. С другой стороны, объем сег-
  мента даннх не может превышать 64 Кбайт, и большая система меню  мо-
  жет использовать значительную долю этого пространства.

П р и м е р ы
    function InitMenu(var M : Menu) : Word;
    const
      FileStr : String[4] = 'File';
      EditStr : String[4] = 'Edit';
    begin
      ...
      M.AddItemPtr(Filestr, 4, 1, 1);
      M.AddItemPtr(Editstr, 20, 1, 4);

  Добавляет элементы с именами "File" и "Edit" к текущему уровню меню.
  Заметим, что типизованные константы могут быть объявлены внутри про-
  цедуры. Типизованные константы Turbo  Pascal  сохраняют  неизменными
  свои  значения  даже  в том случае, если та часть программы, где они
  были объявлены, не является активной.
    var
      ItemStr : String;
    begin
      ...
      ItemStr := 'File';
      M.AddItemPtr(Itemstr, 4, 1, 1);
      ItemStr := 'Save';
      M.AddItemPtr(Itemstr, 5, 1, 2);
  НЕВЕРНО! AddItemHelpPtr сохраняет адрес переменной Itemstr, но не ее
  значение. Если вы изменяете значение, вы изменяете отображение  меню
  на  экране.  Этот  пример приведет к выводу на экран строки "Save" в
  том месте, где вы ожидаете увидеть "File".

С м о т р и   т а к ж е
  AddItemHelpPtr
______________________________________________________________________

A d d S e p a r a t o r
______________________________________________________________________

О б ъ я в л е н и е
  procedure AddSeparator(FirstChar, SpanChar, LastChar : Char;
                         DisplayPos : Byte);

Н а з н а ч е н и е
  Добавить в  окно линейку-разделитель со смещением, заданным аргумен-
  том DisplayPos.

О п и с а н и е
  Метод AddSeparator   генерирует   соответствующий    вызов    метода
  AddSpanHeaderColor  для  основной рамки активного окна. Если относя-
  щийся к этому окну список элементов является вертикальным, то линей-
  ка-разделитель  располагается  горизонтально  и  наоборот.  Аргумент
  FirstChar  указывает собой символ, из которых составлена верхняя или
  левая граница окна; LastChar указывает символ, из которых составлена
  его нижняя или правая граница. Символ, заданный с помощью  SpanChar,
  путем  его последовательного повторения используется для изображения
  самого разделителя окна, "стягивающего" его границы.  Если  меню  не
  имеет  границы, то укажите для аргументов FirstChar и LastChar такое
  же значение, как и для аргумента SpanChar. Аргумент DisplayPos пред-
  ставляет собой смещение от левого или верхнего края  (соответственно
  для горизонтальных  или вертикальных меню) до того места, где распо-
  лагается  разделитель,  образуя  в  рамке  перемычку.  Заметим,  что
  DisplayPos определяется согласованно с аналогичным параметром, пере-
  даваемым  в AddItem. Например, если элементы вашего меню расположены
  в 1, 2 и 4 рядах вертикального меню, и вы  хотите  установить  между
  ними линейку-разделитель,  то  вам  нужно  в  AddSeparator   указать
  значение DisplayPos = 3.

  Цвет линейки-разделителя  соответствует  цвету  символов, образующих
  границу для окна.

  Если на  входе  в  метод AddSeparator обнаруживается ошибка Menu, то
  выполнение этого метода немедленно прекращается.

  Для получения более подробной информации и полной  программы-примера
  обратитесь к разделу "Настройка меню".

П р и м е р
    M.AddSeparator(#195, #196, #180, 3);

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

A d d S e p a r a t o r C o l o r
_______________________________________________________________________

О б ъ я в л е н и е
    procedure AddSeparatorColor(FirstChar, SpanChar, LastChar : Char;
                                DisplayPos : Byte;
                                AttrColor, AttrMono : Byte);
Н а з н а ч е н и е
  Добавить линейку-разделитель   со   смещением,  заданным  аргументом
  DisplayPos, в окно, использующее указанные цвета.

О п и с а н и е
  Работает абсолютно  так  же,  как AddSeparator, за исключением того,
  что линейка-разделитель будет изображена с учетом  заданных  атрибу-
  тов.

П р и м е р
    M.AddSeparatorColor(#195, #196, #180, 3, $02, $07);

  Добавляет цветную  линейку-разделитель в текущий уровень меню (зеле-
  ный цвет на черном фоне для цветных мониторов,  обычное  изображение
  для монохромных мониторов).
______________________________________________________________________

A d d S h a d o w s
______________________________________________________________________

О б ъ я в л е н и е
  {$IFDEF UseShadows}
  procedure AddShadows(MainMenu : Boolean; Posn : ShadowPosType;
                       DrawType : ShadowDrawType);

Н а з н а ч е н и е
  Добавить тени ко всем подменю.

О п и с а н и е
  Если аргумент  MainMenu имеет значение "False" ("Ложь"), то тени бу-
  дут добавлены ко всем подменю, кроме меню верхнего уровня.  Аргумент
  Posn  задает  положение  тени (shBR - "тень снизу справа" или shBL -
  "тень снизу слева"), в то время  как  аргумент  DrawType  определяет
  стиль  тени  (shSeeThru  - "тень прозрачная" или shOverWrite - "тень
  поверх  записи").  Цвет  тени  определяется  значениями   аргументов
  ShadowColor  и ShadowMono в ColorSet, который используется для того,
  чтобы инициализировать систему меню.

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

  Если на входе в метод AddShadow обнаруживается ошибка Menu,  то  вы-
  полнение этого метода немедленно прекращается.

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

П р и м е р
    M.AddShadow(False, shBR, shOverWrite);
  Добавляет непрозрачные тени снизу и справа ко  всем  подменю  (кроме
  основного меню).

С м о т р и   т а к ж е
  Frame.AddShadow
______________________________________________________________________

A d d S u b M e n u
______________________________________________________________________

О б ъ я в л е н и е
  procedure AddSubMenu(X1, Y1, X2, Y2 : Byte;
                       Orient : mnOrientation);

Н а з н а ч е н и е
  Добавить необрамленное подменю с опциями и атрибутами цвета, заимст-
  вованными из основного меню.

О п и с а н и е
  Работает совершенно так же, как AddFramedSubMenu, за исключением то-
  го, что новое подменю не имеет границы.

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

П р и м е р
    M.AddSubMenu(1, 1, Screenwidth, 1, Horizontal);

  Добавляет необрамленное подменю к текущему  элементу  меню  (т.е.  к
  последнему элементу,  который  был  добавлен).  Это подменю занимает
  всего одну строку и простирается во весь верхний ряд экрана. Элемен-
  ты будут размещены горизонтально. Такие параметры характерны для ме-
  ню в стиле Lotus.

С м о т р и   т а к ж е
  AddFramedSubMenu                     AddSubMenuCustom
______________________________________________________________________
                                                                                                                                                                                                                                                               
A d d s u b M e n u C u s t o m
______________________________________________________________________
                                                                                                                                                                                                                                                               
О б ъ я в л е н и е
  procedure AddSubMenuCustom(X1, Y1, X2, Y2 : Byte;
                             var Colors : ColorSet;
                             Options : LongInt;
                             Orient : mnOrientation;
                             FA : FramedArray);
                                                                                                                                                                                                                                                               
Н а з н а ч е н и е
  Добавить подменю с опциями настройки окна.
                                                                                                                                                                                                                                                               
О п и с а н и е
  Этот метод  сочетает  в  себе  всю  гибкость  методов  AddSubMenu  и
  AddFramedSubMenu с дополнительными возможностями  управления  цветом
  окон и их опциями.
     
  К списку элементов подменю могут быть  отнесены  следующие  поля  из
  ColorSet:
     
    TextColor, TextMono                    - нормальные элементы
    SelItemColor, SelItemMono              - выбранный элемент
    HighItemColor, HighItemMono            - выделенные элементы
    ProItemColor, ProItemMono              - защищенные элементы

  Те поля, которые обычно относятся к границе окна, заголовкам  и  те-
  ням, будут применимы к самому SubMenu.
       
  Перед тем,  как  использовать  указанное для окна значение аргумента
  Options, метод AddSubMenuCustom отключает опцию mnResizeable и вклю-
  чает опции wUserContents и wClear.
     
П р и м е р
    M.AddSubMenuCustom(4, 4, 20, 10, MyColorSet,
                       DefWindowOptions or wBordered or wSoundEffects,
                       Vertical, DefWindowFrame);
    M.ActiveWinPtr^.EnableExplosions(15);
     
  Добавляет обрамленное подменю к текущему элементу меню (т.е. к  пос-
  леднему добавленному к меню элементу). Граница окна будет нарисована
  с использованием тех символов, которые используются по умолчанию для
  оформления рамки окна. Это подменю будет использовать указанный цве-
  товой набор  и будет создавать звуковые эффекты при мгновенных отоб-
  ражениях окон.
     
С м о т р и   т а к ж е
  AddFramedSubMenu                            AddSubMenu
______________________________________________________________________
  
C u r r e n t I t e m
______________________________________________________________________

О б ъ я в л е н и е
  procedure CurrentItem(IPtr : MenuItemNodePtr); virtual;
                                                                                                                                                                                                                                                               
Н а з н а ч е н и е
  Вызвать процедуру текущего элемента сразу же после того, как на  эк-
  ране будет нарисован текущий выбранный элемент.
     
О п и с а н и е
  Этот метод вызывает "процедуру текущего элемента", которая была ука-
  зана с помощью метода SetCurrentItemProc. Типы,  полученные из Menu,
  могут  отвергать  этот  метод с тем, чтобы обеспечить альтернативное
  поведение.
     
С м о т р и   т а к ж е
  SetCurrentItemProc
______________________________________________________________________
                                                                                                                                                                                                                                                               
D e f a u l t I t e m
______________________________________________________________________
                                                                                                                                                                                                                                                               
О б ъ я в л е н и е
  procedure DefaultItem(Key : LongInt);
                                                                                                                                                                                                                                                               
Н а з н а ч е н и е
  Сделать элемент с ключом Key выбираемым по умолчанию из своего  под-
  меню. Не обновлять экран.
     
О п и с а н и е
  Если указанный ключ Key элемента найден где-либо в системе меню, ме-
  тод  DefaultItem  делает соответствующий этому ключу элемент элемен-
  том, который выбирается из своего подменю по  умолчанию.  Когда  это
  подменю  будет выбираться в следующий раз, этот элемент станет теку-
  щим элементом. DefaultItem не обновляет экран  независимо  от  того,
  отображена уже на экране система меню или нет.
     
П р и м е р ы
    M.DefaultItem(11);

  Делает элемент меню с ключом 11 элементом, выбираемым по умолчанию в
  своем подменю.
         
    M.DefaultItem(11);
    M.DefaultItem(10);
  При том условии, что элементы 10 и 11 находятся в  одном  и  том  же
  подменю, элемент 10 будет элементом по умолчанию, так как он был ус-
  тановлен для значения по умолчанию последним.
     
С м о т р и   т а к ж е
  SelectItem
______________________________________________________________________
 
D e f a u l t P a t h
______________________________________________________________________
     
О б ъ я в л е н и е
  procedure DefaultPath(Key : LongInt);
                                                                                                                                                                                                                                                               
Н а з н а ч е н и е
  Выбрать маршрут к указанному элементу.
                                                                                                                                                                                                                                                               
О п и с а н и е
  Если система меню уже отображена на экране, то DefaultPath  вызывает
  метод  SelectItem  для того, чтобы выбрать указанный элемент и обно-
  вить экран. В противном случае DefaultItem находит указанный элемент
  и строит внутренний стек. Когда в следующий раз будут вызваны методы
  Process или Draw, на экране будут отображаться все подменю,  которые
  приводят к данному элементу, и этот элемент будет выделен.
                                 
  Если не  найден  никакой  элемент,  соответствующий  ключу  Key,  то
  DefaultPath не выполняет никаких действий.
  
П р и м е р
   repeat
     M.Process;
     case M.GetLastCommand of
       ccQuit : Finished := True;
       ccUser0 : M.DefaultPath(11);
     else
       case M.MenuChoice of
         1 : {Выполнить выбор 1};
         2 : {Выполнить выбор 2};
         {...}
       end;
     end;
   until Finished;
     
  Команда выхода ccUser0 используется как способ быстрого вызова  эле-
  мента меню, имеющего ключ 11. При следующем выполнении цикла элемент
  с ключом 11 будет выделен, т.е. готов для того, чтобы его выбрали.
     
С м о т р и   т а к ж е
   SelectItem
______________________________________________________________________
                                                                                                                                                                                                                                                               
D o n e
______________________________________________________________________
     
О б ъ я в л е н и е
  destructor Done; virtual;
                                                                                                                                                                                                                                                               
Н а з н а ч е н и е
  Разрушить систему меню.
                                                                                                                                                                                                                                                               
О п и с а н и е
  Освобождается вся динамически распределяемая область, занятая систе-
  мой меню. Метод Done использует рекурсивный алгоритм для того, чтобы
  выполнить  трассировку все элементы и все подменю. Если система меню
  изображена на экране в тот момент, когда вызывается метод Done,  она
  сначала удаляется.
  
П р и м е р
    M.Done

  Удаляет систему  меню с экрана и отменяет все размещение динамически
  распределяемой области, которое она использовала.
     
С м о т р и   т а к ж е
  CommandWindow.Done
______________________________________________________________________
 
E n a b l e A l l A l t e r n a t e O p e n
______________________________________________________________________
 
О б ъ я в л е н и е
 procedure EnableAllAlternateOpen(OpenProc, CloseProc : RawWindowProc;
                                  StageDelay : Word);
     
Н а з н а ч е н и е
  Сделать возможным альтернативное построение  изображения  и  удалить
  подпрограммы.
     
О п и с а н и е
  EnableAllAlternateOpen вызывает  метод  EnableAlternateOpen  объекта
  RawWindow для каждого окна в системе меню.
  
  Этот метод  следует  вызывать  только  после того, как все подменю и
  элементы уже добавлены к системе меню.
     
  Если на  входе  в метод EnableAllAlternateOpen обнаруживается ошибка
  Menu, то выполнение этого метода немедленно прекращается.
                                                                                                                                                                                                                                                               
П р и м е р
    M.EnableAllAlternateOpen(MyOpenProc, MyCloseProc, 10);
                                                                                                                                                                                                                                                               
  Включает использование альтернативных процедур открывания/закрывания
  (MyOpenProc, MyCloseProc), устанавливая отсрочку между стадиями в 10
  миллисекунд.
     
  Смотрите описание метода RawWindow.EnableAlternateOpen для  ознаком-
  ления  с полным примером альтернативных процедур открывания/закрыва-
  ния.
     
С м о т р и   т а к ж е
  EnableALLExplosions                 EnableAllNormalOpen
______________________________________________________________________
E n a b l e A l l E x p l o s i o n s
______________________________________________________________________
О б ъ я в л е н и е
  procedure EnableAllExplosions(StageDelay : Word);
Н а з н а ч е н и е
  Обеспечивает возможность мгновенного отображения окон,  устанавливая
  с помощью аргумента StageDelay отсрочку между стадиями в миллисекун-
  дах.
     
О п и с а н и е
  EnableAllExplosions вызывает    метод    EnableExplosions    объекта
  RawWindow для каждого окна в системе меню.
     
  Этот метод следует вызывать только после того,  как  все  подменю  и
  элементы уже добавлены к системе меню.
     
  Если на входе  в  метод  EnableAllExplosions  обнаруживается  ошибка
  Menu, то выполнение этого метода немедленно прекращается.
     
П р и м е р
    M.EnableAllExplosions(10);
                                                                                                                                                                                                                                                               
  Включает режим мгновенного отображения/стирания окон в основном меню
  и во всех подменю.
     
С м о т р и   т а к ж е
  EnableAllAlternateOpen
______________________________________________________________________
  
E n a b l e A l l N o r m a l O p e n
______________________________________________________________________
     
О б ъ я в л е н и е
  procedure EnableAllNormalOpen;

Н а з н а ч е н и е
  Делает недоступным мгновенное отображение  окон  или  альтернативные
  подпрограммы построения изображения.
     
О п и с а н и е
  EnableAllNormalOpen вызывает    метод    EnableNormalOpen    объекта
  RawWindow для каждого окна в системе меню.
     
  Этот метод  следует  вызывать  только  после того, как все подменю и
  элементы уже добавлены к системе меню.
     
  Если на  входе  в  метод  EnableAllNormalOpen  обнаруживается ошибка
  Menu, то выполнение этого метода немедленно прекращается.
     
П р и м е р
   M.EnableAllNormalOpen;
                                                                                                                                                                                                                                                               
  Отключает режим мгновенного отображения/стирания окон в основном ме-
  ню и во всех подменю.
     
С м о т р и   т а к ж е

EnableAllAlternateOpen
______________________________________________________________________
     
E r a s e
______________________________________________________________________
О б ъ я в л е н и е
  procedure Erase; virtual;
Н а з н а ч е н и е
  Удалить систему меню. "Запоминает" предыдущие подменю для построения
  следующего изображения.
     
О п и с а н и е
  Отменяет обычный  метод  Erase  для  того, чтобы удалять все видимые
  подменю и меню верхнего уровня. Объект сохраняет внутреннюю запись о
  том, что подменю являются видимыми; когда в следующий раз вызываются
  методы Draw или Process, будут нарисованы те же самые подменю и  вы-
  cвечены те же самые элементы.
     
  Подобно методу StackWindow.Erase, этот метод следует вызывать только
  в том случае, если система меню содержит текущее окно. Это означает,
  что  если поверх системы меню изображено другое окно, не имеющее ме-
  ню, то метод Erase не будет работать. Чтобы обработать такую  ситуа-
  цию,    вам   необходимо     вместо   этого   метода вызвать   метод
  StackWindow.EraseHidden. (EraseHidden  вызывает  метод  Erase  после
  включения в виртуальный экран и удаления всех окон, имеющихся поверх
  указанного окна. Вследствие того, что метод Erase является виртуаль-
  ным,  для  удаления  меню следует вызывать именно тот метод, который
  описан здесь.)
     
П р и м е р
     M.Erase;
  
  Удаляет меню, но не осуществляет  никаких  изменений  его  начальных
  значений.  Когда это меню будет изображено в следующий раз, оно поя-
  вится точно в таком же состоянии, каким было перед тем, как его уда-
  лили.
                                                                                                                                                                                                                                                               
С м о т р и   т а к ж е
  EraseAllSubMenus                          StackWindow.Erase
  EraseClear
______________________________________________________________________
E r a s e A l l S u b M e n u s
______________________________________________________________________
О б ъ я в л е н и е
  procedure EraseAllSubMenus(ShowSelect, ShowHighlight : Boolean);
Н а з н а ч е н и е
  Удалить все подменю, оставить основное меню, показывая его в указан-
  ном состоянии.
     
О п и с а н и е
  Удаляет все  подменю,  кроме  меню верхнего уровня. Список элементов
  верхнего  уровня  перерисовывается  в  соответствии  с  параметрами.
  ShowSelect  контролирует  наличие в текущем элементе линейки выбора.
  ShowLight контролирует, выделяются ли в каждом  элементе  алфавитные
  поисковые  символы.  Одновременно  EraseAllSubMenus обновляет флажки
  опций mnMainSelect и mnMainHighlight.
     
  Если на  входе  в метод EraseAllSubMenus обнаруживается ошибка Menu,
  то выполнение этого метода немедленно прекращается.
  
П р и м е р
   repeat
     M.Process;
     case M.GetLastCommand of
       ccQuit :
         begin
           M.EraseAllSubMenus(False, False);
           Finished := True;
         end;
       ccSelect :
         case M.MenuChoice of
           1..8 :
             {...Осуществляйте выбор меню...};
           9..11 :
             begin
               {...Осуществляйте выбор меню...}
               M.EraseAllSubMenus(True, True);
             end;
           {...}
         end;
     end;
   until Finished;
  Если в то время, когда меню верхнего уровня активно, нажата  клавиша
  <Esc> (инициируя команду выхода ccQuit), то меню верхнего уровня ос-
  тается видимым, но выделение отменяется; обработка цикла  также  за-
  канчивается. После выбора позиций меню с 1 по 8 система меню остает-
  ся  неизмененной.  Для опций меню 9, 10 и 11 мы удаляем все подменю,
  но продолжаем обработку на верхнем уровне.
     
С м о т р и   т а к ж е
  Erase                               EraseCurrentSubMenu
  EraseClear
______________________________________________________________________
E r a s e C l e a r
______________________________________________________________________
О б ъ я в л е н и е
  procedure EraseClear;
Н а з н а ч е н и е
  Удалить меню и очистить активные подменю  для  построения  следующих
  изображений.
                                                                                                                                                                                                                                                               
О п и с а н и е
  Работает так же, как Erase, за исключением того, что когда в следую-
  щий  раз будет изображаться система меню, на экране будет появляться
  только меню верхнего уровня, независимо от того, сколько подменю бы-
  ли вложенными в тот раз, когда оно было удалено. Однако элемент  вы-
  бираемый  в  каждом  подменю по умолчанию, сохраняет свое предыдущее
  значение.

П р и м е р
    M.EraseClear

  Удаляет все меню с экрана и очищает внутренний стек меню.
  
С м о т р и   т а к ж е
  Erase                                  EraseAllSubMenus
______________________________________________________________________
  
E r a s e C u r r e n t S u b M e n u
______________________________________________________________________
     
О б ъ я в л е н и е
  procedure EraseCurrentSubMenu
Н а з н а ч е н и е
  Удалить текущее подменю.
О п и с а н и е
  Удаляется только текущее подменю. Этот метод не эффективен,  если  в
  момент  его  вызова  на  экране было изображено только меню верхнего
  уровня. Характеристики выбора и выделения для меню  верхнего  уровня
  не  изменяются даже в том случае, если оно остается единственным ви-
  димым   меню    после    вызова    (в    противоположность    методу
  EraseAllSubMenus).
     
  Отметим, что такой же эффект может быть получен автоматически  путем
  установки  опции mnPopOnSelect. Однако опция работает не избиратель-
  но, в то время как метод EraseCurrentSubMenu может быть  применен  к
  указанным элементам, как это показано в следующем примере.
     
П р и м е р
   repeat
     M.Process;
     case M.GetLastCommand of
       ccQuit : begin
                  M.EraseAllSubMenus(False, False);
                  Finished := True;
                end;
       ccSelect :
         case M.MenuChoice of
           1..8 : {...Осуществляйте выбор меню...};
           9..11 : begin
                     {...Осуществляйте выбор меню...}
                     M.EraseCurrentSubMenu;
                   end;
           {...}
         end;
     end;
   until Finished;

  После выбора  позиций меню с 1 по 8 система меню остается неизменен-
  ной. Для опций меню 9, 10 и 11 мы удаляем все подменю, но продолжаем
  обработку на предыдущем уровне.
     
С м о т р и   т а к ж е
  EraseAllSubMenus
______________________________________________________________________
                                                                                                                                                                                                                                                               
F i n d I t e m
______________________________________________________________________
                                                                                                                                                                                                                                                               
О б ъ я в л е н и е
  function FindItem(Key : LongInt) : MenuItemNodePtr;
                                                                                                                                                                                                                                                               
Н а з н а ч е н и е
  Возвратить указатель на узел элемента.
                                                                                                                                                                                                                                                               
О п и с а н и е
  Метод FindItem осуществляет поиск полного дерева меню для элемента с
  указанным ключом Key. Если такой элемент не найден, то он возвращает
  пустое значение. В противном случае он возвращает адрес соответству-
  ющего MenuItemNode, который может быть использован для  того,  чтобы
  получить доступ к методам и полям данных объекта для этого элемента.
     
П р и м е р
     case M.GetLastCommand of
       ccQuit  : Finished := True;
       ccUser0 : begin
                   IPtr := M.FindItem(10);
                   if not IPtr^.ChangeName('Copy') then
                     {ошибка};
                   M.Redraw;
                 end;
       ccSelect :
         {Обработайте выбор меню} ;
     end;
                                                                                                                                                                                                                                                               
  Команда выхода  "0"  пользователя  изменяет  имя элемента 10 меню на
  значение "Copy".
     
С м о т р и   т а к ж е
  ActiveItemPtr
______________________________________________________________________

G e t H e l p A t t r
______________________________________________________________________
     
О б ъ я в л е н и е
  procedure GetHelpAttr(var Color, Mono : Byte);
                                                                                                                                                                                                                                                               
Н а з н а ч е н и е
  Получить атрибуты цвета, сохраненные для строки помощи.
  
О п и с а н и е
  Эта подпрограмма просто возвращает значения атрибутов ,  сохраненные
  с  помощью  метода SetHelpAttr. OPMENU никогда в действительности не
  использует эти цвета; она просто их сохраняет  для  использования  в
  подпрограммах текущих элементов, написанных пользователем.
     
П р и м е р
    {$F+}
    procedure CurrentItemProc(CurrentItem : MenuItemNodePtr;
                              MPtr : MenuPtr};
    var
       Color, Mono, Attr : Byte;
    begin
      MPtr^.GetHelpAttr(Color, Mono);
      if UseColor then
        Attr := Color
      else
        Attr := Mono;
      FastWrite(CurrentItem^.HelpString, ScreenHeight, 1, Attr);
    end;

  Подпрограмма текущего элемента, которая записывает строку помощи для
  элемента  в  нижний ряд, используя видео атрибуты, сохраненные с по-
  мощью метода SetHelpAttr.
     
С м о т р и   т а к ж е
  SetCurrentItemProc                          SetHelpAttr
______________________________________________________________________
                                                                                                                                                                                                                                                               
I n i t
______________________________________________________________________
                                                                                                                                                                                                                                                               
О б ъ я в л е н и е
  constructor Init(X1, Y1, X2, Y2 : Byte; Orient : mnOrientation);
                                                                                                                                                                                                                                                               
Н а з н а ч е н и е
  Создать меню с опциями и атрибутами цвета, принятыми по умолчанию.
                                                                                                                                                                                                                                                               
О п и с а н и е
  Этот конструктор вводит Menu, используя значения  по  умолчанию  для
  опций окон (DefMenuOptions), значения по умолчанию для набора цветов
  (DefaultColorSet)   и   значения   по   умолчанию   для  опций  меню
  (DefWindowOptions). Для получения более подробной информации смотри-
  те описание InitCustom.
     
П р и м е р
    if not M.Init(1, 1, ScreenWidth, 1, Horisontal) then begin
      WriteLn('Failed to Init Menu, Status = ', InitStatus);
      Halt;
    end;

  Вводит горизонтальное меню, используя значения по умолчанию для  оп-
  ций окон и атрибутов цвета. Вследствие того, что активные координаты
  меню  охватывают  экран полностью, мы можем догадаться, что это меню
  не имеет обрамления.
     
С м о т р и   т а к ж е
  InitCustom
______________________________________________________________________
                                                                                                                                                                                                                                                               
I n i t C u s t o m
______________________________________________________________________
                                                                                                                                                                                                                                                               
О б ъ я в л е н и е
  constructor InitCustom(X1, Y1, X2, Y2  :  Byte;
                         var  Colors  : ColorSet; Options : LongInt;
                         Orient : mnOrientation);
                                                                                                                                                                                                                                                               
Н а з н а ч е н и е
  Создать меню с  опциями настройки окон.
     
О п и с а н и е
  Этот конструктор  определяет характеристики меню верхнего уровня для
  системы меню. Элементы и подменю добавляются с помощью более поздних
  вызовов методов AddItem и AddSubMenu и родственных им методов.
     
  X1, Y1, X2 и Y2 определяют координаты активного окна, внутри которо-
  го будет изображаться список элементов.
     
  InitCustom отбирает определенные поля из указанного ColorSet для то-
  го,  чтобы использовать их во время построения изображения меню. По-
  мимо тех полей, которые используются в окнах в общем  случае,  метод
  InitCustom  хранит следующие поля в MenuItemList, относящемся к меню
  верхнего уровня:
     
     TextColor, TextMono                  - нормальные элементы
     SelItemColor, SelItemMono            - выбранный элемент
     HighItemColor, HighItemMono          - выделенные символы
     ProItemColor, ProItemMono            - защищенные элементы
     
  Отметим, что  выделенные символы применимы только к невыбранным, не-
  защищенным элементам. Выбранный элемент изображается в  SelItemColor
  или SelItemMono одинаково.
     
  Опции представляют собой флажки с определенным образом установленны-
  ми  битами,  которые  применимы  ко  всем  объектам,  полученным  из
  RawWindow, например, таким, как wBordered. Для получения более  под-
  робной  информации смотрите раздел "Константы RawWindow". InitCustom
  включает  флажок  wUserContents,  т.к.   Menu   обеспечивает   метод
  UpdateContents,  который может повторно генерировать содержимое окон
  по запросу. Он выключает флажок wResizeable, т.к.  размеры  меню  не
  могут быть изменены (за исключением того, что они могут быть измене-
  ны  с помощью MAKEMENU, которая принимает специальные меры предосто-
  рожности).
     
  Параметр Orient характеризует ориентацию списка элементов меню верх-
  него  уровня.  Этот   параметр   может   принимать   значения   либо
  "Horisontal", либо "Vertical".
     
  Наряду с  размещением  для  CommandWindow динамически распределяемой
  области  метод  InitCustom  также   размещает   два   ввода   метода
  PointerStack,  каждый  из  которых  способен содержать указатели (по
  умолчанию до 8) для метода MenuDepth. Эти стеки используются для то-
  го, чтобы управлять активными подменю. Если система меню будет глуб-
  же 8 уровней, то прежде чем вызывать конструктор, вам необходимо от-
  регулировать значение MenuDepth (которое является типизованной конс-
  тантой). Это позволит избежать фрагментирования динамически  распре-
  деляемой области, которое могло быть произойти в том случае, если бы
  методы PointerStack изменяли размеры сами.
     
  Метод InitCustom   присваивает  значения  опций  меню  по  умолчанию
  (DefMenuOptions)  в  меню,  но  он  включает  опции  mnMainSelect  и
  mnMainHighlight.
     
  Командный процессор MenuCommands присваивается  объекту  Menu.  Меню
  назначается коду модуля ucMenu (для того, чтобы идентифицировать его
  при  работе  программ обработки ошибок и управления помощью). Курсор
  клавиатуры устанавливается так, чтобы ввести режим команды cuHidden,
  принятый по умолчанию.
     
  Определяемые пользователем  процедуры строки и текущего элемента ус-
  танавливаются в режим "отсутствия выполнения".
     
  Если конструктор  завершит  работу  аварийно,  проверьте  переменную
  InitStatus , чтобы получить подробный код ошибки.
     
П р и м е р ы
 if not M.InitCustom(2, 2, ScreenWidth-1, 2,         {координаты Menu}
                     DefaultColorSet,                {ColorSet}
                     DefWindowOptions or wBordered,  {опции Window}
                     Horisontal)                     {ориентация Menu}
 then begin
   WriteLn('Failed to Init Menu, Status = ', InitStatus);
   Halt;
  end;
                                                                                                                                                                                                                                                               
  Вводит обрамленное  горизонтальное  меню,  используя  значения опций
  цвета, принятые по умолчанию.
     
 if not M.InitCustom(1, 1, ScreenWidth, 1,           {координаты Menu}
                     DefaultColorSet,                {ColorSet}
                     DefWindowOptions или wBordered, {опции Window}
                     Horisontal)                     {ориентация Menu}
 then begin
   WriteLn('Failed to Init Menu, Status = ', InitStatus);
   Halt;
 end;

  НЕВЕРНО! Будет запрашиваться рамка для окна, но размеры окна  остав-
  ляют достаточно пространства для рамки.
  (Прим. перев.: очевидно, здесь ошибка, должно быть написано  "не ос-
  тавляют".)
     
С м о т р и   т а к ж е:
  CommandWindow.InitCustom                 Init
______________________________________________________________________
I s C u r r e n t
______________________________________________________________________
О б ъ я в л е н и е
  function IsCurrent : Boolean; virtual;
                                                                                                                                                                                                                                                               
Н а з н а ч е н и е
  Возвратить значение  "True"  ("Истина"),  если система меню является
  текущим окном.
     
О п и с а н и е
  Работает так же, как метод RawWindow.IsCurrent, за исключением того,
  что  данный  метод возвращает значение "True" в том случае, если для
  любой части этого меню метод IsCurrent возвращает значение "True".
     
П р и м е р
    if M.IsCurrent then
      M.Erase;
                                                                                                                                                                                                                                                               
  Удалить систему меню в том случае, если одно из ее подменю (или меню
  верхнего уровня) является текущим окном.
     
С м о т р и   т а к ж е
    RawWindow.IsCurrent
______________________________________________________________________
  
I t e m s D o n e
______________________________________________________________________
  
О б ъ я в л е н и е
  procedure ItemsDone;

Н а з н а ч е н и е
  Окончить составление текущего списка элементов. Первый элемент уста-
  новить в качестве того элемента, который выбирается по умолчанию.
     
О п и с а н и е
  Вы должны вызывать этот метод (или ItemsDoneCustom) после того,  как
  добавили  в конкретное подменю все элементы. Затем OPMENU выводит на
  экран внутренний стек, поэтому в дальнейшем элементы будут вводиться
  в предыдущее активное подменю.
     
  Для получения более подробной информации и полной  программы-примера
  обратитесь к разделу "Построение системы меню".
     
П р и м е р
   M.AddFramedSubMenu(4, 4, 20, 7, Vertical, DefWindowFrame);
     M.AddItem('New',  1, 1, 2);
     M.AddItem('Save', 2, 1, 3);
     M.AddItem('Dos',  3, 1, 20);
     M.ItemsDone;
                                                                                                                                                                                                                                                               
  Создает подменю, добавляет в него три элемента и  закрывает  подменю
  посредством  вызова ItemsDone. В тот момент, когда это подменю будет
  вызвано на экран, в нем будет выделен первый элемент (New). Вследст-
  вие  того,  что  ItemsDone  не оптимизирует размер подменю, в нижней
  части окна будет расподложен ряд, состоящий из пробелов (окно  имеет
  четыре ряда и только три элемента).
     
С м о т р и   т а к ж е
  ItemsDoneCustom
______________________________________________________________________
I t e m s D o n e C u s t o m
______________________________________________________________________
О б ъ я в л е н и е
  procedure ItemsDoneCustom(OptimizeSize : Boolean;
                           DefaultKey : LongInt);
Н а з н а ч е н и е
  Окончить составление текущего списка элементов и настроить размер  и
  ключ для элемента, выбираемого по умолчанию.
     
О п и с а н и е
  Вы должны вызывать этот метод (или ItemsDone) после того, как  доба-
  вили  в конкретное подменю все элементы. Затем OPMENU выводит на эк-
  ран внутренний стек, поэтому в дальнейшем элементы будут вводиться в
  предварительно активное подменю. Если  параметр  OptimizeSize  имеет
  значение "True" (и в OPDEFINE.INC разрешается устанавливать значения
  условной компиляции метода UseAdjustableWindows), то ItemsDoneCustom
  переопределяет  размер  подменю  таким образом, чтобы точно охватить
  рамкой имеющиеся элементы. Он рассчитывает размер на основе ориента-
  ции подменю, длины названия каждого элемента, а также длины маркеров
  выбора и наличия "заполнителя" (padding) на момент вызова.
     
  Метод DefaultKey определяет тот элемент, который должен быть  выбран
  из  подменю  по умолчанию. Если указанный ключ не найден, то элемен-
  том, выбираемым по умолчанию, становится первый незащищенный элемент
  в подменю. Если заданный с помощью ключа элемент  является  защищен-
  ным,  то  по  умолчанию будет выбран из подменю самый близкий к нему
  предшествующий элемент. В эту позицию может быть передана  константа
  mnNotAKey  (значение которой равно "-1"), чтобы выбрать по умолчанию
  первый элемент.
     
  Для получения более подробной информации обратитесь к разделу "Пост-
  роение системы меню".
     
П р и м е р
   M.AddFramedSubMenu(4, 4, 20, 10, Vertical, DefWindowFrame);
     M.AddItem('New',      1, 1, 2);
     M.AddItem('Save    ', 2, 1, 3);
     M.AddItem('Dos',      3, 1, 4);
     M.ItemsDoneCustom(True, 4);
  Создает подменю,  добавляет  три  элемента  и завершает формирование
  списка посредством вызова ItemsDoneCustom. Размеры окна подменю  бу-
  дут изменены так, чтобы оно точно соответствовало элементам, которые
  мы  добавили. Отметим, что при определении размеров учитываются про-
  белы в конце строки 'Save'. Посредством ввода в подменю  одного  до-
  полнительного  элемента  вы  можете  зарезервировать место для того,
  чтобы вносить информацию о состоянии с помощью  процедуры  настройки
  строки.  Когда  данное подменю будет активизировано в первый раз, то
  будет выделен элемент 'Dos'.
     
С м о т р и   т а к ж е
  DefaultItem                       SetLeftPad
  ItemsDone                         SetSelectMarker
______________________________________________________________________
                                                                                                                                                                                                                                                               
L o a d
______________________________________________________________________
                                                                                                                                                                                                                                                               
О б ъ я в л е н и е
  constructor Load(var S : IdStream);
                                                                                                                                                                                                                                                               
Н а з н а ч е н и е
  Загрузить Menu из потока.
                                                                                                                                                                                                                                                               
О п и с а н и е
  S представляет собой соответствующим образом инициализированный объ-
  ект потока (например, файл потока, который открыт для чтения). Заме-
  тим, что S может быть любым потомком типа IdStream, который включает
  DosIdStream, BufIdStream и MemIdStream.
     
  Load читает очередную последовательность байтов  из  потока  S.  Эти
  байты   должны   быть  записаны  с  помощью  предшествующего  вызова
  Menu.Store. Load сначала вызывает CommandWindow.Load для того, чтобы
  прочитать основной объект CommandWindow.  Затем  он  читает  данные,
  специфичные  для  данного Menu. Этот метод включает потенциально ре-
  курсивную последовательность вызовов для того, чтобы прочитать  эле-
  менты меню, их подменю и элементы этих подменю.
     
  Для объекта  Menu процедурой регистрации потока является MenuStream.
  Существуют также  два указателя процедур (для подпрограммы настройки
  строки и подпрограммы текущего элемента), которые, возможно,  должны
  быть  зарегистрированы  независимо. Приводимая ниже программа-пример
  демонстрирует, как это делается. Более подробные сведения  приведены
  в описании объекта Store.
     

П р и м е р
   uses
     OpCrt, OpString, OpRoot, OpCmd, OpFrame, OpWindow, OpMenu;
   var
     M : Menu;
     S : BufIdStream;
                                                                                                                                                                                                                                                               
     {$F+}
     procedure CurrentItemProc(CurrentItemPtr : MenuItemNodePtr;
                              MPtr : MenuPtr);
     begin
       FastWrite(Pad(CurrentItemPtr^.HelpString, ScreenWidth),
                 ScreenHeight, 1, TextAttr);
     end;
     {$F-}
                                                                                                                                                                                                                                                               
     begin
       {Загрузите систему меню из потока}
       S.Init('MENU.STM', SOpen, 1024);
       S.RegisterHier(MenuStream);
       S.RegisterPointer(1000, @CurrentItemProc);
       S.Get(M);
       S.Done;
       M.Process;
       M.Done;
     end.
  Вводит M из потока, созданного с  помощью  примера,  приведенного  в
  описании метода Store. Отметим, что адрес процедуры текущего элемен-
  та  регистрируется  с помощью того же самого пользовательского кода,
  который использовался  при  записи посредством Store. S.GET вызывает
  непосредственно Menu.Load.
     
  Обратитесь к описанию BufIdStream (в подразделе, описывающем OPROOT)
  для информации  об ошибках, которые могут возникнуть при использова-
  нии потоков.
     
С м о т р и   т а к ж е
  CommandWindow.Load                      Store
______________________________________________________________________
                                                                                                                                                                                                                                                               
M e n u C h o i c e
______________________________________________________________________
                                                                                                                                                                                                                                                               
О б ъ я в л е н и е
  function MenuChoice : LongInt;
                                                                                                                                                                                                                                                               
Н а з н а ч е н и е
  Возвратить последний выбранный элемент меню.
                                                                                                                                                                                                                                                               
О п и с а н и е
  Вызов MenuChoice   производится   только   после   вызова   Process.
  MenuChoice  возвращает значение ключа элемента, выбранного пользова-
  телем.
     
П р и м е р
   repeat
     M.Process;
     case M.GetLastCommand of
       ccSelect :
         case M.MenuChoice of
           1 : {Выполните действия для элемента 1 данного меню};
           2 : {Выполните действия для элемента 2 данного меню};
           {...}
         end;
       ccError :
         Finished := True;
       ccQuit :
         {Пользователь нажал  на <Esc> на верхнем уровне. Возмож-
          ность просто проигнорировать эту команду.}
         ;
       {...}
     end;
   until Finished;
                                                                                                                                                                                                                                                               
  Показывает, как используется MenuChoice для того, чтобы  определить,
  какой именно элемент меню был выбран. Сначала всегда нужно проверить
  GetLastCommand,  чтобы убедиться в том, что пользователь выбрал эле-
  мент и не вышел из системы меню или не нажал клавиши какой-либо дру-
  гой команды выхода из меню.
     
С м о т р и   т а к ж е
  Process
_______________________________________________________________________
  
m n O p t i o n s A r e O n
_______________________________________________________________________

О б ъ я в л е н и е
  function mnOptionsAreOn(OptionFlags : Word) : Boolean;
                                                                                                                                                                                                                                                               
Н а з н а ч е н и е
  Возвратить значение "True" ("Истина") в том случае, если все указан-
  ные опции включены.
     
О п и с а н и е
  Эта функция проверяет опции меню, которые описаны в подразделе "Кон-
  станты" почти в самом начале этого раздела.
     
П р и м е р
   if M.mnOptionsAreOn(mnAlphaMatch) then
     {предпримите некоторое действие};
  Предпринимается некоторое действие в том случае, если включена опция
  mnAlphaMatch.
     
С м о т р и   т а к ж е
 mnOptionsOff                                  mnOptionsOn
______________________________________________________________________
m n O p t i o n s O f f
______________________________________________________________________
О б ъ я в л е н и е
  procedure mnOptionsOff(OptionFlags : Word);
                                                                                                                                                                                                                                                               
Н а з н а ч е н и е
  Сделать некоторое множество опций не активными.
                                                                                                                                                                                                                                                               
О п и с а н и е
  Этот метод делает не активным(и) указанную(ые) опцию(и), за исключе-
  нием тех, которые назначены как BadMenuOptions (обратитесь к имеюще-
  муся выше разделу "Константы").
     
П р и м е р
    M.mnOptionsOff(mnAlphaMatch+mnArrowSelect);
     
  Выключает опцию выбора элемента меню на основе соответствия алфавит-
  ного символа и опцию использования клавиш со стрелками в расширенном
  режиме.
______________________________________________________________________
  
m n O p t i o n s O n
______________________________________________________________________
  
О б ъ я в л е н и е
  procedure mnOptionsOn(OptionFlags : Word);
     
Н а з н а ч е н и е
  Активизировать некоторое множество опций.
     
О п и с а н и е
  Этот метод  активизирует указанную(ые) опцию(и), за исключением тех,
  которые назначены как BadMenuOptions (обратитесь к  имеющемуся  выше
  разделу "Константы").
     
П р и м е р
    M.mnOptionsOn(mnUseItemForTopic+mnSelectOnClick);
     
  Включает опцию  использования  ключа  текущего  элемента  для выдачи
  ("hook") контекстно-зависимой помощи и опцию выбора элементов с  по-
  мощью нажатия на кнопки мыши.
______________________________________________________________________
     
M o v e W i n d o w
______________________________________________________________________
О б ъ я в л е н и е
  {$IFDF UseAdjustableWindows}
  procedure MoveWindow(DX, DY : Integer); virtual;
     
Н а з н а ч е н и е
  Переместить окно.
     
О п и с а н и е
  Этот метод отвергает StackWindow.MoveWindow таким  образом,  что  он
  одновременно сдвигает все окна (активные и неактивные), которые сос-
  тавляют систему меню. Для того, чтобы метод MoveWindow мог работать,
  система  меню либо должна быть неактивной, либо должна содержать те-
  кущее   окно;   в   противном   случае    он    генерирует    ошибку
  epNonFatal+ecWinNotCurrent.  Если система меню отображена на экране,
  то метод MoveWindow размещает временный виртуальный экран, чтобы вы-
  полнить обновления. Если для виртуального экрана не хватает  памяти,
  то  метод генерирует ошибку epNonFatal+epOutOfMemory и завершает ра-
  боту до внесения в систему меню каких-нибудь изменений.
  
  MoveWindow посещает  все  окна  системы меню и предпринимает попытку
  отрегулировать их положения в соответствии с заданным числом колонок
  (DX) и рядов (DY). В том случае, когда осуществление  этой  операции
  выдвинет  окно  за  пределы указанных для него координат, MoveWindow
  передвигает окно к соответствующему пределу и не генерирует ошибку.
  
П р и м е р
    M.MoveWindow(+1, +1);
  
  Перемещает полностью систему меню на одну колонку вправо и  на  один
  ряд  вниз.  Если  при  этом какое-либо подменю должно выдвинуться за
  край экрана, MoveWindow перемещает это подменю на  меньшее  расстоя-
  ние.
  
С м о т р и   т а к ж е
  StackWindow.MoveWindow
______________________________________________________________________
  
P r o c e s s
______________________________________________________________________
  
О б ъ я в л е н и е
  procedure Process; virtual;
  
Н а з н а ч е н и е
  Обработать команды меню, осуществляющие выбор.
  
О п и с а н и е
  Метод Process  объекта  Menu  действует  по общей схеме, описанной в
  разделе для CommandWindow.Process, со следующими дополнениями и иск-
  лючениями:
  
  Он обрабатывает те команды, которые описаны в начале настоящего раз-
  дела в подразделе "Команды меню".
  
  Перед тем, как обновить меню и  начать  цикл  обработки  команд,  он
  включает опции mnMainSelect и mnMainHighlight.
  
  Перед завершением работы Process сохраняет самый последний выбранный
  элемент в виде мгновенной переменной, к которой можно  обратиться  с
  помощью метода MenuChoice. Если доступна опция mnPopOnSelect и поль-
  зователь завершает работу с помощью команды ccSelect, то Process пе-
  ред  окончанием  своей  работы  удаляет активное подменю (но не меню
  верхнего уровня).
  
  Метод Process может вызвать любую из определенных пользователем под-
  программ. Процедура настройки строки и процедура  текущего  элемента
  являются индивидуальными для Menu. Процедура обработки ошибок насле-
  дуется  из  CommandWindow. А процедуры контекстно-зависимой помощи и
  обработки фона клавиатуры наследуются из CommandProcessor.
  
П р и м е р
  Полный пример приведен во введении к настоящему разделу.
  
С м о т р и   т а к ж е
  CommandWindow.Process                          MenuChoice
_______________________________________________________________________
  
P r o t e c t I t e m
_______________________________________________________________________
  
О б ъ я в л е н и е
  procedure  ProtectItem(Key : LongInt);
  
Н а з н а ч е н и е
  Защитить указанный элемент. Не обновлять экран.
  
О п и с а н и е
  Если не найден никакой элемент, соответствующий указанному ключу, то
  ProtectItem завершает работу, не регистрируя ошибку. Если  указанный
  элемент является выбранным элементом, то ProtectItem пытается  пере-
  местить выбор к ближайшему предыдущему незащищенному элементу. Отме-
  тим, что если указанный элемент является выбранным и имеет относяще-
  еся к нему подменю, которое тоже является видимым, то ProtectItem не
  предпринимает  ничего  для того, чтобы отменить выбор этого подменю.
  Защита элемента в этих  обстоятельствах  представляет  собой  ошибку
  программирования.
  
  Более подробные  сведения приведены в подразделе "Защищенные элемен-
  ты" во введении.
  
П р и м е р
    M.ProtectItem(9);
    M.ProtectItem(10);
    M.Process;
  
  Защищает элементы меню с ключами 9 и 10 перед тем, как  обрабатывать
  меню.
  
С м о т р и   т а к ж е
  UnprotectItem
_______________________________________________________________________
     
R e d r a w
_______________________________________________________________________
  
О б ъ я в л е н и е
  procedure Redraw;
  
Н а з н а ч е н и е
  Удалить и  перерисовать систему меню, возможно, после изменения эле-
  мента.
  
О п и с а н и е
  OPMENU активизирует временный виртуальный экран, чтобы избежать мер-
  цания  экрана во время обновления. Вследствие того, что используется
  виртуальный экран, имеется возможность изображать  в  верхней  части
  системы  меню  другие  окна  в  тот  момент,  когда вызывается метод
  Redraw. Однако эти окна должны соответствовать требованиям, установ-
  ленным в StackWindow.ActivateWrite.
  
  Наиболее часто  метод Redraw вызывается после проведения мероприятий
  по защите или по отмене защиты элементов или после  изменения  пере-
  менных  состояния,  которые влияют на процедуру настройки строки для
  меню.
  
П р и м е р
     M.Process;
     case M.GetLastCommand of
       ccSelect :
         case M.MenuChoice of
           {...обработайте выбор...}
           99 :
             begin
               if IsAdvanced then begin
                 M.ProtectItem(10);
                 M.ProtectItem(11);
               end else begin
                 M.UnprotectItem(10);
                 M.UnprotectItem(11);
               end;
               M.Redraw;
             end;
         end;
       {...}
     end;

  Предполагается, что элемент 99 системы меню является элементом,  пе-
  реключающим  состояние системы меню от режима "специалиста" к режиму
  "новичка" и обратно. После изменения защиты он перерисовывает систе-
  му меню. Сам метод Process будет обновлять только текущее подменю.

С м о т р и   т а к ж е
  Erase
_______________________________________________________________________

S e l e c t I t e m
_______________________________________________________________________

О б ъ я в л е н и е
  procedure SelectItem(Key : LongInt);

Н а з н а ч е н и е
  Выбрать указанный элемент и обновить экран.

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

  Следующий вызов метода Process будет  осуществляться  из  выбранного
  элемента.

П р и м е р ы
     InitMenu(M);
     M.SelectItem(10);
     M.Process;

  Устанавливает элемент  10 как начальный выбранный элемент и вызывает
  Process, чтобы предоставить пользователю возможность подтвердить вы-
  бор или изменить его.

     repeat
       M.Process;
       case M.GetLastCommand of
         ccSelect :
           {...обработайте выбранные элементы...}
         ccUser0 :
           M.SelectItem(10);
         {...}
       end;
     until Finished;

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

С м о т р и   т а к ж е
  DefaultItem                                   SelectSubMenu
______________________________________________________________________
S e l e c t I t e m B y P o s
______________________________________________________________________
О б ъ я в л е н и е
  function SelectItemByPos(X, Y, :  Byte) : Boolean;

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

О п и с а н и е
  Этот метод полезен в тех ситуациях, когда может использоваться  мышь
  и  система  меню остается на экране в то время, когда активны другие
  окна. (Такой пример дает DESKPOP; именно она послужила стимулом  для
  написания  этого метода.) Если указанные координаты лежат в пределах
  текста незащищенного элемента меню, то метод SelectItemByPos выберет
  этот элемент меню и возвратит значение "True" ("Истина"). В  против-
  ном  случае  он  ничего  не  делает,  но возвращает значение "False"
  ("Ложь").

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

П р и м е р
   var
     MX, MY : Byte;
     Status : ButtonStatus;
     WPtr : WindowPtr;
     M : Menu;
    begin
      ...
      MouseWhereXYabs(MX, MY , Status);
      WPtr := wStack.EvaluateStackPos(MX, MY);
      if (WPtr = nil) or (WPtr = @M) then
        {Указатель мыши находится не в пределах какого-либо окна,  но,
        возможно, на меню верхнего уровня}
        if M.SelectItemByPos(MX, MY) then begin
          {Система меню активизирована, выбирайте}
          M.Process;
          ...
         end;

  Вызов MouseWhereXYabs происходит после того, как уже была отображена
  система  меню,  были нарисованы одно или несколько окон и было уста-
  новлено, что  указатель  мыши  находтся  вне  текущего  окна.  Метод
  EvaluateStackPos  сканирует  стек  окна по умолчанию для того, чтобы
  определить, в каком окне, если таковое имеется, находится курсор мы-
  ши. Если  возвращаемое значение указателя является "пустым", то кур-
  сор мыши находится не в пределах видимого StackWindow (что не исклю-
  чает возможность того, что этот курсор находится внутри подменю, ко-
  торое не управляется стеком окна по умолчанию); если же возвращаемое
  значение равно "@M", то курсор находится в  пределах  меню  верхнего
  уровня. Метод SelectItemByPos пытается выбрать элемент меню в преде-
  лах любой активной части системы меню. Если выбор завершается успеш-
  но, он обновляет экран, чтобы показать, какой элемент выбран. В этой
  точке  логичным шагом является вызов Menu.Process, так что пользова-
  тель может осуществить выбор меню.

С м о т р и   т а к ж е
  SelectItem                    WindowStack.EvaluateStackPos
_______________________________________________________________
S e l e c t S u b M e n u
_______________________________________________________________

О б ъ я в л е н и е
  procedure SelectSubMenu(Key : LongInt);

Н а з н а ч е н и е
  Выбрать текущий элемент подменю, содержащий ключ Key, и обновить эк-
  ран.

О п и с а н и е
  Работает точно так же, как метод SelectItem,  за  исключением  того,
  что  текущий  элемент  наиболее  глубоко вложенного соответствующего
  подменю не изменяется. Ключ служит только для того, чтобы  идентифи-
  цировать указанное подменю; значение его может соответствовать любо-
  му элементу в подменю. По соглашению мы указываем первый  элемент  в
  подменю как элемент, передаваемый в SelectSubMenu.

П р и м е р
    M.SelectSubMenu(11);

  Выбирает элемент по умолчанию из того подменю, которое содержит эле-
  мент 11.

С м о т р и   т а к ж е
DefaultItem                           SelectItem
______________________________________________________________
S e t A l l X x x A t t r
______________________________________________________________
О б ъ я в л е н и е
  procedure SetAllXxxAttr(Color, Mono : Byte);

Н а з н а ч е н и е
  Установить указанные атрибуты для всех окон в системе меню.

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

    procedureSetAllFrameAttr(Color, Mono : Byte);
    procedureSetAllHeaderAttr(Color, Mono : Byte);
    procedureSetAllHighAttr(Color, Mono : Byte);
    procedureSetAllNormAttr(Color, Mono : Byte);
    procedureSetAllProtectAttr(Color, Mono : Byte);
    procedureSetAllSelectAttr(Color, Mono : Byte);
    {$IFDEF UseShadows}
    procedureSetAllShadowAttr(Color, Mono : Byte);
    {$ENDIF}

  Аргумент Color представляет собой видео атрибут, который использует-
  ся  в  режиме цветного изображения; аргумент Mono представляет собой
  атрибут для монохромного режима.

  Для получения  более  подробной  информации  обратитесь к подразделу
  "Настройка меню" почти в самом начале настоящего раздела.

П р и м е р
    M.SetAllHighAttr($0A, $70);

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

С м о т р и   т а к ж е
  SetHelpAttr                                    SetXxxAttr
____________________________________________________________
S e t A l l S e l e c t M a r k e r
____________________________________________________________

О б ъ я в л е н и е

  procedure SetAllSelectMarker(Left, Right : String);

Н а з н а ч е н и е
  Определить строки, которые должны использоваться для того, чтобы по-
  мечать выбранные элементы во всех подменю.

О п и с а н и е
  SetAllSelectMarker посещает  все  списки  элементов в системе меню и
  для каждого из них вызывает метод SetSelectMarker. Вы  должны  вызы-
  вать  этот метод только после того, как система меню будет полностью
  определена.

П р и м е р
     M.SetAllSelectMarker('< ', ' >');

  Устанавливает маркеры для обозначения выбранных элементов в основном
  меню и во всех подменю.

С м о т р и   т а к ж е
  SetSelectMarker
_____________________________________________________________
S e t C u r r e n t I t e m P r o c
_______________________________________________________________

О б ъ я в л е н и е
  procedure SetCurrentItemProc(IP : mnCurrentItemProc);

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

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

  Та процедура,  которая  передается  в  качестве   параметра   методу
  SetCurrentItemProc, должна быть откомпилирована с использованием мо-
  дели  FAR (c директивой компилятора {$F+}), должна быть глобальной и
  должна иметь параметры, которые соответствуют следующему прототипу:

        {$F+}
        procedure CurrentItemProc(CurrentItem : MenuItemNodePtr;
                                  MPtr : MenuPtr);

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

С м о т р и   т а к ж е
  CurrentItem                     SetCustomStringProc
_______________________________________________________________

S e t C u s t o m S t r i n g P r o c
_______________________________________________________________

О б ъ я в л е н и е
  procedure SetCustomStringProc(CP : mnCustomProc);

Н а з н а ч е н и е
  Установить процедуру настройки строки элемента.

О п и с а н и е
  OPMENU перед тем, как она выводит на экран каждый элемент,  передает
  управление  подпрограмме, написанной пользователем, названной проце-
  дурой настройки строки. Эта процедура может модифицировать отобража-
  емую на экране строку так, чтобы включать в нее информацию о состоя-
  нии, специфичную для данного элемента. Процедура строки по умолчанию
  не  делает ничего. SetCustomStringProc устанавливает, какая конкрет-
  ная написанная пользователем процедура  получит  управление  в  этот
  раз.

  Та процедура,  которая  передается  в  качестве   параметра   методу
  SetCustomStringProc,  должна  быть  откомпилирована с использованием
  модели FAR (c директивой компилятора {$F+}), должна быть  глобальной
  и  должна иметь параметры, которые соответствуют следующему прототи-
  пу:

        {$F+}
        procedure CustomStringProc(var Name : String; Key : LongInt;
                                   Selected, Highlighted : Boolean;
                                   WPtr : RawWindowPtr);
  Для получения  более подробной информации и полной программы-примера
  обратитесь к подразделу "Процедура настройки строки" во  введении  к
  настоящему  разделу. Отметим, что MAKEMENU никогда не генерирует для
  вас процедуру настройки строки, т.к. полная реализация  должна  быть
  тесно связана с конкретным применением.

С м о т р и   т а к ж е
  SetCurrentItemProc
_______________________________________________________________

S e t H e l p A t t r
_______________________________________________________________
О б ъ я в л е н и е
  procedure SetHelpAtrr(Color, Mono : Byte);
Н а з н а ч е н и е
  Установить цвета для строки помощи.

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

С м о т р и   т а к ж е
  GetHelpAtrr
_______________________________________________________________
S e t X x x A t t r
_______________________________________________________________

О б ъ я в л е н и е
  procedure SetXxxAttr(Color, Mono : Byte);

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

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

    procedureSetHighAttr(Color, Mono : Byte);
    procedureSetNormAttr(Color, Mono : Byte);
    procedureSetProtectAttr(Color, Mono : Byte);
    procedureSetSelectAttr(Color, Mono : Byte);
    procedureSetFrameAttr(Color, Mono : Byte);
    procedureSetHeaderAttr(Color, Mono : Byte);
    {$IFDEF UseShadows}
    procedureSetShadowAttr(Color, Mono : Byte);
    {$ENDIF}

  Аргумент Color представляет собой видео атрибут, который использует-
  ся в режиме цветного изображения; аргумент  Mono представляет  собой
  атрибут для монохромного режима.

  Для получения  более  подробной  информации  обратитесь к подразделу
  "Настройка меню" почти в самом начале настоящего раздела.

П р и м е р
    M.AddFramedSubMenu(9, 4, 15, 5, Vertical, Frame2);
    M.SetNormAttr($02, $07);

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

С м о т р и   т а к ж е
  SetAllXxxAttr
______________________________________________________________
S e t L e f t P a d
______________________________________________________________

О б ъ я в л е н и е
  procedure SetLeftPad(LeftPad : Byte);

Н а з н а ч е н и е
  Установить число символов для каждого  элемента,  являющегося  левым
  "заполнителем" ("pad"), когда он отображается на экране.

О п и с а н и е
  Этот метод применяется только к тому подменю, которое было добавлено
  самым последним при инициализации системы меню.

  Отметим, что  по умолчанию вертикальные подменю дополнены слева "за-
  полнителем" ("are left-padded") шириной в один символ;  горизонталь-
  ные подменю по умолчанию "заполнителя" не имеют. В дополнение к это-
  му символы, число которых указано посредством аргумента LeftPad, до-
  бавляются  с  ПРАВОЙ  стороны  имени каждого элемента в вертикальном
  подменю после того, как  значение  строки  возвращено  подпрограммой
  настройки строки. Такая практика приводит к более приятным для восп-
  риятия изображениям симметричных вертикальных подменю.

  Для получения  более  подробной  информации  обратитесь к подразделу
  "Настройка меню" почти в самом начале настоящего раздела.

П р и м е р ы
    M.SetLeftPad(2);

  Вставляет два пробела перед каждым элементом меню.

    M.AddFramedSubMenu(9, 4, 15, 5, Vertical, Frame2);
    M.SetLeftPad(0);

  Удаляет все  "заполнители"  для элементов того подменю, которое было
  только что добавлено.
______________________________________________________________
S e t S e l e c t M a r k e r
______________________________________________________________

О б ъ я в л е н и е
  procedure SetSelectMarker(Left, Right : String);

Н а з н а ч е н и е
  Определить последовательность  литер,  с помощью которых будут поме-
  чаться выбранные элементы.

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

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

П р и м е р
    M.SetSelectMarker('[', ']');

  Взять имя выбранного элемента в квадратные скобки.
______________________________________________________________
S t o r e
______________________________________________________________
О б ъ я в л е н и е
  procedure Store(var s : IDStream);

Н а з н а ч е н и е
  Сохранить список в потоке.

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

  Store записывает   образ   Menu  в  поток  S.  Сначала  он  вызывает
  CommandWindow.Store, затем продолжает записывать данные, специфичные
  для данного Menu. Для элементов меню может  потребоваться  запись  в
  рекурсивной последовательности с тем, чтобы сохранить связанные друг
  с другом подменю и их элементы.

  Для того, чтобы проверить ошибки, которые могут возникнуть во  время
  работы Store, вызовите функцию GetStatus потока.

  Для объекта  Menu процедурой регистрации потока является MenuStream.
  Если предполагается использование  процедуры  настройки  строки  или
  процедуры текущего элемента, то их адреса также должны быть зарегис-
  трированы независимо. Приводимая ниже программа-пример  демонстриру-
  ет, как это делается.

П р и м е р
        uses
          OpCrt, OpString, OpRoot, OpCmd, OpFrame, OpWindow, OpMenu;
        var
          M : Menu;
          S : BufIdStream;

          {$F+}
          procedure CurrentItemProc(CurrentItemPtr : MenuItemNodePtr;
                                   MPtr : MenuPtr);
          begin
            FastWrite(Pad(CurrentItemPtr^.HelpString, ScreenWidth),
                      ScreenHeight, 1, TextAttr);
          end;
          {$F-}
          procedure InitMenu(var M : Menu);
          begin
            with M do begin
              InitCustom(2, 2, ScreenWidth-1, 2, DefaultColorSet,
                         DefWindowOptions or wBordered, Horisontal);
              AddItemHelp('File', 4, 1, 1, 'New/Save files');
              AddFramedSubMenu(4, 4, 10, 6, Vertical, DefWindowFrame);
                AddItemHelp('New',  1, 1, 2, 'Create a new file');
                AddItemHelp('Save', 2, 1, 3, 'Save the current file');
                AddItemHelp('Dos',  3, 1, 20, 'Shell to DOS');
                ItemsDone;
              AddItemHelp('Edit',    20, 1, 4,
                          'Edit the current file');
              AddItemHelp('Options', 35, 1, 5, 'Set program ortions');
              ItemsDone;
              SetCurrentItemProc(CurrentItemProc);
            end;
          end;

        begin
          InitMenu(M);
          {Сохраните систему меню в потоке}
          S.Init('MENU.STM', SCreate, 1024);
          S.RegisterHier(MenuStream);
          S.RegisterPointer(1000, @CurrentItemProc);
          S.Put(M);
          S.Done;
          M.Process;
          M.Done;
        end;

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

  Обратитесь к  описанию  BufIdStream  (в разделе, описывающем OPROOT)
  для соответствующего контроля ошибок, возникающих при  использовании
  потоков.

С м о т р и   т а к ж е
  CommandWindow.Load                                    Store
_______________________________________________________________
U n p r o t e c t I t e m
_______________________________________________________________

О б ъ я в л е н и е
  procedure UnprotectItem(Key : LongInt);

Н а з н а ч е н и е
   Отменить защиту указанного элемента. Не обновлять экран.

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

  Более подробные  сведения приведены в подразделе "Защищенные элемен-
  ты" во введении.

П р и м е р
    M.UnProtectItem(9);
    M.UnProtectItem(10);
    M.Process;

  Отменяет защиту элементов меню, имеющих ключи 9 и 10,  которые,  как
  предполагается, ранее были защищенными.

С м о т р и   т а к ж е
  ProtectItem
______________________________________________________________
U p d a t e S c r e e n S i z e
______________________________________________________________
О б ъ я в л е н и е
  {$IFDEF UseAdjustableWindows}
  procedure UpdateScreenSize;

Н а з н а ч е н и е
  Обновляет размер окна, положение и границы размера текущего экрана.

О п и с а н и е
  Этот метод работает точно так же, как RawWindow.UpdateScreenSize, за
  исключением того,  что  он  применим ко всем окнам, которые входят в
  систему меню.

С м о т р и   т а к ж е
  RawWindow.UpdateScreenSize
____________________________________________________________
V i s i t A l l I t e m s
____________________________________________________________

О б ъ я в л е н и е
  procedure VisitAllItems(IProc : mnItemProc; var D);

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

О п и с а н и е
  ItemProc должен быть откомпилирован с использованием модели  FAR  (c
  директивой компилятора {$F+}), должен быть глобальным и должен иметь
  параметры, которые соответствуют следующему прототипу:

     {$F+}
     procedure ItemProc(IPtr : MenuItemNodePtr; var D;
                        MPtr : MenuPtr);
  Параметр D,  являющийся  нетипизованной  переменной, предназначается
  для использования процедурой, написанной пользователем.  В  ItemProc
  также  передаются  адрес элемента, в котором "побывал" этот метод, и
  адрес системы меню. VisitAllItems "посещает" элементы в порядке "пе-
  ребора  в  глубину"  ("depth-first")   от   первого   к   последнему
  ("first-to-last"),  начиная с первого элемента меню верхнего уровня.
  Он "посещает" защищенные элементы.

  ItemProc может выполнять любые действия, которые не разрушают струк-
  туру дерева меню. MAKEMENU вызывает методы VisitAllItems  для  того,
  чтобы реализовать команду "Rekey"  ("Переназначить  ключ"),  которая
  последовательно перенумеровывает  все элементы в порядке "перебора в
  глубину".

П р и м е р
   var
     M : Menu;
     B : Byte;

     {$F+}
     procedure ChangeAllSelectPos(IPtr : MenuItemNodePtr; var D;
                                  MPtr : MenuPtr);
     begin
       IPtr^.ChangeSelectPos(Byte(D));
     end;
     {$F-}
     ...
   begin
     InitMenu(M);
     B := 0;
     M.VisitAllItems(ChangeAllSelectPos, B);
   end.

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

С м о т р и   т а к ж е
  VisitAllWindows
_______________________________________________________________

V i s i t A l l W i n d o w s
________________________________________________________________

О б ъ я в л е н и е
  procedure VisitAllWindows(WProc : mnWindowProc; var D);

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

О п и с а н и е
  WProc должен  быть откомпилирован с использованием модели FAR (c ди-
  рективой компилятора {$F+}), должен быть глобальным и  должен  иметь
  параметры, которые соответствуют следующему прототипу:

     {$F+}
     procedure WindowProc(WPtr : RawWindowPtr; var D;
                          MPtr : MenuPtr);

  Параметр D, являющийся  нетипизованной  переменной,  предназначается
  для использования процедурой, написанной пользователем. В WindowProc
  также  передаются  адрес элемента, в котором "побывал" этот метод, и
  адрес системы меню. VisitAllWindows "посещает" окна в порядке "пере-
  бора  в   глубину"   ("depth-first")   от   первого   к   последнему
  ("first-to-last"), начиная с самого объекта Menu.

  WindowProc может  выполнять  любые  действия,  которые  не разрушают
  структуру  дерева  меню.   Модуль   OPMENU   сам   вызывает   методы
  VisitAllItems   для  того,  чтобы  реализовать  EnableALLExplosions,
  EnableAllAlternateOpen, EnableAllNormalOpen, AddShadow, IsCurrent  и
  другие методы.

П р и м е р
   var
     M : Menu;
     B : Boolean;

     {$F+}
     procedure SetSoundOption(WPtr : RawWindowPtr; var D;
                               MPtr : MenuPtr);
     begin
       if Boolean(D) then
         WPtr^.wOptionsOn(wSoundEffects)
       else
         WPtr^.wOptionsOff(wSoundEffects);
     end;
     {$F-}
     ...
   begin
     InitMenu(M);
     B := True;
     M.VisitAllWindows(SetSoundOption, B);
   end.

  Изменяет опцию  звукового  сигнала во всех окнах меню путем "посеще-
  ния" каждого окна с вызовом процедуры SetSoundOption. В данном  слу-
  чае звуковой сигнал включается во всех окнах.

  Отметим, что WindowProc может быть установлен различным для окна ме-
  ню  верхнего уровня и окон подменю при использовании следующего опе-
  ратора:

       if WPtr = RawWindowPtr(MPtr) then
         {Это окно верхнего уровня}
       else
         {Это окно подменю}

С м о т р и   т а к ж е
  VisitAllItems