Одновременное нажатие нескольких клавиш

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Ответить
Аватара пользователя
Romtek
постоялец
Сообщения: 190
Зарегистрирован: 22.05.2005 12:29:35
Откуда: Рамат Ган
Контактная информация:

Сообщение Romtek »

В программе "виртуальное пианино" я, допустим, буду нажимать разные клавиши одновременно (аккорды) и хочу получить их скан-коды + нажата ли или отжата клавиша.

readkey не подходит однозначно. Я так понимаю, надо использовать АПИ-функцию GetKeyboardState, но не знаю как организовать цикл обработки сообщений. Это консольное приложение.

Код: Выделить всё

     while GetMessage(AMessage, 0, 0, 0) Do
     Begin
          TranslateMessage(AMessage);
          DispatchMessage(AMessage);
     End;
не подходит.

FPC 2.0.0, i386-Win32
Аватара пользователя
Romtek
постоялец
Сообщения: 190
Зарегистрирован: 22.05.2005 12:29:35
Откуда: Рамат Ган
Контактная информация:

Сообщение Romtek »

Ответ найден.
Вот исходник на Си.

Код: Выделить всё

#include <stdio.h>
#include <windows.h>

int main(int argc, char* argv[])
{

    HANDLE hStdin;
    DWORD cNumRead, fdwMode, fdwSaveOldMode, i;
    INPUT_RECORD irInBuf[128];
 
    hStdin = GetStdHandle(STD_INPUT_HANDLE);
 
  
    GetConsoleMode(hStdin, &fdwSaveOldMode) ;    
    fdwMode = ENABLE_MOUSE_INPUT;
    SetConsoleMode(hStdin, fdwMode) ;
        
    while (1)
    {
        
        ReadConsoleInput(  hStdin,   irInBuf,  128,    &cNumRead);
        
        for (i = 0; i < cNumRead; i++)
        {
            if (irInBuf[i].EventType==KEY_EVENT)
            {
               if (irInBuf[i].Event.KeyEvent.bKeyDown)
               printf (" %c key pressed\n",
                 irInBuf[i].Event.KeyEvent.uChar.AsciiChar);
               else
               printf (" %c key released\n",
                 irInBuf[i].Event.KeyEvent.uChar.AsciiChar);
            }
      }
   }
 
    return 0;
}

Думаю его нетрудно перевести на Паскаль (возможно, я так и сделаю).
Аватара пользователя
Romtek
постоялец
Сообщения: 190
Зарегистрирован: 22.05.2005 12:29:35
Откуда: Рамат Ган
Контактная информация:

Сообщение Romtek »

А это уже на Паскале:

Код: Выделить всё

program con_events;

uses Windows;

var
     hStdin: THandle;
     cNumRead,
     fdwMode,
     fdwSaveOldMode,
     i: DWORD;
     irInBuf: array [0..127] of INPUT_RECORD;

begin
  hStdin:= GetStdHandle (STD_INPUT_HANDLE);
  GetConsoleMode (hStdin, fdwSaveOldMode);
  SetConsoleMode (hStdin,fdwMode);

  while true do
  begin

    ReadConsoleInput (hStdin, irInBuf[0], 128, cNumRead);

    for i := 0 to Pred (cNumRead) do
      if irInBuf[i].EventType = KEY_EVENT then
      begin

        if irInBuf[i].Event.KeyEvent.wVirtualKeyCode= vk_Escape then
           exit;

        if irInBuf[i].Event.KeyEvent.bKeyDown then
          writeln (irInBuf[i].Event.KeyEvent.AsciiChar, ' key pressed')
        else
          writeln (irInBuf[i].Event.KeyEvent.AsciiChar, ' key released');

      end;

  end;

end.
Uniser
новенький
Сообщения: 46
Зарегистрирован: 13.05.2005 23:13:57
Откуда: Украина, Полтава

Сообщение Uniser »

Пианино не получится:
в аккорде qwer невозможно звучание звуков t,a,s,d,f,z,x,c,v и др :)
аппаратные возможности клавиатуры не совпадают с возможностями синтезатора
Uniser
новенький
Сообщения: 46
Зарегистрирован: 13.05.2005 23:13:57
Откуда: Украина, Полтава

Сообщение Uniser »

Вот небольшая переделка:

Код: Выделить всё

program con_events;

uses Windows;

var
    hStdin: THandle;
    cNumRead,
    fdwMode,
    fdwSaveOldMode,
    i,j: DWORD;
    irInBuf: array [0..127] of INPUT_RECORD;
    S:string; C:char;
begin
 hStdin:= GetStdHandle (STD_INPUT_HANDLE);
 GetConsoleMode (hStdin, fdwSaveOldMode);
 SetConsoleMode (hStdin,fdwMode);

 while true do
 begin

   ReadConsoleInput (hStdin, irInBuf[0], 128, cNumRead);

   for i := 0 to Pred (cNumRead) do
     if irInBuf[i].EventType = KEY_EVENT then
     begin

       if irInBuf[i].Event.KeyEvent.wVirtualKeyCode= vk_Escape then
          exit;

       C:=irInBuf[i].Event.KeyEvent.AsciiChar;
       if C in [#32..#255] then begin
         if irInBuf[i].Event.KeyEvent.bKeyDown
         then if Pos(C,S)=0 then S:=S+C else
         else begin
           j:=Pos(C,S);
           if j>0 then delete(S,j,1);
         end;
         write(S,' ');
         for j:=0 to Length(S) do Write(#8);
       end;
     end;

 end;

end.


<span style='color:red'>Настоятельно рекомендую:</span> выделять код тегом [ code ].
Uniser
новенький
Сообщения: 46
Зарегистрирован: 13.05.2005 23:13:57
Откуда: Украина, Полтава

Сообщение Uniser »

А я только подумал, Както мой код не смотрится :)
Ответить