Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Теоретические вопросы _ Как задействовать стрелки?

Автор: ДенисС 2.04.2004 17:22

Стал вот потихоньку разбираться с паскалем, вроде что то получается. Вот возникла проблема: как задействовать стрелки и прочии несимвольные клавиши? С буквами-цифирьками вроде все просто, пишешь например C:=readln, а потом разными способами опредиляешь, что надо сделать с этой клавишей. А вот как быть со стрелками - как то непойму. Они вроде таким способом в строковую переменную ничего не записывают. Где-то краем уха услышал, что используется запись каким-то сложным шифром, а вот как его после этого опредилять, и какие кнопки каким шифром опредиляются - не слышал. Может здесь кто подскажет, как это все надо делать?

Автор: SKVOZNJAK 2.04.2004 17:37

Дык просто. При нажатии курсоров, эфок и т. д. В буфер клавы записывется два числа, впереди стоит 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

Автор: ДенисС 2.04.2004 18:01

Это я понял, спасибо. А вот как потом этот код обрабатывать?. Влоб "If c=ord(75) then..." (Влево) - не берется. Вроде как то подругому надо, только как?

Автор: SKVOZNJAK 2.04.2004 18:10

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 2.04.2004 19:46

Раз уж речь пошла про клавиатуру, то позвольте рссказать о еще одном методе (вместо READ, READKEY и прочего) считывания нажатых клавиш
без всеких "If Ord(readkey) =0 then нажата не буква"
1)начиная с адреса 0:$41A до 0:$41C находится буфер клавиатуры
просматривая его можно определять что нажато
2) If Port[$60]<$80 then ...
так нужно опрашивать порт клавы, с целью выяснения нажатой клавиши,
лично я использую всегда его - он очень быстрый и красивый,
не нужно мучаться с кодами клавиш - там используется номер клавиши на клавиатере, и все клавиши пронумерованны!

Автор: SKVOZNJAK 3.04.2004 1:14

Но обнулять буфер всё-равно надо! Иначе при запусках, торможениях и ускорениях оно таких глюканов ловить будет!

Автор: Altair 3.04.2004 12:04

Да, SKVOZNJAK, согласен с вами, обнуление буфера - это так надо сделать:
mem[0:$41C]:=mem[0:$41A] - т.е. концу буфера приравниваем начало.

Автор: ДенисС 3.04.2004 13:10

Oleg_Z
А можно поподробнее про этот метод, я паскалем недавно занялся и можно сказать, что пока еще чайник.

Автор: APAL 4.04.2004 14:02

А может проще:

Код

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 4.04.2004 16:14

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 4.04.2004 16:45

А если надо узнать в какой кодировке была нажата клавиша и если важен регистр?
Ведь это дополнительные затруднения!
Конечно они решаются, но это добавочные усложнения. (можно конечно все это офрмить в виде функций)

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

К примеру - элементарный случай - программист начинающий. smile.gif

Автор: Altair 4.04.2004 16:53

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

Автор: APAL 4.04.2004 17:36

Полностью согласен!

P.S.: У тебя хорошо получается разложить все "по полочкам".
Доходчиво!

Автор: BlackShadow 6.04.2004 14:28

Я бы ещё порекомендовал использовать модифицированную функцию 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 6.04.2004 17:05

Отлично, думаю надо создать тему "Замена стандартных средств"
и скидывать туда все подобные исходники!
APAL, что вы на это скажите? (тем более в разделе задачи, про листинг Assign есть исходники модуля system - можно переделать!)

Автор: P@sh@ 6.04.2004 18:43

не забывайте также, что седьмой бит значения 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 7.04.2004 1:32

Цитата(Oleg_Z @ 6.04.04 10:05)
APAL, что вы на это скажите?

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

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

Так можно заменить все в Паскале, но главное чтобы это было оправдано...

Автор: SKVOZNJAK 7.04.2004 1:51

Ну, если уж почувствовали в себе силушку богатырскую, то могу подсказать, где паскаль перепахивать ;) - в доступе к памяти в ПМ до сих пор конь не валялся. Вот потому-то FPC и рулит.

Автор: P@sh@ 7.04.2004 9:04

процедурка для проверки нажатых клавиш - обычных, модификаторов (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@ 7.04.2004 9:06

ASCII можно объявить как Char, в ней будет возвращаться то же, что и из обычного Readkey...
procedure ReadKeyExt(var ASCII: char; var Scan, Reg: byte);

Автор: ДенисС 13.04.2004 10:25

Ой, углубились вы куда-то. Операторы какие-то страшные и незнакомые пишите. Ни хрена не понятно. Ну ладно, думаю со временем разберусь. Возвращаясь к readkey, как я понял, для стрелок и других клавиш, с кодами, начинающимися на 0 этот самый readkey нужно прописывать дважды. Так чтоли?

Автор: Altair 13.04.2004 10:26

точно.

Автор: buy phentermine viagra online xa 10.11.2021 7:53

Comprare Il Viagra On Line

Автор: can i buy priligy over the count 15.11.2021 19:19

Get Progesterone Fedex Shipping

Автор: do you need a prescription for p 19.12.2021 9:32

cheap generic cialis uk