2017-11-12 15 views
1

現在のキーボードレイアウトでサポートされている可能性のあるすべてのキーの組み合わせを列挙したいと思います(仮想キーコード、スキャンコード、 Unicode値)。リモートユーザー入力をシミュレートするためにキーにマップする。VC++:可能なすべてのキー組み合わせのスキャンコードとともに仮想キーコードのリストを列挙します。

仮想キーコードと修飾子(ALT、SHIFT、CTRL)を受け入れ、スキャンコードを提供できるVC++用のUCKeyTranslate(ObjectiveC)のようなAPIを期待していましたが、

多くの調査と2日間の過ごした後、私はMapVirtualKeyExを除いて他の選択肢はありませんでした。

BOOL PopulateKeyMap() 
{ 
    TCHAR Buff[120 * sizeof(TCHAR)] = { 0 }; 
    GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILANGUAGE, Buff, sizeof(Buff)); 
    HKL hKeyboardLayout = ::LoadKeyboardLayout(Buff, KLF_ACTIVATE); 

    { 
     lock_guard<recursive_mutex> lockHolder(cs_populate_key); 

     if (hCurrentKeyboardLayout) 
     { 
      UnloadKeyboardLayout(hCurrentKeyboardLayout); 
     } 

     hCurrentKeyboardLayout = hKeyboardLayout; 

     // Prepopulate keyCodeDictionary with common key combinations. 
     for (int keyIndex = 0; keyIndex < KEY_CODES_DICT_SIZE; ++keyIndex) 
     { 
      { 
       unsigned int Vk; 

       tstring key_name = GetKeyName(keyIndex, Vk); 

       if (key_name.compare(_T("")) != 0) 
       { 
        SmartPtr<KeyCodeInfo> key = (new KeyCodeInfo); 

        if (key) 
        { 
         key->nIndex = keyIndex; 
         key->sVKCode = keyIndex; 
         key->nScanCode = Vk; 

         keyboard_map[key_name] = key; 
        } 
       }// End if 
      } 
     }// End for 

     bKeyMapInitialized = TRUE; 
    } 

    return TRUE; 
} 

tstring GetKeyName(unsigned int virtualKey, unsigned int &scanCode) 
{ 
    if (!hCurrentKeyboardLayout) 
    { 
     PopulateKeyMap(); 
    } 

    scanCode = MapVirtualKeyEx(virtualKey, MAPVK_VK_TO_VSC, hCurrentKeyboardLayout); 

    // because MapVirtualKey strips the extended bit for some keys 
    switch (virtualKey) 
    { 
     case VK_LEFT: case VK_UP: case VK_RIGHT: case VK_DOWN: // arrow keys 
     case VK_PRIOR: case VK_NEXT: // page up and page down 
     case VK_END: case VK_HOME: 
     case VK_INSERT: case VK_DELETE: 
     case VK_DIVIDE: // numpad slash 
     case VK_NUMLOCK: 
     { 
      scanCode |= KF_EXTENDED; // set extended bit 
      break; 
     } 
    } 

    TCHAR keyName[256]; 
    if (GetKeyNameText(scanCode << 16, keyName, sizeof(keyName)) != 0) 
    { 
     return keyName; 
    } 
    else 
    { 
     return _T(""); 
    } 
} 

MapVirtualKeyExは私だけで、基本的なスキャンコードのリストと修飾子の組み合わせで、キーのないスキャンコードを提供し、私は次のコードで来たが、それは多くの問題を持っています(ALT、CTRL、SHIFT)。必要なキーの組み合わせを生成できるように、関数の入力として修飾子の組み合わせを提供する方法はありますか。

ご協力いただければ幸いです。前もって感謝します。

答えて

0

最後に、このためのソリューションを持って、https://dxr.mozilla.org/mozilla-central/source/widget/windows/KeyboardLayout.cpp

void 
FillKbdState(PBYTE aKbdState, 
    const ShiftState aShiftState) 
{ 
    if (aShiftState & STATE_SHIFT) { 
     aKbdState[VK_SHIFT] |= 0x80; 
    } 
    else { 
     aKbdState[VK_SHIFT] &= ~0x80; 
     aKbdState[VK_LSHIFT] &= ~0x80; 
     aKbdState[VK_RSHIFT] &= ~0x80; 
    } 

    if (aShiftState & STATE_CONTROL) { 
     aKbdState[VK_CONTROL] |= 0x80; 
    } 
    else { 
     aKbdState[VK_CONTROL] &= ~0x80; 
     aKbdState[VK_LCONTROL] &= ~0x80; 
     aKbdState[VK_RCONTROL] &= ~0x80; 
    } 

    if (aShiftState & STATE_ALT) { 
     aKbdState[VK_MENU] |= 0x80; 
    } 
    else { 
     aKbdState[VK_MENU] &= ~0x80; 
     aKbdState[VK_LMENU] &= ~0x80; 
     aKbdState[VK_RMENU] &= ~0x80; 
    } 

    if (aShiftState & STATE_CAPSLOCK) { 
     aKbdState[VK_CAPITAL] |= 0x01; 
    } 
    else { 
     aKbdState[VK_CAPITAL] &= ~0x01; 
    } 
} 

inline int32_t GetKeyIndex(uint8_t aVirtualKey) 
{ 
    // Currently these 68 (NS_NUM_OF_KEYS) virtual keys are assumed 
    // to produce visible representation: 
    // 0x20 - VK_SPACE   ' ' 
    // 0x30..0x39    '0'..'9' 
    // 0x41..0x5A    'A'..'Z' 
    // 0x60..0x69    '0'..'9' on numpad 
    // 0x6A - VK_MULTIPLY  '*' on numpad 
    // 0x6B - VK_ADD   '+' on numpad 
    // 0x6D - VK_SUBTRACT  '-' on numpad 
    // 0x6E - VK_DECIMAL  '.' on numpad 
    // 0x6F - VK_DIVIDE   '/' on numpad 
    // 0x6E - VK_DECIMAL  '.' 
    // 0xBA - VK_OEM_1   ';:' for US 
    // 0xBB - VK_OEM_PLUS  '+' any country 
    // 0xBC - VK_OEM_COMMA  ',' any country 
    // 0xBD - VK_OEM_MINUS  '-' any country 
    // 0xBE - VK_OEM_PERIOD  '.' any country 
    // 0xBF - VK_OEM_2   '/?' for US 
    // 0xC0 - VK_OEM_3   '`~' for US 
    // 0xC1 - VK_ABNT_C1  '/?' for Brazilian 
    // 0xC2 - VK_ABNT_C2  separator key on numpad (Brazilian or JIS for Mac) 
    // 0xDB - VK_OEM_4   '[{' for US 
    // 0xDC - VK_OEM_5   '\|' for US 
    // 0xDD - VK_OEM_6   ']}' for US 
    // 0xDE - VK_OEM_7   ''"' for US 
    // 0xDF - VK_OEM_8 
    // 0xE1 - no name 
    // 0xE2 - VK_OEM_102  '\_' for JIS 
    // 0xE3 - no name 
    // 0xE4 - no name 

    static const int8_t xlat[256] = 
    { 
     // 0 1 2 3 4 5 6 7 8 9 A B C D E F 
     //----------------------------------------------------------------------- 
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00 
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10 
     0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 20 
     1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, // 30 
     -1, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 40 
     26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -1, -1, -1, -1, -1, // 50 
     37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, -1, 49, 50, 51, // 60 
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 70 
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80 
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 90 
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // A0 
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 52, 53, 54, 55, 56, 57, // B0 
     58, 59, 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // C0 
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 61, 62, 63, 64, 65, // D0 
     -1, 66, 67, 68, 69, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // E0 
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // F0 
    }; 

    return xlat[aVirtualKey]; 
} 

void PopulateKeyMap(HKL aLayout) 
{ 
    BYTE kbdState[256]; 
    memset(kbdState, 0, sizeof(kbdState)); 

    BYTE originalKbdState[256]; 
    // Bitfield with all shift states that have at least one dead-key. 
    uint16_t shiftStatesWithDeadKeys = 0; 
    // Bitfield with all shift states that produce any possible dead-key base 
    // characters. 
    uint16_t shiftStatesWithBaseChars = 0; 

    ::GetKeyboardState(originalKbdState); 

    int index = 0; 

    // For each shift state gather all printable characters that are produced 
    // for normal case when no any dead-key is active. 

    for (ShiftState shiftState = 0; shiftState < 16; shiftState++) 
    { 
     FillKbdState(kbdState, shiftState); 

     for (uint32_t virtualKey = 0; virtualKey < 256; virtualKey++) 
     { 
      int32_t vki = GetKeyIndex(virtualKey); 

      if (vki < 0) 
      { 
       continue; 
      } 

      wchar_t uniChars[5]; 
      int32_t ret = 
       ::ToUnicodeEx(virtualKey, 0, kbdState, (LPWSTR)uniChars, 
        ArrayLength(uniChars), 0, hCurrentKeyboardLayout); 

      // neither a dead-key nor there is no translation 
      if (ret > 0) 
      { 
       if (ret == 1) 
       { 
        // dead-key can pair only with exactly one base character. 
        shiftStatesWithBaseChars |= (1 << shiftState); 
       } 


       { 
        index++; 

        uniChars[ret] = '\0'; 

        CString key_name(uniChars); 

        unsigned int scanCode = MapVirtualKeyEx(virtualKey, MAPVK_VK_TO_VSC, hCurrentKeyboardLayout); 

        // because MapVirtualKey strips the extended bit for some keys 
        switch (virtualKey) 
        { 
        case VK_LEFT: case VK_UP: case VK_RIGHT: case VK_DOWN: // arrow keys 
        case VK_PRIOR: case VK_NEXT: // page up and page down 
        case VK_END: case VK_HOME: 
        case VK_INSERT: case VK_DELETE: 
        case VK_DIVIDE: // numpad slash 
        case VK_NUMLOCK: 
        { 
         scanCode |= KF_EXTENDED; // set extended bit 
         break; 
        } 
        } 

        if (false == key_name.IsEmpty()) 
        { 
         SmartPtr<KeyCodeInfo> key = (new KeyCodeInfo)->template DetachObject<KeyCodeInfo>(); 

         if (key) 
         { 
          key->nIndex = index; 
          key->sVKCode = virtualKey; 
          key->nScanCode = scanCode; 

          keyboard_map[tstring(key_name.GetBuffer())] = key; 
         } 
        }// End if 
       } 
      } 
     } 
    } 

    ::SetKeyboardState(originalKbdState); 
} 
を参照
関連する問題