8

MSDNによると、wparam はキー コードを保持する必要があります。問題は、Shift キーを押すとコードが 16(VK_SHIFT) になることですが、VK_LSHIFT と VK_RSHIFT を区別する必要があります。

VK_CONTROL の場合、回避策があるようです。

if(wParam == VK_CONTROL) {
    if ( lParam&EXTENDED_KEYMASK )
        wParam = VK_RCONTROL;
    else
        wParam = VK_LCONTROL;
}

ただし、VK_SHIFT では同じことはできません。

if(wparam == VK_SHIFT) {
    if ( lParam&EXTENDED_KEYMASK )
        wParam = VK_RSHIFT;
    else
        wParam = VK_LSHIFT;
}

後者の例では、常に LSHIFT を前提としています。

4

4 に答える 4

15

Shift、Ctrl、または Alt キーの左右のバージョンを区別するにはMapVirtualKey()、仮想キーのメッセージで渡される lParam の関数または「拡張キー」ビットを使用する必要があります。次の関数がその変換を実行します。メッセージから仮想キーコードと lParam を渡すだけで、必要に応じて左/右の特定の仮想キーコードが返されます。

WPARAM MapLeftRightKeys( WPARAM vk, LPARAM lParam)
{
    WPARAM new_vk = vk;
    UINT scancode = (lParam & 0x00ff0000) >> 16;
    int extended  = (lParam & 0x01000000) != 0;

    switch (vk) {
    case VK_SHIFT:
        new_vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX);
        break;
    case VK_CONTROL:
        new_vk = extended ? VK_RCONTROL : VK_LCONTROL;
        break;
    case VK_MENU:
        new_vk = extended ? VK_RMENU : VK_LMENU;
        break;
    default:
        // not a key we map from generic to left/right specialized
        //  just return it.
        new_vk = vk;
        break;    
    }

    return new_vk;
}

渡された仮想キーコードが左/右バージョンにマップされたものでない場合、元のキーコードが変更されずに返されます。したがって、 // /WM_KEYDOWN左と右のバリアントを区別する必要があるときはいつでも、関数を介してメッセージ パラメータを実行できます。WM_KEYUPWM_SYSKEYDOWNWM_SYSKEYUP

を使用MapVirtualKey()することで、左シフトと右シフトのスキャンコードが 0x2a と 0x36 であるという伝承を知る必要はありません。API がその詳細を処理します。そして、それらが異なることが起こった場合 (それが実際に起こるわけではありません)、あなたではなく、Windows がそれに対処する責任を負います。

したがって、WM_KEYDOWN// WM_KEYUP/ハンドラに次のようなコード行を追加するだけですWM_SYSKEYDOWN:WM_SYSKEYUP

wparam = MapLeftRightKeys(wparam, lparam);

コードの残りの部分は、システム メッセージが最初にそれらを提供したかのように、左/右固有の VK コードで動作できます。

于 2013-04-12T17:40:56.280 に答える
8

あなたの質問の背後には古代の歴史があります。オリジナルの IBM PC キーボードには、適切な Alt キーと Ctrl キーがありませんでした。これらは後で拡張キーボード レイアウトに追加され、キーボード コントローラーは拡張キーとして区別するために 0xe0 プレフィックスを付けてスキャン コードに送信します。ただし、元のキーボード レイアウトには常に 2 つのシフト キーがあったため、独自の拡張されていないスキャン コードがあります。これが、コードが機能しない理由です。

David の答えは、問題を解決する良い方法です。しかし、実際にはメッセージからそれを読み取ることができます。これらのスキャン コードは、Windows ロゴの要件によって固定されています。lParam で利用できます。左シフト キーのスキャン コードは 42、右シフト キーのスキャン コードは 54 です。残念ながら、Windows ヘッダーに #define がないため、見苦しくなります。

于 2013-04-12T09:38:41.087 に答える
6

コールGetKeyStateパッシングVK_LSHIFTまたはVK_RSHIFT.

于 2013-04-12T08:37:15.830 に答える
1

「MSDNによると」:

  • VK_LSHIFT
  • VK_RSHIFT
  • VK_LCONTROL
  • VK_RCONTROL
  • VK_LMENU
  • VK_RMENU

これらの左と右を区別する定数は、GetKeyboardState、SetKeyboardState、GetAsyncKeyState、GetKeyState、および MapVirtualKey 関数を介してのみアプリケーションで使用できます。

于 2013-04-12T09:19:17.397 に答える