12

Windows 8 のものと同様のオンスクリーン キーボードを作成しています。Win32 の SendInput を使用して、必要な文字のほとんどを問題なく送信できます。

問題は、新しい Windows 8 Emoji に関してです。これらは、Segoe UI Symbol フォントを使用して U+1F600 から始まります。

Windows 8 のオンスクリーン キーボードで Spy++ を使用すると、すべての絵文字グリフに対して次の出力が得られます。

<00001> 000C064A P WM_KEYDOWN nVirtKey:VK_PACKET cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<00002> 000C064A P WM_CHAR chCharCode:'63' (63) cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<00003> 000C064A P WM_KEYUP nVirtKey:VK_PACKET cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:1 fUp:1
<00004> 000C064A P WM_KEYDOWN nVirtKey:VK_PACKET cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<00005> 000C064A P WM_CHAR chCharCode:'63' (63) cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<00006> 000C064A P WM_KEYUP nVirtKey:VK_PACKET cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:1 fUp:1

それらはすべて同じ出力を生成するため、一意のグリフを実際に識別するために送信されたものはわかりません。

SendInput には、Unicode 文字を送信するための KEYEVENTF_UNICODE パラメータがあることを認識しています。しかし、これらの文字はある種の拡張 Unicode ページにあるようです。16 ビットの Unicode 範囲 (U+0000 から U+FFFF) を超えると、C# char または INPUT 構造体の短い wScan 値で表すことができます。

これが私の SendCharUnicode メソッドです。

public static void SendCharUnicode(char ch)
{
    Win32.INPUT[] input = new Win32.INPUT[2];

    input[0] = new Win32.INPUT();
    input[0].type = Win32.INPUT_KEYBOARD;
    input[0].ki.wVk = 0;
    input[0].ki.wScan = (short)ch;
    input[0].ki.time = 0;
    input[0].ki.dwFlags = Win32.KEYEVENTF_UNICODE;
    input[0].ki.dwExtraInfo = Win32.GetMessageExtraInfo();

    input[1] = new Win32.INPUT();
    input[1].type = Win32.INPUT_KEYBOARD;
    input[1].ki.wVk = 0;
    input[1].ki.wScan = (short)ch;
    input[1].ki.time = 0;
    input[1].ki.dwFlags = Win32.KEYEVENTF_UNICODE | Win32.KEYEVENTF_KEYUP;
    input[1].ki.dwExtraInfo = Win32.GetMessageExtraInfo();

    Win32.SendInput(2, input, Marshal.SizeOf(typeof(Win32.INPUT)));
}

(U+1F600) などの Unicode 文字を正常に送信するようにこのメソッドを変更するにはどうすればよいですか?

4

1 に答える 1

6

Windows 8 のオンスクリーン キーボードで API Monitor を使用しましたが、実際に SendInput を使用しています。さらに調査した結果、UTF-32 Unicode 文字を UTF-16 サロゲート ペアに分割する必要があることがわかりました。U+1F604 は [U+D83D U+DE04] になります。したがって、D83D を送信してから DE04 を送信すると、U+1F604 を正常に送信できます。

作業方法は次のとおりです。

public static void SendCharUnicode(int utf32)
{
    string unicodeString = Char.ConvertFromUtf32(utf32);
    Win32.INPUT[] input = new Win32.INPUT[unicodeString.Length];

    for (int i = 0; i < input.Length; i++)
    {
        input[i] = new Win32.INPUT();
        input[i].type = Win32.INPUT_KEYBOARD;
        input[i].ki.wVk = 0;
        input[i].ki.wScan = (short)unicodeString[i];
        input[i].ki.time = 0;
        input[i].ki.dwFlags = Win32.KEYEVENTF_UNICODE;
        input[i].ki.dwExtraInfo = IntPtr.Zero;
    }

    Win32.SendInput((uint)input.Length, input, Marshal.SizeOf(typeof(Win32.INPUT)));
}
于 2014-03-10T18:48:50.653 に答える