hea*_*aze 9 c# unicode winapi sendinput
我正在编写类似于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
Run Code Online (Sandbox Code Playgroud)
由于它们都产生相同的输出,我无法看到实际识别唯一字形的发送内容.
我知道SendInput有一个KEYEVENTF_UNICODE参数用于发送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)));
}
Run Code Online (Sandbox Code Playgroud)
如何修改此方法以成功发送(U + 1F600)等Unicode字符?
我在 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)));
}
Run Code Online (Sandbox Code Playgroud)