![]() |
1. Заголовок или название темы должно быть информативным !
2. Все тексты фрагментов программ должны помещаться в теги [code] ... [/code] или [code=pas] ... [/code].
3. Прежде чем задавать вопрос, см. "FAQ" и используйте ПОИСК !
4. НЕ используйте форум для личного общения!
5. Самое главное - это раздел теоретический, т.е. никаких задач и программ (за исключением небольших фрагментов) - для этого есть отдельный раздел!
![]() ![]() |
![]() |
ДенисС |
![]()
Сообщение
#1
|
Группа: Пользователи Сообщений: 9 Репутация: ![]() ![]() ![]() |
Стал вот потихоньку разбираться с паскалем, вроде что то получается. Вот возникла проблема: как задействовать стрелки и прочии несимвольные клавиши? С буквами-цифирьками вроде все просто, пишешь например C:=readln, а потом разными способами опредиляешь, что надо сделать с этой клавишей. А вот как быть со стрелками - как то непойму. Они вроде таким способом в строковую переменную ничего не записывают. Где-то краем уха услышал, что используется запись каким-то сложным шифром, а вот как его после этого опредилять, и какие кнопки каким шифром опредиляются - не слышал. Может здесь кто подскажет, как это все надо делать?
|
SKVOZNJAK |
![]()
Сообщение
#2
|
![]() Профи ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 930 Пол: Мужской Репутация: ![]() ![]() ![]() |
Дык просто. При нажатии курсоров, эфок и т. д. В буфер клавы записывется два числа, впереди стоит 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 Сообщение отредактировано: SKVOZNJAK - |
ДенисС |
![]()
Сообщение
#3
|
Группа: Пользователи Сообщений: 9 Репутация: ![]() ![]() ![]() |
Это я понял, спасибо. А вот как потом этот код обрабатывать?. Влоб "If c=ord(75) then..." (Влево) - не берется. Вроде как то подругому надо, только как?
|
SKVOZNJAK |
![]()
Сообщение
#4
|
![]() Профи ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 930 Пол: Мужской Репутация: ![]() ![]() ![]() |
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 |
![]()
Сообщение
#5
|
![]() Ищущий истину ![]() ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 4 825 Пол: Мужской Реальное имя: Олег Репутация: ![]() ![]() ![]() |
Раз уж речь пошла про клавиатуру, то позвольте рссказать о еще одном методе (вместо READ, READKEY и прочего) считывания нажатых клавиш
без всеких "If Ord(readkey) =0 then нажата не буква" 1)начиная с адреса 0:$41A до 0:$41C находится буфер клавиатуры просматривая его можно определять что нажато 2) If Port[$60]<$80 then ... так нужно опрашивать порт клавы, с целью выяснения нажатой клавиши, лично я использую всегда его - он очень быстрый и красивый, не нужно мучаться с кодами клавиш - там используется номер клавиши на клавиатере, и все клавиши пронумерованны! -------------------- Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С) |
SKVOZNJAK |
![]()
Сообщение
#6
|
![]() Профи ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 930 Пол: Мужской Репутация: ![]() ![]() ![]() |
Но обнулять буфер всё-равно надо! Иначе при запусках, торможениях и ускорениях оно таких глюканов ловить будет!
|
Altair |
![]()
Сообщение
#7
|
![]() Ищущий истину ![]() ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 4 825 Пол: Мужской Реальное имя: Олег Репутация: ![]() ![]() ![]() |
Да, SKVOZNJAK, согласен с вами, обнуление буфера - это так надо сделать:
mem[0:$41C]:=mem[0:$41A] - т.е. концу буфера приравниваем начало. -------------------- Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С) |
ДенисС |
![]()
Сообщение
#8
|
Группа: Пользователи Сообщений: 9 Репутация: ![]() ![]() ![]() |
Oleg_Z
А можно поподробнее про этот метод, я паскалем недавно занялся и можно сказать, что пока еще чайник. |
APAL |
![]()
Сообщение
#9
|
![]() Смотрю... ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 055 Пол: Мужской Реальное имя: Пшеничный Алексей Анатольевич Репутация: ![]() ![]() ![]() |
А может проще:
Код 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 |
![]()
Сообщение
#10
|
![]() Ищущий истину ![]() ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 4 825 Пол: Мужской Реальное имя: Олег Репутация: ![]() ![]() ![]() |
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 |
![]()
Сообщение
#11
|
![]() Смотрю... ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 055 Пол: Мужской Реальное имя: Пшеничный Алексей Анатольевич Репутация: ![]() ![]() ![]() |
А если надо узнать в какой кодировке была нажата клавиша и если важен регистр?
Ведь это дополнительные затруднения! Конечно они решаются, но это добавочные усложнения. (можно конечно все это офрмить в виде функций) Я конечно не спорю, в некоторых случаях предпочтительно обращаться прямо к порту, НО также, в некоторых случаях, удобнее использовать ReadKey и KeyPressed. К примеру - элементарный случай - программист начинающий. ![]() -------------------- |
Altair |
![]()
Сообщение
#12
|
![]() Ищущий истину ![]() ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 4 825 Пол: Мужской Реальное имя: Олег Репутация: ![]() ![]() ![]() |
Да,APAL, согласен тогда разделим сферы интересов:
------------------- Port[$60] : 1) игры (где надо управлять с клавы чем-либо ) 2) резиденты ( в зависимости от цели конечно) 3) вирусы (где надо отключить клаву (хотя на пасе -это редкость)) 4) ОС (тут тогда можно свою кодировку придумать) 5) учебные программы (я заметил, что сейчас модно заставлять студентов не пользоваться стандартными средствами) ----------------- keypressed (и прочие встроенные средства): ВСЕ ОСТАЛЬНОЕ -------------------- Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С) |
APAL |
![]()
Сообщение
#13
|
![]() Смотрю... ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 055 Пол: Мужской Реальное имя: Пшеничный Алексей Анатольевич Репутация: ![]() ![]() ![]() |
Полностью согласен!
P.S.: У тебя хорошо получается разложить все "по полочкам". Доходчиво! -------------------- |
BlackShadow |
![]()
Сообщение
#14
|
Гость ![]() |
Я бы ещё порекомендовал использовать модифицированную функцию 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 |
![]()
Сообщение
#15
|
![]() Ищущий истину ![]() ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 4 825 Пол: Мужской Реальное имя: Олег Репутация: ![]() ![]() ![]() |
Отлично, думаю надо создать тему "Замена стандартных средств"
и скидывать туда все подобные исходники! APAL, что вы на это скажите? (тем более в разделе задачи, про листинг Assign есть исходники модуля system - можно переделать!) -------------------- Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С) |
P@sh@ |
![]()
Сообщение
#16
|
![]() Бывалый ![]() ![]() ![]() Группа: Пользователи Сообщений: 180 Пол: Мужской Репутация: ![]() ![]() ![]() |
не забывайте также, что седьмой бит значения 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 |
![]()
Сообщение
#17
|
![]() Смотрю... ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 055 Пол: Мужской Реальное имя: Пшеничный Алексей Анатольевич Репутация: ![]() ![]() ![]() |
Цитата(Oleg_Z @ 6.04.04 10:05) APAL, что вы на это скажите? Идея хорошая! Если откапаю в своем архиве выложу модуль для вывода текста через видио память и сохранение области экрана в кэш и может еще что-то найду. Это уже почти CRT... ![]() Так можно заменить все в Паскале, но главное чтобы это было оправдано... -------------------- |
SKVOZNJAK |
![]()
Сообщение
#18
|
![]() Профи ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 930 Пол: Мужской Репутация: ![]() ![]() ![]() |
Ну, если уж почувствовали в себе силушку богатырскую, то могу подсказать, где паскаль перепахивать ;) - в доступе к памяти в ПМ до сих пор конь не валялся. Вот потому-то FPC и рулит.
|
P@sh@ |
![]()
Сообщение
#19
|
![]() Бывалый ![]() ![]() ![]() Группа: Пользователи Сообщений: 180 Пол: Мужской Репутация: ![]() ![]() ![]() |
процедурка для проверки нажатых клавиш - обычных, модификаторов (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@ |
![]()
Сообщение
#20
|
![]() Бывалый ![]() ![]() ![]() Группа: Пользователи Сообщений: 180 Пол: Мужской Репутация: ![]() ![]() ![]() |
ASCII можно объявить как Char, в ней будет возвращаться то же, что и из обычного Readkey...
procedure ReadKeyExt(var ASCII: char; var Scan, Reg: byte); |
![]() ![]() |
![]() |
Текстовая версия | 7.04.2025 7:02 |