使用されるキーボードと同じキーボードレイアウトを作成することは可能ですか?

StackOverflow https://stackoverflow.com/questions/4822261

質問

キーボードのように見えるユーザーにカスタマイズするためのキーボードレイアウトを生成する必要がある場合、どうすればできますか?

たとえば、次のようなもの:

enter image description here

フランス語、スウェーデン語、英語、カナダ人など、レイアウトは異なります。これは多くの作業ですか、それとも何らかの組み込みの.NETリージョナルクラスを使用するだけの問題ですか?

役に立ちましたか?

解決

キープレスは、Windowsオペレーティングシステムに「スキャンコード」を報告するハードウェアイベントを生成します。このスキャンコードは、スキャンコードと他のキーボード状態の要因に基づいて「仮想キーコード」に変換されます(キャップスロック 州、 シフト/alt/Ctrl キーステート、および保留中の死んだキーストローク)。変換されたVK値は、 KeyDown イベントなど。

スキャンコードからVKコードへの変換は、現在の入力ロケールに依存します - 単純なことに、入力ロケールはスキャンコードと仮想キーコード間のマッピングを定義します。見る MSDNドキュメント キーボード入力の完全な説明。

このルックアッププロセスを逆転させることにより、各仮想キーコードに対応するスキャンコードを決定することができます(もちろん、同じスキャンコードは、シフト/CTRL/ALT状態などのために複数のVKコードにマッピングされます)。 Win32 APIはを提供します MapVirtualKeyEx を使用して、このマッピングを実行する機能 MAPVK_VK_TO_VSC_EX オプション。これを使用して、特定のVKコードを生成するスキャンコードを決定できます。

残念ながら、これはプログラムで行くことができる限りです。キーボードの物理レイアウトや各スキャンコードのキーの位置を決定する方法はありません。ただし、ほとんどの物理キーボードは同じ方法で配線されているため、(たとえば)左上キーには、ほとんどの物理キーボード設計で同じスキャンコードがあります。基本的な物理キーボードレイアウト(101-Key、102-Keyなど)に応じて、この想定条約を使用して、スキャンコードに対応する物理的な場所を推測できます。それは保証されていませんが、それはかなり安全な推測です。

次のコードは、私が書いたより大きなキーボード処理ライブラリからの抜粋です(私はそれをオープンソースするつもりでしたが、時間がなかったことを意図していました)。メソッドはアレイを初期化します(this._virtualKeyScanCodes)特定の入力ロケールのVKコードによってインデックスが付けられています(に保存されています this._inputLanguage これはaとして宣言されています System.Windows.Forms.InputLanguage. 。配列を使用して、EGを調べてVKコードに対応するスキャンコードを決定できます。 this._virtualKeyScanCodes[VK_NUMPAD0] - スキャンコードがゼロの場合、そのVKは現在の入力ロケールのキーボードで使用できません。ゼロ以外の場合、それはあなたが物理キーを推測できるスキャンコードです。

残念ながら、デッドキーの領域に入ると、問題はこれよりもわずかに複雑です(たとえば、アクセントのある文字を生成する複数のキーの組み合わせ)。それはすべて複雑すぎて今は入りませんが、マイケル・S・カプランは詳細なシリーズを書きました ブログ投稿 これをさらに探求したい場合。幸運を!

private void Initialize()
{
    this._virtualKeyScanCodes = new uint[MaxVirtualKeys];

    // Scroll through the Scan Code (SC) values and get the Virtual Key (VK)
    // values in it. Then, store the SC in each valid VK so it can act as both a 
    // flag that the VK is valid, and it can store the SC value.
    for (uint scanCode = 0x01; scanCode <= 0xff; scanCode++)
    {
        uint virtualKeyCode = NativeMethods.MapVirtualKeyEx(
            scanCode, 
            NativeMethods.MAPVK_VSC_TO_VK, 
            this._inputLanguage.Handle);
        if (virtualKeyCode != 0)
        {
            this._virtualKeyScanCodes[virtualKeyCode] = scanCode;
        }
    }

    // Add the special keys that do not get added from the code above
    for (KeysEx ke = KeysEx.VK_NUMPAD0; ke <= KeysEx.VK_NUMPAD9; ke++)
    {
        this._virtualKeyScanCodes[(uint)ke] = NativeMethods.MapVirtualKeyEx(
            (uint)ke, 
            NativeMethods.MAPVK_VK_TO_VSC, 
            this._inputLanguage.Handle);
    }

    this._virtualKeyScanCodes[(uint)KeysEx.VK_DECIMAL] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_DECIMAL, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_DIVIDE] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_DIVIDE, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_CANCEL] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_CANCEL, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);

    this._virtualKeyScanCodes[(uint)KeysEx.VK_LSHIFT] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_LSHIFT, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_RSHIFT] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_RSHIFT, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_LCONTROL] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_LCONTROL, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_RCONTROL] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_RCONTROL, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_LMENU] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_LMENU, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_RMENU] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_RMENU, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_LWIN] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_LWIN, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_RWIN] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_RWIN, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_PAUSE] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_PAUSE, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_VOLUME_UP] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_VOLUME_UP, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_VOLUME_DOWN] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_VOLUME_DOWN, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_VOLUME_MUTE] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_VOLUME_MUTE, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);

    this._virtualKeyScanCodes[(uint)KeysEx.VK_MEDIA_NEXT_TRACK] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_MEDIA_NEXT_TRACK, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_MEDIA_PREV_TRACK] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_MEDIA_PREV_TRACK, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_MEDIA_PLAY_PAUSE] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_MEDIA_PLAY_PAUSE, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
    this._virtualKeyScanCodes[(uint)KeysEx.VK_MEDIA_STOP] =
        NativeMethods.MapVirtualKeyEx(
            (uint)KeysEx.VK_MEDIA_STOP, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);

    this._stateController = new KeyboardStateController();
    this._baseVirtualKeyTable = new VirtualKeyTable(this);
}

編集:参照 この質問 あなたのものに似ています。

他のヒント

キーボードレイアウトを含む組み込みの.NETクラスはありません。キーボードレイアウトは、通常はWindowsのオペレーティングシステムの関数です。 .NETが関与するまでに、キープレスがハードウェアイベントからソフトウェアイベントに変換されました。これを実際に見たい場合は、キーがそれらの間に移動した2つのキーボードレイアウトを見つけてください。イベントハンドラーを使用してダミーアプリをセットアップします Key_Down イベント、そしてイベントのargsは同一であることに注意してください。あなたが押した場合 - あなたが押したキー - それに関係なくキー - キーがあります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top