Помощь - Поиск - Пользователи - Календарь
Полная версия: Как задействовать стрелки?
Форум «Всё о Паскале» > Pascal, Object Pascal > Теоретические вопросы
ДенисС
Стал вот потихоньку разбираться с паскалем, вроде что то получается. Вот возникла проблема: как задействовать стрелки и прочии несимвольные клавиши? С буквами-цифирьками вроде все просто, пишешь например C:=readln, а потом разными способами опредиляешь, что надо сделать с этой клавишей. А вот как быть со стрелками - как то непойму. Они вроде таким способом в строковую переменную ничего не записывают. Где-то краем уха услышал, что используется запись каким-то сложным шифром, а вот как его после этого опредилять, и какие кнопки каким шифром опредиляются - не слышал. Может здесь кто подскажет, как это все надо делать?
SKVOZNJAK
Дык просто. При нажатии курсоров, эфок и т. д. В буфер клавы записывется два числа, впереди стоит 0.
Код

{ПРОСМОТР КОДОВ КЛАВЫ} USES CRT;
VAR Q3:BYTE;
    Q8:WORD;
BEGIN
FOR Q3:=1 TO 100 DO BEGIN Q8:=ORD(READKEY); WRITELN(Q8); DELAY(200);
 END;
END.


Для чтения клавы в проге используй IF KEYPRESSED=TRUE THEN READKEY
Время от времени обнуляй буфер FOR Q:=1 TO 15 DO IF KEYPRESSED=TRUE THEN READKEY
ДенисС
Это я понял, спасибо. А вот как потом этот код обрабатывать?. Влоб "If c=ord(75) then..." (Влево) - не берется. Вроде как то подругому надо, только как?
SKVOZNJAK
IF KEYPRESSED=TRUE THEN IF ORD(READKEY)=0 THEN IF ORD(READKEY)= ВТОРАЯ ЦИФРА КОДА КЛАВИШИ THEN GOTO 1111
Хотя, вместо гото можно использовать и что-нибудь другое.

IF KEYPRESSED=TRUE THEN CASE ORD(READKEY)
50: .....
100: .........
0: CASE ORD(READKEY)
Altair
Раз уж речь пошла про клавиатуру, то позвольте рссказать о еще одном методе (вместо READ, READKEY и прочего) считывания нажатых клавиш
без всеких "If Ord(readkey) =0 then нажата не буква"
1)начиная с адреса 0:$41A до 0:$41C находится буфер клавиатуры
просматривая его можно определять что нажато
2) If Port[$60]<$80 then ...
так нужно опрашивать порт клавы, с целью выяснения нажатой клавиши,
лично я использую всегда его - он очень быстрый и красивый,
не нужно мучаться с кодами клавиш - там используется номер клавиши на клавиатере, и все клавиши пронумерованны!
SKVOZNJAK
Но обнулять буфер всё-равно надо! Иначе при запусках, торможениях и ускорениях оно таких глюканов ловить будет!
Altair
Да, SKVOZNJAK, согласен с вами, обнуление буфера - это так надо сделать:
mem[0:$41C]:=mem[0:$41A] - т.е. концу буфера приравниваем начало.
ДенисС
Oleg_Z
А можно поподробнее про этот метод, я паскалем недавно занялся и можно сказать, что пока еще чайник.
APAL
А может проще:

Код

Repeat
  {выполняем программу до нажатия}
Until KeyPressed;
 Ch:=ReadKey;
 If Ch=#0 then
 Begin   {функциональная клавиша}
   Ch:=ReadKey;
   Case Ch of
   ....
   End;
 End
    else
 Begin    {обычная клавиша}
   Case Ch of
   ...
   End;
 End;

Altair
APAL, не согласен с вами, так не проще.
ДенисС, этот метод как раз использует функция keypressed (определяет нажата ли клавиша)
Вот тестовая программа, которая позволяет узнать сканкоды всех клавиш:
Код
uses dos;
var

scancod:word;

begin
repeat
 If port[$60]<$80 then
 begin
  scancod:=port[$60];
  mem[0:$41C]:=mem[0:$41A]; {очистка}
  writeln(scancod)
 end
until scancod=1;
end.


а вот эта более продвинутая программа:
Код

uses dos,crt;
var

scancod:word;

begin
clrscr;
repeat
 If port[$60]<$80 then
 begin
  scancod:=port[$60];
  mem[0:$41C]:=mem[0:$41A]; {®зЁбвЄ }
  writeln(scancod);
  port[$60]:=$80;
 end;
If (scancod<>1) and (scancod<>0) then begin port[$60]:=$80; scancod:=0 end;
until scancod=1;
end.

Итак обращаясь к порту $60 мы можем не только определить нажата ли клавиша, но и (что гораздо важнее) определить нажатую клавишу!

в этих программах код клавиш - scancod .
Вот примеры сканкодов:
ESC =1
ENTER=28
SPASE=57
1=2 (клавиша 1 имеет код 2 )
n=n+1(клавиша n имеет код n+1, например 3-код4)
q=16
... (клавиши левее на 1 больше)
p=25 и т.д

--------------------------------
преимущества использования конструкции PORT[$60]
1) выигрыш в скорости:
keypressed использует тоже обращение к портам,
keypressed лежит в модуле CRT ---> компилируется с типом FAR --> задержка на несколько милисекунд, и занимает лишний байт!!!!!!
2) можно использовать не только как keypressed но и как readkey (2 в 1)
3) не надо мучаться с кодировками, все клавиши пронумерованны на всех компах одинаково
------------------------------
какие будут вопросики B)
APAL
А если надо узнать в какой кодировке была нажата клавиша и если важен регистр?
Ведь это дополнительные затруднения!
Конечно они решаются, но это добавочные усложнения. (можно конечно все это офрмить в виде функций)

Я конечно не спорю, в некоторых случаях предпочтительно обращаться прямо к порту, НО также, в некоторых случаях, удобнее использовать ReadKey и KeyPressed.

К примеру - элементарный случай - программист начинающий. smile.gif
Altair
Да,APAL, согласен тогда разделим сферы интересов:
-------------------
Port[$60] :
1) игры (где надо управлять с клавы чем-либо )
2) резиденты ( в зависимости от цели конечно)
3) вирусы (где надо отключить клаву (хотя на пасе -это редкость))
4) ОС (тут тогда можно свою кодировку придумать)
5) учебные программы (я заметил, что сейчас модно заставлять студентов не пользоваться стандартными средствами)
-----------------
keypressed (и прочие встроенные средства):
ВСЕ ОСТАЛЬНОЕ
APAL
Полностью согласен!

P.S.: У тебя хорошо получается разложить все "по полочкам".
Доходчиво!
BlackShadow
Я бы ещё порекомендовал использовать модифицированную функцию ReadKey:

Function ReadKey:Word;Assembler;
Asm
XOR AH,AH
INT 16h
OR AL,AL
JZ @@1
XOR AH,AH
@@1:
End;

Отличие от стандартной заключается в том, что эта возвращает расширенный код клавиши. Для клавишь типа '1' или 'y' он ничем не отличается, а для 'F1' или '<-' возращает значение типа $XX00.
Altair
Отлично, думаю надо создать тему "Замена стандартных средств"
и скидывать туда все подобные исходники!
APAL, что вы на это скажите? (тем более в разделе задачи, про листинг Assign есть исходники модуля system - можно переделать!)
P@sh@
не забывайте также, что седьмой бит значения scancode:=Port[$60] - это флаг нажатия/отпускания клавиши... т.е. если scancode and $80>0, то клавишу отпустили, если 0 - нажали...
также есть некоторые клавиши (Pause, WinKeys, дополнительная цифровая клавиатура - т.н. GreyPad), которые выдают несколько кодов за раз (до четырех) и на нажатие и на отпускание
пример:
Код

var scancode: byte;
     keyup: boolean; {false - нажатие}
     shift: boolean;  {индикатор нажатия клавиши "Shift"}
...
 scancode:=Port[$60];  {последнее событие клавиатуры}
 keyup:=scancode and $80>0; {выцепляем 7-й бит}
 scancode:=scancode and $7F; {убираем 7-й бит}
 if scancode=$2B then shift:=not keyup;  {шифт нажат или отпущен}
...

далее можно проверять флаг shift при обработке обычных клавиш...

но этот код лучше всего использовать в составе обработчика прерывания клавиатуры (как например сделано в моей игрушке "танки", кое-какие исходники которой выложены на форуме). Если же нужна вся клавиатура, а обработчик делать влом (таблицы офигенные набивать), есть еще вариант, небольшая процедурка, потом запишу сюда, если надо
APAL
Цитата(Oleg_Z @ 6.04.04 10:05)
APAL, что вы на это скажите?

Идея хорошая!

Если откапаю в своем архиве выложу модуль для вывода текста через видио память и сохранение области экрана в кэш и может еще что-то найду. Это уже почти CRT... smile.gif

Так можно заменить все в Паскале, но главное чтобы это было оправдано...
SKVOZNJAK
Ну, если уж почувствовали в себе силушку богатырскую, то могу подсказать, где паскаль перепахивать ;) - в доступе к памяти в ПМ до сих пор конь не валялся. Вот потому-то FPC и рулит.
P@sh@
процедурка для проверки нажатых клавиш - обычных, модификаторов (shift, ctrl, alt) и переключателей (Num Lock, Caps Lock, Scroll Lock). Если нет нажатых клавиш - везде нули... нажатий не ждет...
вариант чисто на Паскале:
Код

uses dos;

procedure ReadKeyExt(var ASCII,Scan,Reg:Byte);
var Regs:Registers;
begin
 Regs.AH:=2; Intr($16,Regs); Reg:=Regs.AL; Scan:=0;
 Regs.AH:=1; Intr($16,Regs); ASCII:=0;
 if Regs.Flags and fZero=0 then begin
   Regs.AH:=0; Intr($16,Regs);
   Scan:=Regs.AH; ASCII:=Regs.AL;
 end;
end;

Reg рассматривать как набор битов - флагов клавиш-модификаторов
Scan - сканкод клавиши (любой)
ASCII - код нажатого символа (в текущей кодировке/состоянии регистров)
если хотите, можете переписать на ассемблере
P@sh@
ASCII можно объявить как Char, в ней будет возвращаться то же, что и из обычного Readkey...
procedure ReadKeyExt(var ASCII: char; var Scan, Reg: byte);
ДенисС
Ой, углубились вы куда-то. Операторы какие-то страшные и незнакомые пишите. Ни хрена не понятно. Ну ладно, думаю со временем разберусь. Возвращаясь к readkey, как я понял, для стрелок и других клавиш, с кодами, начинающимися на 0 этот самый readkey нужно прописывать дважды. Так чтоли?
Altair
точно.
buy phentermine viagra online xa
Comprare Il Viagra On Line
can i buy priligy over the count
Get Progesterone Fedex Shipping
do you need a prescription for p
cheap generic cialis uk
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.