Информационный сервер для программистов: Исходники со всего света. Паскальные исходники со всего света
  Powered by Поисковый сервер Яndex: Найдется ВСЁ!
На Главную Pascal Форум Информер Страны мира
   ЧАВО - Частые Вопросы и Ответы    >>    ctraltsh
   
 
 KBD. Как прочитать нажатия клавиш Ctrl, Alt, Shift   Sly Golovanov 27.12.1997

Как получить код клавиш, на которые RedKey вообще не реагирует.


 
 

Pascal FAQ created by SLY Golovanov, 2:5020/278.13 (slightly corrected by Valery Votintsev 2:5021/22) ============================================================================== Q:> А как прочитать нажатия клавиш Ctrl, Alt и подобных? A: Для функции ReadKey эти клавиши не генерируют никаких кодов. Однако, информация о нажатии подобных клавиш все-таки имеется и располагается в памяти (область данных BIOS) по адресу: Seg0040:$17 - Keyboard Status Flags #1 (основные флаги спец.клавиш) Ячейка Seg0040:$0017: <-+---- номера битов Њ7+6+5+4+3+2+1+0­ | |i|c|n|s|A|^|S|S| Бит Знач. Назначение бита Іs+s+s+s+-+-+L+R| N | | | | | | | +-. 0: 01h нажат Right-shift | | | | | | +---. 1: 02h нажат Left-shift | | | | | +-----. 2: 04h нажат Ctrl (любой) | | | | +-------. 3: 08h нажат Alt (любой) | | | +---------. 4: 10h состяние ScrollLock | | +-----------. 5: 20h состяние NumLock | +-------------. 6: 40h состяние CapsLock +---------------. 7: 80h состяние Insert В этих ячейках каждый бит отвечает за одну конкретную спец.клавишу - если бит установлен, то клавиша нажата, если сброшен - то не нажата. Исключение составляют клавиши ScrollLock, NumLock, CapsLock, Insert - при первом нажатии соответствующий бит устанавливается в 1, а при следующем - сбрасывается в 0. Вот вам функция для вытаскивания этой информации их байтов Seg040:$17. Пример вызова: if GetLockKey(Ctrl) then {нажат Ctrl} Type Keytype=(Ins, Caps, Num, Scroll, Ctrl, Alt, LShift, RShift); function GetLockKey(lock:Keytype):Boolean; {Проверяет, нажата ли спец.клавиша} var b:word; begin case lock of Ins : b:=$0080; Caps : b:=$0040; Num : b:=$0020; Scroll : b:=$0010; Alt : b:=$0008; Ctrl : b:=$0004; LShift : b:=$0002; RShift : b:=$0001; end; if (mem[0:$417] and b)=b then GetLockKey:=true else GetLockKey:=false; end; Аналогично (домашнее задание! ;-) можно анализировать и байт по адресу Seg040:$18 (Keyboard Status Flags #2) Ячейка Seg0040:$0018: <-+---- номера битов Њ7+6+5+4+3+2+1+0­ | |i|c|n|s|p|q|A|^| Бит Знач. Назначение бита Іd+d+d+d+-+d+l+l| N | | | | | | | +-. 0: 01h нажат левый Ctrl | | | | | | +---. 1: 02h нажат левый Alt | | | | | +-----. 2: 04h SysReq DOWN | | | | +-------. 3: 08h hold/pause state | | | +---------. 4: 10h нажат ScrollLock | | +-----------. 5: 20h нажат NumLock | +-------------. 6: 40h нажат CapsLock +---------------. 7: 80h нажат Insert Посмотрите на прилагаемый тест, попробуйте нажать несколько клавиш сразу, обратите внимание на то, что статус клавиатуры изменяется как при нажатии на клавиши, так и при отпускании тоже! --- * Origin: (2:5020/794.13) {> Cut here. FileName= GETKEY.PAS } {From: Valery Votintsev 2:5021/22} {Alt, Shift, Ctrl test for 0040:0017 keyboard status} Uses CRT; Const RightShift = $0001; LeftShift = $0002; AnyCtrl = $0004; AnyAlt = $0008; ScrollActive = $0010; NumLockActive = $0020; CapsLockActive= $0040; InsActive = $0080; LeftCtrl = $0100; LeftAlt = $0200; SysReq = $0400; PauseKey = $0800; ScrollLock = $1000; NumLock = $2000; CapsLock = $4000; Insert = $8000; const hex_num:array [0..15] of char='0123456789ABCDEF'; var key:char; {код нажатой клавиши} flags:word; {флаги состояния клавиатуры} newflags:word; function word2hex(w:word):string; {перевод в 16-ричное число} var b:array[1..2] of byte absolute w; begin word2hex:=hex_num[b[2] shr 4]+hex_num[b[2] and $0F] + hex_num[b[1] shr 4]+hex_num[b[1] and $0F] end; function GetFlags:Word; {Считывает состояние флагов спец.клавиш} begin GetFlags:=memW[0:$417]; end; function AnyKeyEvent:boolean; begin AnyKeyEvent:= (KeyPressed or (newflags<>flags)); end; function Pressed(lock:word):Boolean; {Проверяет, нажата ли спец.клавиша с кодом LOCK} begin if (flags and word(lock))<>0 then Pressed:=true else Pressed:=false; end; Procedure WriteKeyCode; begin TextAttr:=White; If KeyPressed then begin key:= ReadKey; {читаем код } if Key = #0 then begin {код оказался расширенным} Write(Ord(Key):3,','); {печатаем нулевой код } key:= ReadKey; {читаем расширенный код } end; Write(Ord(Key):3); {печатаем основной код } end else write(' '); end; Procedure WriteFlags; begin TextAttr:=LightGray; Write(' Flags:',word2hex(memW[Seg0040:$17])); {Теперь печатаем флаги спец.клавиш} TextAttr:=Cyan; If Pressed(RightShift) then Write(' RightShift'); If Pressed(LeftShift ) then Write(' LeftShift'); If Pressed(AnyAlt ) then Write(' AnyAlt'); If Pressed(AnyCtrl ) then Write(' AnyCtrl'); If Pressed(LeftCtrl ) then Write(' LeftCtrl'); If Pressed(LeftAlt ) then Write(' LeftAlt'); If Pressed(SysReq ) then Write(' SysReq'); If Pressed(PauseKey ) then Write(' Pause'); If Pressed(ScrollLock) then Write(' ScrollLock'); If Pressed(NumLock ) then Write(' NumLock'); If Pressed(CapsLock ) then Write(' CapsLock'); If Pressed(Insert ) then Write(' Insert'); {Теперь печатаем состояние переключателей} TextAttr:=Yellow; If Pressed(ScrollActive ) then Write(' ScrollLockActive'); If Pressed(NumLockActive ) then Write(' NumLockActive'); If Pressed(CapsLockActive) then Write(' CapsLockActive'); If Pressed(InsActive ) then Write(' InsActive'); Writeln; TextAttr:=LightGray; end; begin while keypressed do readkey; {Очистить буфер клавиатуры} flags:=GetFlags; {начальное состояние флагов} repeat newflags:=GetFlags; {новое состояние флагов} If AnyKeyEvent then begin {если чего-нибудь нажато} WriteKeyCode; flags:=newflags; {запомнить состояние флагов} WriteFlags; end; until Key = #27; {Цикл, пока не нажмем Esc} while keypressed do readkey; {Очистить буфер клавиатуры} end.