C_Kurs_Lekt / C_III_семестр / 16_Menu
.pdfСОЗДАНИЕ «ВСПЛЫВАЮЩИХ» МЕНЮ
При создании меню будем придерживаться следующей последовательности:
1.Сохранить область экрана под меню;
2.Высветить рамку вокруг меню, если надо;
3.Высветить меню;
4.Получить ответ пользователя;
5.Восстановить экран в исходное состояние.
Функции, создающей исчезающее меню, должна быть передана некоторая информация:
1.Во-первых, это список предоставляемых меню режимов, т.е. число режимов(пунктов в меню) и названия этих пунктов;
2.Список «горячих» клавиш. (Передаем строку, которая содержит символы "горячих" клавиш в том же порядке, что и строки меню);
3.Функция должна также знать, где расположить меню, то есть нужны координаты X и Y;
4.В некоторых ситуациях может быть желательным помещать меню в рамку, а в других - нет. Поэтому должно быть передано значение рамка включена/выключена.
Управление:
Пользователь может вводить выбор одним из двух способов. Во-первых с помощью клавиш СТРЕЛКА ВНИЗ и СТРЕЛКА ВВЕРХ может переместить освещение на строку и нажать Ввод для ее выбора, (Обычно освещение строки выполняется в инверсном режиме.) Освещенную строку также можно передвигать «пробелом».
Каждый раз при нажатии стрелки освещенная опция переходит в нормальное изображение, а следующая - освещается. Нажатие стрелки вниз (или «пробел»), в момент освещения крайней нижней позиции, означает возвращение к первому значению. То же самое, но наоборот происходит когда нажимается стрелка вверх при освещенной первой позиции.
Второй способ это нажатие клавиши, связанной с выбором (нажатие «горячей» клавиши).
Выход из меню: нажатие клавиши ESC.
При опросе клавиатуры мы должны использовать bioskey() вместо getchar(). Проблема заключается в том, что программа должна иметь возможность считывать полный 16 битный скан код, генерируемый нажатием клавиши. Если нажата символьная клавиша, то символ помещается в младшие 8 бит, а старшие 8 бит равны 0. Однако, если нажата специальная клавиша, такая, как стрелка, младший байт равен 0, а старший содержит код позиции клавиши. Коды позиции для стрелки вверх и стрелки вниз равны 72 и 80 соответственно. Такие функции, как getchar(), возвращают только код символа, а необходимо анализировать полный 16-битный скан код. Используя bioskey() мы можем анализировать нажатия F1, F2, …, SHIFT, CapsLock и т.д.
bioskey Интерфейс клавиатуры, напрямую использующий операции BIOS
Синтаксис #include <bios.h> int bioskey(int cmd);
-----------------------------------------------------------------
¦=================================================================-
Это - интерфейс прикладного уровня с клавиатурой. Нажатия клавиш на самом деле обрабатываются асинхронно на заднем плане. Когда клавиша получена от клавиатуры, она обрабатывается прерыванием INT 09H и помещается в циклическую очередь (буфер клавиатуры).
INT 16H: Сервис клавиатуры (int cmd в bioskey)
-----------------------------------------------------------------
00H читать (ожидать) следующую нажатую клавишу
Выход: AL = ASCII символ (если AL=0, AH содержит Расширенный код
ASCII )
AH = Сканкод или Расширенный код ASCII
------------------------------------------------------------------
01H Проверить готовность символа (и показать его, если так) Выход: ZF = 1 если символ не готов.
ZF = 0 если символ готов.
AX = как для подфункции 00H (но символ здесь не удаляется из очереди).
------------------------------------------------------------------
02H Читать состояние shift-клавиш. Определить, какие shift-клавиши нажаты в данный момент, находится ли клавиатура в состоянии NumLock, и т.п.
Выход: AL = статус клавиатуры
------------------------------------------------------------------
clskbr(); for(;;) {
while(!bioskey(1)); /* ждать нажатия */ c.i=bioskey(0); // взять код из буфера клавиатуры
if(c.ch[0]) { /* обычная клавиша */ switch(c.ch[0]) {
case '\r' : return arrow_choice;
case ' ' : arrow_choice++; break; /* "пробел" - на пункт ниже */ case 27 : return -1; /* выйти из меню */
}
}
else { /* специальная клавиша */ switch(c.ch[1]) {
case 72 : arrow_choice--; break;/* стрелка вниз */ case 80 : arrow_choice++; break;/* стрелка вверх */
}
}
Возможные модификации (улучшения):
1.Добавить подсказку под меню (необходимо проверять возможность вывода )
2.Добавить вывод рамок в цвете;
3.Добавить выбор типа линии для рамки;
4.Добавить «раскраску» горячих клавиш;
5.Очистка места (под меню)
6.Переход на прямой доступ к видеопамяти – ускорит вывод данных.
bioskey Интерфейс клавиатуры, напрямую использующий
операции BIOS
-----------------------------------------------------------------
Синтаксис |
#include <bios.h> |
|
|
|
|
|
|
int bioskey(int cmd); |
|
|
|
||
Замечания |
Эта функция |
выполняет |
различные |
операции |
с |
|
|
клавиатурой, используя при этом прерывание BIOS |
|||||
|
0х16. Параметр cmd определяет выполняемую опе- |
|||||
|
рацию. |
|
|
|
|
|
Возвращаемое |
Значение, возвращаемое |
функцией, |
зависит |
от |
||
значение |
выполняемой |
ею |
операции, которая, в свою |
очередь, определяется значением параметра cmd:
0 Если младшие 8 бит отличны от нуля, bioskey возвращает символ в коде ASCII, представляющий следующую нажатую клавишу клавиатуры (или ожидающую из буфера клавиатуры). Если же младшие 8 бит нулевые, то в старших 8 битах передаются расширенные коды клавиатуры, приведенные в Техническом справочном руководстве по IBM PC.
1 Производит проверку |
наличия |
символа |
для |
|
чтения |
(нажата ли клавиша). |
Если возвращае- |
||
мое значение равно 0, считывать нечего. Если |
||||
нажата |
комбинация |
клавиш <Ctrl/Break>, |
то |
|
возвращаемое значение равно 0xFFFFF (-1). |
В |
|||
противном случае возвращается значение сле- |
||||
дующей |
нажатой клавиши. Сам же код нажатой |
|||
клавиши сохраняется для возвращения при сле- |
||||
дующем |
вызове bioskey со значением cmd, рав- |
|||
ном 0. |
|
|
|
|
2 Запрашивает текущий статус функциональных клавиш (типа <Shift>). Возвращаемое значение получается при логическом сложении следующих значений (операция OR):
бит 7 |
0x80 |
включен режим |
Insert |
(вставка) |
бит 6 |
0x40 |
включен режим |
Caps |
|
бит 5 |
0x20 |
включен режим |
Num Lock |
|
бит 4 |
0x10 |
включен режим |
Scroll |
Lock |
бит 3 |
0x08 |
нажата клавиша Alt |
|
|
бит 2 |
0x04 |
нажата клавиша Ctrl |
Shift |
|
бит 1 |
0x02 |
нажата левая клавиша |
||
бит 0 |
0x01 |
нажата правая |
клавиша Shift |
Пример
#include <stdio.h> #include <bios.h> #include <ctype.h>
#define RIGHT |
0x01 |
|
#define LEFT |
0x02 |
|
#define |
CTRL |
0x04 |
#define |
ALT |
0x08 |
int main (void)
{
int key, modifiers;
/* пока не будет нажата клавиша функция 1 возвращает 0 */ while(bioskey(1) == 0);
/* функция 0 используется для получения значения нажатой клавиши*/
key = bioskey(0);
/* функция 2 используется для определения того, была ли нажата функциональная клавиша типа <Sсhift> */
modifiers = bioskey (2);
if (modifiers) |
|
{ |
|
printf ("["); |
printf("RIGHT"); |
if (modifiers & RIGHT) |
|
if (modifiers & LEFT) |
printf("LEFT"); |
if (modifiers & CTRL) |
printf("CTRL"); |
if (modifiers & ALT ) |
printf("ALT"); |
printf ("]"); |
|
} |
|
/* вывести прочитанный символ */ if (isalnum(key & 0xFF))
printf("'%c'\n", key); else
printf("%#02x\n", key);
return 0;
}