Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Object Pascal: кроссплатформенные технологии > Как правильно отлавливать все нажатия клавиш?


Автор: karataev 28.1.2006, 01:20
Люди добрые, подскжите пожалуйста, как правильно отловить в Паскале нажатия клавиш, например стрелок и т.п. У меня получается отлавливать только клавиши со значениями таблицы ASCII а всякие там управляющие клавиши не получается... smile

Автор: Snowy 28.1.2006, 02:03
Цитата
Описывая свою проблему, не забывайте указывать компилятор и версию.

Если речь идет о TP7, то здесь 3 варианта:
1. Читать данные с порта клавиатуры.
2. Через ассемблерные вставки, используя прерывание клавиатуры.
3. Через чтение области памяти BIOS.
Только вот пример привести не могу - всего не упомнишь, а тут конкретные цифры нужны.
Уж лет 10 на TP не кодил - не помню. Даже прерывание клавы не помню. Вроде $16...

Автор: volvo877 28.1.2006, 02:27
Цитата(karataev @ 28.1.2006, 00:20 Найти цитируемый пост)
как правильно отловить в Паскале нажатия клавиш, например стрелок и т.п.

Стрелки и другие управляющие клавиши - это расширенный код: сначала идет нулевой байт, а потом - собственно код... Программно это выглядит вот так:
Код
ch := readkey;
case ch of
  #0: { расширенный код - какая-то из специальных клавиш }
    case readkey of { берем сам код и обрабатываем: }
      #72: begin { стрелка вверх } end; 
      #80: begin { стрелка вниз   } end; 
      #75: begin { стрелка влево } end; 
      #72: begin { стрелка вправо } end; 
    end;

  #13: { а здесь уже отлавливаешь обычные клавиши - это например был Enter }
  { ... }
end;


Если нужно Ctrl/Shift/Alt/Locks - то там немного по другому: надо смотреть состояние байт по адресу $0:$417 и $0:$418...
Цитата
Байт $0417
Биты
0        Нажат правый Shift
1        Нажат левый Shift
2        Нажат Ctrl
3        Нажат Alt
4        ScrollLock
5        NumLock
6        CapsLock
7        Ins (режим вставки/замещения)

Байт $0418
Биты
0        1, если нажаты Ctrl+Shift (слева)
1        1, если нажаты Alt+Shift (слева)
2        зависит от клавиатуры
3        зависит от клавиатуры
4        1, если нажат ScrollLock
5        1, если нажат NumLock
6        1, если нажат CapsLock
7        1, если нажата клавиша Ins

Автор: karataev 28.1.2006, 10:12
Цитата

Стрелки и другие управляющие клавиши - это расширенный код: сначала идет нулевой байт, а потом - собственно код...

Спасибо большое, с этим я разобрался smile

Цитата

Если нужно Ctrl/Shift/Alt/Locks - то там немного по другому: надо смотреть состояние байт по адресу $0:$417 и $0:$418...

А вот тут не могу объявить переменную, чтобы лежала по этому адресу. Не напомните как это сделать?

Автор: volvo877 28.1.2006, 12:59
Цитата(karataev @ 28.1.2006, 09:12 Найти цитируемый пост)
А вот тут не могу объявить переменную, чтобы лежала по этому адресу. Не напомните как это сделать?
Используй директиву Absolute:
Код
Var controlByte: byte Absolute $0000:$0417;

Автор: Zero 28.1.2006, 13:18
Нажатие контрол и остальных клавиш отдельно не фиксируется, а если их нажимать в сочетании, то определить код легко можно так:
С начала напиши такой код:
Код

uses crt;
var
  c:char;
begin
  c:=readkey;
end.

А дальше в отладчике, в пошаговом режиме смотри за изменением, при выполнении строки
Код

c:=readkey;
у тебя будет ожидание нажатия клавиши, и когда ты её нажмёш, в Watches листе воткни переменную с (поставь на неё курсор и нажми CTRL+<F7>, Enter)
Потом в пошаговом режиме посмотри, если нажать одну любую обычную клавишу (например 'q'), то в для неё кодовый символ так и будет 'q' в вочлисте, а если перед этим удерживать клавишу CTRL, а потом нажать 'q', то там будет код #17
Вот пример кода, который выдаст сообщение если нажата комбинация CTRL+<q>:
Код

uses crt;
var
  c:char;
begin
  c:=readkey;
  if c=#17 then write('нажата комбинация клавиш CTRL+<q>');
end.

Автор: volvo877 28.1.2006, 13:28
Цитата(Zero @ 28.1.2006, 12:18 Найти цитируемый пост)
Нажатие контрол и остальных клавиш отдельно не фиксируется
Уверен? Тогда запусти вот это:
Код

uses crt;
Var
  ct_byte: byte Absolute $0000:$0417;
  s: string;

begin
  repeat
    s := '';
    if (ct_byte and $01) > 0 then s := s + ' R-Shift ';
    if (ct_byte and $02) > 0 then s := s + ' L_Shift ';
    if (ct_byte and $04) > 0 then s := s + ' Ctrl ';
    if (ct_byte and $08) > 0 then s := s + ' Alt ';

    writeln(s);

  until keypressed;
end.

(для выхода - любая обычная клавиша)

Автор: karataev 28.1.2006, 14:08
Цитата

Используй директиву Absolute:

Код

Var controlByte: byte Absolute $0000:$0417;



Я ее и использую, только у меня Free Pascal и он говорит что "Error: absolute can only be associated with a var or const"...

Автор: UpL1nK 28.1.2006, 14:50
Цитата(karataev @ 28.1.2006, 14:08 Найти цитируемый пост)

"Error: absolute can only be associated with a var or const"

Может в FP нельзя задавать абсолютный адрес, а только делать наложение на ранее определенную переменную ?

Код

Var t:byte;
      a:integer absolute t;

Автор: karataev 28.1.2006, 15:34
Цитата

Может в FP нельзя задавать абсолютный адрес, а только делать наложение на ранее определенную переменную ?


Ну тогда нужно чтобы у переменной t был нужный мне адрес - это какой то замкнутый круг получается... smile

Автор: UpL1nK 28.1.2006, 16:02
Просто у меня BPW и абсолютный адрес и наложение работает, хотя я не думаю что есть чтото возможное в BPW , но невозможное в FP smile

Автор: volvo877 28.1.2006, 18:08
karataev, под какой ОС сидишь? Если под Windows, так пользуйся модулем Windows (какая разница, ты же можешь получить доступ к его функциям и из консольной программы):
Код

uses crt, windows;
Var
  s: string;

begin
  repeat

    s := '';
    if GetKeyState(VK_SHIFT) < 0 then s := s + ' shift ';
    if GetKeyState(VK_CONTROL) < 0 then s := s + ' ctrl ';

    writeln(s);

  until keypressed;
end.

Понажимай Ctrl и Shift, и посмотри как меняется текст...

Автор: karataev 28.1.2006, 18:41
Все, спасибо, я поставил себе Turbo Pascal 7.0 и все заработало. smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)