/** * 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; }
/* return code -1 means that event_queue_ptr won't be incremented. In other word, this event makes two key codes. (by himi) */ static int key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead) { static int mod_key_state = 0; int wParam; *isdead = 0; /* Skip key-up events. */ if (!event->bKeyDown) { switch (event->wVirtualKeyCode) { case VK_LWIN: mod_key_state &= ~LEFT_WIN_PRESSED; break; case VK_RWIN: mod_key_state &= ~RIGHT_WIN_PRESSED; break; case VK_APPS: mod_key_state &= ~APPS_PRESSED; break; } return 0; } /* Ignore keystrokes we fake ourself; see below. */ if (faked_key == event->wVirtualKeyCode) { faked_key = 0; return 0; } /* To make it easier to debug this code, ignore modifier keys! */ switch (event->wVirtualKeyCode) { case VK_LWIN: if (NILP (Vw32_pass_lwindow_to_system)) { /* Prevent system from acting on keyup (which opens the Start menu if no other key was pressed) by simulating a press of Space which we will ignore. */ if ((mod_key_state & LEFT_WIN_PRESSED) == 0) { if (NUMBERP (Vw32_phantom_key_code)) faked_key = XUINT (Vw32_phantom_key_code) & 255; else faked_key = VK_SPACE; keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0); } } mod_key_state |= LEFT_WIN_PRESSED; if (!NILP (Vw32_lwindow_modifier)) return 0; break; case VK_RWIN: if (NILP (Vw32_pass_rwindow_to_system)) { if ((mod_key_state & RIGHT_WIN_PRESSED) == 0) { if (NUMBERP (Vw32_phantom_key_code)) faked_key = XUINT (Vw32_phantom_key_code) & 255; else faked_key = VK_SPACE; keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0); } } mod_key_state |= RIGHT_WIN_PRESSED; if (!NILP (Vw32_rwindow_modifier)) return 0; break; case VK_APPS: mod_key_state |= APPS_PRESSED; if (!NILP (Vw32_apps_modifier)) return 0; break; case VK_CAPITAL: /* Decide whether to treat as modifier or function key. */ if (NILP (Vw32_enable_caps_lock)) goto disable_lock_key; return 0; case VK_NUMLOCK: /* Decide whether to treat as modifier or function key. */ if (NILP (Vw32_enable_num_lock)) goto disable_lock_key; return 0; case VK_SCROLL: /* Decide whether to treat as modifier or function key. */ if (NILP (Vw32_scroll_lock_modifier)) goto disable_lock_key; return 0; disable_lock_key: /* Ensure the appropriate lock key state is off (and the indicator light as well). */ wParam = event->wVirtualKeyCode; if (GetAsyncKeyState (wParam) & 0x8000) { /* Fake another press of the relevant key. Apparently, this really is the only way to turn off the indicator. */ faked_key = wParam; keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), KEYEVENTF_EXTENDEDKEY | 0, 0); keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0), KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); } break; case VK_MENU: case VK_CONTROL: case VK_SHIFT: return 0; case VK_CANCEL: /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL, which is confusing for purposes of key binding; convert VK_CANCEL events into VK_PAUSE events. */ event->wVirtualKeyCode = VK_PAUSE; break; case VK_PAUSE: /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing for purposes of key binding; convert these back into VK_NUMLOCK events, at least when we want to see NumLock key presses. (Note that there is never any possibility that VK_PAUSE with Ctrl really is C-Pause as per above.) */ if (NILP (Vw32_enable_num_lock) && (event->dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0) event->wVirtualKeyCode = VK_NUMLOCK; break; } /* Recognize state of Windows and Apps keys. */ event->dwControlKeyState |= mod_key_state; /* Distinguish numeric keypad keys from extended keys. */ event->wVirtualKeyCode = map_keypad_keys (event->wVirtualKeyCode, (event->dwControlKeyState & ENHANCED_KEY)); if (lispy_function_keys[event->wVirtualKeyCode] == 0) { if (!NILP (Vw32_recognize_altgr) && (event->dwControlKeyState & LEFT_CTRL_PRESSED) && (event->dwControlKeyState & RIGHT_ALT_PRESSED)) { /* Don't try to interpret AltGr key chords; ToAscii seems not to process them correctly. */ } /* Handle key chords including any modifiers other than shift directly, in order to preserve as much modifier information as possible. */ else if (event->dwControlKeyState & ( RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED | RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED | (!NILP (Vw32_lwindow_modifier) ? LEFT_WIN_PRESSED : 0) | (!NILP (Vw32_rwindow_modifier) ? RIGHT_WIN_PRESSED : 0) | (!NILP (Vw32_apps_modifier) ? APPS_PRESSED : 0) | (!NILP (Vw32_scroll_lock_modifier) ? SCROLLLOCK_ON : 0))) { /* Don't translate modified alphabetic keystrokes, so the user doesn't need to constantly switch layout to type control or meta keystrokes when the normal layout translates alphabetic characters to non-ascii characters. */ if ('A' <= event->wVirtualKeyCode && event->wVirtualKeyCode <= 'Z') { event->uChar.AsciiChar = event->wVirtualKeyCode; if ((event->dwControlKeyState & SHIFT_PRESSED) == 0) event->uChar.AsciiChar += ('a' - 'A'); } /* Try to handle unrecognized keystrokes by determining the base character (ie. translating the base key plus shift modifier). */ else if (event->uChar.AsciiChar == 0) w32_kbd_patch_key (event, -1); } if (event->uChar.AsciiChar == 0) { emacs_ev->kind = NO_EVENT; return 0; } else if (event->uChar.AsciiChar > 0) { /* Pure ASCII characters < 128. */ emacs_ev->kind = ASCII_KEYSTROKE_EVENT; emacs_ev->code = event->uChar.AsciiChar; } else if (event->uChar.UnicodeChar > 0 && w32_console_unicode_input) { /* Unicode codepoint; only valid if we are using Unicode console input mode. */ emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; emacs_ev->code = event->uChar.UnicodeChar; } else { /* Fallback handling of non-ASCII characters for non-Unicode versions of Windows, and for non-Unicode input on NT family of Windows. Only characters in the current console codepage are supported by this fallback. */ wchar_t code; char dbcs[2]; int cpId; /* Get the current console input codepage to interpret this key with. Note that the system defaults for the OEM codepage could have been changed by calling SetConsoleCP or w32-set-console-codepage, so using GetLocaleInfo to get LOCALE_IDEFAULTCODEPAGE is not TRT here. */ cpId = GetConsoleCP (); dbcs[0] = dbcs_lead; dbcs[1] = event->uChar.AsciiChar; if (dbcs_lead) { dbcs_lead = 0; if (!MultiByteToWideChar (cpId, 0, dbcs, 2, &code, 1)) { /* Garbage */ DebPrint (("Invalid DBCS sequence: %d %d\n", dbcs[0], dbcs[1])); emacs_ev->kind = NO_EVENT; } } else if (IsDBCSLeadByteEx (cpId, dbcs[1])) { dbcs_lead = dbcs[1]; emacs_ev->kind = NO_EVENT; } else { if (!MultiByteToWideChar (cpId, 0, &dbcs[1], 1, &code, 1)) { /* Garbage */ DebPrint (("Invalid character: %d\n", dbcs[1])); emacs_ev->kind = NO_EVENT; } } emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; emacs_ev->code = code; } } else { /* Function keys and other non-character keys. */ emacs_ev->kind = NON_ASCII_KEYSTROKE_EVENT; emacs_ev->code = event->wVirtualKeyCode; } XSETFRAME (emacs_ev->frame_or_window, get_frame ()); emacs_ev->modifiers = w32_kbd_mods_to_emacs (event->dwControlKeyState, event->wVirtualKeyCode); emacs_ev->timestamp = GetTickCount (); return 1; }
//*-----------------------------------------------------------------------------------------// /// @brief 채팅을 한번 할때마다 Enter 를 입력 해야 하는 방식 //*-----------------------------------------------------------------------------------------// bool CITStateNormal::ProcessHotKeyNormalInput( unsigned uiMsg, WPARAM wParam, LPARAM lParam ) { if( CTEditBox::s_pFocusEdit == NULL )///입력 포커스가 없는경우 { switch(uiMsg) { case WM_KEYDOWN: { unsigned int oemScan = int( lParam & (0xff << 16) ) >> 16; UINT vk = MapVirtualKey( oemScan, 1 ); switch( vk ) { case 0x41: g_itMGR.OpenDialog( DLG_TYPE_CHAR); return true; case 0x43: g_itMGR.OpenDialog( DLG_TYPE_COMMUNITY ); return true; case 0x48: return true; case 0x49: case 0x56: g_itMGR.OpenDialog( DLG_TYPE_ITEM ); return true; case 0x53: g_itMGR.OpenDialog( DLG_TYPE_SKILL ); return true; case 0x51: g_itMGR.OpenDialog( DLG_TYPE_QUEST ); return true; case 0x4d: { CMinimapDLG* pDlg = ( CMinimapDLG*)g_itMGR.FindDlg( DLG_TYPE_MINIMAP ); pDlg->ToggleShowMinimap(); return true; } case 0x4c: { CMinimapDLG* pDlg = ( CMinimapDLG*)g_itMGR.FindDlg( DLG_TYPE_MINIMAP ); pDlg->ToggleZoomMinimap(); return true; } case 0x4e: { g_itMGR.OpenDialog( DLG_TYPE_CLAN ); return true; } /* case 0x58: g_itMGR.OpenDialog( DLG_TYPE_SYSTEM ); return true;*/ case 0x4f: g_itMGR.OpenDialog( DLG_TYPE_OPTION ); return true; default: break; } } return false; default: break; } } return ProcessHotKeyAutoEnter( uiMsg, wParam, lParam ); }
// Parses the keys in m_sKeys string and puts them into m_KeyList void CKeystrokeEngine::ParseKeys() { KeyStruct tempKey, keyAltHold, keyCtrlHold, keyShiftHold, keyAltRelease, keyCtrlRelease, keyShiftRelease; keyAltHold.nAction = Action_KeyDown; keyAltHold.nOptional = 0; keyAltHold.nSpecial = SK_None; keyAltHold.Vk = VK_MENU; keyAltHold.nScan = MapVirtualKey (VK_MENU, 0); keyCtrlHold.nAction = Action_KeyDown; keyCtrlHold.nOptional = 0; keyCtrlHold.nSpecial = SK_None; keyCtrlHold.Vk = VK_CONTROL; keyCtrlHold.nScan = MapVirtualKey (VK_CONTROL, 0); keyShiftHold.nAction = Action_KeyDown; keyShiftHold.nOptional = 0; keyShiftHold.nSpecial = SK_None; keyShiftHold.Vk = VK_SHIFT; keyShiftHold.nScan = MapVirtualKey (VK_SHIFT, 0); keyAltRelease.nAction = Action_KeyUp; keyAltRelease.nOptional = 0; keyAltRelease.nSpecial = SK_None; keyAltRelease.Vk = VK_MENU; keyAltRelease.nScan = MapVirtualKey (VK_MENU, 0); keyCtrlRelease.nAction = Action_KeyUp; keyCtrlRelease.nOptional = 0; keyCtrlRelease.nSpecial = SK_None; keyCtrlRelease.Vk = VK_CONTROL; keyCtrlRelease.nScan = MapVirtualKey (VK_CONTROL, 0); keyShiftRelease.nAction = Action_KeyUp; keyShiftRelease.nOptional = 0; keyShiftRelease.nSpecial = SK_None; keyShiftRelease.Vk = VK_SHIFT; keyShiftRelease.nScan = MapVirtualKey (VK_SHIFT, 0); m_KeyList.clear (); int idx = 0; int nKeyLength = m_sKeys.size (); char c = 0; char szTemp [MAX_SK_LEN]; SHORT nTemp; bool bNotASpecialKey = false; bool bPushAltRelease = false, bPushCtrlRelease = false, bPushShiftRelease = false; while (idx < nKeyLength) { c = m_sKeys[idx]; // if a normal key if (bNotASpecialKey || ((c != '<') || ((c == '<') && (idx == nKeyLength - 1))) ) { bNotASpecialKey = false; tempKey.nAction = Action_KeyPress; tempKey.nSpecial = SK_None; nTemp = VkKeyScan (c); tempKey.Vk = LOBYTE (nTemp); int nTempState = HIBYTE(nTemp); if (nTempState & 0x0001) m_KeyList.push_back (keyShiftHold); if (nTempState & 0x0002) m_KeyList.push_back (keyCtrlHold); if (nTempState & 0x0004) m_KeyList.push_back (keyAltHold); tempKey.nScan = MapVirtualKey (tempKey.Vk, 0); m_KeyList.push_back (tempKey); if (nTempState & 0x0004) m_KeyList.push_back (keyAltRelease); if (nTempState & 0x0002) m_KeyList.push_back (keyCtrlRelease); if (nTempState & 0x0001) m_KeyList.push_back (keyShiftRelease); if (bPushAltRelease) m_KeyList.push_back (keyAltRelease); if (bPushCtrlRelease) m_KeyList.push_back (keyCtrlRelease); if (bPushShiftRelease) m_KeyList.push_back (keyShiftRelease); bPushAltRelease = false; bPushCtrlRelease = false; bPushShiftRelease = false; ++ idx; } // if a special key else { bNotASpecialKey = false; int nTempIdx = idx + 1; int nOffset = 0; while (nTempIdx < nKeyLength && (nTempIdx < nTempIdx + MAX_SK_LEN - 1)) { c = m_sKeys[nTempIdx]; // found the first token if (c == ' ' || c == '>') { ++nTempIdx; szTemp [nOffset] = '\0'; KeyType nType = GetNextSpecialKey (szTemp, tempKey); if (nType != Key_StartRepeat && nType != Key_Delay) { if (c == ' ') { string sDest; int i = GetKeyParam (m_sKeys.c_str(), sDest, nTempIdx); if (i > 0) nTempIdx += i; else { bNotASpecialKey = true; break; } } } if (nType != Key_NotFound && nType != Key_Normal) { if (bPushAltRelease) m_KeyList.push_back (keyAltRelease); if (bPushCtrlRelease) m_KeyList.push_back (keyCtrlRelease); if (bPushShiftRelease) m_KeyList.push_back (keyShiftRelease); } switch (nType) { case Key_NotFound: bNotASpecialKey = true; break; case Key_Ignore: bPushAltRelease = false; bPushCtrlRelease = false; bPushShiftRelease = false; break; case Key_Normal: m_KeyList.push_back (tempKey); if (bPushAltRelease) m_KeyList.push_back (keyAltRelease); if (bPushCtrlRelease) m_KeyList.push_back (keyCtrlRelease); if (bPushShiftRelease) m_KeyList.push_back (keyShiftRelease); bPushAltRelease = false; bPushCtrlRelease = false; bPushShiftRelease = false; break; case Key_Alt: m_KeyList.push_back (keyAltHold); bPushAltRelease = true; bPushCtrlRelease = false; bPushShiftRelease = false; break; case Key_Ctrl: m_KeyList.push_back (keyCtrlHold); bPushCtrlRelease = true; bPushAltRelease = false; bPushShiftRelease = false; break; case Key_Shift: m_KeyList.push_back (keyShiftHold); bPushShiftRelease = true; bPushAltRelease = false; bPushCtrlRelease = false; break; case Key_CtrlAlt: m_KeyList.push_back (keyCtrlHold); m_KeyList.push_back (keyAltHold); bPushShiftRelease = false; bPushAltRelease = true; bPushCtrlRelease = true; break; case Key_CtrlShift: m_KeyList.push_back (keyCtrlHold); m_KeyList.push_back (keyShiftHold); bPushShiftRelease = true; bPushAltRelease = false; bPushCtrlRelease = true; break; case Key_AltShift: m_KeyList.push_back (keyShiftHold); m_KeyList.push_back (keyAltHold); bPushShiftRelease = true; bPushAltRelease = true; bPushCtrlRelease = false; break; case Key_CtrlAltShift: m_KeyList.push_back (keyCtrlHold); m_KeyList.push_back (keyAltHold); m_KeyList.push_back (keyShiftHold); bPushShiftRelease = true; bPushAltRelease = true; bPushCtrlRelease = true; break; case Key_StartRepeat: if (c == '>') tempKey.nOptional = 0; else { string sDest; nTempIdx += GetKeyParam (m_sKeys.c_str(), sDest, nTempIdx); tempKey.nOptional = atoi (sDest.c_str()); m_KeyList.push_back (tempKey); } bPushShiftRelease = false; bPushAltRelease = false; bPushCtrlRelease = false; break; case Key_Delay: if (c == '>') tempKey.nOptional = 0; else { string sDest; nTempIdx += GetKeyParam (m_sKeys.c_str(), sDest, nTempIdx); tempKey.nOptional = atoi (sDest.c_str()); m_KeyList.push_back (tempKey); } bPushShiftRelease = false; bPushAltRelease = false; bPushCtrlRelease = false; break; } if (nType != Key_NotFound) idx = nTempIdx; break; } else { szTemp [nOffset] = c; ++nTempIdx; ++nOffset; } } // Not found! if (nTempIdx >= nKeyLength || (nTempIdx >= nTempIdx + MAX_SK_LEN - 1)) bNotASpecialKey = true; } } }
inline unsigned int mapVirtualKey(unsigned int key) { return MapVirtualKey(key, MAPVK_VK_TO_VSC); }
void plInputManager::HandleWin32ControlEvent(UINT message, WPARAM Wparam, LPARAM Lparam, hsWindowHndl hWnd) { if( !fhWnd ) fhWnd = hWnd; bool bExtended; switch (message) { case SYSKEYDOWN: case KEYDOWN: { bExtended = Lparam >> 24 & 1; bool bRepeat = ((Lparam >> 29) & 0xf) != 0; for (int i=0; i<fInputDevices.Count(); i++) fInputDevices[i]->HandleKeyEvent( KEYDOWN, UntranslateKey((plKeyDef)Wparam, bExtended), true, bRepeat ); } break; case SYSKEYUP: case KEYUP: { bExtended = Lparam >> 24 & 1; for (int i=0; i<fInputDevices.Count(); i++) fInputDevices[i]->HandleKeyEvent( KEYUP, UntranslateKey((plKeyDef)Wparam, bExtended), false, false ); } break; case CHAR_MSG: { wchar_t ch = (wchar_t)Wparam; // These are handled by KEYUP/KEYDOWN and should not be sent // We don't like garbage getting in string fields if (std::iscntrl(ch, localeC)) break; BYTE scan = (BYTE)(Lparam >> 16); UINT vkey = MapVirtualKey(scan, 1); //MAPVK_VSC_TO_VK bExtended = Lparam >> 24 & 1; bool bRepeat = ((Lparam >> 29) & 0xf) != 0; bool down = !(Lparam >> 31); for (int i=0; i<fInputDevices.Count(); i++) fInputDevices[i]->HandleKeyEvent( CHAR_MSG, (plKeyDef)vkey, down, bRepeat, ch ); } break; case MOUSEWHEEL: { plMouseEventMsg* pMsg = new plMouseEventMsg; int zDelta = GET_WHEEL_DELTA_WPARAM(Wparam); pMsg->SetWheelDelta((float)zDelta); if (zDelta < 0) pMsg->SetButton(kWheelNeg); else pMsg->SetButton(kWheelPos); RECT rect; GetClientRect(hWnd, &rect); pMsg->SetXPos(LOWORD(Lparam) / (float)rect.right); pMsg->SetYPos(HIWORD(Lparam) / (float)rect.bottom); pMsg->Send(); } break; case MOUSEMOVE: case L_BUTTONDN: case L_BUTTONUP: case R_BUTTONDN: case R_BUTTONUP: case L_BUTTONDBLCLK: case R_BUTTONDBLCLK: case M_BUTTONDN: case M_BUTTONUP: { RECT rect; GetClientRect(hWnd, &rect); plIMouseXEventMsg* pXMsg = new plIMouseXEventMsg; plIMouseYEventMsg* pYMsg = new plIMouseYEventMsg; plIMouseBEventMsg* pBMsg = new plIMouseBEventMsg; pXMsg->fWx = LOWORD(Lparam); pXMsg->fX = (float)LOWORD(Lparam) / (float)rect.right; pYMsg->fWy = HIWORD(Lparam); pYMsg->fY = (float)HIWORD(Lparam) / (float)rect.bottom; // Apply mouse scale // pXMsg->fX *= fMouseScale; // pYMsg->fY *= fMouseScale; if (Wparam & MK_LBUTTON && message != L_BUTTONUP) { pBMsg->fButton |= kLeftButtonDown; } else { pBMsg->fButton |= kLeftButtonUp; } if (Wparam & MK_RBUTTON && message != R_BUTTONUP) { pBMsg->fButton |= kRightButtonDown; } else { pBMsg->fButton |= kRightButtonUp; } if (Wparam & MK_MBUTTON && message != M_BUTTONUP) { pBMsg->fButton |= kMiddleButtonDown; } else { pBMsg->fButton |= kMiddleButtonUp; } if( message == L_BUTTONDBLCLK ) pBMsg->fButton |= kLeftButtonDblClk; // We send the double clicks separately if( message == R_BUTTONDBLCLK ) pBMsg->fButton |= kRightButtonDblClk; for (int i=0; i<fInputDevices.Count(); i++) { fInputDevices[i]->MsgReceive(pXMsg); fInputDevices[i]->MsgReceive(pYMsg); fInputDevices[i]->MsgReceive(pBMsg); } POINT pt; if (RecenterMouse() && (pXMsg->fX <= 0.1 || pXMsg->fX >= 0.9) ) { pt.x = (rect.right - rect.left) / 2; pt.y = HIWORD(Lparam); ClientToScreen(hWnd, &pt); SetCursorPos( pt.x, pt.y ); } else if (RecenterMouse() && (pYMsg->fY <= 0.1 || pYMsg->fY >= 0.9) ) { pt.y = (rect.bottom - rect.top) / 2; pt.x = LOWORD(Lparam); ClientToScreen(hWnd, &pt); SetCursorPos( pt.x, pt.y ); } if (RecenterMouse() && Lparam == 0) { pt.y = (rect.bottom - rect.top) / 2; pt.x = (rect.right - rect.left) / 2; ClientToScreen(hWnd, &pt); SetCursorPos( pt.x, pt.y ); } delete(pXMsg); delete(pYMsg); delete(pBMsg); } break; case WM_ACTIVATE: { bool activated = ( LOWORD( Wparam ) == WA_INACTIVE ) ? false : true; Activate( activated ); } break; } }
static int _get_key_count(void) { int num_keys = 0, vk; PDC_LOG(("_get_key_count() - called\n")); vk = KEV.wVirtualKeyCode; if (KEV.bKeyDown) { /* key down */ save_press = 0; if (vk == VK_CAPITAL || vk == VK_NUMLOCK || vk == VK_SCROLL) { /* throw away these modifiers */ } else if (vk == VK_SHIFT || vk == VK_CONTROL || vk == VK_MENU) { /* These keys are returned on keyup only. */ save_press = vk; switch (vk) { case VK_SHIFT: left_key = GetKeyState(VK_LSHIFT); break; case VK_CONTROL: left_key = GetKeyState(VK_LCONTROL); break; case VK_MENU: left_key = GetKeyState(VK_LMENU); } } else { /* Check for diacritics. These are dead keys. Some locales have modified characters like umlaut-a, which is an "a" with two dots on it. In some locales you have to press a special key (the dead key) immediately followed by the "a" to get a composed umlaut-a. The special key may have a normal meaning with different modifiers. */ if (KEV.uChar.UnicodeChar || !(MapVirtualKey(vk, 2) & 0x80000000)) num_keys = KEV.wRepeatCount; } } else { /* key up */ /* Only modifier keys or the results of ALT-numpad entry are returned on keyup */ if ((vk == VK_MENU && KEV.uChar.UnicodeChar) || ((vk == VK_SHIFT || vk == VK_CONTROL || vk == VK_MENU) && vk == save_press)) { save_press = 0; num_keys = 1; } } PDC_LOG(("_get_key_count() - returning: num_keys %d\n", num_keys)); return num_keys; }
NzKeyboard::Key NzWindowImpl::ConvertVirtualKey(WPARAM key, LPARAM flags) { switch (key) { case VK_CONTROL: return (HIWORD(flags) & KF_EXTENDED) ? NzKeyboard::RControl : NzKeyboard::LControl; case VK_MENU: return (HIWORD(flags) & KF_EXTENDED) ? NzKeyboard::RAlt : NzKeyboard::LAlt; case VK_SHIFT: { static UINT scancode = MapVirtualKey(VK_SHIFT, MAPVK_VK_TO_VSC); return (((flags >> 16) & 0xFF) == scancode) ? NzKeyboard::LShift : NzKeyboard::RShift; } case 0x30: return NzKeyboard::Num0; case 0x31: return NzKeyboard::Num1; case 0x32: return NzKeyboard::Num2; case 0x33: return NzKeyboard::Num3; case 0x34: return NzKeyboard::Num4; case 0x35: return NzKeyboard::Num5; case 0x36: return NzKeyboard::Num6; case 0x37: return NzKeyboard::Num7; case 0x38: return NzKeyboard::Num8; case 0x39: return NzKeyboard::Num9; case 0x41: return NzKeyboard::A; case 0x42: return NzKeyboard::B; case 0x43: return NzKeyboard::C; case 0x44: return NzKeyboard::D; case 0x45: return NzKeyboard::E; case 0x46: return NzKeyboard::F; case 0x47: return NzKeyboard::G; case 0x48: return NzKeyboard::H; case 0x49: return NzKeyboard::I; case 0x4A: return NzKeyboard::J; case 0x4B: return NzKeyboard::K; case 0x4C: return NzKeyboard::L; case 0x4D: return NzKeyboard::M; case 0x4E: return NzKeyboard::N; case 0x4F: return NzKeyboard::O; case 0x50: return NzKeyboard::P; case 0x51: return NzKeyboard::Q; case 0x52: return NzKeyboard::R; case 0x53: return NzKeyboard::S; case 0x54: return NzKeyboard::T; case 0x55: return NzKeyboard::U; case 0x56: return NzKeyboard::V; case 0x57: return NzKeyboard::W; case 0x58: return NzKeyboard::X; case 0x59: return NzKeyboard::Y; case 0x5A: return NzKeyboard::Z; case VK_ADD: return NzKeyboard::Add; case VK_BACK: return NzKeyboard::Backspace; case VK_BROWSER_BACK: return NzKeyboard::Browser_Back; case VK_BROWSER_FAVORITES: return NzKeyboard::Browser_Favorites; case VK_BROWSER_FORWARD: return NzKeyboard::Browser_Forward; case VK_BROWSER_HOME: return NzKeyboard::Browser_Home; case VK_BROWSER_REFRESH: return NzKeyboard::Browser_Refresh; case VK_BROWSER_SEARCH: return NzKeyboard::Browser_Search; case VK_BROWSER_STOP: return NzKeyboard::Browser_Stop; case VK_CAPITAL: return NzKeyboard::CapsLock; case VK_CLEAR: return NzKeyboard::Clear; case VK_DECIMAL: return NzKeyboard::Decimal; case VK_DELETE: return NzKeyboard::Delete; case VK_DIVIDE: return NzKeyboard::Divide; case VK_DOWN: return NzKeyboard::Down; case VK_END: return NzKeyboard::End; case VK_ESCAPE: return NzKeyboard::Escape; case VK_F1: return NzKeyboard::F1; case VK_F2: return NzKeyboard::F2; case VK_F3: return NzKeyboard::F3; case VK_F4: return NzKeyboard::F4; case VK_F5: return NzKeyboard::F5; case VK_F6: return NzKeyboard::F6; case VK_F7: return NzKeyboard::F7; case VK_F8: return NzKeyboard::F8; case VK_F9: return NzKeyboard::F9; case VK_F10: return NzKeyboard::F10; case VK_F11: return NzKeyboard::F11; case VK_F12: return NzKeyboard::F12; case VK_F13: return NzKeyboard::F13; case VK_F14: return NzKeyboard::F14; case VK_F15: return NzKeyboard::F15; case VK_HOME: return NzKeyboard::Home; case VK_INSERT: return NzKeyboard::Insert; case VK_LEFT: return NzKeyboard::Left; case VK_LWIN: return NzKeyboard::LSystem; case VK_MEDIA_NEXT_TRACK: return NzKeyboard::Media_Next; case VK_MEDIA_PLAY_PAUSE: return NzKeyboard::Media_Play; case VK_MEDIA_PREV_TRACK: return NzKeyboard::Media_Previous; case VK_MEDIA_STOP: return NzKeyboard::Media_Stop; case VK_MULTIPLY: return NzKeyboard::Multiply; case VK_NEXT: return NzKeyboard::PageDown; case VK_NUMPAD0: return NzKeyboard::Numpad0; case VK_NUMPAD1: return NzKeyboard::Numpad1; case VK_NUMPAD2: return NzKeyboard::Numpad2; case VK_NUMPAD3: return NzKeyboard::Numpad3; case VK_NUMPAD4: return NzKeyboard::Numpad4; case VK_NUMPAD5: return NzKeyboard::Numpad5; case VK_NUMPAD6: return NzKeyboard::Numpad6; case VK_NUMPAD7: return NzKeyboard::Numpad7; case VK_NUMPAD8: return NzKeyboard::Numpad8; case VK_NUMPAD9: return NzKeyboard::Numpad9; case VK_NUMLOCK: return NzKeyboard::NumLock; case VK_OEM_1: return NzKeyboard::Semicolon; case VK_OEM_2: return NzKeyboard::Slash; case VK_OEM_3: return NzKeyboard::Tilde; case VK_OEM_4: return NzKeyboard::LBracket; case VK_OEM_5: return NzKeyboard::Backslash; case VK_OEM_6: return NzKeyboard::RBracket; case VK_OEM_7: return NzKeyboard::Quote; case VK_OEM_COMMA: return NzKeyboard::Comma; case VK_OEM_MINUS: return NzKeyboard::Dash; case VK_OEM_PERIOD: return NzKeyboard::Period; case VK_OEM_PLUS: return NzKeyboard::Equal; case VK_RIGHT: return NzKeyboard::Right; case VK_PRIOR: return NzKeyboard::PageUp; case VK_PAUSE: return NzKeyboard::Pause; case VK_PRINT: return NzKeyboard::Print; case VK_SCROLL: return NzKeyboard::ScrollLock; case VK_SNAPSHOT: return NzKeyboard::PrintScreen; case VK_SUBTRACT: return NzKeyboard::Subtract; case VK_RETURN: return NzKeyboard::Return; case VK_RWIN: return NzKeyboard::RSystem; case VK_SPACE: return NzKeyboard::Space; case VK_TAB: return NzKeyboard::Tab; case VK_UP: return NzKeyboard::Up; case VK_VOLUME_DOWN: return NzKeyboard::Volume_Down; case VK_VOLUME_MUTE: return NzKeyboard::Volume_Mute; case VK_VOLUME_UP: return NzKeyboard::Volume_Up; default: return NzKeyboard::Undefined; } }
/*-------window procedure--------------*/ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_ACTIVATEAPP: // g_windowActive is used to control if the Windows key is filtered by the keyboard hook or not. if( wParam == TRUE ) { #if USE_KEY_HOOK //re-register keyboard hook if (g_keyboardHook == NULL) g_keyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, ge_module, 0 ); g_windowActive = true; #endif } else { #if USE_KEY_HOOK if (g_keyboardHook != NULL) { UnhookWindowsHookEx(g_keyboardHook);//unregister keyboard hook g_keyboardHook = NULL; } g_windowActive = false; #endif } break; case WM_INPUT://raw input RawInputMessage(wParam , lParam); break; case WM_MOUSEMOVE://mouse move { HQPointi point = { lParam & 0xffff, (lParam & 0xffff0000) >> 16 }; HQEngineApp::GetInstance()->GetMouseListener()->MouseMove(point); } break; case WM_MOUSEWHEEL: { HQPointi point = { lParam & 0xffff, (lParam & 0xffff0000) >> 16 }; ScreenToClient(hwnd, (POINT*) &point); HQEngineApp::GetInstance()->GetMouseListener()->MouseWheel( (hqfloat32)GET_WHEEL_DELTA_WPARAM(wParam) , point ); } break; /*------left button--------*/ case WM_LBUTTONDOWN://pressed { HQPointi point = { lParam & 0xffff, (lParam & 0xffff0000) >> 16 }; HQEngineApp::GetInstance()->GetMouseListener()->MousePressed(HQKeyCode::LBUTTON, point); } break; case WM_LBUTTONUP://released { HQPointi point = { lParam & 0xffff, (lParam & 0xffff0000) >> 16 }; HQEngineApp::GetInstance()->GetMouseListener()->MouseReleased(HQKeyCode::LBUTTON, point); } break; /*------right button--------*/ case WM_RBUTTONDOWN://pressed { HQPointi point = { lParam & 0xffff, (lParam & 0xffff0000) >> 16 }; HQEngineApp::GetInstance()->GetMouseListener()->MousePressed(HQKeyCode::RBUTTON, point); } break; case WM_RBUTTONUP://released { HQPointi point = { lParam & 0xffff, (lParam & 0xffff0000) >> 16 }; HQEngineApp::GetInstance()->GetMouseListener()->MouseReleased(HQKeyCode::RBUTTON, point); } break; /*------middle button--------*/ case WM_MBUTTONDOWN://pressed { HQPointi point = { lParam & 0xffff, (lParam & 0xffff0000) >> 16 }; HQEngineApp::GetInstance()->GetMouseListener()->MousePressed(HQKeyCode::MBUTTON, point); } break; case WM_MBUTTONUP://released { HQPointi point = { lParam & 0xffff, (lParam & 0xffff0000) >> 16 }; HQEngineApp::GetInstance()->GetMouseListener()->MouseReleased(HQKeyCode::MBUTTON, point); } break; case WM_MOVE://window move if (!HQEngineApp::GetInstance()->IsMouseCursorEnabled()) { RECT rect; GetWindowRect(hwnd , &rect); ClipCursor(&rect); } break; case WM_ACTIVATE: break; case WM_SYSKEYDOWN: case WM_KEYDOWN: if(KeyDownMessage(wParam , lParam)) return 0; break; case WM_SYSKEYUP: case WM_KEYUP: if (KeyUpMessage(wParam , lParam)) return 0; break; case WM_CLOSE: if(HQEngineApp::GetInstance()->GetWindowListener()->WindowClosing() == false) return 0; HQEngineApp::GetInstance()->Stop(); break; case WM_DESTROY: HQEngineApp::GetInstance()->GetWindowListener()->WindowClosed(); break; } return DefWindowProc(hwnd, message, wParam, lParam); } /*--------handle raw input message------------------*/ void RawInputMessage(WPARAM wParam, LPARAM lParam) { if (GET_RAWINPUT_CODE_WPARAM(wParam) == RIM_INPUT) { unsigned int bufferSize; //get buffer size GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &bufferSize, sizeof (RAWINPUTHEADER)); if (bufferSize > 40)//invalid return;//message handling chain will continue else { GetRawInputData((HRAWINPUT)lParam, RID_INPUT, (void*)g_mouseInputBuffer, &bufferSize, sizeof (RAWINPUTHEADER)); RAWINPUT *rawInput = (RAWINPUT*) g_mouseInputBuffer; if (rawInput->header.dwType == RIM_TYPEMOUSE) { RAWMOUSE & mouseData = rawInput->data.mouse; //get mouse listener HQEngineMouseListener *listener = HQEngineApp::GetInstance()->GetMouseListener(); HQPointi point = { ( hq_int32) mouseData.lLastX , ( hq_int32) mouseData.lLastY }; if (mouseData.usFlags & MOUSE_MOVE_ABSOLUTE)//mouse movement data is based on absolute position { } else//mouse movement data is relative to last point { if (0 != point.x || 0 != point.y) listener->MouseMove(point); } //left button if (mouseData.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) listener->MousePressed(HQKeyCode::LBUTTON, point); else if (mouseData.usButtonFlags & RI_MOUSE_LEFT_BUTTON_UP) listener->MouseReleased(HQKeyCode::LBUTTON, point); //right button if (mouseData.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) listener->MousePressed(HQKeyCode::RBUTTON, point); else if (mouseData.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_UP) listener->MouseReleased(HQKeyCode::RBUTTON, point); //middle button if (mouseData.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) listener->MousePressed(HQKeyCode::MBUTTON, point); else if (mouseData.usButtonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) listener->MouseReleased(HQKeyCode::MBUTTON, point); //wheel if (mouseData.usButtonFlags & RI_MOUSE_WHEEL) listener->MouseWheel((hqfloat32)(SHORT)mouseData.usButtonData, point); }//if (rawInput->header.dwType == RIM_TYPEMOUSE) else if (rawInput->header.dwType == RIM_TYPEKEYBOARD)//keyboard { RAWKEYBOARD &keyData = rawInput->data.keyboard; USHORT scanCode = keyData.MakeCode; HQKeyCodeType keyCode = keyData.VKey; switch (keyData.VKey) { case VK_CONTROL: keyCode = (scanCode & 0xe000) != 0 ? HQKeyCode::RCONTROL : HQKeyCode::LCONTROL; break; case VK_MENU: keyCode = (scanCode & 0xe000) != 0 ? HQKeyCode::RALT : HQKeyCode::LALT; break; case VK_SHIFT: keyCode = MapVirtualKey(scanCode, MAPVK_VSC_TO_VK_EX); break; }//switch (keyData.VKey) if (keyData.Flags & RI_KEY_BREAK)//key up { HQEngineApp::GetInstance()->GetKeyListener()->KeyReleased(keyCode); g_keyPressed[keyCode] = false; } else { HQEngineApp::GetInstance()->GetKeyListener()->KeyPressed(keyCode, g_keyPressed[keyCode]); g_keyPressed[keyCode] = true; } }//else if (rawInput->header.dwType == RIM_TYPEKEYBOARD) }//else }//if (GET_RAWINPUT_CODE_WPARAM(wParam) == RIM_INPUT) } /*--------handle legacy key down message------------------*/ bool KeyDownMessage(WPARAM wParam, LPARAM lParam) { bool repeated_msg = (lParam & 0x40000000) != 0; switch (wParam) { case VK_CONTROL: if ((lParam & (0x1 << 24)) == 0)//left HQEngineApp::GetInstance()->GetKeyListener()->KeyPressed(HQKeyCode::LCONTROL, repeated_msg); else//right HQEngineApp::GetInstance()->GetKeyListener()->KeyPressed(HQKeyCode::RCONTROL, repeated_msg); break; case VK_MENU: if ((lParam & (0x1 << 24)) == 0)//left HQEngineApp::GetInstance()->GetKeyListener()->KeyPressed(HQKeyCode::LALT, repeated_msg); else//right HQEngineApp::GetInstance()->GetKeyListener()->KeyPressed(HQKeyCode::RALT, repeated_msg); return 0; case VK_SHIFT: { UINT vkeyCode = MapVirtualKey((lParam & (0xff << 16)) >> 16 , MAPVK_VSC_TO_VK_EX); HQEngineApp::GetInstance()->GetKeyListener()->KeyPressed(vkeyCode, repeated_msg); } break; default: HQEngineApp::GetInstance()->GetKeyListener()->KeyPressed(wParam, repeated_msg); if(wParam == VK_F10) return true;//message handling chain break at this point break; } return false;//message handling chain will continue } /*--------handle legacy key up message------------------*/ bool KeyUpMessage(WPARAM wParam, LPARAM lParam) { switch (wParam) { case VK_CONTROL: if ((lParam & (0x1 << 24)) == 0)//left HQEngineApp::GetInstance()->GetKeyListener()->KeyReleased(HQKeyCode::LCONTROL); else//right HQEngineApp::GetInstance()->GetKeyListener()->KeyReleased(HQKeyCode::RCONTROL); break; case VK_MENU: if ((lParam & (0x1 << 24)) == 0)//left HQEngineApp::GetInstance()->GetKeyListener()->KeyReleased(HQKeyCode::LALT); else//right HQEngineApp::GetInstance()->GetKeyListener()->KeyReleased(HQKeyCode::RALT); break; case VK_SHIFT: { UINT vkeyCode = MapVirtualKey((lParam & (0xff << 16)) >> 16 , MAPVK_VSC_TO_VK_EX); HQEngineApp::GetInstance()->GetKeyListener()->KeyReleased(vkeyCode); } break; default: HQEngineApp::GetInstance()->GetKeyListener()->KeyReleased(wParam); break; } return false;//message handling chain will continue } #if USE_KEY_HOOK /*-----low level keyboard hook----------------------*/ LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam ) { if (nCode < 0 || nCode != HC_ACTION ) // do not process message return CallNextHookEx( g_keyboardHook, nCode, wParam, lParam); bool eatKeystroke = false; KBDLLHOOKSTRUCT* p = (KBDLLHOOKSTRUCT*)lParam; switch (wParam) { case WM_KEYDOWN: case WM_KEYUP: { eatKeystroke = (g_windowActive && ((p->vkCode == VK_LWIN) || (p->vkCode == VK_RWIN))); break; } } if( eatKeystroke ) return 1; else return CallNextHookEx( g_keyboardHook, nCode, wParam, lParam ); } #endif//#if USE_KEY_HOOK /*----------disable window accessibility keys------*/ void AllowAccessibilityShortcutKeys( bool allowKeys ) { if( allowKeys ) { //restore stickyKeys/etc to original state SystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &g_oldStickyKeys, 0); SystemParametersInfo(SPI_SETTOGGLEKEYS, sizeof(TOGGLEKEYS), &g_oldToggleKeys, 0); SystemParametersInfo(SPI_SETFILTERKEYS, sizeof(FILTERKEYS), &g_oldFilterKeys, 0); } else { STICKYKEYS skOff = g_oldStickyKeys; if( (skOff.dwFlags & SKF_STICKYKEYSON) == 0 ) { //disable the hotkey and the confirmation skOff.dwFlags &= ~SKF_HOTKEYACTIVE; skOff.dwFlags &= ~SKF_CONFIRMHOTKEY; SystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(STICKYKEYS), &skOff, 0); } TOGGLEKEYS tkOff = g_oldToggleKeys; if( (tkOff.dwFlags & TKF_TOGGLEKEYSON) == 0 ) { //disable the hotkey and the confirmation tkOff.dwFlags &= ~TKF_HOTKEYACTIVE; tkOff.dwFlags &= ~TKF_CONFIRMHOTKEY; SystemParametersInfo(SPI_SETTOGGLEKEYS, sizeof(TOGGLEKEYS), &tkOff, 0); } FILTERKEYS fkOff = g_oldFilterKeys; if( (fkOff.dwFlags & FKF_FILTERKEYSON) == 0 ) { //disable the hotkey and the confirmation fkOff.dwFlags &= ~FKF_HOTKEYACTIVE; fkOff.dwFlags &= ~FKF_CONFIRMHOTKEY; SystemParametersInfo(SPI_SETFILTERKEYS, sizeof(FILTERKEYS), &fkOff, 0); } } } /*-------engine 's window class--------*/ HQEngineWindow::HQEngineWindow(const char *title, const char *settingFileDir , HQWIPPlatformSpecificType* icons) : HQEngineBaseWindow(settingFileDir) { /*--------copy title----------*/ size_t len = strlen(title); m_title = HQ_NEW wchar_t [len + 1]; m_title[len] = '\0'; for (size_t i = 0; i < len ; ++i) m_title[i] = title[i]; /*-------create window class---------*/ WNDCLASSEX wndclass ; if (icons == NULL) { wndclass.hIconSm = LoadIcon(NULL,IDI_APPLICATION); wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); } else { wndclass.hIconSm = icons->sicon; wndclass.hIcon = icons->icon; } wndclass.cbSize = sizeof(wndclass); wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = ge_module; wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = m_title; wndclass.style = CS_HREDRAW | CS_VREDRAW ; if (RegisterClassEx(&wndclass) == 0) throw std::bad_alloc(); RECT winRect = {0 , 0 , this->GetWidth() , this->GetHeight()}; AdjustWindowRect(&winRect,HQ_WINDOW_STYLE,FALSE); /*---------create window----------------*/ if (!(m_window = CreateWindowEx( NULL, m_title, m_title, HQ_WINDOW_STYLE, 0, 0, winRect.right - winRect.left, winRect.bottom - winRect.top, NULL, NULL, ge_module , NULL))) { UnregisterClass(m_title , ge_module);//unregister window class throw std::bad_alloc(); } #if USE_KEY_HOOK //performance problem /*-----disable window key--------------*/ if (g_keyboardHook == NULL) g_keyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, ge_module, 0 ); #else RAWINPUTDEVICE rid; rid.usUsagePage = 1; rid.usUsage = 6;//keyboard rid.dwFlags = RIDEV_NOLEGACY | RIDEV_NOHOTKEYS | RIDEV_APPKEYS; rid.hwndTarget = m_window; if (RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE)) == FALSE) { //do something? } g_keyPressed.clear();//reset hash table #endif /*--- save the current sticky/toggle/filter key settings so they can be restored later--*/ SystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(STICKYKEYS), &g_oldStickyKeys, 0); SystemParametersInfo(SPI_GETTOGGLEKEYS, sizeof(TOGGLEKEYS), &g_oldToggleKeys, 0); SystemParametersInfo(SPI_GETFILTERKEYS, sizeof(FILTERKEYS), &g_oldFilterKeys, 0); AllowAccessibilityShortcutKeys( false ); } HQEngineWindow::~HQEngineWindow() { #if USE_KEY_HOOK if (g_keyboardHook != NULL) { UnhookWindowsHookEx(g_keyboardHook); g_keyboardHook = NULL; } #else RAWINPUTDEVICE rid; rid.usUsagePage = 1; rid.usUsage = 6;//keyboard rid.dwFlags = RIDEV_REMOVE; rid.hwndTarget = m_window; //remove raw keyboard if (RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE)) == FALSE) { //do something? } #endif //restore shortcut keys setting AllowAccessibilityShortcutKeys(true); DestroyWindow(m_window);//destroy window UnregisterClass(m_title , ge_module);//unregister window class delete[] m_title; } HQReturnVal HQEngineWindow::Show() { if (ShowWindow(m_window, SW_SHOW)) return HQ_OK; else return HQ_FAILED; }
/***************************************************************************** * EventThread: Create video window & handle its messages ***************************************************************************** * This function creates a video window and then enters an infinite loop * that handles the messages sent to that window. * The main goal of this thread is to isolate the Win32 PeekMessage function * because this one can block for a long time. *****************************************************************************/ static void *EventThread( void *p_this ) { event_thread_t *p_event = (event_thread_t *)p_this; vout_display_t *vd = p_event->vd; MSG msg; POINT old_mouse_pos = {0,0}, mouse_pos; int canc = vlc_savecancel (); bool b_mouse_support = var_InheritBool( p_event->vd, "mouse-events" ); bool b_key_support = var_InheritBool( p_event->vd, "keyboard-events" ); vlc_mutex_lock( &p_event->lock ); /* Create a window for the video */ /* Creating a window under Windows also initializes the thread's event * message queue */ if( Win32VoutCreateWindow( p_event ) ) p_event->b_error = true; p_event->b_ready = true; vlc_cond_signal( &p_event->wait ); const bool b_error = p_event->b_error; vlc_mutex_unlock( &p_event->lock ); if( b_error ) { vlc_restorecancel( canc ); return NULL; } /* Prevent monitor from powering off */ if (var_GetBool(vd, "disable-screensaver")) SetThreadExecutionState( ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED | ES_CONTINUOUS ); /* Main loop */ /* GetMessage will sleep if there's no message in the queue */ for( ;; ) { vout_display_place_t place; video_format_t source; if( !GetMessage( &msg, 0, 0, 0 ) ) { vlc_mutex_lock( &p_event->lock ); p_event->b_done = true; vlc_mutex_unlock( &p_event->lock ); break; } /* Check if we are asked to exit */ vlc_mutex_lock( &p_event->lock ); const bool b_done = p_event->b_done; vlc_mutex_unlock( &p_event->lock ); if( b_done ) break; if( !b_mouse_support && isMouseEvent( msg.message ) ) continue; if( !b_key_support && isKeyEvent( msg.message ) ) continue; /* Handle mouse state */ if( msg.message == WM_MOUSEMOVE || msg.message == WM_NCMOUSEMOVE ) { GetCursorPos( &mouse_pos ); /* FIXME, why this >2 limits ? */ if( (abs(mouse_pos.x - old_mouse_pos.x) > 2 || (abs(mouse_pos.y - old_mouse_pos.y)) > 2 ) ) { old_mouse_pos = mouse_pos; UpdateCursor( p_event, true ); } } else if( isMouseEvent( msg.message ) ) { UpdateCursor( p_event, true ); } else if( msg.message == WM_VLC_HIDE_MOUSE ) { UpdateCursor( p_event, false ); } /* */ switch( msg.message ) { case WM_MOUSEMOVE: vlc_mutex_lock( &p_event->lock ); place = p_event->place; source = p_event->source; vlc_mutex_unlock( &p_event->lock ); if( place.width > 0 && place.height > 0 ) { if( msg.hwnd == p_event->hvideownd ) { /* Child window */ place.x = 0; place.y = 0; } const int x = source.i_x_offset + (int64_t)(GET_X_LPARAM(msg.lParam) - place.x) * source.i_width / place.width; const int y = source.i_y_offset + (int64_t)(GET_Y_LPARAM(msg.lParam) - place.y) * source.i_height / place.height; vout_display_SendEventMouseMoved(vd, x, y); } break; case WM_NCMOUSEMOVE: break; case WM_VLC_HIDE_MOUSE: break; case WM_LBUTTONDOWN: MousePressed( p_event, msg.hwnd, MOUSE_BUTTON_LEFT ); break; case WM_LBUTTONUP: MouseReleased( p_event, MOUSE_BUTTON_LEFT ); break; case WM_LBUTTONDBLCLK: vout_display_SendEventMouseDoubleClick(vd); break; case WM_MBUTTONDOWN: MousePressed( p_event, msg.hwnd, MOUSE_BUTTON_CENTER ); break; case WM_MBUTTONUP: MouseReleased( p_event, MOUSE_BUTTON_CENTER ); break; case WM_RBUTTONDOWN: MousePressed( p_event, msg.hwnd, MOUSE_BUTTON_RIGHT ); break; case WM_RBUTTONUP: MouseReleased( p_event, MOUSE_BUTTON_RIGHT ); break; case WM_KEYDOWN: case WM_SYSKEYDOWN: { /* The key events are first processed here and not translated * into WM_CHAR events because we need to know the status of the * modifier keys. */ int i_key = Win32VoutConvertKey( msg.wParam ); if( !i_key ) { /* This appears to be a "normal" (ascii) key */ i_key = tolower( (unsigned char)MapVirtualKey( msg.wParam, 2 ) ); } if( i_key ) { if( GetKeyState(VK_CONTROL) & 0x8000 ) { i_key |= KEY_MODIFIER_CTRL; } if( GetKeyState(VK_SHIFT) & 0x8000 ) { i_key |= KEY_MODIFIER_SHIFT; } if( GetKeyState(VK_MENU) & 0x8000 ) { i_key |= KEY_MODIFIER_ALT; } vout_display_SendEventKey(vd, i_key); } break; } case WM_MOUSEWHEEL: { int i_key; if( GET_WHEEL_DELTA_WPARAM( msg.wParam ) > 0 ) { i_key = KEY_MOUSEWHEELUP; } else { i_key = KEY_MOUSEWHEELDOWN; } if( i_key ) { if( GetKeyState(VK_CONTROL) & 0x8000 ) { i_key |= KEY_MODIFIER_CTRL; } if( GetKeyState(VK_SHIFT) & 0x8000 ) { i_key |= KEY_MODIFIER_SHIFT; } if( GetKeyState(VK_MENU) & 0x8000 ) { i_key |= KEY_MODIFIER_ALT; } vout_display_SendEventKey(vd, i_key); } break; } case WM_VLC_CHANGE_TEXT: { vlc_mutex_lock( &p_event->lock ); wchar_t *pwz_title = NULL; if( p_event->psz_title ) { const size_t i_length = strlen(p_event->psz_title); pwz_title = malloc( 2 * (i_length + 1) ); if( pwz_title ) { mbstowcs( pwz_title, p_event->psz_title, 2 * i_length ); pwz_title[i_length] = 0; } } vlc_mutex_unlock( &p_event->lock ); if( pwz_title ) { SetWindowTextW( p_event->hwnd, pwz_title ); if( p_event->hfswnd ) SetWindowTextW( p_event->hfswnd, pwz_title ); free( pwz_title ); } break; } default: /* Messages we don't handle directly are dispatched to the * window procedure */ TranslateMessage(&msg); DispatchMessage(&msg); break; } /* End Switch */ } /* End Main loop */ /* Check for WM_QUIT if we created the window */ if( !p_event->hparent && msg.message == WM_QUIT ) { msg_Warn( vd, "WM_QUIT... should not happen!!" ); p_event->hwnd = NULL; /* Window already destroyed */ } msg_Dbg( vd, "Win32 Vout EventThread terminating" ); Win32VoutCloseWindow( p_event ); vlc_restorecancel(canc); return NULL; }
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HMENU hmenu; RECT rect; int c; LRESULT r; switch (message) { case WM_COMMAND: hmenu = GetMenu(hwnd); switch (LOWORD(wParam)) { case IDM_FILE_RESET: EnterCriticalSection(&cs); main_reset(); LeaveCriticalSection(&cs); break; case IDM_FILE_LSTATE: EnterCriticalSection(&cs); if (!getfile(hwnd, "Save State (*.SNP)\0*.SNP\0All files (*.*)\0*.*\0\0", savestate_name)) { CheckMenuItem(hmenu, IDM_TUBE_6502 + selecttube, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_MODEL_0 + curmodel, MF_UNCHECKED); savestate_load(); CheckMenuItem(hmenu, IDM_TUBE_6502 + selecttube, MF_CHECKED); CheckMenuItem(hmenu, IDM_MODEL_0 + curmodel, MF_CHECKED); } main_cleardrawit(); LeaveCriticalSection(&cs); break; case IDM_FILE_SSTATE: EnterCriticalSection(&cs); if (curtube != -1) { log_error("Second processor save states not supported yet."); } else { if (!getsfile(hwnd, "Save State (*.SNP)\0*.SNP\0All files (*.*)\0*.*\0\0", savestate_name, "SNP")) savestate_save(); } main_cleardrawit(); LeaveCriticalSection(&cs); break; case IDM_FILE_EXIT: PostQuitMessage (0); /* send a WM_QUIT to the message queue */ break; case IDM_DISC_AUTOBOOT: if (!getfile(hwnd, "Disc image (*.SSD;*.DSD;*.IMG;*.ADF;*.ADL;*.FDI)\0*.SSD;*.DSD;*.IMG;*.ADF;*.ADL;*.FDI\0All files (*.*)\0*.*\0", discfns[0])) { doautoboot = 1; } break; case IDM_DISC_LOAD_0: if (!getfile(hwnd, "Disc image (*.SSD;*.DSD;*.IMG;*.ADF;*.ADL;*.FDI)\0*.SSD;*.DSD;*.IMG;*.ADF;*.ADL;*.FDI\0All files (*.*)\0*.*\0", discfns[0])) { disc_close(0); disc_load(0, discfns[0]); if (defaultwriteprot) writeprot[0] = 1; CheckMenuItem(hmenu, IDM_DISC_WPROT_0, (writeprot[0]) ? MF_CHECKED : MF_UNCHECKED); } break; case IDM_DISC_LOAD_1: if (!getfile(hwnd, "Disc image (*.SSD;*.DSD;*.IMG;*.ADF;*.ADL;*.FDI)\0*.SSD;*.DSD;*.IMG;*.ADF;*.ADL;*.FDI\0All files (*.*)\0*.*\0", discfns[1])) { disc_close(1); disc_load(1, discfns[1]); if (defaultwriteprot) writeprot[1] = 1; CheckMenuItem(hmenu, IDM_DISC_WPROT_1, (writeprot[1]) ? MF_CHECKED : MF_UNCHECKED); } break; case IDM_DISC_EJECT_0: disc_close(0); discfns[0][0] = 0; setejecttext(0, ""); break; case IDM_DISC_EJECT_1: disc_close(1); discfns[1][0] = 0; setejecttext(1, ""); break; case IDM_DISC_NEW_0: if (!getsfile(hwnd, "Disc image (*.SSD;*.DSD;*.ADF;*.ADL)\0*.SSD;*.DSD;*.ADF;*.ADL\0All files (*.*)\0*.*\0", discfns[0], "SSD")) { disc_close(0); disc_new(0, discfns[0]); if (defaultwriteprot) writeprot[0] = 1; CheckMenuItem(hmenu, IDM_DISC_WPROT_0, (writeprot[0]) ? MF_CHECKED : MF_UNCHECKED); } break; case IDM_DISC_NEW_1: if (!getsfile(hwnd, "Disc image (*.SSD;*.DSD;*.ADF;*.ADL)\0*.SSD;*.DSD;*.ADF;*.ADL\0All files (*.*)\0*.*\0", discfns[1], "SSD")) { disc_close(1); disc_new(1, discfns[1]); if (defaultwriteprot) writeprot[1] = 1; CheckMenuItem(hmenu, IDM_DISC_WPROT_1, (writeprot[1]) ? MF_CHECKED : MF_UNCHECKED); } break; case IDM_DISC_WPROT_0: writeprot[0] = !writeprot[0]; if (fwriteprot[0]) writeprot[0] = 1; CheckMenuItem(hmenu, IDM_DISC_WPROT_0, (writeprot[0]) ? MF_CHECKED : MF_UNCHECKED); break; case IDM_DISC_WPROT_1: writeprot[1] = !writeprot[1]; if (fwriteprot[1]) writeprot[1] = 1; CheckMenuItem(hmenu, IDM_DISC_WPROT_1, (writeprot[1]) ? MF_CHECKED : MF_UNCHECKED); break; case IDM_DISC_WPROT_D: defaultwriteprot = !defaultwriteprot; CheckMenuItem(hmenu, IDM_DISC_WPROT_D, (defaultwriteprot) ? MF_CHECKED : MF_UNCHECKED); break; case IDM_DISC_VDFS_ENABLE: vdfs_enabled = !vdfs_enabled; CheckMenuItem(hmenu, IDM_DISC_VDFS_ENABLE, (vdfs_enabled) ? MF_CHECKED : MF_UNCHECKED); break; case IDM_DISC_VDFS_ROOT: strncpy(openfilestring, vdfs_get_root(), MAX_PATH); if (!getDir(hwnd, "VDFS Root")) vdfs_set_root(openfilestring); break; case IDM_TAPE_LOAD: if (!getfile(hwnd, "Tape image (*.UEF;*.CSW)\0*.UEF;*.CSW\0All files (*.*)\0*.*\0", tape_fn)) { tape_close(); tape_load(tape_fn); tape_loaded = 1; } break; case IDM_TAPE_EJECT: tape_close(); tape_loaded = 0; break; case IDM_TAPE_REWIND: tape_close(); tape_load(tape_fn); break; case IDM_TAPE_CAT: showcatalogue(hinstance, ghwnd); break; case IDM_TAPES_NORMAL: case IDM_TAPES_FAST: fasttape = LOWORD(wParam) - IDM_TAPES_NORMAL; CheckMenuItem(hmenu, IDM_TAPES_NORMAL, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_TAPES_FAST, MF_UNCHECKED); CheckMenuItem(hmenu, LOWORD(wParam), MF_CHECKED); break; case IDM_VIDEO_NOBORDERS: case IDM_VIDEO_MBORDERS: case IDM_VIDEO_FBORDERS: CheckMenuItem(hmenu, IDM_VIDEO_NOBORDERS + vid_fullborders, MF_UNCHECKED); vid_fullborders = LOWORD(wParam) - IDM_VIDEO_NOBORDERS; CheckMenuItem(hmenu, IDM_VIDEO_NOBORDERS + vid_fullborders, MF_CHECKED); break; case IDM_VIDEO_FULLSCR: fullscreen = 1; EnterCriticalSection(&cs); video_enterfullscreen(); LeaveCriticalSection(&cs); break; case IDM_VIDEO_NULA: if (nula_disable) nula_disable = 0; else nula_disable = 1; break; case IDM_VIDEO_RESIZE: videoresize = !videoresize; CheckMenuItem(hmenu, IDM_VIDEO_RESIZE, (videoresize) ? MF_CHECKED : MF_UNCHECKED); if (videoresize) SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE); else SetWindowLong(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX) | WS_VISIBLE); GetWindowRect(hwnd, &rect); SetWindowPos(hwnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_FRAMECHANGED); break; case IDM_VIDEO_SLINEDBL: case IDM_VIDEO_LINEDBL: case IDM_VIDEO_SCANLINES: case IDM_VIDEO_INTERLACED: case IDM_VIDEO_PAL: case IDM_VIDEO_PALI: CheckMenuItem(hmenu, IDM_VIDEO_SLINEDBL, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_VIDEO_LINEDBL, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_VIDEO_SCANLINES, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_VIDEO_INTERLACED, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_VIDEO_PAL, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_VIDEO_PALI, MF_UNCHECKED); CheckMenuItem(hmenu, LOWORD(wParam), MF_CHECKED); vid_scanlines = vid_interlace = vid_linedbl = vid_pal = 0; if (LOWORD(wParam) == IDM_VIDEO_INTERLACED) vid_interlace = 1; if (LOWORD(wParam) == IDM_VIDEO_SCANLINES) vid_scanlines = 1; if (LOWORD(wParam) == IDM_VIDEO_SLINEDBL) vid_linedbl = 1; if (LOWORD(wParam) == IDM_VIDEO_PAL) vid_pal = 1; if (LOWORD(wParam) == IDM_VIDEO_PALI) vid_interlace = vid_pal = 1; video_clearscreen(); break; case IDM_TUBE_NONE: case IDM_TUBE_6502: case IDM_TUBE_Z80: case IDM_TUBE_65816: case IDM_TUBE_32016: CheckMenuItem(hmenu, IDM_TUBE_NONE, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_TUBE_6502, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_TUBE_65816, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_TUBE_Z80, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_TUBE_32016, MF_UNCHECKED); CheckMenuItem(hmenu, LOWORD(wParam), MF_CHECKED); selecttube = LOWORD(wParam) - IDM_TUBE_6502; main_restart(); break; case IDM_TUBES_4: case IDM_TUBES_8: case IDM_TUBES_16: case IDM_TUBES_32: case IDM_TUBES_64: CheckMenuItem(hmenu, IDM_TUBES_4, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_TUBES_8, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_TUBES_16, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_TUBES_32, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_TUBES_64, MF_UNCHECKED); CheckMenuItem(hmenu, LOWORD(wParam), MF_CHECKED); tube_6502_speed = (LOWORD(wParam) - IDM_TUBES_4) + 1; tube_updatespeed(); break; case IDM_SOUND_INTERNAL: sound_internal = !sound_internal; CheckMenuItem(hmenu, IDM_SOUND_INTERNAL, (sound_internal) ? MF_CHECKED : MF_UNCHECKED); break; case IDM_SOUND_BEEBSID: sound_beebsid = !sound_beebsid; CheckMenuItem(hmenu, IDM_SOUND_BEEBSID, (sound_beebsid) ? MF_CHECKED : MF_UNCHECKED); break; case IDM_SOUND_MUSIC5000: sound_music5000 = !sound_music5000; CheckMenuItem(hmenu, IDM_SOUND_MUSIC5000, (sound_music5000) ? MF_CHECKED : MF_UNCHECKED); break; case IDM_SOUND_DAC: sound_dac = !sound_dac; CheckMenuItem(hmenu, IDM_SOUND_DAC, (sound_dac) ? MF_CHECKED : MF_UNCHECKED); break; case IDM_SOUND_DDNOISE: sound_ddnoise = !sound_ddnoise; CheckMenuItem(hmenu, IDM_SOUND_DDNOISE, (sound_ddnoise) ? MF_CHECKED : MF_UNCHECKED); break; case IDM_SOUND_TAPE: sound_tape = !sound_tape; CheckMenuItem(hmenu, IDM_SOUND_TAPE, (sound_tape) ? MF_CHECKED : MF_UNCHECKED); break; case IDM_SOUND_FILTER: sound_filter = !sound_filter; CheckMenuItem(hmenu, IDM_SOUND_FILTER, (sound_filter) ? MF_CHECKED : MF_UNCHECKED); break; case IDM_WAVE_SQUARE: case IDM_WAVE_SAW: case IDM_WAVE_SINE: case IDM_WAVE_TRI: case IDM_WAVE_SID: CheckMenuItem(hmenu, IDM_WAVE_SQUARE + curwave, MF_UNCHECKED); curwave = LOWORD(wParam) - IDM_WAVE_SQUARE; CheckMenuItem(hmenu, IDM_WAVE_SQUARE + curwave, MF_CHECKED); break; case IDM_SID_INTERP: case IDM_SID_RESAMP: CheckMenuItem(hmenu, IDM_SID_INTERP, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_SID_RESAMP, MF_UNCHECKED); CheckMenuItem(hmenu, LOWORD(wParam), MF_CHECKED); sidmethod = LOWORD(wParam) - IDM_SID_INTERP; sid_settype(sidmethod, cursid); break; case IDM_DDV_33: case IDM_DDV_66: case IDM_DDV_100: CheckMenuItem(hmenu, (IDM_DDV_33 + ddnoise_vol) - 1, MF_UNCHECKED); ddnoise_vol = (LOWORD(wParam) - IDM_DDV_33) + 1; CheckMenuItem(hmenu, (IDM_DDV_33 + ddnoise_vol) - 1, MF_CHECKED); break; case IDM_DDT_525: case IDM_DDT_35: CheckMenuItem(hmenu, IDM_DDT_525 + ddnoise_type, MF_UNCHECKED); ddnoise_type = LOWORD(wParam) - IDM_DDT_525; CheckMenuItem(hmenu, IDM_DDT_525 + ddnoise_type, MF_CHECKED); ddnoise_close(); ddnoise_init(); break; case IDM_DEBUGGER: EnterCriticalSection(&cs); rest(200); debug_toggle_core(); CheckMenuItem(hmenu, IDM_DEBUGGER, (debug_core) ? MF_CHECKED: MF_UNCHECKED); LeaveCriticalSection(&cs); break; case IDM_DEBUG_TUBE: EnterCriticalSection(&cs); rest(200); debug_toggle_tube(); CheckMenuItem(hmenu, IDM_DEBUG_TUBE, (debug_tube) ? MF_CHECKED: MF_UNCHECKED); LeaveCriticalSection(&cs); break; case IDM_BREAK: debug_step = 1; break; case IDM_SCRSHOT: if (!getsfile(hwnd, "Bitmap file (*.BMP)\0*.BMP\0All files (*.*)\0*.*\0", vid_scrshotname, "BMP")) { vid_savescrshot = 1; } break; case IDM_KEY_REDEFINE: redefinekeys(); break; case IDM_KEY_AS: keyas = !keyas; CheckMenuItem(hmenu, IDM_KEY_AS, (keyas) ? MF_CHECKED : MF_UNCHECKED); break; case IDM_MOUSE_AMX: mouse_amx = !mouse_amx; CheckMenuItem(hmenu, IDM_MOUSE_AMX, (mouse_amx) ? MF_CHECKED : MF_UNCHECKED); main_setmouse(); updatewindowtitle(); break; case IDM_SCSI_ENABLE: EnterCriticalSection(&cs); CheckMenuItem(hmenu, IDM_SCSI_ENABLE, (!scsi_enabled) ? MF_CHECKED : MF_UNCHECKED); scsi_enabled = !scsi_enabled; main_restart(); LeaveCriticalSection(&cs); break; case IDM_IDE_ENABLE: EnterCriticalSection(&cs); CheckMenuItem(hmenu, IDM_IDE_ENABLE, (!ide_enable) ? MF_CHECKED : MF_UNCHECKED); ide_enable = !ide_enable; main_restart(); LeaveCriticalSection(&cs); break; case IDM_SPD_10: case IDM_SPD_25: case IDM_SPD_50: case IDM_SPD_75: case IDM_SPD_100: case IDM_SPD_150: case IDM_SPD_200: case IDM_SPD_300: case IDM_SPD_400: case IDM_SPD_500: CheckMenuItem(hmenu, IDM_SPD_10 + emuspeed, MF_UNCHECKED); emuspeed = curmodel = LOWORD(wParam) - IDM_SPD_10; changetimerspeed(timerspeeds[emuspeed]); vid_fskipmax = frameskips[emuspeed]; CheckMenuItem(hmenu, IDM_SPD_10 + emuspeed, MF_CHECKED); break; } if (LOWORD(wParam) >= IDM_MODEL_0 && LOWORD(wParam) < (IDM_MODEL_0 + 50)) { CheckMenuItem(hmenu, IDM_MODEL_0 + curmodel, MF_UNCHECKED); oldmodel = curmodel; curmodel = LOWORD(wParam) - IDM_MODEL_0; CheckMenuItem(hmenu, IDM_MODEL_0 + curmodel, MF_CHECKED); main_restart(); updatewindowtitle(); } if (LOWORD(wParam) >= IDM_SID_TYPE && LOWORD(wParam) < (IDM_SID_TYPE + 100)) { CheckMenuItem(hmenu, IDM_SID_TYPE + cursid, MF_UNCHECKED); cursid = LOWORD(wParam) - IDM_SID_TYPE; CheckMenuItem(hmenu, IDM_SID_TYPE + cursid, MF_CHECKED); sid_settype(sidmethod, cursid); } return 0; case WM_USER: if (videoresize) SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE); else SetWindowLong(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX) | WS_VISIBLE); GetWindowRect(hwnd, &rect); SetWindowPos(hwnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_FRAMECHANGED); break; case WM_USER+1: if (videoresize) SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW & ~WS_VISIBLE); else SetWindowLong(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX) & ~WS_VISIBLE); GetWindowRect(hwnd,&rect); SetWindowPos(hwnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_FRAMECHANGED); break; case WM_DESTROY: PostQuitMessage (0); /* send a WM_QUIT to the message queue */ break; case WM_KILLFOCUS: // log_debug("KillFocus\n"); // infocus=0; // spdcount=0; if (mousecapture) { ClipCursor(&oldclip); mousecapture = 0; updatewindowtitle(); } break; case WM_LBUTTONUP: if (!mousecapture && (curtube == 3 || mouse_amx)) { GetClipCursor(&oldclip); GetWindowRect(hwnd, &newclip); newclip.left += GetSystemMetrics(SM_CXFIXEDFRAME) + 10; newclip.right -= GetSystemMetrics(SM_CXFIXEDFRAME) + 10; newclip.top += GetSystemMetrics(SM_CXFIXEDFRAME) + GetSystemMetrics(SM_CYMENUSIZE) + GetSystemMetrics(SM_CYCAPTION) + 10; newclip.bottom -= GetSystemMetrics(SM_CXFIXEDFRAME) + 10; ClipCursor(&newclip); mousecapture = 1; updatewindowtitle(); } break; case WM_ENTERMENULOOP: // log_debug("EnterMenuLoop\n"); bempause = 1; //EnterCriticalSection(&cs); break; case WM_EXITMENULOOP: // log_debug("ExitMenuLoop\n"); bempause = 0; key_clear(); for (c = 0; c < 128; c++) key[c] = 0; //LeaveCriticalSection(&cs); break; case WM_SETFOCUS: // log_debug("SetFocus\n"); key_clear(); for (c = 0; c < 128; c++) key[c] = 0; bempause = 0; break; case WM_SIZE: winsizex = lParam & 0xFFFF; winsizey = lParam >> 16; break; case WM_SYSKEYDOWN: case WM_KEYDOWN: if (LOWORD(wParam) != 255) { //log_debug("Key %04X %04X\n",LOWORD(wParam),VK_LEFT); c = MapVirtualKey(LOWORD(wParam),0); c = hw_to_mycode[c]; // log_debug("MVK %i %i %i\n",c,hw_to_mycode[c],KEY_PGUP); if (LOWORD(wParam) == VK_LEFT) c = KEY_LEFT; if (LOWORD(wParam) == VK_RIGHT) c = KEY_RIGHT; if (LOWORD(wParam) == VK_UP) c = KEY_UP; if (LOWORD(wParam) == VK_DOWN) c = KEY_DOWN; if (LOWORD(wParam) == VK_HOME) c = KEY_HOME; if (LOWORD(wParam) == VK_END) c = KEY_END; if (LOWORD(wParam) == VK_INSERT) c = KEY_INSERT; if (LOWORD(wParam) == VK_DELETE) c = KEY_DEL; if (LOWORD(wParam) == VK_PRIOR) c = KEY_PGUP; if (LOWORD(wParam) == VK_NEXT) c = KEY_PGDN; //log_debug("MVK2 %i %i %i\n",c,hw_to_mycode[c],KEY_PGUP); key[c]=1; } break; case WM_SYSKEYUP: case WM_KEYUP: if (LOWORD(wParam) != 255) { // log_debug("Key %04X %04X\n",LOWORD(wParam),VK_LEFT); c = MapVirtualKey(LOWORD(wParam), 0); c = hw_to_mycode[c]; if (LOWORD(wParam) == VK_LEFT) c = KEY_LEFT; if (LOWORD(wParam) == VK_RIGHT) c = KEY_RIGHT; if (LOWORD(wParam) == VK_UP) c = KEY_UP; if (LOWORD(wParam) == VK_DOWN) c = KEY_DOWN; if (LOWORD(wParam) == VK_HOME) c = KEY_HOME; if (LOWORD(wParam) == VK_END) c = KEY_END; if (LOWORD(wParam) == VK_INSERT) c = KEY_INSERT; if (LOWORD(wParam) == VK_DELETE) c = KEY_DEL; if (LOWORD(wParam) == VK_PRIOR) c = KEY_PGUP; if (LOWORD(wParam) == VK_NEXT) c = KEY_PGDN; // log_debug("MVK %i\n",c); key[c] = 0; } break; case WM_CREATE: // initbbc(argc,argv); // free(argv); // mainthread=(HANDLE)_beginthread(_mainthread,0,NULL); break; default: r = DefWindowProc (hwnd, message, wParam, lParam); return r; } return 0; }
// pvkKeys - 0-terminated VKKeys array bool CConEmuInside::SendVkKeySequence(HWND hWnd, WORD* pvkKeys) { bool bSent = false; //DWORD_PTR nRc1, nRc2; LRESULT lSendRc = 0; DWORD nErrCode = 0; if (!pvkKeys || !*pvkKeys) { _ASSERTE(pvkKeys && *pvkKeys); return false; } // Только для XP _ASSERTE(gnOsVer < 0x600); HWND hWorker1 = GetDlgItem(hWnd, 0xA005); if (!CheckClassName(hWorker1, L"WorkerW")) return false; HWND hReBar1 = GetDlgItem(hWorker1, 0xA005); if (!CheckClassName(hReBar1, L"ReBarWindow32")) return false; HWND hMenuBar = FindTopWindow(hReBar1, L"ToolbarWindow32"); if (!hMenuBar) return false; size_t k = 0; HWND hSend = hMenuBar; while (pvkKeys[k]) { // Prep send msg values UINT nMsg1 = (pvkKeys[k] == VK_F10) ? WM_SYSKEYDOWN : WM_KEYDOWN; DEBUGTEST(UINT nMsg2 = (pvkKeys[k] == VK_F10) ? WM_SYSKEYUP : WM_KEYUP); UINT vkScan = MapVirtualKey(pvkKeys[k], 0/*MAPVK_VK_TO_VSC*/); LPARAM lParam1 = 0x00000001 | (vkScan << 16); DEBUGTEST(LPARAM lParam2 = 0xC0000001 | (vkScan << 16)); // Post KeyDown&KeyUp if (pvkKeys[k] == VK_F10) { PostMessage(hMenuBar, WM_LBUTTONDOWN, 0, MAKELONG(5,5)); PostMessage(hMenuBar, WM_LBUTTONUP, 0, MAKELONG(5,5)); //lSendRc = PostMessage(hWnd, nMsg1, pvkKeys[k], lParam1) // && PostMessage(hWnd, nMsg2, pvkKeys[k], lParam2); Sleep(100); hSend = hMenuBar; } else { // Sequental keys send to "menu" control lSendRc = PostMessage(hSend, nMsg1, pvkKeys[k], lParam1); if (lSendRc) { Sleep(100); //lSendRc = PostMessage(hSend, nMsg2, pvkKeys[k], lParam2); //Sleep(100); } } if (lSendRc) { bSent = true; } else { // failed, may be ERROR_TIMEOUT? nErrCode = GetLastError(); bSent = false; break; } k++; } // SendMessageTimeout failed? _ASSERTE(bSent); UNREFERENCED_PARAMETER(nErrCode); return bSent; }
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_WindowsKeyboard_MapVirtualKey(JNIEnv *env, jclass unused, jint uCode, jint uMapType) { return MapVirtualKey(uCode, uMapType); }
static int _glfwTranslateKey( DWORD wParam, DWORD lParam ) { MSG next_msg; DWORD msg_time; DWORD scan_code; // Check which key was pressed or released switch( wParam ) { // The SHIFT keys require special handling case VK_SHIFT: // Compare scan code for this key with that of VK_RSHIFT in // order to determine which shift key was pressed (left or // right) scan_code = MapVirtualKey( VK_RSHIFT, 0 ); if( ((lParam & 0x01ff0000) >> 16) == scan_code ) { return GLFW_KEY_RSHIFT; } return GLFW_KEY_LSHIFT; // The CTRL keys require special handling case VK_CONTROL: // Is this an extended key (i.e. right key)? if( lParam & 0x01000000 ) { return GLFW_KEY_RCTRL; } // Here is a trick: "Alt Gr" sends LCTRL, then RALT. We only // want the RALT message, so we try to see if the next message // is a RALT message. In that case, this is a false LCTRL! msg_time = GetMessageTime(); if( PeekMessage( &next_msg, NULL, 0, 0, PM_NOREMOVE ) ) { if( next_msg.message == WM_KEYDOWN || next_msg.message == WM_SYSKEYDOWN ) { if( next_msg.wParam == VK_MENU && (next_msg.lParam & 0x01000000) && next_msg.time == msg_time ) { // Next message is a RALT down message, which // means that this is NOT a proper LCTRL message! return GLFW_KEY_UNKNOWN; } } } return GLFW_KEY_LCTRL; // The ALT keys require special handling case VK_MENU: // Is this an extended key (i.e. right key)? if( lParam & 0x01000000 ) { return GLFW_KEY_RALT; } return GLFW_KEY_LALT; // The ENTER keys require special handling case VK_RETURN: // Is this an extended key (i.e. right key)? if( lParam & 0x01000000 ) { return GLFW_KEY_KP_ENTER; } return GLFW_KEY_ENTER; // Special keys (non character keys) case VK_ESCAPE: return GLFW_KEY_ESC; case VK_TAB: return GLFW_KEY_TAB; case VK_BACK: return GLFW_KEY_BACKSPACE; case VK_HOME: return GLFW_KEY_HOME; case VK_END: return GLFW_KEY_END; case VK_PRIOR: return GLFW_KEY_PAGEUP; case VK_NEXT: return GLFW_KEY_PAGEDOWN; case VK_INSERT: return GLFW_KEY_INSERT; case VK_DELETE: return GLFW_KEY_DEL; case VK_LEFT: return GLFW_KEY_LEFT; case VK_UP: return GLFW_KEY_UP; case VK_RIGHT: return GLFW_KEY_RIGHT; case VK_DOWN: return GLFW_KEY_DOWN; case VK_F1: return GLFW_KEY_F1; case VK_F2: return GLFW_KEY_F2; case VK_F3: return GLFW_KEY_F3; case VK_F4: return GLFW_KEY_F4; case VK_F5: return GLFW_KEY_F5; case VK_F6: return GLFW_KEY_F6; case VK_F7: return GLFW_KEY_F7; case VK_F8: return GLFW_KEY_F8; case VK_F9: return GLFW_KEY_F9; case VK_F10: return GLFW_KEY_F10; case VK_F11: return GLFW_KEY_F11; case VK_F12: return GLFW_KEY_F12; case VK_F13: return GLFW_KEY_F13; case VK_F14: return GLFW_KEY_F14; case VK_F15: return GLFW_KEY_F15; case VK_F16: return GLFW_KEY_F16; case VK_F17: return GLFW_KEY_F17; case VK_F18: return GLFW_KEY_F18; case VK_F19: return GLFW_KEY_F19; case VK_F20: return GLFW_KEY_F20; case VK_F21: return GLFW_KEY_F21; case VK_F22: return GLFW_KEY_F22; case VK_F23: return GLFW_KEY_F23; case VK_F24: return GLFW_KEY_F24; case VK_SPACE: return GLFW_KEY_SPACE; // Numeric keypad case VK_NUMPAD0: return GLFW_KEY_KP_0; case VK_NUMPAD1: return GLFW_KEY_KP_1; case VK_NUMPAD2: return GLFW_KEY_KP_2; case VK_NUMPAD3: return GLFW_KEY_KP_3; case VK_NUMPAD4: return GLFW_KEY_KP_4; case VK_NUMPAD5: return GLFW_KEY_KP_5; case VK_NUMPAD6: return GLFW_KEY_KP_6; case VK_NUMPAD7: return GLFW_KEY_KP_7; case VK_NUMPAD8: return GLFW_KEY_KP_8; case VK_NUMPAD9: return GLFW_KEY_KP_9; case VK_DIVIDE: return GLFW_KEY_KP_DIVIDE; case VK_MULTIPLY: return GLFW_KEY_KP_MULTIPLY; case VK_SUBTRACT: return GLFW_KEY_KP_SUBTRACT; case VK_ADD: return GLFW_KEY_KP_ADD; case VK_DECIMAL: return GLFW_KEY_KP_DECIMAL; // The rest (should be printable keys) default: // Convert to printable character (ISO-8859-1 or Unicode) wParam = MapVirtualKey( wParam, 2 ) & 0x0000FFFF; // Make sure that the character is uppercase if( _glfwSys.HasUnicode ) { wParam = (DWORD) CharUpperW( (LPWSTR) wParam ); } else { wParam = (DWORD) CharUpperA( (LPSTR) wParam ); } // Valid ISO-8859-1 character? if( (wParam >= 32 && wParam <= 126) || (wParam >= 160 && wParam <= 255) ) { return (int) wParam; } return GLFW_KEY_UNKNOWN; } }
//----------------------------------------------------------- //function keys void PushFnKey(CString KeyCode) { // Outputs function key. KeyCode may have a number of times to be output LONG NumPushes; INT index; CString FnKey; CString OrigCode; bool isfnkey=false; // Work out which function key to push and how many times //get key press count & strip out count characters NumPushes=GetFunctionKeyCount(KeyCode); //keep a copy OrigCode=KeyCode; FnKey=KeyCode.UpperCase(); //direct code entry if (FnKey.Pos("\\")==1) { ProcessFuncKey(FnKey); return; } //braces if (FnKey=="LEFTBRACE" || FnKey=="RIGHTBRACE") { char pc=FnKey.Pos("LEFT")<1 ? '}' : '{'; for (index=1;index<=NumPushes;index++) { PushAKey(pc); } return; } //search for F key byte fnkey=GetFunctionKey(FnKey); if (fnkey==(byte)-1) fnkey=GetControlKey(FnKey); if (fnkey!=(byte)-1) { isfnkey=true; } //press f key if (isfnkey) { bool dodos=false; //do DOS conversion? if (DOSKey) { byte vk[]={VK_BELL,VK_BREAK,VK_RETURN,VK_ESCAPE,VK_CLEAR,VK_LINEFEED,VK_TAB}; char dk[]={'G','C','M','[','L','J','I'}; //search for key equivalent for (int i=0;i<sizeof(vk)/sizeof(vk[0]);i++) { if (fnkey==vk[i]) { //match found dodos=true; for (index=1;index<=NumPushes;index++) { //do key press PushCTRLKey(dk[i]); } break; } } } if (!dodos)//normal fkey { for (index=1;index<=NumPushes;index++) { //reserved characters if (GetControlKey(fnkey)!=(byte)-1) { PushAKey(fnkey); } else { //full printscreen if (fnkey==VK_SNAPSHOT && !AltOn) { PressKey(fnkey,1); } else { PressKey(fnkey,MapVirtualKey(fnkey,0)); } } } } } //sleeep or NL or clear clipboard or run else if(FnKey!="SLEEP" && FnKey!="NEWLINE" && FnKey!="NL" && FnKey !="EMPTYCLIP" && FnKey.Pos("RUN ")!=1) { // Ordinary keys for (index=1; index<=NumPushes; index++) { for (int i=0;i<OrigCode.GetLength();i++) { char ss=OrigCode[i+1]; //watch for {~ 2} if(ss!='~' || OrigCode=="~") { OnKeyHandler(false,ss); } else { //{hello world~ 3} OnKeyHandler(true,"ENTER"); } } } } }
void generateKey(jchar key, jboolean pressed) { SHORT letter = 0; TCHAR ch = key; UINT scancode = 0; SHORT modifiers = 0; letter = VkKeyScan(ch); if(letter == -1) { /* printf("No key found\n"); */ return; } modifiers = HIBYTE(letter); letter = LOBYTE(letter); if(pressed) { /* shift */ if(modifiers & 1) { generateSymbol("shift", JNI_TRUE); } /* ctrl */ if(modifiers & 2) { generateSymbol("ctrl", JNI_TRUE); } /* alt */ if(modifiers & 4) { generateSymbol("alt", JNI_TRUE); } /* hankaku */ if(modifiers & 8) { generateSymbol("hankaku", JNI_TRUE); } } /* find scancode */ scancode = MapVirtualKey(letter, 0); /* press and release key as well as modifiers */ keybd_event(letter, scancode, pressed ? 0 : KEYEVENTF_KEYUP, 0); if(!pressed) { /* shift */ if(modifiers & 1) { generateSymbol("shift", JNI_FALSE); } /* ctrl */ if(modifiers & 2) { generateSymbol("ctrl", JNI_FALSE); } /* alt */ if(modifiers & 4) { generateSymbol("alt", JNI_FALSE); } /* hankaku */ if(modifiers & 8) { generateSymbol("hankaku", JNI_FALSE); } } }
//----------------------------------------------------------- //friend of TPK on key handler //extract key string and pass to handler //process keypushes etc on return void OnKeyHandler(bool IsFnKey,CString Key) { CString k=Key; CString uk=k.UpperCase(); int count; bool CallKeyHandler=false; //delay bool IsSleep=uk.Pos("SLEEP")==1; //********************* //clear clipboard bool IsClearClip=uk.Pos("EMPTYCLIP")==1; //run bool IsRun=uk.Pos("RUN ")==1; //{\0xxx} bool IsDirect=k.Pos("\\")==1 && k.GetLength()>1; if (k=="\\") { IsDirect=false; IsFnKey=false; } //function key? or clear clipboard or run if(IsFnKey || IsSleep || IsDirect || IsClearClip || IsRun) { //get count value & strip out count characters if (!IsRun) { count=GetFunctionKeyCount(k); } if(IsAFunctionKey(uk) || IsDirect) { //not a control key? if (GetControlKey(uk)==(byte)-1) k="{"+uk+"}"; CallKeyHandler=true; } //sleep or clear clipboard or run if (IsSleep || IsClearClip || IsRun) { k="{"+Key.UpperCase()+"}"; CallKeyHandler=true; } } else { if (k.GetLength()==1) { CallKeyHandler=true; } } if (!CallKeyHandler) return; //set up shiftstate to pass here //************************** TShiftState KeyState,CopyOfKeyState; if (ShiftOn) KeyState<<ssShift; if (ControlOn) KeyState<<ssCtrl; if (AltOn) KeyState<<ssAlt; //keep a copy CopyOfKeyState=KeyState; //pass to onkey & delay handler //************************ GTPK->HandleOnKeyEvent(k,KeyState); //returned keys //************************ CString returned=k; int rl=returned.GetLength(); uk=returned.UpperCase(); if (rl==0) return; //process returned shiftstate //************** //changed? if (KeyState!=CopyOfKeyState) { //set key states SetKeyStates(KeyState); } //process keys returned //*************************** IsSleep=uk.Pos("{SLEEP")==1; //clear clipboard IsClearClip=uk.Pos("{EMPTYCLIP")==1; //run IsRun=uk.Pos("{RUN ")==1; //single key(s)? if (rl<3) { PushAString(returned); } else { if (returned[1]=='{' && returned[rl]=='}') { //strip out braces CString fk=returned.SubString(2,rl-2).UpperCase(); bool IsNL=k=="{NEWLINE}" || uk=="{NL}"; //is it a function key? if(IsAFunctionKey(fk) && !IsNL) { PushFnKey(fk); } //CRLF else if (IsNL) { // New line = Carriage return & Line Feed = ^M^J for (int i=0;i<count;i++) { if (DOSKey)//ANSI equivalent { PushCTRLKey('M'); PushCTRLKey('J'); } else { UINT ScanKey = MapVirtualKey(VK_RETURN, 0); PressKey(VK_RETURN,ScanKey); ScanKey = MapVirtualKey(VK_LINEFEED, 0); PressKey(VK_LINEFEED,ScanKey); } } } //direct {\xxxx} else if(fk.Pos("\\")==1 && fk.GetLength()>1) { if (fk.GetLength()>1) { //start key presses ALTOn(); //step along numbers for (int numpointer=2;numpointer<=fk.GetLength();numpointer++) { char number=fk[numpointer]; if (number>='0' && number<='9') { //get numpad key byte npk[]={VK_NUMPAD0,VK_NUMPAD1,VK_NUMPAD2,VK_NUMPAD3,VK_NUMPAD4 ,VK_NUMPAD5,VK_NUMPAD6,VK_NUMPAD7,VK_NUMPAD8,VK_NUMPAD9}; byte numpadkey=npk[number-'0']; //press key PressKey(numpadkey,MapVirtualKey(numpadkey,0)); } } //all done ALTOff(); } } //delay else if(IsSleep)//sleep { int count=GetFunctionKeyCount(fk); DoDelay(count); } //clear clipboard else if (IsClearClip) { int count=GetFunctionKeyCount(fk); for (int c=0;c<count;c++) { if (OpenClipboard(NULL)) { EmptyClipboard(); CloseClipboard(); } } } else if (IsRun)//run { CString runcmd=Key.SubString(4,fk.GetLength()); WinExec(runcmd.c_str(),SW_SHOWNORMAL); } else //do single keys { PushAString(returned); } } else { PushAString(returned); } } //reset changed shiftstate //************** //changed? if (KeyState!=CopyOfKeyState) { //reset key states SetKeyStates(CopyOfKeyState); } //do inter-key delay if not a sleep command if(!IsSleep) { GTPK->DoKeyDelay(); } }
static KeySym KeycodeToKeysym( unsigned int keycode, int state, int noascii) { BYTE keys[256]; int result, deadkey, shift; char buf[4]; unsigned int scancode = MapVirtualKey(keycode, 0); /* * Do not run keycodes of lock keys through ToAscii(). One of ToAscii()'s * side effects is to handle the lights on the keyboard, and we don't want * to mess that up. */ if (noascii || keycode == VK_CAPITAL || keycode == VK_SCROLL || keycode == VK_NUMLOCK) { goto skipToAscii; } /* * Use MapVirtualKey() to detect some dead keys. */ if (MapVirtualKey(keycode, 2) > 0x7fffUL) { return XK_Multi_key; } /* * Set up a keyboard with correct modifiers */ memset(keys, 0, 256); if (state & ShiftMask) { keys[VK_SHIFT] = 0x80; } if (state & ControlMask) { keys[VK_CONTROL] = 0x80; } if (state & Mod2Mask) { keys[VK_MENU] = 0x80; } /* * Make sure all lock button info is correct so we don't mess up the * lights. */ if (state & LockMask) { keys[VK_CAPITAL] = 1; } if (state & Mod3Mask) { keys[VK_SCROLL] = 1; } if (state & Mod1Mask) { keys[VK_NUMLOCK] = 1; } result = ToAscii(keycode, scancode, keys, (LPWORD) buf, 0); if (result < 0) { /* * Win95/98: This was a dead char, which is now remembered by the * keyboard. Call ToAscii() again to forget it. * WinNT: This was a dead char, overwriting any previously remembered * key. Calling ToAscii() again does not affect anything. */ ToAscii(keycode, scancode, keys, (LPWORD) buf, 0); return XK_Multi_key; } if (result == 2) { /* * This was a dead char, and there were one previously remembered by * the keyboard. Call ToAscii() again with proper parameters to * restore it. * * Get information about the old char */ deadkey = VkKeyScan(buf[0]); shift = deadkey >> 8; deadkey &= 255; scancode = MapVirtualKey(deadkey, 0); /* * Set up a keyboard with proper modifier keys */ memset(keys, 0, 256); if (shift & 1) { keys[VK_SHIFT] = 0x80; } if (shift & 2) { keys[VK_CONTROL] = 0x80; } if (shift & 4) { keys[VK_MENU] = 0x80; } ToAscii(deadkey, scancode, keys, (LPWORD) buf, 0); return XK_Multi_key; }
LRESULT CALLBACK CWinEventsWin32::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { XBMC_Event newEvent; ZeroMemory(&newEvent, sizeof(newEvent)); static HDEVNOTIFY hDeviceNotify; if (uMsg == WM_CREATE) { SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG)(((LPCREATESTRUCT)lParam)->lpCreateParams)); DIB_InitOSKeymap(); g_uQueryCancelAutoPlay = RegisterWindowMessage(TEXT("QueryCancelAutoPlay")); shcne.pidl = NULL; shcne.fRecursive = TRUE; long fEvents = SHCNE_DRIVEADD | SHCNE_DRIVEREMOVED | SHCNE_MEDIAREMOVED | SHCNE_MEDIAINSERTED; SHChangeNotifyRegister(hWnd, SHCNRF_ShellLevel | SHCNRF_NewDelivery, fEvents, WM_MEDIA_CHANGE, 1, &shcne); RegisterDeviceInterfaceToHwnd(USB_HID_GUID, hWnd, &hDeviceNotify); return 0; } m_pEventFunc = (PHANDLE_EVENT_FUNC)GetWindowLongPtr(hWnd, GWLP_USERDATA); if (!m_pEventFunc) return DefWindowProc(hWnd, uMsg, wParam, lParam); if(g_uQueryCancelAutoPlay != 0 && uMsg == g_uQueryCancelAutoPlay) return S_FALSE; switch (uMsg) { case WM_CLOSE: case WM_QUIT: case WM_DESTROY: newEvent.type = XBMC_QUIT; m_pEventFunc(newEvent); break; case WM_SHOWWINDOW: { bool active = g_application.m_AppActive; g_application.m_AppActive = wParam != 0; if (g_application.m_AppActive != active) g_Windowing.NotifyAppActiveChange(g_application.m_AppActive); CLog::Log(LOGDEBUG, __FUNCTION__"Window is %s", g_application.m_AppActive ? "shown" : "hidden"); } break; case WM_ACTIVATE: { bool active = g_application.m_AppActive; if (HIWORD(wParam)) { g_application.m_AppActive = false; } else { WINDOWPLACEMENT lpwndpl; lpwndpl.length = sizeof(lpwndpl); if (LOWORD(wParam) != WA_INACTIVE) { if (GetWindowPlacement(hWnd, &lpwndpl)) g_application.m_AppActive = lpwndpl.showCmd != SW_HIDE; } else { g_application.m_AppActive = g_Windowing.WindowedMode(); } } if (g_application.m_AppActive != active) g_Windowing.NotifyAppActiveChange(g_application.m_AppActive); CLog::Log(LOGDEBUG, __FUNCTION__"Window is %s", g_application.m_AppActive ? "active" : "inactive"); } break; case WM_SETFOCUS: case WM_KILLFOCUS: g_application.m_AppFocused = uMsg == WM_SETFOCUS; g_Windowing.NotifyAppFocusChange(g_application.m_AppFocused); if (uMsg == WM_KILLFOCUS) { CStdString procfile; if (CWIN32Util::GetFocussedProcess(procfile)) CLog::Log(LOGDEBUG, __FUNCTION__": Focus switched to process %s", procfile.c_str()); } break; case WM_SYSKEYDOWN: switch (wParam) { case VK_F4: //alt-f4, default event quit. return(DefWindowProc(hWnd, uMsg, wParam, lParam)); case VK_RETURN: //alt-return if ((lParam & REPEATED_KEYMASK) == 0) g_graphicsContext.ToggleFullScreenRoot(); return 0; } //deliberate fallthrough case WM_KEYDOWN: { switch (wParam) { case VK_CONTROL: if ( lParam & EXTENDED_KEYMASK ) wParam = VK_RCONTROL; else wParam = VK_LCONTROL; break; case VK_SHIFT: /* EXTENDED trick doesn't work here */ if (GetKeyState(VK_LSHIFT) & 0x8000) wParam = VK_LSHIFT; else if (GetKeyState(VK_RSHIFT) & 0x8000) wParam = VK_RSHIFT; break; case VK_MENU: if ( lParam & EXTENDED_KEYMASK ) wParam = VK_RMENU; else wParam = VK_LMENU; break; } XBMC_keysym keysym; TranslateKey(wParam, HIWORD(lParam), &keysym, 1); newEvent.type = XBMC_KEYDOWN; newEvent.key.keysym = keysym; m_pEventFunc(newEvent); } return(0); case WM_SYSKEYUP: case WM_KEYUP: { switch (wParam) { case VK_CONTROL: if ( lParam&EXTENDED_KEYMASK ) wParam = VK_RCONTROL; else wParam = VK_LCONTROL; break; case VK_SHIFT: { uint32_t scanCodeL = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC); uint32_t scanCodeR = MapVirtualKey(VK_RSHIFT, MAPVK_VK_TO_VSC); uint32_t keyCode = (uint32_t)((lParam & 0xFF0000) >> 16); if (keyCode == scanCodeL) wParam = VK_LSHIFT; else if (keyCode == scanCodeR) wParam = VK_RSHIFT; } break; case VK_MENU: if ( lParam&EXTENDED_KEYMASK ) wParam = VK_RMENU; else wParam = VK_LMENU; break; } XBMC_keysym keysym; TranslateKey(wParam, HIWORD(lParam), &keysym, 1); if (wParam == VK_SNAPSHOT) newEvent.type = XBMC_KEYDOWN; else newEvent.type = XBMC_KEYUP; newEvent.key.keysym = keysym; m_pEventFunc(newEvent); } return(0); case WM_APPCOMMAND: // MULTIMEDIA keys are mapped to APPCOMMANDS { CLog::Log(LOGDEBUG, "WinEventsWin32.cpp: APPCOMMAND %d", GET_APPCOMMAND_LPARAM(lParam)); newEvent.appcommand.type = XBMC_APPCOMMAND; newEvent.appcommand.action = GET_APPCOMMAND_LPARAM(lParam); if (m_pEventFunc(newEvent)) return TRUE; else return DefWindowProc(hWnd, uMsg, wParam, lParam); } case WM_GESTURENOTIFY: { OnGestureNotify(hWnd, lParam); return DefWindowProc(hWnd, WM_GESTURENOTIFY, wParam, lParam); } case WM_GESTURE: { OnGesture(hWnd, lParam); return 0; } case WM_SYSCHAR: if (wParam == VK_RETURN) //stop system beep on alt-return return 0; break; case WM_SETCURSOR: if (HTCLIENT != LOWORD(lParam)) g_Windowing.ShowOSMouse(true); break; case WM_MOUSEMOVE: newEvent.type = XBMC_MOUSEMOTION; newEvent.motion.x = GET_X_LPARAM(lParam); newEvent.motion.y = GET_Y_LPARAM(lParam); newEvent.motion.state = 0; m_pEventFunc(newEvent); return(0); case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: newEvent.type = XBMC_MOUSEBUTTONDOWN; newEvent.button.state = XBMC_PRESSED; newEvent.button.x = GET_X_LPARAM(lParam); newEvent.button.y = GET_Y_LPARAM(lParam); newEvent.button.button = 0; if (uMsg == WM_LBUTTONDOWN) newEvent.button.button = XBMC_BUTTON_LEFT; else if (uMsg == WM_MBUTTONDOWN) newEvent.button.button = XBMC_BUTTON_MIDDLE; else if (uMsg == WM_RBUTTONDOWN) newEvent.button.button = XBMC_BUTTON_RIGHT; m_pEventFunc(newEvent); return(0); case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: newEvent.type = XBMC_MOUSEBUTTONUP; newEvent.button.state = XBMC_RELEASED; newEvent.button.x = GET_X_LPARAM(lParam); newEvent.button.y = GET_Y_LPARAM(lParam); newEvent.button.button = 0; if (uMsg == WM_LBUTTONUP) newEvent.button.button = XBMC_BUTTON_LEFT; else if (uMsg == WM_MBUTTONUP) newEvent.button.button = XBMC_BUTTON_MIDDLE; else if (uMsg == WM_RBUTTONUP) newEvent.button.button = XBMC_BUTTON_RIGHT; m_pEventFunc(newEvent); return(0); case WM_MOUSEWHEEL: { // SDL, which our events system is based off, sends a MOUSEBUTTONDOWN message // followed by a MOUSEBUTTONUP message. As this is a momentary event, we just // react on the MOUSEBUTTONUP message, resetting the state after processing. newEvent.type = XBMC_MOUSEBUTTONDOWN; newEvent.button.state = XBMC_PRESSED; // the coordinates in WM_MOUSEWHEEL are screen, not client coordinates POINT point; point.x = GET_X_LPARAM(lParam); point.y = GET_Y_LPARAM(lParam); WindowFromScreenCoords(hWnd, &point); newEvent.button.x = (uint16_t)point.x; newEvent.button.y = (uint16_t)point.y; newEvent.button.button = GET_Y_LPARAM(wParam) > 0 ? XBMC_BUTTON_WHEELUP : XBMC_BUTTON_WHEELDOWN; m_pEventFunc(newEvent); newEvent.type = XBMC_MOUSEBUTTONUP; newEvent.button.state = XBMC_RELEASED; m_pEventFunc(newEvent); } return(0); case WM_SIZE: newEvent.type = XBMC_VIDEORESIZE; newEvent.resize.type = XBMC_VIDEORESIZE; newEvent.resize.w = GET_X_LPARAM(lParam); newEvent.resize.h = GET_Y_LPARAM(lParam); if (newEvent.resize.w * newEvent.resize.h) m_pEventFunc(newEvent); return(0); case WM_MEDIA_CHANGE: { // There may be multiple notifications for one event // There are also a few events we're not interested in, but they cause no harm // For example SD card reader insertion/removal long lEvent; PIDLIST_ABSOLUTE *ppidl; HANDLE hLock = SHChangeNotification_Lock((HANDLE)wParam, (DWORD)lParam, &ppidl, &lEvent); if (hLock) { char drivePath[MAX_PATH+1]; if (!SHGetPathFromIDList(ppidl[0], drivePath)) break; switch(lEvent) { case SHCNE_DRIVEADD: case SHCNE_MEDIAINSERTED: CLog::Log(LOGDEBUG, __FUNCTION__": Drive %s Media has arrived.", drivePath); if (GetDriveType(drivePath) == DRIVE_CDROM) g_application.getApplicationMessenger().OpticalMount(drivePath, true); else CWin32StorageProvider::SetEvent(); break; case SHCNE_DRIVEREMOVED: case SHCNE_MEDIAREMOVED: CLog::Log(LOGDEBUG, __FUNCTION__": Drive %s Media was removed.", drivePath); if (GetDriveType(drivePath) == DRIVE_CDROM) g_application.getApplicationMessenger().OpticalUnMount(drivePath); else CWin32StorageProvider::SetEvent(); break; } SHChangeNotification_Unlock(hLock); } break; } case WM_POWERBROADCAST: if (wParam==PBT_APMSUSPEND) { CLog::Log(LOGDEBUG,"WM_POWERBROADCAST: PBT_APMSUSPEND event was sent"); CWin32PowerSyscall::SetOnSuspend(); } else if(wParam==PBT_APMRESUMEAUTOMATIC) { CLog::Log(LOGDEBUG,"WM_POWERBROADCAST: PBT_APMRESUMEAUTOMATIC event was sent"); CWin32PowerSyscall::SetOnResume(); } break; case WM_DEVICECHANGE: { PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE) lParam; CStdString dbcc_name(b->dbcc_name); dbcc_name = CKeymapLoader::ParseWin32HIDName(b->dbcc_name); switch (wParam) { case DBT_DEVICEARRIVAL: CKeymapLoader().DeviceAdded(dbcc_name); break; case DBT_DEVICEREMOVECOMPLETE: CKeymapLoader().DeviceRemoved(dbcc_name); break; case DBT_DEVNODES_CHANGED: //CLog::Log(LOGDEBUG, "HID Device Changed"); //We generally don't care about Change notifications, only need to know if a device is removed or added to rescan the device list break; } break; } case WM_PAINT: //some other app has painted over our window, mark everything as dirty g_windowManager.MarkDirty(); break; } return(DefWindowProc(hWnd, uMsg, wParam, lParam)); }
Keys::Key TranslateKeycode( WPARAM wParam, LPARAM lParam ) { switch(wParam) { case VK_SHIFT: { static UINT lShift = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC); UINT scancode = (UINT)((lParam & (0xFF << 16)) >> 16); return scancode == lShift ? Keys::LShift : Keys::RShift; } break; case VK_MENU: return (HIWORD(lParam) & KF_EXTENDED) ? Keys::RAlt : Keys::LAlt; break; case VK_CONTROL: return (HIWORD(lParam) & KF_EXTENDED) ? Keys::RControl : Keys::LControl; break; case VK_LWIN: return Keys::LSystem; break; case VK_RWIN: return Keys::RSystem; break; case VK_APPS: return Keys::Menu; break; case VK_OEM_1: return Keys::SemiColon; break; case VK_OEM_2: return Keys::Slash; break; case VK_OEM_PLUS: return Keys::Equal; break; case VK_OEM_MINUS: return Keys::Dash; break; case VK_OEM_4: return Keys::LBracket; break; case VK_OEM_6: return Keys::RBracket; break; case VK_OEM_COMMA: return Keys::Comma; break; case VK_OEM_PERIOD: return Keys::Period; break; case VK_OEM_7: return Keys::Quote; break; case VK_OEM_5: return Keys::BackSlash; break; case VK_OEM_3: return Keys::Tilde; break; case VK_ESCAPE: return Keys::Escape; break; case VK_SPACE: return Keys::Space; break; case VK_RETURN: return Keys::Return; break; case VK_BACK: return Keys::Back; break; case VK_TAB: return Keys::Tab; break; case VK_PRIOR: return Keys::PageUp; break; case VK_NEXT: return Keys::PageDown; break; case VK_END: return Keys::End; break; case VK_HOME: return Keys::Home; break; case VK_INSERT: return Keys::Insert; break; case VK_DELETE: return Keys::Delete; break; case VK_ADD: return Keys::Add; break; case VK_SUBTRACT: return Keys::Subtract; break; case VK_MULTIPLY: return Keys::Multiply; break; case VK_DIVIDE: return Keys::Divide; break; case VK_PAUSE: return Keys::Pause; break; case VK_F1: return Keys::F1; break; case VK_F2: return Keys::F2; break; case VK_F3: return Keys::F3; break; case VK_F4: return Keys::F4; break; case VK_F5: return Keys::F5; break; case VK_F6: return Keys::F6; break; case VK_F7: return Keys::F7; break; case VK_F8: return Keys::F8; break; case VK_F9: return Keys::F9; break; case VK_F10: return Keys::F10; break; case VK_F11: return Keys::F11; break; case VK_F12: return Keys::F12; break; case VK_F13: return Keys::F13; break; case VK_F14: return Keys::F14; break; case VK_F15: return Keys::F15; break; case VK_LEFT: return Keys::Left; break; case VK_RIGHT: return Keys::Right; break; case VK_UP: return Keys::Up; break; case VK_DOWN: return Keys::Down; break; case VK_NUMPAD0: return Keys::Numpad0; break; case VK_NUMPAD1: return Keys::Numpad1; break; case VK_NUMPAD2: return Keys::Numpad2; break; case VK_NUMPAD3: return Keys::Numpad3; break; case VK_NUMPAD4: return Keys::Numpad4; break; case VK_NUMPAD5: return Keys::Numpad5; break; case VK_NUMPAD6: return Keys::Numpad6; break; case VK_NUMPAD7: return Keys::Numpad7; break; case VK_NUMPAD8: return Keys::Numpad8; break; case VK_NUMPAD9: return Keys::Numpad9; break; case 'A': return Keys::A; break; case 'Z': return Keys::Z; break; case 'E': return Keys::E; break; case 'R': return Keys::R; break; case 'T': return Keys::T; break; case 'Y': return Keys::Y; break; case 'U': return Keys::U; break; case 'I': return Keys::I; break; case 'O': return Keys::O; break; case 'P': return Keys::P; break; case 'Q': return Keys::Q; break; case 'S': return Keys::S; break; case 'D': return Keys::D; break; case 'F': return Keys::F; break; case 'G': return Keys::G; break; case 'H': return Keys::H; break; case 'J': return Keys::J; break; case 'K': return Keys::K; break; case 'L': return Keys::L; break; case 'M': return Keys::M; break; case 'W': return Keys::W; break; case 'X': return Keys::X; break; case 'C': return Keys::C; break; case 'V': return Keys::V; break; case 'B': return Keys::B; break; case 'N': return Keys::N; break; case '0': return Keys::Num0; break; case '1': return Keys::Num1; break; case '2': return Keys::Num2; break; case '3': return Keys::Num3; break; case '4': return Keys::Num4; break; case '5': return Keys::Num5; break; case '6': return Keys::Num6; break; case '7': return Keys::Num7; break; case '8': return Keys::Num8; break; case '9': return Keys::Num9; break; } return Keys::Invalid; }
/** * Set current state of a keyboard modifier. * * @param idModifier Modifier to set (VK_CAPITAL, VK_SCROLL or VK_NUMLOCK) * @param fState State to set */ static void winSetModifierState(int idModifier, bool fState) { AssertReturnVoid((idModifier == VK_CAPITAL) || (idModifier == VK_SCROLL) || (idModifier == VK_NUMLOCK)); /* If the modifier is already in desired state, just do nothing. Otherwise, toggle it. */ if (winGetModifierState(idModifier) != fState) { /* Simulate KeyUp+KeyDown keystroke */ keybd_event(idModifier, 0, KEYEVENTF_EXTENDEDKEY, 0); keybd_event(idModifier, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); LogRel2(("HID LEDs sync: setting %s state to %s (0x%X).\n", VBOX_CONTROL_TO_STR_NAME(idModifier), VBOX_BOOL_TO_STR_STATE(fState), MapVirtualKey(idModifier, MAPVK_VK_TO_VSC))); } else { LogRel2(("HID LEDs sync: setting %s state: skipped: state is already %s (0x%X).\n", VBOX_CONTROL_TO_STR_NAME(idModifier), VBOX_BOOL_TO_STR_STATE(fState), MapVirtualKey(idModifier, MAPVK_VK_TO_VSC))); } }
VOID DoStringPaste( IN PCONSOLE_INFORMATION Console, IN PWCHAR pwStr, IN UINT DataSize ) { PINPUT_RECORD StringData,CurRecord; PWCHAR CurChar; WCHAR Char; DWORD i; DWORD ChunkSize,j; ULONG EventsWritten; if(!pwStr) { return; } if (DataSize > DATA_CHUNK_SIZE) { ChunkSize = DATA_CHUNK_SIZE; } else { ChunkSize = DataSize; } // // allocate space to copy data. // StringData = (PINPUT_RECORD)HeapAlloc(pConHeap,MAKE_TAG( TMP_TAG ),(ChunkSize/sizeof(WCHAR))*sizeof(INPUT_RECORD)*8); // 8 is maximum number of events per char if (StringData == NULL) { return; } // // transfer data to the input buffer in chunks // CurChar = pwStr; // LATER remove this for (j = 0; j < DataSize; j += ChunkSize) { if (ChunkSize > DataSize - j) { ChunkSize = DataSize - j; } CurRecord = StringData; for (i = 0, EventsWritten = 0; i < ChunkSize; i++) { // filter out LF if not first char and preceded by CR Char = *CurChar; if (Char != UNICODE_LINEFEED || (i==0 && j==0) || (*(CurChar-1)) != UNICODE_CARRIAGERETURN) { SHORT KeyState; BYTE KeyFlags; BOOL AltGr=FALSE; BOOL Shift=FALSE; if (Char == 0) { j = DataSize; break; } KeyState = VkKeyScan(Char); // if VkKeyScanW fails (char is not in kbd layout), we must // emulate the key being input through the numpad if (KeyState == -1) { CHAR CharString[4]; UCHAR OemChar; PCHAR pCharString; ConvertToOem(Console->OutputCP, &Char, 1, &OemChar, 1 ); _itoa(OemChar, CharString, 10); EventsWritten++; LoadKeyEvent(CurRecord,TRUE,0,VK_MENU,0x38,LEFT_ALT_PRESSED); CurRecord++; for (pCharString=CharString;*pCharString;pCharString++) { WORD wVirtualKey, wScancode; EventsWritten++; wVirtualKey = *pCharString-'0'+VK_NUMPAD0; wScancode = MapVirtualKey(wVirtualKey, 0); LoadKeyEvent(CurRecord,TRUE,0,wVirtualKey,wScancode,LEFT_ALT_PRESSED); CurRecord++; EventsWritten++; LoadKeyEvent(CurRecord,FALSE,0,wVirtualKey,wScancode,LEFT_ALT_PRESSED); CurRecord++; } EventsWritten++; LoadKeyEvent(CurRecord,FALSE,Char,VK_MENU,0x38,0); CurRecord++; } else { KeyFlags = HIBYTE(KeyState); // handle yucky alt-gr keys if ((KeyFlags & 6) == 6) { AltGr=TRUE; EventsWritten++; LoadKeyEvent(CurRecord,TRUE,0,VK_MENU,0x38,ENHANCED_KEY | LEFT_CTRL_PRESSED | RIGHT_ALT_PRESSED); CurRecord++; } else if (KeyFlags & 1) { Shift=TRUE; EventsWritten++; LoadKeyEvent(CurRecord,TRUE,0,VK_SHIFT,0x2a,SHIFT_PRESSED); CurRecord++; } EventsWritten++; LoadKeyEvent(CurRecord, TRUE, Char, LOBYTE(KeyState), MapVirtualKey(CurRecord->Event.KeyEvent.wVirtualKeyCode,0), 0); if (KeyFlags & 1) CurRecord->Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED; if (KeyFlags & 2) CurRecord->Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED; if (KeyFlags & 4) CurRecord->Event.KeyEvent.dwControlKeyState |= RIGHT_ALT_PRESSED; CurRecord++; EventsWritten++; *CurRecord = *(CurRecord-1); CurRecord->Event.KeyEvent.bKeyDown = FALSE; CurRecord++; // handle yucky alt-gr keys if (AltGr) { EventsWritten++; LoadKeyEvent(CurRecord,FALSE,0,VK_MENU,0x38,ENHANCED_KEY); CurRecord++; } else if (Shift) { EventsWritten++; LoadKeyEvent(CurRecord,FALSE,0,VK_SHIFT,0x2a,0); CurRecord++; } } } CurChar++; } EventsWritten = WriteInputBuffer(Console, &Console->InputBuffer, StringData, EventsWritten ); } HeapFree(pConHeap,0,StringData); return; }
// Gets next special key form the given String... CKeystrokeEngine::KeyType CKeystrokeEngine::GetNextSpecialKey(const char* sKey, CKeystrokeEngine::KeyStruct &key) { KeyType nType = Key_Normal; key.nSpecial = SK_None; key.nAction = Action_KeyPress; if (sKey == "ENTER") key.Vk = VK_RETURN; else if (sKey == "BACK") key.Vk = VK_BACK; else if (sKey == "TAB") key.Vk = VK_TAB; else if (sKey == "SHIFT") nType = Key_Shift; else if (sKey == "CTRL") nType = Key_Ctrl; else if (sKey == "ALT") nType = Key_Alt; else if (sKey == "CTRL+ALT") nType = Key_CtrlAlt; else if (sKey == "CTRL+SHIFT") nType = Key_CtrlShift; else if (sKey == "CTRL+ALT+SHIFT") nType = Key_CtrlAltShift; else if (sKey == "ALT+SHIFT") nType = Key_AltShift; else if (sKey == "CTRL_LOCK") { key.Vk = VK_CONTROL; key.nAction = Action_KeyDown; key.nSpecial = SK_CtrlLock; } else if (sKey == "CTRL_UNLOCK") { key.Vk = VK_CONTROL; key.nAction = Action_KeyUp; key.nSpecial = SK_CtrlUnlock; } else if (sKey == "ALT_LOCK") { key.Vk = VK_MENU; key.nAction = Action_KeyDown; key.nSpecial = SK_AltLock; } else if (sKey == "ALT_UNLOCK") { key.Vk = VK_MENU; key.nAction = Action_KeyUp; key.nSpecial = SK_AltUnlock; } else if (sKey == "SHIFT_LOCK") { key.Vk = VK_SHIFT; key.nAction = Action_KeyDown; key.nSpecial = SK_ShiftLock; } else if (sKey == "SHIFT_UNLOCK") { key.Vk = VK_SHIFT; key.nAction = Action_KeyUp; key.nSpecial = SK_ShiftUnlock; } else if (sKey == "PAUSE") key.Vk = VK_PAUSE; else if (sKey == "CAPSLOCK") key.Vk = VK_CAPITAL; else if (sKey == "CAPSLOCK_ON") { key.Vk = VK_CAPITAL; if (LOBYTE (GetKeyState (VK_CAPITAL)) != 0) nType = Key_Ignore; } else if (sKey == "CAPSLOCK_OFF") { key.Vk = VK_CAPITAL; if (LOBYTE (GetKeyState (VK_CAPITAL)) != 1) nType = Key_Ignore; } else if (sKey == "ESC") key.Vk = VK_ESCAPE; else if (sKey == "PAGEUP") key.Vk = VK_PRIOR; else if (sKey == "PAGEDOWN") key.Vk = VK_NEXT; else if (sKey == "END") key.Vk = VK_END; else if (sKey == "HOME") key.Vk = VK_HOME; else if (sKey == "LEFT") key.Vk = VK_LEFT; else if (sKey == "UP") key.Vk = VK_UP; else if (sKey == "RIGHT") key.Vk = VK_RIGHT; else if (sKey == "DOWN") key.Vk = VK_DOWN; else if (sKey == "PRINTSCRN") key.Vk = VK_SNAPSHOT; else if (sKey == "INSERT") key.Vk = VK_INSERT; else if (sKey == "DELETE") key.Vk = VK_DELETE; else if (sKey == "LWIN") key.Vk = VK_LWIN; else if (sKey == "RWIN") key.Vk = VK_RWIN; else if (sKey == "APPS") key.Vk = VK_APPS; else if (sKey == "NUMPAD0") key.Vk = VK_NUMPAD0; else if (sKey == "NUMPAD1") key.Vk = VK_NUMPAD1; else if (sKey == "NUMPAD2") key.Vk = VK_NUMPAD2; else if (sKey == "NUMPAD3") key.Vk = VK_NUMPAD3; else if (sKey == "NUMPAD4") key.Vk = VK_NUMPAD4; else if (sKey == "NUMPAD5") key.Vk = VK_NUMPAD5; else if (sKey == "NUMPAD6") key.Vk = VK_NUMPAD6; else if (sKey == "NUMPAD7") key.Vk = VK_NUMPAD7; else if (sKey == "NUMPAD8") key.Vk = VK_NUMPAD8; else if (sKey == "NUMPAD9") key.Vk = VK_NUMPAD9; else if (sKey == "F1") key.Vk = VK_F1; else if (sKey == "F2") key.Vk = VK_F2; else if (sKey == "F3") key.Vk = VK_F3; else if (sKey == "F4") key.Vk = VK_F4; else if (sKey == "F5") key.Vk = VK_F5; else if (sKey == "F6") key.Vk = VK_F6; else if (sKey == "F7") key.Vk = VK_F7; else if (sKey == "F8") key.Vk = VK_F8; else if (sKey == "F9") key.Vk = VK_F9; else if (sKey == "F10") key.Vk = VK_F10; else if (sKey == "F11") key.Vk = VK_F11; else if (sKey == "F12") key.Vk = VK_F12; else if (sKey == "NUMLOCK") key.Vk = VK_NUMLOCK; else if (sKey == "NUMLOCK_ON") { key.Vk = VK_NUMLOCK; if (LOBYTE (GetKeyState (VK_NUMLOCK)) != 0) nType = Key_Ignore; } else if (sKey == "NUMLOCK_OFF") { key.Vk = VK_NUMLOCK; if (LOBYTE (GetKeyState (VK_NUMLOCK)) != 1) nType = Key_Ignore; } else if (sKey == "SCROLLLOCK") key.Vk = VK_SCROLL; else if (sKey == "SCROLLLOCK_ON") { key.Vk = VK_SCROLL; if (LOBYTE (GetKeyState (VK_SCROLL)) != 0) nType = Key_Ignore; } else if (sKey == "SCROLLLOCK_OFF") { key.Vk = VK_SCROLL; if (LOBYTE (GetKeyState (VK_SCROLL)) != 1) nType = Key_Ignore; } else if (sKey == "REPEAT") { key.nSpecial = SK_StartRepeat; nType = Key_StartRepeat; } else if (sKey == "END_REPEAT") { key.nSpecial = SK_EndRepeat; } else if (sKey == "DELAY") { key.nSpecial = SK_Delay; nType = Key_Delay; } else return Key_NotFound; key.nScan = MapVirtualKey (key.Vk, 0); return nType; }
// TwEventWin32 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 TwEventWin32(void *wnd, unsigned int msg, unsigned int _W64 wParam, int _W64 lParam) { int handled = 0; switch( msg ) { case WM_MOUSEMOVE: // send signed! mouse coordinates handled = TwMouseMotion((short)LOWORD(lParam), (short)HIWORD(lParam)); break; case WM_LBUTTONDOWN: 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: 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: 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); } 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 TweakBar TwWindowSize(LOWORD(lParam), HIWORD(lParam)); // do not set 'handled', WM_SIZE may be also processed by the calling application break; } return handled; }
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { int home, away, timecode; char buf[BUFLEN]; switch(uMsg) { case WM_DESTROY: // Exit the application when the window closes PostQuitMessage(1); return true; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED) { if ((HWND)lParam == g_saveButtonControl) { SaveSettings(); // modify status text SendMessage(g_statusTextControl, WM_SETTEXT, 0, (LPARAM)"SAVED"); } else if ((HWND)lParam == g_restoreButtonControl) { RestoreSettings(); // modify status text SendMessage(g_statusTextControl, WM_SETTEXT, 0, (LPARAM)"RESTORED"); } } else if (HIWORD(wParam) == EN_CHANGE) { HWND control = (HWND)lParam; // modify status text SendMessage(g_statusTextControl, WM_SETTEXT, 0, (LPARAM)"CHANGES MADE"); } else if (HIWORD(wParam) == CBN_EDITCHANGE) { HWND control = (HWND)lParam; // modify status text SendMessage(g_statusTextControl, WM_SETTEXT, 0, (LPARAM)"CHANGES MADE"); } break; case WM_APP_KEYDEF: HWND target = (HWND)lParam; ZeroMemory(buf, BUFLEN); GetKeyNameText(MapVirtualKey(wParam, 0) << 16, buf, BUFLEN); SendMessage(target, WM_SETTEXT, 0, (LPARAM)buf); SendMessage(g_statusTextControl, WM_SETTEXT, 0, (LPARAM)"CHANGES MADE"); // update config if (target == g_keySwitchLeftControl) g_keyCfg.keyboard.keySwitchLeft = (WORD)wParam; else if (target == g_keySwitchRightControl) g_keyCfg.keyboard.keySwitchRight = (WORD)wParam; else if (target == g_keyResetControl) g_keyCfg.keyboard.keyReset = (WORD)wParam; else if (target == g_keyRandomControl) g_keyCfg.keyboard.keyRandom = (WORD)wParam; else if (target == g_keyPrevControl) g_keyCfg.keyboard.keyPrev = (WORD)wParam; else if (target == g_keyNextControl) g_keyCfg.keyboard.keyNext = (WORD)wParam; else if (target == g_keyPrevValControl) g_keyCfg.keyboard.keyPrevVal = (WORD)wParam; else if (target == g_keyNextValControl) g_keyCfg.keyboard.keyNextVal = (WORD)wParam; else if (target == g_keyInfoPagePrevControl) g_keyCfg.keyboard.keyInfoPagePrev = (WORD)wParam; else if (target == g_keyInfoPageNextControl) g_keyCfg.keyboard.keyInfoPageNext = (WORD)wParam; else if (target == g_keyAction1Control) g_keyCfg.keyboard.keyAction1 = (WORD)wParam; else if (target == g_keyAction1Control) g_keyCfg.keyboard.keyAction2 = (WORD)wParam; else if (target == g_keySwitch1Control) g_keyCfg.keyboard.keySwitch1 = (WORD)wParam; else if (target == g_keySwitch1Control) g_keyCfg.keyboard.keySwitch2 = (WORD)wParam; break; } return DefWindowProc(hwnd,uMsg,wParam,lParam); }
// Keyboard hook for the Finder Tool. // This hook just monitors the ESCAPE key static LRESULT CALLBACK draghookproc(int code, WPARAM wParam, LPARAM lParam) { ULONG state = (ULONG)lParam; static int count; if(code < 0) return CallNextHookEx(draghook, code, wParam, lParam); switch(wParam) { case VK_ESCAPE: if(!(state & 0x80000000)) { //don't let the current window procedure process a VK_ESCAPE, //because we want it to cancel the mouse capture PostMessage(draghookhwnd, WM_CANCELMODE, 0, 0); return -1; } break; case VK_SHIFT: if(state & 0x80000000) { //InvertWindow(hwndCurrent, fShowHidden); HideSel(hwndCurrent); FireWndFindNotify(draghookhwnd, WFN_SHIFT_UP, 0); //InvertWindow(hwndCurrent, fShowHidden); ShowSel(hwndCurrent); } else { if(!(state & 0x40000000)) { //InvertWindow(hwndCurrent, fShowHidden); HideSel(hwndCurrent); FireWndFindNotify(draghookhwnd, WFN_SHIFT_DOWN, 0); //InvertWindow(hwndCurrent, fShowHidden); ShowSel(hwndCurrent); } } return -1; case VK_CONTROL: if(state & 0x80000000) { //InvertWindow(hwndCurrent, fShowHidden); HideSel(hwndCurrent); FireWndFindNotify(draghookhwnd, WFN_CTRL_UP, 0); //InvertWindow(hwndCurrent, fShowHidden); ShowSel(hwndCurrent); } else { if(!(state & 0x40000000)) { //InvertWindow(hwndCurrent, fShowHidden); HideSel(hwndCurrent); FireWndFindNotify(draghookhwnd, WFN_CTRL_DOWN, 0); //InvertWindow(hwndCurrent, fShowHidden); ShowSel(hwndCurrent); } } return -1; } // Test to see if a key is pressed for first time if(!(state & 0xC0000000)) { // Find ASCII character UINT ch = MapVirtualKey((UINT)wParam, 2); if(ch == _T('c') || ch == _T('C')) { //InvertWindow(hwndCurrent, fShowHidden); HideSel(hwndCurrent); CaptureWindow(GetParent(draghookhwnd), hwndCurrent); //InvertWindow(hwndCurrent, fShowHidden); ShowSel(hwndCurrent); return -1; } } return CallNextHookEx(draghook, code, wParam, lParam); }
void MSWindowsKeyState::getKeyMap(synergy::KeyMap& keyMap) { // update keyboard groups if (getGroups(m_groups)) { m_groupMap.clear(); SInt32 numGroups = (SInt32)m_groups.size(); for (SInt32 g = 0; g < numGroups; ++g) { m_groupMap[m_groups[g]] = g; } } HKL activeLayout = GetKeyboardLayout(0); // clear table memset(m_virtualKeyToButton, 0, sizeof(m_virtualKeyToButton)); m_keyToVKMap.clear(); synergy::KeyMap::KeyItem item; SInt32 numGroups = (SInt32)m_groups.size(); for (SInt32 g = 0; g < numGroups; ++g) { item.m_group = g; ActivateKeyboardLayout(m_groups[g], 0); // clear tables memset(m_buttonToVK, 0, sizeof(m_buttonToVK)); memset(m_buttonToNumpadVK, 0, sizeof(m_buttonToNumpadVK)); // map buttons (scancodes) to virtual keys for (KeyButton i = 1; i < 256; ++i) { UINT vk = MapVirtualKey(i, 1); if (vk == 0) { // unmapped continue; } // deal with certain virtual keys specially switch (vk) { case VK_SHIFT: // this is important for sending the correct modifier to the // client, a patch from bug #242 (right shift broken for ms // remote desktop) removed this to just use left shift, which // caused bug #2799 (right shift broken for osx). // we must not repeat this same mistake and must fix platform // specific bugs in code that only affects that platform. if (MapVirtualKey(VK_RSHIFT, 0) == i) { vk = VK_RSHIFT; } else { vk = VK_LSHIFT; } break; case VK_CONTROL: vk = VK_LCONTROL; break; case VK_MENU: vk = VK_LMENU; break; case VK_NUMLOCK: vk = VK_PAUSE; break; case VK_NUMPAD0: case VK_NUMPAD1: case VK_NUMPAD2: case VK_NUMPAD3: case VK_NUMPAD4: case VK_NUMPAD5: case VK_NUMPAD6: case VK_NUMPAD7: case VK_NUMPAD8: case VK_NUMPAD9: case VK_DECIMAL: // numpad keys are saved in their own table m_buttonToNumpadVK[i] = vk; continue; case VK_LWIN: case VK_RWIN: break; case VK_RETURN: case VK_PRIOR: case VK_NEXT: case VK_END: case VK_HOME: case VK_LEFT: case VK_UP: case VK_RIGHT: case VK_DOWN: case VK_INSERT: case VK_DELETE: // also add extended key for these m_buttonToVK[i | 0x100u] = vk; break; } if (m_buttonToVK[i] == 0) { m_buttonToVK[i] = vk; } } // now map virtual keys to buttons. multiple virtual keys may map // to a single button. if the virtual key matches the one in // m_buttonToVK then we use the button as is. if not then it's // either a numpad key and we use the button as is or it's an // extended button. for (UINT i = 1; i < 255; ++i) { // skip virtual keys we don't want switch (i) { case VK_LBUTTON: case VK_RBUTTON: case VK_MBUTTON: case VK_XBUTTON1: case VK_XBUTTON2: case VK_SHIFT: case VK_CONTROL: case VK_MENU: continue; } // get the button KeyButton button = static_cast<KeyButton>(MapVirtualKey(i, 0)); if (button == 0) { continue; } // deal with certain virtual keys specially switch (i) { case VK_NUMPAD0: case VK_NUMPAD1: case VK_NUMPAD2: case VK_NUMPAD3: case VK_NUMPAD4: case VK_NUMPAD5: case VK_NUMPAD6: case VK_NUMPAD7: case VK_NUMPAD8: case VK_NUMPAD9: case VK_DECIMAL: m_buttonToNumpadVK[button] = i; break; default: // add extended key if virtual keys don't match if (m_buttonToVK[button] != i) { m_buttonToVK[button | 0x100u] = i; } break; } } // add alt+printscreen if (m_buttonToVK[0x54u] == 0) { m_buttonToVK[0x54u] = VK_SNAPSHOT; } // set virtual key to button table if (GetKeyboardLayout(0) == m_groups[g]) { for (KeyButton i = 0; i < 512; ++i) { if (m_buttonToVK[i] != 0) { if (m_virtualKeyToButton[m_buttonToVK[i]] == 0) { m_virtualKeyToButton[m_buttonToVK[i]] = i; } } if (m_buttonToNumpadVK[i] != 0) { if (m_virtualKeyToButton[m_buttonToNumpadVK[i]] == 0) { m_virtualKeyToButton[m_buttonToNumpadVK[i]] = i; } } } } // add numpad keys for (KeyButton i = 0; i < 512; ++i) { if (m_buttonToNumpadVK[i] != 0) { item.m_id = getKeyID(m_buttonToNumpadVK[i], i); item.m_button = i; item.m_required = KeyModifierNumLock; item.m_sensitive = KeyModifierNumLock | KeyModifierShift; item.m_generates = 0; item.m_client = m_buttonToNumpadVK[i]; addKeyEntry(keyMap, item); } } // add other keys BYTE keys[256]; memset(keys, 0, sizeof(keys)); for (KeyButton i = 0; i < 512; ++i) { if (m_buttonToVK[i] != 0) { // initialize item item.m_id = getKeyID(m_buttonToVK[i], i); item.m_button = i; item.m_required = 0; item.m_sensitive = 0; item.m_client = m_buttonToVK[i]; // get flags for modifier keys synergy::KeyMap::initModifierKey(item); if (item.m_id == 0) { // translate virtual key to a character with and without // shift, caps lock, and AltGr. struct Modifier { UINT m_vk1; UINT m_vk2; BYTE m_state; KeyModifierMask m_mask; }; static const Modifier modifiers[] = { { VK_SHIFT, VK_SHIFT, 0x80u, KeyModifierShift }, { VK_CAPITAL, VK_CAPITAL, 0x01u, KeyModifierCapsLock }, { VK_CONTROL, VK_MENU, 0x80u, KeyModifierControl | KeyModifierAlt } }; static const size_t s_numModifiers = sizeof(modifiers) / sizeof(modifiers[0]); static const size_t s_numCombinations = 1 << s_numModifiers; KeyID id[s_numCombinations]; bool anyFound = false; KeyButton button = static_cast<KeyButton>(i & 0xffu); for (size_t j = 0; j < s_numCombinations; ++j) { for (size_t k = 0; k < s_numModifiers; ++k) { //if ((j & (1 << k)) != 0) { // http://msdn.microsoft.com/en-us/library/ke55d167.aspx if ((j & (1i64 << k)) != 0) { keys[modifiers[k].m_vk1] = modifiers[k].m_state; keys[modifiers[k].m_vk2] = modifiers[k].m_state; } else { keys[modifiers[k].m_vk1] = 0; keys[modifiers[k].m_vk2] = 0; } } id[j] = getIDForKey(item, button, m_buttonToVK[i], keys, m_groups[g]); if (id[j] != 0) { anyFound = true; } } if (anyFound) { // determine what modifiers we're sensitive to. // we're sensitive if the KeyID changes when the // modifier does. item.m_sensitive = 0; for (size_t k = 0; k < s_numModifiers; ++k) { for (size_t j = 0; j < s_numCombinations; ++j) { //if (id[j] != id[j ^ (1u << k)]) { // http://msdn.microsoft.com/en-us/library/ke55d167.aspx if (id[j] != id[j ^ (1ui64 << k)]) { item.m_sensitive |= modifiers[k].m_mask; break; } } } // save each key. the map will automatically discard // duplicates, like an unshift and shifted version of // a key that's insensitive to shift. for (size_t j = 0; j < s_numCombinations; ++j) { item.m_id = id[j]; item.m_required = 0; for (size_t k = 0; k < s_numModifiers; ++k) { if ((j & (1i64 << k)) != 0) { item.m_required |= modifiers[k].m_mask; } } addKeyEntry(keyMap, item); } } } else { // found in table switch (m_buttonToVK[i]) { case VK_TAB: // add kKeyLeftTab, too item.m_id = kKeyLeftTab; item.m_required |= KeyModifierShift; item.m_sensitive |= KeyModifierShift; addKeyEntry(keyMap, item); item.m_id = kKeyTab; item.m_required &= ~KeyModifierShift; break; case VK_CANCEL: item.m_required |= KeyModifierControl; item.m_sensitive |= KeyModifierControl; break; case VK_SNAPSHOT: item.m_sensitive |= KeyModifierAlt; if ((i & 0x100u) == 0) { // non-extended snapshot key requires alt item.m_required |= KeyModifierAlt; } break; } addKeyEntry(keyMap, item); } } } } // restore keyboard layout ActivateKeyboardLayout(activeLayout, 0); }
JNIEXPORT void JNICALL Java_org_cef_browser_CefBrowser_1N_N_1SendKeyEvent (JNIEnv *env, jobject obj, jobject key_event) { CefRefPtr<CefBrowser> browser = JNI_GET_BROWSER_OR_RETURN(env, obj); jclass cls = env->GetObjectClass(key_event); if (!cls) return; JNI_STATIC_DEFINE_INT(env, cls, KEY_PRESSED); JNI_STATIC_DEFINE_INT(env, cls, KEY_RELEASED); JNI_STATIC_DEFINE_INT(env, cls, KEY_TYPED); int event_type, modifiers; char key_char; if (!CallJNIMethodI_V(env, cls, key_event, "getID", &event_type) || !CallJNIMethodC_V(env, cls, key_event, "getKeyChar", &key_char) || !CallJNIMethodI_V(env, cls, key_event, "getModifiersEx", &modifiers)) { return; } CefKeyEvent cef_event; cef_event.modifiers = GetCefModifiers(env, cls, modifiers); #if defined(OS_WIN) BYTE VkCode = LOBYTE(VkKeyScanA(key_char)); UINT scanCode = MapVirtualKey(VkCode, MAPVK_VK_TO_VSC); cef_event.native_key_code = (scanCode << 16) | // key scan code 1; // key repeat count #elif defined(OS_LINUX) || defined(OS_MACOSX) int key_code; if (!CallJNIMethodI_V(env, cls, key_event, "getKeyCode", &key_code)) { return; } JNI_STATIC_DEFINE_INT(env, cls, VK_BACK_SPACE); JNI_STATIC_DEFINE_INT(env, cls, VK_DELETE); JNI_STATIC_DEFINE_INT(env, cls, VK_DOWN); JNI_STATIC_DEFINE_INT(env, cls, VK_ENTER); JNI_STATIC_DEFINE_INT(env, cls, VK_ESCAPE); JNI_STATIC_DEFINE_INT(env, cls, VK_LEFT); JNI_STATIC_DEFINE_INT(env, cls, VK_RIGHT); JNI_STATIC_DEFINE_INT(env, cls, VK_TAB); JNI_STATIC_DEFINE_INT(env, cls, VK_UP); #if defined(OS_LINUX) if (key_code == JNI_STATIC(VK_BACK_SPACE)) cef_event.native_key_code = GDK_BackSpace; else if (key_code == JNI_STATIC(VK_DELETE)) cef_event.native_key_code = GDK_Delete; else if (key_code == JNI_STATIC(VK_DOWN)) cef_event.native_key_code = GDK_Down; else if (key_code == JNI_STATIC(VK_ENTER)) cef_event.native_key_code = GDK_KEY_KP_Enter; else if (key_code == JNI_STATIC(VK_ESCAPE)) cef_event.native_key_code = GDK_Escape; else if (key_code == JNI_STATIC(VK_LEFT)) cef_event.native_key_code = GDK_Left; else if (key_code == JNI_STATIC(VK_RIGHT)) cef_event.native_key_code = GDK_Right; else if (key_code == JNI_STATIC(VK_TAB)) cef_event.native_key_code = GDK_Tab; else if (key_code == JNI_STATIC(VK_UP)) cef_event.native_key_code = GDK_Up; else cef_event.native_key_code = key_char; #elif defined(OS_MACOSX) if (key_code == JNI_STATIC(VK_BACK_SPACE)) { cef_event.native_key_code = kVK_Delete; cef_event.unmodified_character = kBackspaceCharCode; } else if (key_code == JNI_STATIC(VK_DELETE)) { cef_event.native_key_code = kVK_ForwardDelete; cef_event.unmodified_character = kDeleteCharCode; } else if (key_code == JNI_STATIC(VK_DOWN)) { cef_event.native_key_code = kVK_DownArrow; cef_event.unmodified_character = /* NSDownArrowFunctionKey */ 0xF701; } else if (key_code == JNI_STATIC(VK_ENTER)) { cef_event.native_key_code = kVK_Return; cef_event.unmodified_character = kReturnCharCode; } else if (key_code == JNI_STATIC(VK_ESCAPE)) { cef_event.native_key_code = kVK_Escape; cef_event.unmodified_character = kEscapeCharCode; } else if (key_code == JNI_STATIC(VK_LEFT)) { cef_event.native_key_code = kVK_LeftArrow; cef_event.unmodified_character = /* NSLeftArrowFunctionKey */ 0xF702; } else if (key_code == JNI_STATIC(VK_RIGHT)) { cef_event.native_key_code = kVK_RightArrow; cef_event.unmodified_character = /* NSRightArrowFunctionKey */ 0xF703; } else if (key_code == JNI_STATIC(VK_TAB)) { cef_event.native_key_code = kVK_Tab; cef_event.unmodified_character = kTabCharCode; } else if (key_code == JNI_STATIC(VK_UP)) { cef_event.native_key_code = kVK_UpArrow; cef_event.unmodified_character = /* NSUpArrowFunctionKey */ 0xF700; } else { cef_event.native_key_code = GetMacKeyCodeFromChar(key_char); if (cef_event.native_key_code == -1) return; cef_event.unmodified_character = key_char; } cef_event.character = cef_event.unmodified_character; // Fill in |character| according to flags. if (cef_event.modifiers & EVENTFLAG_SHIFT_DOWN) { if (key_char >= '0' && key_char <= '9') { cef_event.character = kShiftCharsForNumberKeys[key_char - '0']; } else if (key_char >= 'A' && key_char <= 'Z') { cef_event.character = 'A' + (key_char - 'A'); } else { switch (cef_event.native_key_code) { case kVK_ANSI_Grave: cef_event.character = '~'; break; case kVK_ANSI_Minus: cef_event.character = '_'; break; case kVK_ANSI_Equal: cef_event.character = '+'; break; case kVK_ANSI_LeftBracket: cef_event.character = '{'; break; case kVK_ANSI_RightBracket: cef_event.character = '}'; break; case kVK_ANSI_Backslash: cef_event.character = '|'; break; case kVK_ANSI_Semicolon: cef_event.character = ':'; break; case kVK_ANSI_Quote: cef_event.character = '\"'; break; case kVK_ANSI_Comma: cef_event.character = '<'; break; case kVK_ANSI_Period: cef_event.character = '>'; break; case kVK_ANSI_Slash: cef_event.character = '?'; break; default: break; } } } // Control characters. if (cef_event.modifiers & EVENTFLAG_CONTROL_DOWN) { if (key_char >= 'A' && key_char <= 'Z') cef_event.character = 1 + key_char - 'A'; else if (cef_event.native_key_code == kVK_ANSI_LeftBracket) cef_event.character = 27; else if (cef_event.native_key_code == kVK_ANSI_Backslash) cef_event.character = 28; else if (cef_event.native_key_code == kVK_ANSI_RightBracket) cef_event.character = 29; } #endif // defined(OS_MACOSX) #endif // defined(OS_LINUX) || defined(OS_MACOSX) if (event_type == JNI_STATIC(KEY_PRESSED)) { #if defined(OS_WIN) cef_event.windows_key_code = VkCode; #endif cef_event.type = KEYEVENT_RAWKEYDOWN; } else if (event_type == JNI_STATIC(KEY_RELEASED)) { #if defined(OS_WIN) cef_event.windows_key_code = VkCode; // bits 30 and 31 should always be 1 for WM_KEYUP cef_event.native_key_code |= 0xC0000000; #endif cef_event.type = KEYEVENT_KEYUP; } else if (event_type == JNI_STATIC(KEY_TYPED)) { #if defined(OS_WIN) cef_event.windows_key_code = key_char; #endif cef_event.type = KEYEVENT_CHAR; } else { return; } browser->GetHost()->SendKeyEvent(cef_event); }
//*-----------------------------------------------------------------------------------------// /// @brief 항상 입력창에 포커스가 위치하여 엔터를 칠 필요가 없을때 HotKey처리 /// @warning NormalInput일경우에도 AutoEnter()를 처리하고 있다. //*-----------------------------------------------------------------------------------------// bool CITStateNormal::ProcessHotKeyAutoEnter( unsigned uiMsg, WPARAM wParam, LPARAM lParam ) { switch(uiMsg) { case WM_SYSKEYDOWN: { unsigned int oemScan = int( lParam & (0xff << 16) ) >> 16; UINT vk = MapVirtualKey( oemScan, 1 ); switch(vk) { case 0x41: // 'a' //캐릭터창을 연다 g_itMGR.OpenDialog( DLG_TYPE_CHAR); return true; case 0x43:// 'c' g_itMGR.OpenDialog( DLG_TYPE_COMMUNITY ); return true; case 0x48://h return true; case 0x49: // 'i' case 0x56: // 'v' /// 2004 / 1 / 26 / Navy /추가( SYSTEM + I가 한손으로 누르기 힘들다는 의견으로 ) #ifdef __TEST // 인벤토리 단축키 추가 case 0x45: // 'e' /// 오전 9:52 2006-10-17 홍근. #endif //인벤토리를 연다 g_itMGR.OpenDialog( DLG_TYPE_ITEM ); return true; ///스킬창 case 0x53: // 's' g_itMGR.OpenDialog( DLG_TYPE_SKILL ); return true; /// 퀘스트창 case 0x51: // 'q' g_itMGR.OpenDialog( DLG_TYPE_QUEST ); return true; ///미니맵 보이기 / 숨기기 case 0x4d: // 'm' { CMinimapDLG* pDlg = ( CMinimapDLG*)g_itMGR.FindDlg( DLG_TYPE_MINIMAP ); pDlg->ToggleShowMinimap(); return true; } ///미니맵 확대 / 축소 case 0x4c: // 'l' { CMinimapDLG* pDlg = ( CMinimapDLG*)g_itMGR.FindDlg( DLG_TYPE_MINIMAP ); pDlg->ToggleZoomMinimap(); return true; } case 0x4e: //n { g_itMGR.OpenDialog( DLG_TYPE_CLAN ); return true; } case 0x58: //'x' g_itMGR.OpenDialog( DLG_TYPE_SYSTEM ); return true; case 0x4f: //'o' g_itMGR.OpenDialog( DLG_TYPE_OPTION ); return true; default: break; } } return false; break; default: break; } return true; }
LRESULT WINAPI vmdWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; /* Paint structure. */ // XXX this enum has to be replicated here since its otherwise // private to the DisplayDevice class and children. enum EventCodes { WIN_REDRAW, WIN_LEFT, WIN_MIDDLE, WIN_RIGHT, WIN_WHEELUP, WIN_WHEELDOWN, WIN_MOUSEX, WIN_MOUSEY, WIN_KBD, WIN_KBD_ESCAPE, WIN_KBD_UP, WIN_KBD_DOWN, WIN_KBD_LEFT, WIN_KBD_RIGHT, WIN_KBD_PAGE_UP, WIN_KBD_PAGE_DOWN, WIN_KBD_HOME, WIN_KBD_END, WIN_KBD_INSERT, WIN_KBD_DELETE, WIN_KBD_F1, WIN_KBD_F2, WIN_KBD_F3, WIN_KBD_F4, WIN_KBD_F5, WIN_KBD_F6, WIN_KBD_F7, WIN_KBD_F8, WIN_KBD_F9, WIN_KBD_F10, WIN_KBD_F11, WIN_KBD_F12, WIN_NOEVENT }; wgldata *glwsrv; OpenGLDisplayDevice * ogldispdev; // Upon first window creation, immediately set our user-data field // to store caller-provided handles for this window instance if (msg == WM_NCCREATE) { #if defined(_M_X64) || defined(_WIN64) || defined(_Wp64) SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) (((CREATESTRUCT *) lParam)->lpCreateParams)); #else SetWindowLong(hwnd, GWL_USERDATA, (LONG) (((CREATESTRUCT *) lParam)->lpCreateParams)); #endif } // check to make sure we have a valid window data structure in case // it is destroyed while there are still pending messages... #if defined(_M_X64) || defined(_WIN64) || defined(_Wp64) ogldispdev = (OpenGLDisplayDevice *) GetWindowLongPtr(hwnd, GWLP_USERDATA); #else ogldispdev = (OpenGLDisplayDevice *) GetWindowLong(hwnd, GWL_USERDATA); #endif // when VMD destroys its window data structures it is possible that // the window could still get messages briefly thereafter, this prevents // us from attempting to handle any messages when the VMD state that goes // with the window has already been destructed. (most notably when using // the spaceball..) If we have a NULL pointer, let windows handle the // event for us using the default window proc. if (ogldispdev == NULL) return DefWindowProc(hwnd, msg, wParam, lParam); glwsrv = &ogldispdev->glwsrv; #ifdef VMDSPACEWARE // see if it is a spaceball event, if so do something about it. if (vmd_processwin32spaceballevent(glwsrv, msg, wParam, lParam)) return 0; // #endif switch(msg) { case WM_CREATE: glwsrv->hWnd = hwnd; glwsrv->hRC = SetupOpenGL(glwsrv); glwsrv->WEvents = WIN_REDRAW; return 0; case WM_SIZE: wglMakeCurrent(glwsrv->hDC, glwsrv->hRC); ogldispdev->xSize = LOWORD(lParam); ogldispdev->ySize = HIWORD(lParam); ogldispdev->reshape(); glViewport(0, 0, (GLsizei) ogldispdev->xSize, (GLsizei) ogldispdev->ySize); glwsrv->WEvents = WIN_REDRAW; return 0; case WM_SIZING: wglMakeCurrent(glwsrv->hDC, glwsrv->hRC); glClear(GL_COLOR_BUFFER_BIT); SwapBuffers(glwsrv->hDC); glDrawBuffer(GL_BACK); return 0; case WM_CLOSE: PostQuitMessage(0); return 0; case WM_PAINT: BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); glwsrv->WEvents = WIN_REDRAW; return 0; case WM_KEYDOWN: glwsrv->KeyFlag = MapVirtualKey((UINT) wParam, 2); // map to ASCII glwsrv->WEvents = WIN_KBD; if (glwsrv->KeyFlag == 0) { unsigned int keysym = wParam; switch (keysym) { case VK_ESCAPE: glwsrv->WEvents = WIN_KBD_ESCAPE; break; case VK_UP: glwsrv->WEvents = WIN_KBD_UP; break; case VK_DOWN: glwsrv->WEvents = WIN_KBD_DOWN; break; case VK_LEFT: glwsrv->WEvents = WIN_KBD_LEFT; break; case VK_RIGHT: glwsrv->WEvents = WIN_KBD_RIGHT; break; case VK_PRIOR: glwsrv->WEvents = WIN_KBD_PAGE_UP; break; case VK_NEXT: glwsrv->WEvents = WIN_KBD_PAGE_DOWN; break; case VK_HOME: glwsrv->WEvents = WIN_KBD_HOME; break; case VK_END: glwsrv->WEvents = WIN_KBD_END; break; case VK_INSERT: glwsrv->WEvents = WIN_KBD_INSERT; break; case VK_DELETE: glwsrv->WEvents = WIN_KBD_DELETE; break; case VK_F1: glwsrv->WEvents = WIN_KBD_F1; break; case VK_F2: glwsrv->WEvents = WIN_KBD_F2; break; case VK_F3: glwsrv->WEvents = WIN_KBD_F3; break; case VK_F4: glwsrv->WEvents = WIN_KBD_F4; break; case VK_F5: glwsrv->WEvents = WIN_KBD_F5; break; case VK_F6: glwsrv->WEvents = WIN_KBD_F6; break; case VK_F7: glwsrv->WEvents = WIN_KBD_F7; break; case VK_F8: glwsrv->WEvents = WIN_KBD_F8; break; case VK_F9: glwsrv->WEvents = WIN_KBD_F9; break; case VK_F10: glwsrv->WEvents = WIN_KBD_F10; break; case VK_F11: glwsrv->WEvents = WIN_KBD_F11; break; case VK_F12: glwsrv->WEvents = WIN_KBD_F12; break; default: glwsrv->WEvents = WIN_NOEVENT; break; } } return 0; case WM_MOUSEMOVE: vmd_transwin32mouse(ogldispdev, lParam); glwsrv->MouseFlags = (long) wParam; return 0; case WM_MOUSEWHEEL: { int zDelta = ((short) HIWORD(wParam)); // XXX // zDelta is in positive or negative multiples of WHEEL_DELTA for // clicky type scroll wheels on existing mice, may need to // recode this for continuous wheels at some future point in time. // WHEEL_DELTA is 120 in current versions of Windows. // We only activate an event if the user moves the mouse wheel at // least half of WHEEL_DELTA, so that they don't do it by accident // all the time. if (zDelta > (WHEEL_DELTA / 2)) { glwsrv->WEvents = WIN_WHEELUP; } else if (zDelta < -(WHEEL_DELTA / 2)) { glwsrv->WEvents = WIN_WHEELDOWN; } } return 0; case WM_LBUTTONDOWN: SetCapture(hwnd); vmd_transwin32mouse(ogldispdev, lParam); glwsrv->MouseFlags = (long) wParam; glwsrv->WEvents = WIN_LEFT; return 0; case WM_LBUTTONUP: vmd_transwin32mouse(ogldispdev, lParam); glwsrv->MouseFlags = (long) wParam; glwsrv->WEvents = WIN_LEFT; if (!(glwsrv->MouseFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON))) ReleaseCapture(); return 0; case WM_MBUTTONDOWN: SetCapture(hwnd); vmd_transwin32mouse(ogldispdev, lParam); glwsrv->MouseFlags = (long) wParam; glwsrv->WEvents = WIN_MIDDLE; return 0; case WM_MBUTTONUP: vmd_transwin32mouse(ogldispdev, lParam); glwsrv->MouseFlags = (long) wParam; glwsrv->WEvents = WIN_MIDDLE; if (!(glwsrv->MouseFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON))) ReleaseCapture(); return 0; case WM_RBUTTONDOWN: SetCapture(hwnd); vmd_transwin32mouse(ogldispdev, lParam); glwsrv->MouseFlags = (long) wParam; glwsrv->WEvents = WIN_RIGHT; return 0; case WM_RBUTTONUP: vmd_transwin32mouse(ogldispdev, lParam); glwsrv->MouseFlags = (long) wParam; glwsrv->WEvents = WIN_RIGHT; if (!(glwsrv->MouseFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON))) ReleaseCapture(); return 0; case WM_SETCURSOR: // We process the mouse cursor hit test codes here, they tell us // what part of the window we're over, which helps us set the cursor // to the correct style for sizing borders, moves, etc. switch (LOWORD(lParam)) { case HTBOTTOM: case HTTOP: SetCursor(LoadCursor(NULL, IDC_SIZENS)); break; case HTLEFT: case HTRIGHT: SetCursor(LoadCursor(NULL, IDC_SIZEWE)); break; case HTTOPRIGHT: case HTBOTTOMLEFT: SetCursor(LoadCursor(NULL, IDC_SIZENESW)); break; case HTTOPLEFT: case HTBOTTOMRIGHT: SetCursor(LoadCursor(NULL, IDC_SIZENWSE)); break; case HTCAPTION: SetCursor(LoadCursor(NULL, IDC_ARROW)); break; case HTCLIENT: default: ogldispdev->set_cursor(glwsrv->cursornum); } return 0; // // Handle Windows File Drag and Drop Operations // This code needs to be linked against SHELL32.DLL // case WM_DROPFILES: { char lpszFile[4096]; UINT numfiles, fileindex, numc; HDROP hDropInfo = (HDROP)wParam; // Get the number of simultaneous dragged/dropped files. numfiles = DragQueryFile(hDropInfo, (DWORD)(-1), (LPSTR)NULL, 0); msgInfo << "Ignoring Drag and Drop operation, received " << ((int) numfiles) << " files:" << sendmsg; FileSpec spec; for (fileindex=0; fileindex<numfiles; fileindex++) { // lpszFile: complete pathname with device, colon and backslashes numc = DragQueryFile(hDropInfo, fileindex, (char *) &lpszFile, 4096); // VMD loads the file(s) here, or queues them up in its own // list to decide how to cope with them. Deciding how to deal // with these files is definitely the tricky part. msgInfo << " File(" << ((int) fileindex) << "): " << lpszFile << " (numc=" << ((int) numc) << ")" << sendmsg; // attempt to load the file into a new molecule ogldispdev->vmdapp->molecule_load(-1, lpszFile, NULL, &spec); } DragFinish(hDropInfo); // finish drop operation and release memory } return 0; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; }