{Устанавливаем флаг нажатия, анализируя скэн-код и состояние байта нажатия клавиш регистров: }

| CtrlRShiftD:=(C=HotKey) and ((M and KlavReg)=KlavReg);

| if CtrlRShiftD

| then begin { Специальная обработка }

| L:=Port[$61]; H:=L; { портов, если нажата }

| L:=L or $80; { требуемая комбинация }

| Port[$61] :=L;

| Port[$61]:=H;

| Port[$20] :=$20

| end

| else { Иначе пусть выполняется }

| inline($FF/$1E/>OldInt09H); { настоящее прерывание }

| END;

| {$F-}

| VAR

| 1 : Word; {=== ОСНОВНАЯ ЧАСТЬ ПРИМЕРА ==== }

| LABEL Stop;

| BEGIN

| CtrlRShiftD:=False; {обязательное стартовое значение! }

| ClrScr:

| Write('Нажатие Ctrl+Пр.Shift+D приостановит цикл. ');

| GetIntVec($09, OldInt09H); { сохраняем старый вектор }

| SetIntVec($09, @IntProc ); { подставляем новый вектор }

| {...}

Рис. 21.11

- 510 -

| for i:=1 to 30000 do

| begin { рабочий цикл }

| GotoXY( 5,5 );

| Write( 1:6, ' из 30000.');

| { Программа должна периодически проверять, было ли }

| { одновременное нажатие Ctrl+Правая Shift + D ? }

| if CtrlRShiftD

| then { Да. Обработка нажатия горячего ключа }

| begin

| Write('Комбинация нажата...Закончить(Y/N)? ');

| if UpCase( ReadKey )='Y'

| then

| Goto Stop;

| ClrScr;

| { ... }

| end

| else

| { Нет. Дальнейшие действия программы }

| begin

| {...}

| end; {if}

| end; {for i}

| { конец рабочего цикла }

| { ... }

| Stop: { метка выхода из цикла }

| SetIntVec{ $09, OldInt09H );

| { вернем исходный вектор }

| ClrScr

| END.

Рис. 21.11 (окончание)

только устанавливать соответствующие значения скэн-кодов «горячих» клавиш в HotKey и числа для побитового сравнения с байтами $417/$418 в KlavReg.

Недостатком примера является задержка между нажатием комбинации клавиш и началом анализа. Избежать ее можно, если вставить вызовы процедур реакции на «горячие» комбинации прямо в Interrupt-процедуру. Однако не советуем спешить это сделать. При такой организации программы необходимо принимать специальные меры по предохранению содержимого регистров процессора, блокированию прочих прерываний, их согласованию и т.п., о чем можно всегда прочитать в любой толстой книге по системному программированию на языке ассемблера. В большинстве же программ может пригодиться и предложенный способ.

<p>21.7. Эффект обратной записи в буфер ввода</p>

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

- 511 -

лов. Если нажимается клавиша, то ее атрибуты уходят в этот буфер и могут быть оттуда считаны стандартными процедурами Read и ReadKey. Наличие хотя бы одного символа в буфере показывает логическая функция KeyPressed. При считывании из буфера символа его место освобождается. Если программа не опрашивает буфер клавиатуры, то, нажимая клавиши, можно его переполнить. Компьютер при этом издает характерное жалобное попискивание, и все «излишки» в буквальном смысле пропадают.

Ниже рассматривается пример, который вместо того, чтобы считывать информацию из буфера, записывает ее туда. При этом получается достаточно интересный эффект. Можно программно «изобразить» последовательность нажатий до 16 клавиш, в действительности к ним даже не прикасаясь. Такой прием, в частности, может хорошо работать при написании демонстрационных версий программ — достаточно лишь перед операторами ввода с клавиатуры заполнить буфер нужными ответами. Более того, можно организовывать запуск субпроцессов и отвечать на ряд вопросов запускаемых программ, в том числе и управлять меню или функциональными клавишами.

Сама структура буфера достаточно сложна. И способ хранения символов в ней тоже не очевиден (для обычных кодов хранится ASCII-код символа и скэн-код клавиши, для расширенных запоминается код 0 и собственно расширенный код). В силу этого вид процедуры UnReadKey на рис. 21.12 может показаться запутанным. Тем не менее процедура нормально работает.

| { $М 4096, 0, 0}

| { Программа не использует кучи и мало использует стек. }

| { Такая директива нужна для запуска субпроцесса OUTER. }

Перейти на страницу:

Поиск

Похожие книги