Помощь - Поиск - Пользователи - Календарь
Полная версия: Работа с клавиатурой
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Capitan Nemo
Кому не трудно, выделите , пожалуйста, минут 10-15 своего времени...
с этим вопросом уже обращался, с тех пор вычитал немерено разной инфы, скачал много модулей, но недостаточно моих знаний, чтоб это понять! а курсовик сделать надо...
нужно сделать, чтоб при нажатии клавиши клавиатуры воспроизводился звук, например sound(200), а при отпускании клавиши прекращался...

Я находил несколько модулей, в которых есть такая возможность... но как конкретно - не могу понять...

вот модули, в которых это есть:
http://forum.sources.ru/index.php?showtopic=84101
http://www.ishodniki.ru/list/info.php?id=3889


не кидайте, пожалуйста, ссылки на какой-нибудь очередной модуль или типа того... помогите, пожалуйста, для конкретно моей работы.
volvo
Я же по-моему тебе говорил (или не тебе?), как это можно сделать: читаешь скан-код клавиши, если он меньше 128, значит, клавиша нажата - запускаешь звук... Если же скан-код больше 128, значит клавиша отпущена, звук надо останавливать...
Capitan Nemo
сканкод считывается через readkey?
volvo
Нет... Для этого надо писать или обработчик прерывания, или через массив Port ...
Capitan Nemo
а прерывание, как я понимаю через asm?
volvo
Совсем не обязательно... Вот тут, например, смотри в аттаче, как получают скан-код:
прерывания
Capitan Nemo
пытаюсь разобраться с кодом - но многое непонятно...
не смог понять что делает процедура New9...
что необходимо сделать мне для считывания скан-кода?

Scan := Port[ $60 ] - здесь что-то инициализируется?


ЗЫ был бы безумно признателен, если б кто-нибудь набросал код необходимый мне... ну не как ен могу разобраться... не мой это уровень...
мне препод сказал: "не сделаешь это - больше 4 не поставлю"...
но он когда это говорил - был уверен, что функция keypressed возвращает состояние клавиши (нажата или нет в данный момент)...
Возможно, завтра у меня все и так разрулится... а возможно нет... поэтому очень необходимо все-таки реализовать поставленную задачу...
volvo
Цитата
Scan := Port[ $60 ] - здесь что-то инициализируется?
Здесь Скан-код нажатой (или отпущенной) клавиши записывается в переменную Scan... Все, его можно анализировать! Только делать это желательно в основной программе, и уж тем более включать/выключать звук - это довольно длительные действия, а процедура обработки прерывания должна как можно быстрее возвращать управление...

Поэтому переменную Scan описывай глобально, и как только действия по нажатию/отпусканию произведены (т.е., ты поймал момент и включил/выключил звук), Scan обнуляй... Сейчас покажу...

Добавлено через 15 мин.
Вот, смотри:
uses dos, crt;
Var
wasShift, isRight: boolean;
isCtrl, isAlt, do_exit: boolean;
Old_09: Pointer;
KbdIntVec: procedure;

Var
Scan: Byte;

{$f+}
{ Ну, это - собственно процедура - обработчик прерывания, здесь все понятно }
Procedure New9; Interrupt;
Begin
Scan := Port[ $60 ]; { запоминаем скан-код нажатой клавиши в глобальной переменной }
do_exit := (scan = $01); { и смотрим, не нажат ли Escape, для выхода из программы }

Inline( $9C ); { здесь - вызываем старый обработчик прерывания }
KbdIntVec;
End;
{$f-}

var
checked: boolean;

BEGIN
{ запоминаем вектор прерывания 9H... причем, это делаем дважды: }
GetIntVec($9, @KbdIntVec); { Здесь - для удобного вызова с использованием процедурного типа }
GetIntVec($9, Old_09); { а здесь - чтобы потом иметь возможность восстановить текущее значение }
SetIntVec($9, Addr(New9)); { заменяем стандартную процедуру обработки на свою }

Scan := 128; checked := false; { начальные значения }

repeat
{ проверяем значения scan-кода }
case scan of
1 .. 127: { если здесь - то кнопка нажата }
begin
{
для того, чтобы не производить лишних действий -
если кнопка ДО ЭТОГО еще не была нажата, то устанавливаем флажок,
и производим необходимое действие один раз...
Если же факт нажатия кнопки уже зафиксирован установленным флагом -
то ничего не надо делать, только сбросить Scan в начальное значение
}
if not checked then begin
checked := true;
writeln('key pressed ... ');
{ sound(200); }
end;
Scan := 128;
end;
129 .. 255: { если здесь - то клавиша была отпущена (скан-код увеличен на 128) }
begin
{
в принципе, эту проверку можно было бы и не производить, но я уже сделал
по аналогии с обработкой нажатия клавиши...
}
if checked then begin
checked := false;
writeln('key released ... ');
{ nosound; }
end;
Scan := 128;
end;
end;

until do_exit; { цикл закончится только тогда, когда будет нажата кнопка Escape }

{ восстанавливаем ранее сохраненный вектор прерывания перед выходом из программы }
SetIntVec($9, Old_09);
END.


Жми кнопку, выйдет сообщение, что нажал. Пока не отпустишь - больше никаких сообщений не будет. Вместо вывода сообщения поставь то, что закомментировано. Вот и все...

P.S. Могут быть проблемы с F11, F12 - у них разные скан-коды на разных клавиатурах...
Capitan Nemo
огромнейшее спасибо!!!!!

наберусь наглости попросить несколько комментариев по основным этапам сего действия...
Чтоб я хоть мог объяснить как я это сделал)
volvo
Комментарии добавлены...
Capitan Nemo
Огромнейшее спасибо!!!
Вы спасли брянского студента от мозголюбства от препода))
Capitan Nemo
встроил эту штуку в свою программу...
все работает. но с багом... иногда, когда нажму на клавишу - звук начинается, отпускаю - он не прерывается...
если еще раз нажму на эту клавишу и подержу подольше - все нормально становится...
что это может быть, не знаете?
Capitan Nemo
все, разобрался, все исправно работает)

только один нюанс: почему, когда нажимаешь клавиши раз в пятый в колонках раздается звук... кстати, так же и с программой, описанной выше volvo

Добавлено через 3 мин.
и еще вопрос. на этот раз уж точно последний)
как установить задержку на определенное число миллисекунд, кроме как через delay?
volvo
Потому, что я совсем забыл чистить буфер клавиатуры... Когда ты нажимаешь клавишу, ее Ascii-код попадает в буфер, однако оттуда ничем не читается. Буфер переполняется, и начинается писк.
Capitan Nemo
и как это исправить? как очистить буфер?

Добавлено через 11 мин.
readkey, по ходу)

Добавлено через 2 мин.
а насчет задержки вот что мне нужно:
при входе в цикл, если клавиша нажата - я засекаю системное время, при выходе - когда клавиша отжата - засекаю время... отнимаю от конечного начальное, умножаю секунды, прибавляю миллисек, в общем, получаю длительность в миллисекундах....
затем, в другой процедуре я использую эту длительность для воспроизведения...
если ставлю delay(кол-во миллисекунд) он делает не такую паузу, как надо... слишком быстро он, не по кол-ву миллисекунд...
что можно сделать?
volvo
Зайди сюда и посмотри, что есть для работы со временем:
http://volvo71.narod.ru/time_count.htm
Capitan Nemo
спасибо большое, пригодилась ссылка...

все-таки остается неясным. почему delay(ms) делает задержку не на ровно ms времени. а значительно меньше?
можно ли как-нибудь точно сделать?
Capitan Nemo
пошарил по форуму, нашел)
спасибо за помощь!
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.