Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Книга о KOL.doc
Скачиваний:
29
Добавлен:
30.04.2019
Размер:
1.77 Mб
Скачать

5. Невизуальные объекты kol и mck

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

Все такие объекты унаследованы напрямую от TObj, т.е. являются простыми объектами. Но, в то же время, для всех для них существуют зеркальные компоненты в пакете Mirror Classes Kit, позволяющие использовать их в визуальном проектировании. Т.е., их можно бросить на форму и настроить нужные свойства и события. В результате автоматически генерируется код, который обеспечивает создание соответствующих объектов вместе с формой, и их разрушение вместе с разрушением объекта формы.

5 .1. Меню (tMenu)

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

Более того, главное меню отображается на форме, в том числе, и на этапе разработки, позволяя создавать обработчики событий (и быстро переходить в их код) при выборе соответствующего элемента в меню. Примечание: однако, в отличие от VCL, для создания новых пунктов главного меню, или для перемещения пунктов, в MCK следует использовать редактор меню, который вызывается двойным щелчком по зеркальному компоненту.

В библиотеке KOL и главное меню, и всплывающее меню (popup menu), и элементы меню - все они реализуются в одном объектом типе TMenu, сохраняя традицию экономии на разнообразии объектов. Конструктор меню использует технику шаблонов на основе списков строк, подобно тому, как это реализовано для линейки инструментов. Исторически, меню разрабатывалось раньше линейки кнопок, и такой способ экономной конструкции многоэлементных объектов применен был впервые именно для построения дерева меню. Если копнуть историю еще глубже, то этот объект впервые появился в XCL - предшественнике KOL, и с тех пор мало что в нем изменилось.

При создании первого меню, и присваивании его форме, это объект меню автоматически делается главным меню для формы (и, если в нем есть хотя бы один элемент, оно отображается в верхней части формы). Все последующие добавляемые к форме объекты меню становятся всплывающими (popup), и не отображаются до тех пор, пока для них не будет программно или автоматически (SetAutoPopupMenu) вызван метод Popup или PopupEx. В частности, если форма не должна иметь главного меню, но на ней есть одно или несколько всплывающих меню, то в первую очередь следует добавить фиктивное главное меню, не имеющее отображаемых элементов.

Конструкторы:

NewMenu( Parent, dummy, template, onmenu ) - конструирует меню на основе заданного шаблона template, добавляя его к форме, указанной параметром Parent;

NewMenuEx( Parent, dummy, template, onitems_array ) - аналогично предыдущей функции, но позволяет назначить собственные обработчики событий сразу для всех или для части пунктов меню.

Параметр dummy сохранен для совместимости с первыми версиями KOL, когда он использовался и назывался maxcmdreserve (а затем firstcmd). С тех пор, как в меню для каждого элемента стал создаваться собственный экземпляр объекта TMenu, надобность в этом параметре отпала.

На правилах построения шаблона template следует остановиться подробнее. Шаблон - это массив строк (типа PChar), определяющих для пунктов меню:

  • их внешний вид (текст, мнемоники, ускорители);

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

Для задания всех этих возможностей используются символы префиксов в строках:

'&' - Символ перед буквой или цифрой, которая становится мнемоникой элемента меню. Мнемоника отображается с подчеркиванием (в новых версиях ОС по умолчанию подчеркивание показывается только при нажатой клавише Alt), и позволяет вызывать меню с клавиатуры. Напомню, что для того, чтобы в приложении KOL имелась возможность использовать мнемоники в меню без предварительной активизации самого меню, необходимо обеспечить вызов метода SupportMnemonics;

'+' - Элемент меню "отмечен" специальной галочкой. Для радио-переключаемых пунктов меню вместо галочки используется кружок. Если такой префикс указан перед текстом элемента, то элемент становится автоматически переключаемым. В этом случае, при выборе пункта меню пользователем, он автоматически меняет свое состояние с «отмечен» на «не отмечен». Если вслед за префиксом '+' (или '-', см. ниже) следует символ '!', то элемент меню является радио-переключаемым. Система объединяет несколько подряд следующих радио-переключателей в одну группу автоматически (между ними не должно быть пунктов меню других типов);

'-' - Элемент меню "не отмечен", но в остальном все сказанное о префиксе '+' верно и для '-';

'-' - Если текст элемента состоит из единственного минуса, то элемент является сепаратором (и изображается в меню как узкая линия между группами обычных элементов меню). Сепаратор всегда недоступен для выбора, и поэтому для него не имеет смысла назначать обработчик события OnMenu;

'(' - Начинает вложенного меню, подчиненное предыдущему пункту меню;

')' - Заканчивает вложенное меню, возвращаясь на предыдущий уровень вложенности.

В конструкторе NewMenuEx, а так же в методе AssignEvents, когда события из параметра-массива присваиваются элементам меню, сепараторы и элементы шаблона '(' и ')' не принимаются во внимание (пропускаются).

Свойства, методы и события объекта TMenu:

Handle - дескриптор меню. Такой дескриптор имеет и само меню, и любой его элемент (включая разделители). Этот дескриптор является числом (типа hMenu), известным системе, и позволяет обращаться к функциям API для выполнения каких-то действий с меню на низком уровне. Например, меню вместе со всеми своими вложенными меню может быть передано как параметр функциям TrackPopupMenu и TrackPopupMenuEx для "всплытия" меню с какими-либо дополнительными стилями отображения;

SubMenu - дескриптор подчиненного меню. Фактически, эквивалентен Handle;

MenuID - внутренний числовой "идентификатор" элемента меню, назначается кодом KOL. Т.к. число доступных идентификаторов не может превышать 65535, и эти идентификаторы не могут переиспользоваться повторно, то не следует постоянно в процессе длительной работы создавать и удалять пункты меню слишком часто. В том числе, не следует делать их "скрытыми", т.к. сокрытие и показ пунктов меню реализуется именно как уничтожение и создание новых элементов (в Windows нет возможности прятать пункты меню по-другому). Вместо этого рекомендуется использовать возможность делать пункты меню недоступными или доступными (разрешенными - enabled) по мере надобности;

Insert( i, s, event, options ) - добавляет новый пункт меню (создавая еще один объект TMenu, соответствующий вновь созданному пункту меню, и возвращая указатель PMenu на этот объект;

Parent - родительское меню (при наличии);

TopParent - родительское меню самого верхнего уровня;

Owner - объект типа TControl, к которому принадлежит данное меню (должен быть формой);

Items[ i ] - подчиненные элементы меню (включая вложенные в них элементов меню, в том числе разделители). В качестве параметра i может использоваться абсолютный индекс вложенного элемента со значением от 0 до 4096, или числовой дескриптор ID. Значение -1 возвращает сам элемент меню (себя);

Count - количество подчиненных элементов меню, включая рекурсивно вложенные элементы;

IndexOf( s ) - возвращает индекс подчиненного элемента меню (включая вложенные элементы любого уровня), отыскивая его по тексту s. Значение -1 возвращается для самого элемента меню, и -2, если такой пункт меню не обнаружен;

InsertSubMenu( submenu, i ) - позволяет добавить в качестве элемента данного меню заранее заготовленное меню вместе со всеми своими подчиненными элементами;

RemoveSubmenu( i ) - отсоединяет подчиненное меню, добавленное, например, методом InsertSubMenu;

AddItem( s, event, options ) - добавляет пункт меню в конец списка;

InsertItem( i, s, event, options ) - вставляет пункт меню в указанную позицию;

AssignBitmaps( i, bitmaps ) - позволяет присвоить сразу несколько точечных изображений пунктам меню, начиная с заданного;