Я создаю легкий клон с помощью DirectX TK. Для ввода я использую пробел. Код, который принимает ввод:
case WM_KEYUP:
Keyboard::ProcessMessage(message, wParam, lParam);
OutputDebugStringA("Up");
break;
Я думал, что WM_KEYUP должен вызываться только один раз, когда клавиша отпущена, что делает его полезным, когда вы хотите получать ввод только для нажатия одной клавиши; однако, когда я запускаю этот код, он печатает «Вверх» как минимум дважды при каждом нажатии клавиши. Если я удерживаю пробел, он постоянно вызывает его, пока я не отпущу его. Как мне это исправить? Спасибо!
Вот код для функции обратного вызова:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static bool s_in_sizemove = false;
static bool s_in_suspend = false;
static bool s_minimized = false;
static bool s_fullscreen = false;
// TODO: Set s_fullscreen to true if defaulting to fullscreen.
auto game = reinterpret_cast<Game*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
switch (message)
{
case WM_PAINT:
if (s_in_sizemove && game)
{
game->Tick();
}
else
{
PAINTSTRUCT ps;
(void)BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
}
break;
case WM_SIZE:
if (wParam == SIZE_MINIMIZED)
{
if (!s_minimized)
{
s_minimized = true;
if (!s_in_suspend && game)
game->OnSuspending();
s_in_suspend = true;
}
}
else if (s_minimized)
{
s_minimized = false;
if (s_in_suspend && game)
game->OnResuming();
s_in_suspend = false;
}
else if (!s_in_sizemove && game)
{
game->OnWindowSizeChanged(LOWORD(lParam), HIWORD(lParam));
}
break;
case WM_ENTERSIZEMOVE:
s_in_sizemove = true;
break;
case WM_EXITSIZEMOVE:
s_in_sizemove = false;
if (game)
{
RECT rc;
GetClientRect(hWnd, &rc);
game->OnWindowSizeChanged(rc.right - rc.left, rc.bottom - rc.top);
}
break;
case WM_GETMINMAXINFO:
if (lParam)
{
auto info = reinterpret_cast<MINMAXINFO*>(lParam);
info->ptMinTrackSize.x = 320;
info->ptMinTrackSize.y = 200;
}
break;
case WM_ACTIVATEAPP:
if (game)
{
if (wParam)
{
game->OnActivated();
}
else
{
game->OnDeactivated();
}
}
Keyboard::ProcessMessage(message, wParam, lParam);
Mouse::ProcessMessage(message, wParam, lParam);
break;
case WM_POWERBROADCAST:
switch (wParam)
{
case PBT_APMQUERYSUSPEND:
if (!s_in_suspend && game)
game->OnSuspending();
s_in_suspend = true;
return TRUE;
case PBT_APMRESUMESUSPEND:
if (!s_minimized)
{
if (s_in_suspend && game)
game->OnResuming();
s_in_suspend = false;
}
return TRUE;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_SYSKEYDOWN:
if (wParam == VK_RETURN && (lParam & 0x60000000) == 0x20000000)
{
// Implements the classic ALT+ENTER fullscreen toggle
if (s_fullscreen)
{
SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
SetWindowLongPtr(hWnd, GWL_EXSTYLE, 0);
int width = 800;
int height = 600;
if (game)
game->GetDefaultSize(width, height);
ShowWindow(hWnd, SW_SHOWNORMAL);
SetWindowPos(hWnd, HWND_TOP, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
}
else
{
SetWindowLongPtr(hWnd, GWL_STYLE, 0);
SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST);
SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
ShowWindow(hWnd, SW_SHOWMAXIMIZED);
}
s_fullscreen = !s_fullscreen;
}
break;
case WM_MENUCHAR:
// A menu is active and the user presses a key that does not correspond
// to any mnemonic or accelerator key. Ignore so we don't produce an error beep.
return MAKELRESULT(0, MNC_CLOSE);
case WM_INPUT:
case WM_MOUSEMOVE:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
Mouse::ProcessMessage(message, wParam, lParam);
break;
case WM_MOUSEWHEEL:
case WM_XBUTTONDOWN:
case WM_XBUTTONUP:
case WM_MOUSEHOVER:
Mouse::ProcessMessage(message, wParam, lParam);
break;
case WM_KEYDOWN:
case WM_KEYUP:
Keyboard::ProcessMessage(message, wParam, lParam);
break;
case WM_SYSKEYUP:
Keyboard::ProcessMessage(message, wParam, lParam);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}