使用SendInput发送超出U + FFFF的unicode字符

我正在编写类似于Windows 8中的屏幕键盘。使用Win32的SendInput发送我需要的大多数字符都没有问题。

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

在Windows 8屏幕键盘上使用Spy ++,我得到所有表情符号字形的以下输出。

 000C064A P WM_KEYDOWN nVirtKey:VK_PACKET cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0  000C064A P WM_CHAR chCharCode:'63' (63) cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0  000C064A P WM_KEYUP nVirtKey:VK_PACKET cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:1 fUp:1  000C064A P WM_KEYDOWN nVirtKey:VK_PACKET cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0  000C064A P WM_CHAR chCharCode:'63' (63) cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0  000C064A P WM_KEYUP nVirtKey:VK_PACKET cRepeat:1 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:1 fUp:1 

由于它们都产生相同的输出,我无法看到实际识别唯一字形的发送内容。

我知道SendInput有一个KEYEVENTF_UNICODE参数用于发送unicode字符。 但是这些字符似乎是在某种扩展的unicode页面中。 除了16位unicode范围(U + 0000到U + FFFF)之外,INPUT结构中的C#char或短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代理对Eg。 😄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))); }