Ассемблер архитектура МП Ассемблерные подпрограммы Звуковые возможности управления клавиатурой Библиотека Turbo Vision графические подпрограммы Процедура InitGraph Обработчик событий Режим редактирования Видимый объект Поток События

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

Диалоговое окно выбора режима

Подведем некоторые итоги. Мы создали программу, которая погружает пользователя в среду объектно-ориентированного диалога Turbo Vision: она поддерживает командные клавиши, работу с мышью, может сменить каталог или диск, выбрать нужный файл и загрузить его в окно просмотра. Не так плохо для 300 строк программного текста! Наша дальнейшая задача - реализовать другие режимы работы (поиск нужной строки, добавление и уничтожение строк, их изменение). Для двух из них (уничтожение и редактирование строки) в программе необходимо каким-то образом указать ту строку, с которой будет работать пользователь. Мы уже реализовали эту возможность, предусмотрев в окне просмотра текста управляемый указатель. Поэтому режим просмотра можно принять в качестве основного режима работы с данными. В связи с этим следует несколько изменить метод TNotebook-HandleEvent, предусмотрев в нем автоматический переход в режим просмотра данных в случае успешного открытия файла с данными:

Procedure TNotebook.HandleEvent(var Event: TEvent); 

{Обработчик событий программы} 

begin

Inherited HandleEvent(Event); 

if Event.What = evCommand then 

case Event.Command of 

cmOpenFile: 

begin

FileOpen;

if OpFileF then Work 

end;

.......

end; {TNotebook.HandleEvent}

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

Для реализации этой идеи в уже созданный нами обработчик событий TInterior.HandleEvent следует ввести обработку события cmClose:

const

{Команды для обработчиков событий:}

.......

cmCan=205; 

cmDelete=206;

cmSearch = 207;

cmEdit = 208;

cmAdd = 209;

Function Control: Word; {Создает и использует диалоговое окновыбора режима работы) 

begin

Control := cmCan 

end; {Control}

{-----------------}

Procedure TInterior.HandleEvent (var Event: TEvent) ;

{Обработчик событий для окна данных}

Procedure DeleteItem;

{Удаляет указанный в Location элемент данных}

begin

end; {DeleteItem}

{-----------------}

Procedure AddItem(Edit: Boolean);

{Добавляет новый или редактирует старый элемент данных}

begin

end; {AddItem}

{-----------------}

Procedure SearchItem;

{Ищет нужный элемент}

begin

end; {SearchItem}

{-----------------}

var

R: TPoint; label Cls;

begin {TInterior.HandleEvent} 

Inherited HandleEvent (Event) ; 

case Event. What of evCommand:

case Event . Command of 

cmClose: 

begin

Cls:

case Control of{Получить команду из основного диалогового окна}

cmCan,

cmCancel:EndModal (cmCancel) ;

cmEdit:AddItem (True);

cmDelete:DeleteItem;

cmSearch:SearchItem;

cmAdd:AddItem (False);

end

end;

cmZoom: exit;

end;

evMouseDown: {Позиционировать мышью}

.....

evKeyDown: {Позиционировать клавишами + -}

case Event.KeyCode of

kbEsc: goto Cls;

kbGrayMinus: if Location > Delta.Y then

.....

end; {TInterior.HandleEvent}

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

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

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

Function Control: Word;

{Получает команду из основного диалогового окна} 

const 

X = 1; 

L = 12; 

DX= 13;

But: array [0. .4]of String [13] = {Надписи на кнопках:}

('~1~ Выход ','~2~Убрать ','~3~ Искать ',

'~4~ Изменить ','~5~ Добавить ') ; 

Txt: array [0..3]of String [52] = (

{Справочный текст:}

'Убрать - удалить запись, выделенную цветом', 'Искать - искать запись, начинающуюся нужными буквами', 'Изменить - изменить поле (поля) выделенной записи', 'Добавить - добавить новую запись'); var

R: TRect; 

D: PDialog; 

k: Integer;

begin 

R.Assign(7,6,74,15) ;

D := New{PDialog,Init(R, 'Выберите продолжение:')); 

with D do 

begin

for k := 0 to 3 do {Вставляем поясняющий текст} 

begin

R.Assign(l,l+k,65,2+k);

Insert(New(PStaticText,Init(R,#3+Txt[k]))) 

end;

for k := 0 to 4 do {Вставляем кнопки:} 

begin

R.Assign(X+k*DX,6,X+k*DX+L,8); 

Insert(New(PButton,Init(R,But[k],cmCan+k,bfNormal))) 

end;

SelectNext(False); {Активизируем первую кнопку} 

end;

Control := DeskTopA.ExecView(D); {Выполняем диалог} 

end; {Control}

Сначала создается диалоговое окно с заданными размерами (чтобы программе стал доступен тип TDialog, укажите в предложении Uses модуль Dialogs). Затем в цикле

for k := 0 to 3 do

в окно вставляется поясняющий текст (см. рис.15.10).

Рис.15.10. Диалоговое окно функции Control

Этот текст не связан с диалогом и называется статическим. Для вставки статической строки в любой видимый элемент используется конструктор TStaticTextJnit, которому в качестве параметров передаются координаты строки и сама строка. Как Вы уже могли заметить, идентификаторы объектов в Turbo Vision начинаются на букву Т, а идентификаторы типов-указателей на экземпляры этих объектов начинаются на букву Р. Таким образом, PStaticText - это тип-указатель на экземпляр объекта TStaticText, поэтому оператор

Insert(New (PStaticText, Init(R,'Текст'))

помещает строку «Текст» на место, заданное координатами переменной R. Отметим, что если строка начинается на символ #3, то при выводе на экран она будет размещаться в центре прямоугольника R. Мы используем это соглашение и дополняем каждую выводимую строку этим символом. В цикле

for k := 0 to 4 do {Вставить кнопки:}

в окно вставляются пять кнопок. При их инициации используется то обстоятельство, что определенные нами команды cmCan, ..., cmAdd образуют непрерывное множество [205..209].

Особо следует остановится на операторе

SelectNext(False); {Активизируем 1-ю кнопку}

Дело в том, что по умолчанию активизируется тот элемент диалогового окна, который задан (вставлен в окно) последним. Чтобы изменить активность по умолчанию, используется вызов процедуры SelectNext, которая смещает активность к следующему элементу. Так как элементы образуют замкнутую цепь (от последнего элемента активность переходит к первому), параметр обращения к этой процедуре указывает направления смещения: если он имеет значение False, активным станет следующий в цепи элемент, если True - предыдущий.

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

s := copy(ParamStr(O),1,pos('.',ParamStr(0)))+'pas'; 

assign(f,s);

.....

exit;

Надеюсь, что Вы заблаговременно подготовили остальной текст этого метода, если это не так, вставьте операторы

seek (DataFile, 0);

while not (EOF (DataFile) or LowMemory) do 

begin

.....

end;

Location := 0

Во-вторых, обратили ли Вы внимание на то, что в процедуре TNotebook. Work указательPW инициируется оператором

PW := New(PWorkWin, Init(R));

а динамическая память, выделенная для размещения экземпляра объекта TWorkWin, не возвращается обратно в кучу? Если да, то у Вас есть хорошие шансы избежать многих неприятностей при программировании в среде Turbo Vision. Конечно же, нам следовало где-то в программе позаботиться об удалении ненужного нам экземпляра объекта. Чтобы не усложнять программу, я не стал этого делать: если вставить оператор

Dispose(PW, Done) 

сразу за оператором

DeskTop.Insert(PW)

то вновь созданное окно будет тут же удалено с экрана, поэтому оператор Dispose нужно разместить в обработчике событий TNotebook. HandleEvent (подумайте, где именно).

После включения диалогового окна в цепочку действий, связанных с инициацией PW, появилась возможность приостановить исполнение программы в процедуре Work: вместо оператора

DeskTop.Insert(PW)

вставьте следующие строки:

Control := DeskTop.ExecView(PW); 

Dispose(PW, Done)

и добавьте описание переменной Control:

var

.....

Control: Word;

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

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

Procedure TNotebook.FileOpen;

..... begin

.....

if OpFileF then 

begin

.....

Work{Переходим к работе} 

end;

.....

end; {FileOpen}

Если Вы внесете в программу все описанные изменения и запустите ее на счет , то при попытке выйти из режима просмотра на экране будет развернуто диалоговое окно, показанное на рис. 15.10. «Нажатие» на любую кнопку этого окна не приводит ни к каким последствиям - наше окно пока откликается только на стандартную команду cmClose, связанную с клавишей Esc.

Файл с данными DataType пока еще не существует. Чтобы программа смогла нормальноработать, в диалоговом окне открытия файла укажите произвольное имя, напримерMYDATA. После завершения работы программы будет создан пустой файл MYDATA.DAT.

Модуль CRT включает процедуры и функции, обеспечивающие управление текстовым режимом работы экрана. С помощью входящих в модуль подпрограмм можно перемещать курсор в произвольную позицию экрана, менять цвет выводимых символов и окружающего их фона, создавать окна. Кроме того, в модуль включены также процедуры «слепого» чтения клавиатуры и управления звуком.
На главную