/** * Handles all keyboard input. * @param vkCode the key pressed * @param bKeyDown <code>true</code> if the key is pressed, else it is released * @param sender the window that send the keyboard messages */ bool ApplicationBase::HandleKeyboard(unsigned int vkCode, bool bKeyDown, BaseGLWindow* sender) { auto handled = 0; static unsigned __int64 s_PrevKeyDown = 0; static __int64 s_PrevKeyDownMod = 0; static auto s_PrevKeyDownHandled = 0; auto kmod = 0; auto testkp = 0; auto k = 0; auto twVKCode = vkCode == VK_NUMRETURN ? VK_RETURN : vkCode; if (sender->GetKeyboardModState(VK_MOD_SHIFT)) kmod |= TW_KMOD_SHIFT; if (sender->GetKeyboardModState(VK_MOD_CTRL)) { kmod |= TW_KMOD_CTRL; testkp = 1; } if (sender->GetKeyboardModState(VK_MOD_MENU)) { kmod |= TW_KMOD_ALT; testkp = 1; } if (twVKCode >= VK_F1 && twVKCode <= VK_F15) k = TW_KEY_F1 + (twVKCode - VK_F1); else if (testkp && twVKCode >= VK_NUMPAD0 && twVKCode <= VK_NUMPAD9) k = '0' + (twVKCode - VK_NUMPAD0); else switch (twVKCode) { case VK_UP: k = TW_KEY_UP; break; case VK_DOWN: k = TW_KEY_DOWN; break; case VK_LEFT: k = TW_KEY_LEFT; break; case VK_RIGHT: k = TW_KEY_RIGHT; break; case VK_INSERT: k = TW_KEY_INSERT; break; case VK_DELETE: k = TW_KEY_DELETE; break; case VK_PRIOR: k = TW_KEY_PAGE_UP; break; case VK_NEXT: k = TW_KEY_PAGE_DOWN; break; case VK_HOME: k = TW_KEY_HOME; break; case VK_END: k = TW_KEY_END; break; case VK_DIVIDE: if (testkp) k = '/'; break; case VK_MULTIPLY: if (testkp) k = '*'; break; case VK_SUBTRACT: if (testkp) k = '-'; break; case VK_ADD: if (testkp) k = '+'; break; case VK_DECIMAL: if (testkp) k = '.'; break; default: if ((kmod&TW_KMOD_CTRL) && (kmod&TW_KMOD_ALT)) k = MapVirtualKey(twVKCode, 2) & 0x0000FFFF; } if (bKeyDown) { if (k != 0) handled = TwKeyPressed(k, kmod); else { // if the key will be handled at next WM_CHAR report this event as handled auto key = static_cast<int>(MapVirtualKey(twVKCode, 2) & 0xff); if (kmod&TW_KMOD_CTRL && key > 0 && key < 27) key += 'a' - 1; if (key > 0 && key < 256) handled = TwKeyPressed(key, kmod); } s_PrevKeyDown = twVKCode; s_PrevKeyDownMod = kmod; s_PrevKeyDownHandled = handled; } else { // if the key has been handled at previous WM_KEYDOWN report this event as handled if (s_PrevKeyDown == twVKCode && s_PrevKeyDownMod == kmod) handled = s_PrevKeyDownHandled; else { // if the key would have been handled report this event as handled auto key = static_cast<int>(MapVirtualKey(twVKCode, 2) & 0xff); if (kmod&TW_KMOD_CTRL && key > 0 && key < 27) key += 'a' - 1; if (key > 0 && key < 256) handled = TwKeyTest(key, kmod); } // reset previous keydown s_PrevKeyDown = 0; s_PrevKeyDownMod = 0; s_PrevKeyDownHandled = 0; } if (bKeyDown && handled == 0) { switch (vkCode) { case VK_ESCAPE: this->win.CloseWindow(); handled = 1; break; case VK_F9: this->programManager->RecompileAll(); handled = 1; break; } } if (handled == 0 && IsRunning() && !IsPaused()) handled = cameraView->HandleKeyboard(vkCode, bKeyDown, sender); return handled == 1; }
// TwEventWin returns zero if msg has not been handled, // and a non-zero value if it has been handled by the AntTweakBar library. int TW_CALL TwEventWin(void *wnd, unsigned int msg, unsigned PARAM_INT _W64 wParam, PARAM_INT _W64 lParam) { int handled = 0; static unsigned PARAM_INT s_PrevKeyDown = 0; static PARAM_INT s_PrevKeyDownMod = 0; static int s_PrevKeyDownHandled = 0; switch( msg ) { case WM_MOUSEMOVE: // send signed! mouse coordinates handled = TwMouseMotion((short)LOWORD(lParam), (short)HIWORD(lParam)); break; case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: SetCapture(wnd); handled = TwMouseButton(TW_MOUSE_PRESSED, TW_MOUSE_LEFT); break; case WM_LBUTTONUP: ReleaseCapture(); handled = TwMouseButton(TW_MOUSE_RELEASED, TW_MOUSE_LEFT); break; case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: SetCapture(wnd); handled = TwMouseButton(TW_MOUSE_PRESSED, TW_MOUSE_MIDDLE); break; case WM_MBUTTONUP: ReleaseCapture(); handled = TwMouseButton(TW_MOUSE_RELEASED, TW_MOUSE_MIDDLE); break; case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: SetCapture(wnd); handled = TwMouseButton(TW_MOUSE_PRESSED, TW_MOUSE_RIGHT); break; case WM_RBUTTONUP: ReleaseCapture(); handled = TwMouseButton(TW_MOUSE_RELEASED, TW_MOUSE_RIGHT); break; case WM_CHAR: case WM_SYSCHAR: { int key = (int)(wParam&0xff); int kmod = 0; if( GetAsyncKeyState(VK_SHIFT)<0 ) kmod |= TW_KMOD_SHIFT; if( GetAsyncKeyState(VK_CONTROL)<0 ) { kmod |= TW_KMOD_CTRL; if( key>0 && key<27 ) key += 'a'-1; } if( GetAsyncKeyState(VK_MENU)<0 ) kmod |= TW_KMOD_ALT; if( key>0 && key<256 ) handled = TwKeyPressed(key, kmod); } break; case WM_KEYDOWN: case WM_SYSKEYDOWN: { int kmod = 0; int testkp = 0; int k = 0; if( GetAsyncKeyState(VK_SHIFT)<0 ) kmod |= TW_KMOD_SHIFT; if( GetAsyncKeyState(VK_CONTROL)<0 ) { kmod |= TW_KMOD_CTRL; testkp = 1; } if( GetAsyncKeyState(VK_MENU)<0 ) { kmod |= TW_KMOD_ALT; testkp = 1; } if( wParam>=VK_F1 && wParam<=VK_F15 ) k = TW_KEY_F1 + ((int)wParam-VK_F1); else if( testkp && wParam>=VK_NUMPAD0 && wParam<=VK_NUMPAD9 ) k = '0' + ((int)wParam-VK_NUMPAD0); else { switch( wParam ) { case VK_UP: k = TW_KEY_UP; break; case VK_DOWN: k = TW_KEY_DOWN; break; case VK_LEFT: k = TW_KEY_LEFT; break; case VK_RIGHT: k = TW_KEY_RIGHT; break; case VK_INSERT: k = TW_KEY_INSERT; break; case VK_DELETE: k = TW_KEY_DELETE; break; case VK_PRIOR: k = TW_KEY_PAGE_UP; break; case VK_NEXT: k = TW_KEY_PAGE_DOWN; break; case VK_HOME: k = TW_KEY_HOME; break; case VK_END: k = TW_KEY_END; break; case VK_DIVIDE: if( testkp ) k = '/'; break; case VK_MULTIPLY: if( testkp ) k = '*'; break; case VK_SUBTRACT: if( testkp ) k = '-'; break; case VK_ADD: if( testkp ) k = '+'; break; case VK_DECIMAL: if( testkp ) k = '.'; break; default: if( (kmod&TW_KMOD_CTRL) && (kmod&TW_KMOD_ALT) ) k = MapVirtualKey( (UINT)wParam, 2 ) & 0x0000FFFF; } } if( k!=0 ) handled = TwKeyPressed(k, kmod); else { // if the key will be handled at next WM_CHAR report this event as handled int key = (int)(wParam&0xff); if( kmod&TW_KMOD_CTRL && key>0 && key<27 ) key += 'a'-1; if( key>0 && key<256 ) handled = TwKeyTest(key, kmod); } s_PrevKeyDown = wParam; s_PrevKeyDownMod = kmod; s_PrevKeyDownHandled = handled; } break; case WM_KEYUP: case WM_SYSKEYUP: { int kmod = 0; if( GetAsyncKeyState(VK_SHIFT)<0 ) kmod |= TW_KMOD_SHIFT; if( GetAsyncKeyState(VK_CONTROL)<0 ) kmod |= TW_KMOD_CTRL; if( GetAsyncKeyState(VK_MENU)<0 ) kmod |= TW_KMOD_ALT; // if the key has been handled at previous WM_KEYDOWN report this event as handled if( s_PrevKeyDown==wParam && s_PrevKeyDownMod==kmod ) handled = s_PrevKeyDownHandled; else { // if the key would have been handled report this event as handled int key = (int)(wParam&0xff); if( kmod&TW_KMOD_CTRL && key>0 && key<27 ) key += 'a'-1; if( key>0 && key<256 ) handled = TwKeyTest(key, kmod); } // reset previous keydown s_PrevKeyDown = 0; s_PrevKeyDownMod = 0; s_PrevKeyDownHandled = 0; } break; case WM_MOUSEWHEEL: { static int s_WheelPos = 0; s_WheelPos += ((short)HIWORD(wParam))/WHEEL_DELTA; handled = TwMouseWheel(s_WheelPos); } break; case WM_SIZE: // tell the new size to AntTweakBar TwWindowSize(LOWORD(lParam), HIWORD(lParam)); // do not set 'handled', WM_SIZE may be also processed by the calling application break; } if( handled ) // Event has been handled by AntTweakBar, so we invalidate the window // content to send a WM_PAINT which will redraw the tweak bar(s). InvalidateRect(wnd, NULL, FALSE); return handled; }