web-dev-qa-db-ja.com

C#仮想キーコードをcharに変換する方法は?

仮想キーコードを文字にマップしようとしています。

私のコードはProcessCmdKeyを使用してWM_KEYDOWNをリッスンし、押されたキーにアクセスできるようにします。たとえば、一重引用符を押すと、222のキーが取得されます。このキーは、キーチェーン39にマッピングされます。

私の開発コンテキストは次のとおりです。-.net Framework 2.0-多くの場所に配置されたUserControl

質問の答えを知っていますか?

23
Horas

System.Windows.Form.KeysConverter クラスの目的は何ですか?

KeysConverter kc = new KeysConverter();
string keyChar = kc.ConvertToString(keyData);
41
Powerlord

はい、MapVirtualKeyメソッドを使用しました。しかし、どのDllImportディレクティブを使用するか、どのenumが文字へのマッピングに固有であるかなど、使用方法の詳細を期待していました。

5秒間グーグルで検索してから解決策を提案するこれらの回答は好きではありません。本当の課題は、すべてのピースをまとめることであり、サンプルのないMSDNページや他のコーディングフォーラムで時間を浪費する必要はありませんあなたの答えを得るために。攻撃台座はありませんが、フォーラムに質問を投稿する前にこの回答があったので、あなたの答えは(良かったとしても)価値がありませんでした!

そこで、私が探していたもの-すぐに使えるC#ソリューション-を投稿します。

1-このディレクティブをクラス内に配置します。

[DllImport("user32.dll")]
static extern int MapVirtualKey(uint uCode, uint uMapType);

2-次のように文字を取得します。

  protected override bool ProcessCmdKey(ref Message msg, Keys keyData)      
  {
     const int WM_KEYDOWN = 0x100;

     if (msg.Msg == WM_KEYDOWN)
     {            
        // 2 is used to translate into an unshifted character value 
        int nonVirtualKey = MapVirtualKey((uint)keyData, 2);

        char mappedChar = Convert.ToChar(nonVirtualKey);
     }

     return base.ProcessCmdKey(ref msg, keyData);
  }

思いやりをありがとう...そしてお楽しみください!

25
Horas

似たようなものを探していましたが、現在のキーボードレイアウトにマップされた文字が必要でした。上記の答えはどれも私の要件を満たしていないので、ここに私が思いついたものがあります。


        public string KeyCodeToUnicode(Keys key)
        {
            byte[] keyboardState = new byte[255];
            bool keyboardStateStatus = GetKeyboardState(keyboardState);

            if (!keyboardStateStatus)
            {
                return "";
            }

            uint virtualKeyCode = (uint)key;
            uint scanCode = MapVirtualKey(virtualKeyCode, 0);
            IntPtr inputLocaleIdentifier = GetKeyboardLayout(0);

            StringBuilder result = new StringBuilder();
            ToUnicodeEx(virtualKeyCode, scanCode, keyboardState, result, (int)5, (uint)0, inputLocaleIdentifier);

            return result.ToString();
        }

        [DllImport("user32.dll")]
        static extern bool GetKeyboardState(byte[] lpKeyState);

        [DllImport("user32.dll")]
        static extern uint MapVirtualKey(uint uCode, uint uMapType);

        [DllImport("user32.dll")]
        static extern IntPtr GetKeyboardLayout(uint idThread);

        [DllImport("user32.dll")]
        static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);

10
Ivan Petrov

提供された回答のいくつかを読んでテストした後、代替案を提案すると思いました。

[〜#〜] mm [〜#〜] で述べたように、System.Windows.KeysConverterはキーの文字表現ではなく、enumの名前を提供します。 「\ n」の代わりに「Enter」。

Horas によって提案されたMapVirtualKeyメソッドは、彼自身の質問への回答としては良い出発点ですが、capslock、またはシフトキーで入力された文字のいずれもサポートしていません。 「!」、「$」、および「>」。

私が使用しているMapVirtualKeyメソッドの代替は、Keysクラスの拡張メソッドです。

public static char ToChar(this Keys key)
{
    char c = '\0';
    if((key >= Keys.A) && (key <= Keys.Z))
    {
        c = (char)((int)'a' + (int)(key - Keys.A));
    }

    else if((key >= Keys.D0) && (key <= Keys.D9))
    {
        c = (char)((int)'0' + (int)(key - Keys.D0));
    }

    return c;
}

上記の方法は、英数字のサポートを提供します。追加の文字のサポートは、switchステートメントまたはルックアップテーブルで実装できます。

7

Ivan Petrov answer の改善を書いたところです。WPFで押されたキーの組み合わせの文字列表現を表示します。以下のコードを参照してください。

public static string GetKeyString(Key key, ModifierKeys modifiers)
{
    string result = "";
    if (key != Key.None)
    {
        // Setup modifiers
        if (modifiers.HasFlag(ModifierKeys.Control))
            result += "Ctrl + ";
        if (modifiers.HasFlag(ModifierKeys.Alt))
            result += "Alt + ";
        if (modifiers.HasFlag(ModifierKeys.Shift))
            result += "Shift + ";
        // Get string representation
        string keyStr = key.ToString();
        int keyInt = (int)key;
        // Numeric keys are returned without the 'D'
        if (key >= Key.D0 && key <= Key.D9)
            keyStr = char.ToString((char)(key - Key.D0 + '0'));
        // Char keys are returned directly
        else if (key >= Key.A && key <= Key.Z)
            keyStr = char.ToString((char)(key - Key.A + 'A'));
        // If the key is a keypad operation (Add, Multiply, ...) or an 'Oem' key, P/Invoke
        else if ((keyInt >= 84 && keyInt <= 89) || keyInt >= 140)
            keyStr = KeyCodeToUnicode(key);
        result += keyStr;
    }
    return result;
}

private static string KeyCodeToUnicode(Key key)
{
    byte[] keyboardState = new byte[255];
    bool keyboardStateStatus = GetKeyboardState(keyboardState);

    if (!keyboardStateStatus)
    {
        return "";
    }

    uint virtualKeyCode = (uint)KeyInterop.VirtualKeyFromKey(key);
    uint scanCode = MapVirtualKey(virtualKeyCode, 0);
    IntPtr inputLocaleIdentifier = GetKeyboardLayout(0);

    StringBuilder result = new StringBuilder();
    ToUnicodeEx(virtualKeyCode, scanCode, new byte[255], result, (int)5, (uint)0, inputLocaleIdentifier);

    return result.ToString();
}

[DllImport("user32.dll")]
static extern bool GetKeyboardState(byte[] lpKeyState);

[DllImport("user32.dll")]
static extern uint MapVirtualKey(uint uCode, uint uMapType);

[DllImport("user32.dll")]
static extern IntPtr GetKeyboardLayout(uint idThread);

[DllImport("user32.dll")]
static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);
2
edupeux

KeysConverterは、キー "text"ではなくキー名を取得します。例: "2"の代わりに "Num2" MapVirtualKeyは英語で動作しますが、MapVirtualKeyExを使用する英語以外のcharドキュメント状態カルチャID定数ですが、正しいID値を見つけた後、試してみたのでうまくいきませんでしたので、最後にすべてをダンプしました

1
mm.