Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как правильно обрабатывать нажатия одной и более к 
:(
    Опции темы
x486
Дата 29.8.2007, 12:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 7.3.2007

Репутация: нет
Всего: нет



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

Код

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); передаётся коды обеих клавиш, не смотря на то, что одна из них по-прежнему нажата. Есть ли другие способы обрабатывать сообщения клавиатуры? Или я что-то не так сделал?
PM MAIL   Вверх
NiJazz
Дата 29.8.2007, 14:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Jazz coder
****


Профиль
Группа: Экс. модератор
Сообщений: 2286
Регистрация: 10.8.2003
Где: Москва

Репутация: 6
Всего: 23



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


PM MAIL   Вверх
kapbepucm
Дата 29.8.2007, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 993
Регистрация: 14.6.2007
Где: Латвия

Репутация: нет
Всего: 12



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


--------------------
(С) kapbepucm
PM MAIL Skype   Вверх
Earnest
Дата 29.8.2007, 16:21 (ссылка) |   (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Зачем переменные, когда есть GetKeyState?


--------------------
...
PM   Вверх
kapbepucm
Дата 29.8.2007, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 993
Регистрация: 14.6.2007
Где: Латвия

Репутация: нет
Всего: 12



Согласен, отзыв.
Я на JS рисовал, там не любят API...

Это сообщение отредактировал(а) kapbepucm - 29.8.2007, 16:55


--------------------
(С) kapbepucm
PM MAIL Skype   Вверх
x486
Дата 29.8.2007, 18:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 7.3.2007

Репутация: нет
Всего: нет



Использование дополнительных флагов тоже ничего не даёт, а использовать 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); например, отдельным потоком таймера, но это как то не по феншую.
PM MAIL   Вверх
Earnest
Дата 30.8.2007, 07:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



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


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

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


--------------------
...
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0701 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.