Я хочу сделать 2 разных команды, если я на короткое время нажимаю на клавиатуру или в течение длительного периода времени. Windows отправляет мне несколько событий keyDown и KeyUp, если я держу ключ.
Прямо сейчас. Я делаю это для обработки "Длительной печати",
c++:
if (pMsg->message == WM_KEYDOWN)
{
return keyboardManager->Execute( (KeyboardCommand)pMsg->wParam, BOOL (HIWORD(pMsg->lParam) & KF_REPEAT) == 0 ) )
}
note: pMsg - это структура MSG (winuser.h), а KeyboardCommand - это перечисление с значениями кодов виртуальных ключей
С#:
public Boolean Execute( KeyboardCommand _command, Boolean _first )
{
switch(_command)
{
case (KeyboardCommand.myCommand):
TimeSpan timeLapse = DateTime.Now - m_TimeKeyDown;
if (_first)
{
m_TimeKeyDown = DateTime.Now;
m_LongCommandExecuted = false;
}
else if (!m_LongCommandExecuted && timeLapse.TotalMilliseconds > 500)
{
m_LongCommandExecuted = true;
handled = ExecuteAction();
}
break;
case (KeyboardCommand.otherCommand):
break;
}
return handled;
}
У вас есть идея о том, как обращаться с "короткой печатью"? Знание того, что KeyUp является последним keyUp (real keyUp), может решить мою проблему.
Я нашел ответ.
c++:
if (pMsg->message == WM_KEYUP || pMsg->message == WM_KEYDOWN)
{
return keyboardManager->Execute( (KeyboardCommand)pMsg->wParam, BOOL (HIWORD(pMsg->lParam) & KF_REPEAT) == 0, (HIWORD(pMsg->lParam) & KF_UP) == KF_UP, pMsg->message == WM_KEYDOWN )
}
С#:
public Boolean Execute( KeyboardCommand _command, Boolean _first, Boolean _last, Boolean _keyDown )
{
if (_keyDown)
{
switch (_command)
{
case (KeyboardCommand.otherCommand):
handled = ExecuteCommand();
break;
}
}
switch (_command)//Short press and long press events
{
case (KeyboardCommand.mycommand):
if (_first)
{
m_TimeKeyDown = DateTime.Now;
m_LongCommandExecuted = false;
}
else
{
TimeSpan timeLapse = DateTime.Now - m_TimeKeyDown;
if (!m_LongCommandExecuted && timeLapse.TotalMilliseconds > 500)//long press
{
m_LongCommandExecuted = true;
handled = myLongcommand();
}
if (!m_LongCommandExecuted && _last)//short press
{
m_LongCommandExecuted = true;
handled = myShortcommand();
}
}
break;
}
//some other jazz
}
Вы можете попробовать что-то вроде следующего. Этот пример просто перехватывает события KeyDown и KeyUp формы, поэтому вам нужно будет изменить его в соответствии с вашими потребностями.
//consider keys held less than one second a short keypress event
const double longThresholdMs = 1000.0;
Dictionary<Keys, DateTime> keyDownTimes = new Dictionary<Keys, DateTime>();
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (!keyDownTimes.ContainsKey(e.KeyCode))
{
keyDownTimes[e.KeyCode] = DateTime.Now;
}
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (keyDownTimes.ContainsKey(e.KeyCode))
{
if (DateTime.Now.Subtract(keyDownTimes[e.KeyCode]).TotalMilliseconds > longThresholdMs)
{
Console.Out.WriteLine(e.KeyCode + " long press");
}
else
{
Console.Out.WriteLine(e.KeyCode + " short press");
}
keyDownTimes.Remove(e.KeyCode);
}
}