Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lection.doc
Скачиваний:
13
Добавлен:
16.11.2019
Размер:
343.55 Кб
Скачать

3. Кто обрабатывает общие сообщения.

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

Конкретный пример: в IDE TurboPascal (Интегрированная Среда Разработки TurboPascal), если пользователь запрашивает открыть окно просмотра, код, который открывает окно просмотра, должен проверить, не открыто ли оно. Если нет, то открывает его; если есть, то переносит наверх.

Передача общего сообщения проста:

AreYouThere := Message(DeskTop, evBroadcast, cmFindWindow, nil);

В методе HandleEvent окна просмотра есть проверка на отклик (очистка события) на команду cmFindWindow:

case Event.What of

cmFindWindow : ClearEvent(Event);

end; .

Вспомним, что ClearEvent не только устанавливает поле What записи события в evNothing, no также устанавливает поле InfoPtr в @Self. Message читает эти поля и, если собы­тие было обработано, возвращает указатель на объект, об­работавший событие-сообщение. В данном случае это окно просмотра. Так, за строкой, которая посылала сообщение, следует:

if AreYouThere = nil then CreateWatchWindow

else AreYouThere^.Select; .

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

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

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

Ответ: конечно, самое верхнее окно редактора. Для того, чтобы определить, какое из окон «верхнее», IDE посылает общее сообщение, отклик на которое знают только окна редакто­ра. Первое окно редактора, которое получает общее сообщение, и будет верхним; оно обработает событие, очищая его, и IDE узнает, какое окно использо­вать для трассировки кода, читая результат, возвращенный Message.

4. Вызов процедуры HandleEvent.

Bы также можете создать или модифицировать событие, а затем вызвать HandleEvent напрямую. Можно сделать три типа вызовов:

1. Bы можете иметь видимый элемент, вызывающий HandleEvent равного подэлемента прямо («равные» видимые элементы – это подэлементы с одним владельцем). Сообщение не передается другим видимым элементам. Оно идет прямо к этому HandleEvent, затем управление возвра­щается к вам.

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

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

Приложение.

Пример программы с использованием библиотеки TurboVision.

program Hello;

uses App, Objects, Menus, Drivers, Views, Dialogs;

const

cmGreetingBox = 200;

{Определение новой команды.}

type

THelloApp = object(TApplication)

{Определение нового типа объекта для обеспечения требуемой

функциональности.}

procedure GreetingBox;

{Определение нового метода, отсутствующего в типе TApplication.}

procedure HandleEvent(var Event: TEvent); virtual;

{Перекрытие HandleEvent для обработки новых событий.}

procedure InitStatusLine; virtual;

{Перекрытие InitStatusLine для инициализации строки статуса.}

procedure InitMenuBar; virtual;

{Перекрытие InitMenuBar для инициализации строки меню.}

end;

var

HelloWorld: THelloApp;

{Образование экземпляра объекта для выполнения.}

procedure THelloApp.GreetingBox;

{Процедура создания диалогового окна ‘Hello, World!’.}

var

R: TRect;

Dialog: PDialog;

Control: Word;

begin

R.Assign(0, 0, 37, 13); R.Move(20, 3);

{Назначение границ для диалогового окна.}

Dialog := New(PDialog, Init(R, 'Hello, World!'));

{Создание экземпляра объекта диалогового окна типа TDialog.}

with Dialog^ do {Вставка подэлементов в диалоговое окно.}

begin

R.Assign(4, 5, 16, 6); {Назначение границ подэлемента.}

Insert(New(PStaticText, Init(R, 'How are you?')));

{Создание и вставка объекта статического текста.}

R.Assign(20, 3, 32, 5);

Insert(New(PButton, Init(R, '~T~errific', cmOK, bfNormal)));

{Создание и вставка объекта кнопки.}

R.Assign(20, 6, 32, 8);

Insert(New(PButton, Init(R, '~O~K', cmOK, bfDefault)));

R.Assign(20, 9, 32, 11);

Insert(New(PButton, Init(R, '~C~ancel', cmCancel, bfNormal)));

end;

Control := DeskTop^.ExecView(Dialog);

{Вставка диалогового окна в панель экрана для модального

выполнения.}

Dispose(Dialog, Done);

{Освобождение памяти, занимаемой объектом диалогового окна, после

его выполнения.}

end;

procedure THelloApp.HandleEvent(var Event: TEvent);

begin

TApplication.HandleEvent(Event); {Наследуемый HandleEvent.}

if Event.What=evCommand then

begin

case Event.Command of

cmGreetingBox : GreetingBox;

{Определение реакции на команду cmGreetingBox.}

else

Exit;

end;

ClearEvent(Event);

{Очистка события после выполнения процедуры GreetingBox.}

end;

end;

procedure THelloApp.InitStatusLine;

{Инициализация строки статуса.}

var

R: TRect;

begin

GetExtent(R); {Возвращает в R область, занимаемую TApplication.}

R.A.Y := R.B.Y - 1; {Преобразует R в нижнюю строку этой области.}

StatusLine := New(PStatusLine, Init(R,

{Создание экземпляра объекта типа TStatusLine.}

NewStatusDef(0, $FFFF,

{Определение поддиапазона контекстной подсказки.}

NewStatusKey('~Alt-X~ Exit', kbAltX, cmQuit,

{Включение в строку статуса элемента «Alt-X Exit» с горячей

клавишей «Alt-X», и связывание с ним команды cmQuit (выход из

программы).}

NewStatusKey('~F10~ Menu', kbF10, cmMenu,

{Включение в строку статуса элемента «F10 Menu» с горячей

клавишей «F10», и связывание с ним команды cmMenu (вызов

меню).}

nil)), {Больше не определено элементов.}

nil) {Больше не определено поддиапазонов контекстной подсказки.}

));

end;

procedure THelloApp.InitMenuBar;

{Инициализация строки меню.}

var

R: TRect;

begin

GetExtent(R); {Возвращает в R область, занимаемую TApplication.}

R.B.Y := R.A.Y + 1; {Преобразует R в верхнюю строку этой области.}

MenuBar := New(PMenuBar, Init(R, NewMenu(

{Создание экземпляра объекта типа TMenuBar.}

NewSubMenu('~H~ello', hcNoContext, NewMenu(

{Определение выпадающего подменю ‘Hello’ с коротким набором

‘H’.}

NewItem('~G~reeting...', '', kbNoKey, cmGreetingBox, hcNoContext,

{Определение элемента подменю «Greeting...» с горячей клавишей

«G», и связывание с ним команды cmGreetingBox.}

NewLine(

{Вставка линии-разделителя между элементами подменю.}

NewItem('E~x~it', 'Alt-X', kbAltX, cmQuit, hcNoContext,

{Определение элемента подменю «Exit» с горячей клавишей

«Alt-X», и связывание с ним команды cmQuit.}

nil)))), {Больше не определено элементов подменю.}

nil) {Больше не определено подменю.}

)));

end;

begin

HelloWorld.Init; {Инициализация HelloWorld.}

HelloWorld.Run; {Выполнение HelloWorld.}

HelloWorld.Done; {Освобождение памяти HelloWorld.}

end.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]