Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Как правильно обрабатывать нажатия одной и более к


Автор: x486 29.8.2007, 12:10
Как правильно обрабатывать нажатия одной и более клавиш? Пишу программу, не важно какую, на обработке сообщений окна у меня висит примерно такой код:

Код

LRESULT CALLBACK WndProc(HWND hWnd, UINT _msg, WPARAM wParam, LPARAM lParam) 
 {
   switch (_msg)
    {
      case WM_CLOSE:
        PostQuitMessage(0);
      return 0;

      case WM_KEYDOWN:
        KeyDownFunc(wParam);
      return 0;   
 
      case WM_KEYUP:
        KeyUpFunc(wParam);
      return 0;   

      default: return DefWindowProc(hWnd, _msg, wParam, lParam);
    }
    return DefWindowProc(hWnd, _msg, wParam, lParam); 
 }
  

При этом, когда я зажимаю одновременно две клавиши происходит обращение к функции KeyDownFunc(wParam); сначала с кодом одной, а потом с кодом второй клавиши. Но когда я отпускаю одну из клавиш, я не получаю возможность отслеживать код оставшейся нажатой клавиши. Вопрос почему? В Функцию KeyUpFunc(wParam); передаётся коды обеих клавиш, не смотря на то, что одна из них по-прежнему нажата. Есть ли другие способы обрабатывать сообщения клавиатуры? Или я что-то не так сделал?

Автор: NiJazz 29.8.2007, 14:57
Можно так: завести переменную, которая будет принимать нужное значение, как только нажата одна из клавиш один раз, если после этого приходит код второй клавиши и эта переменная имеет значение, скажем, true, значит, нажаты обе клавиши. Если приходит код первой клавиши и значение true, значит, нажата она одна и значение переменить на false. Попробуй, вдруг поможет. smile
Ещё можно запоминать время нажатия клавиш. Если между двумя клавишами меньше, скажем, полсекунды, то вперёд.


Автор: kapbepucm 29.8.2007, 15:14
Я бы заводил для каждой клавиши свою переменную. Когда конкретная клавиша нажата соотв. переменная принимает значение True, отпущена- False. В любой момент видишь состояние любой клавиши...

Автор: Earnest 29.8.2007, 16:21
Зачем переменные, когда есть GetKeyState?

Автор: kapbepucm 29.8.2007, 16:53
Согласен, отзыв.
Я на JS рисовал, там не любят API...

Автор: x486 29.8.2007, 18:46
Использование дополнительных флагов тоже ничего не даёт, а использовать GetKeyState нет никакого смысла (что, мне го в бесконечном цикле вызывать прикажите?), мне нужна именно обработка сообщений окна. Вот, например, немного доработанный кусок кода:
Код


bool M[255];

LRESULT CALLBACK WndProc(HWND hWnd, UINT _msg, WPARAM wParam, LPARAM lParam) 
 {
   switch (_msg)
    {
      case WM_CLOSE:
        PostQuitMessage(0);
      return 0;

      case WM_KEYDOWN:
        M[wParam] = true;
        KeyFunc(M);
      return 0;   
 
      case WM_KEYUP:
        M[wParam] = false;
        KeyFunc(M);
      return 0;   

      default: return DefWindowProc(hWnd, _msg, wParam, lParam);
    }
  
    return DefWindowProc(hWnd, _msg, wParam, lParam); 
 }

В принципе всё предельно просто, при нажатии клавиши в массиве M флаг соответствующей клавиши  устанавливается в значение 1, если клавиша отпущена, он принимает значение 0. Отследить нажатие 2-х клавиш одновременно при этом не составляет труда по их кодам

if (M[56] && M[78])
  {
    Делать чё нибуть.
  }

Проблема состоит в том, что если отпустить одну клавишу то оба флага принимают значение «false», точнее, перестаёт поступать событие WM_KEYDOWN: от всё ещё нажатой клавиши. Этого можно конечно избежать вызывая функцию KeyFunc(M); например, отдельным потоком таймера, но это как то не по феншую.

Автор: Earnest 30.8.2007, 07:18
Цитата(x486 @  29.8.2007,  19:46 Найти цитируемый пост)
а использовать GetKeyState нет никакого смысла (что, мне го в бесконечном цикле вызывать прикажите?), 


Цитата(x486 @  29.8.2007,  19:46 Найти цитируемый пост)
оба флага принимают значение «false», точнее, перестаёт поступать событие WM_KEYDOWN: от всё ещё нажатой клавиши. 

Бесконечный цикл - вовсе не единственная альтертанива. При отпускании одной из клавиш (проверив, нажата ли еще вторая) ставь таймер с небольшим периодом и проверяй по таймеру. Например.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)