c# - 使用 SendInput 发送 U+FFFF 之外的 unicode 字符

标签 c# winapi unicode sendinput

我正在编写一个类似于 Windows 8 中的屏幕键盘。我可以使用 Win32 的 SendInput 发送我需要的大部分字符。

问题在于新的 Windows 8 表情符号。它们从 U+1F600 开始,使用 Segoe UI Symbol 字体。

在 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)之外,INPUT 结构中的 C# 字符或短 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)));
}

如何修改此方法以成功发送 Unicode 字符,例如 😃 (U+1F600)?

最佳答案

我在 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)));
}

关于c# - 使用 SendInput 发送 U+FFFF 之外的 unicode 字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22291282/

相关文章:

c# - 将 IList<T1> 转换为 ILIst<T2>

c# - Directory.Exists 对时间敏感吗?

c# - TDD:当方法根据输入返回不同结果时如何测试结果?

windows - 如何列出 Windows 域中的所有用户和组?

python - 使用 String upper() 转换单词对某些字母不起作用?

c# - jQuery 对话框中的 MVC3 数据未回传到服务器

c - 如何使用 TerminateProcess 终止进程

c++ - DirectDraw使用GetProcAddress获取程序地址

objective-c - Unicode 字符在 iOS5 中的绘制方式不同

unicode - 是否可以将类似于 UTF-8 的编码限制为每个字符 3 个字节?