Использование SendInput для отправки символов Юникода за пределы U+FFFF
Я пишу экранную клавиатуру, похожую на ту, что в Windows 8. У меня нет проблем с отправкой большинства символов, которые мне нужны, с помощью Win32 SendInput.
Проблема в том, что касается нового Windows 8 Emoji. Они начинаются с U+1F600 с использованием шрифта Segoe UI Symbol.
Используя Spy++ на экранной клавиатуре Windows 8, я получаю следующий вывод для всех символов Emoji.
<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 имеет параметр KEYEVENTF_UNICODE для отправки символов Юникода. Но эти символы, похоже, находятся на какой-то расширенной странице юникода. За пределами 16-битного диапазона Юникода (от U+0000 до U+FFFF) может представлять символ C# или короткое значение wScan в структуре INPUT.
Вот мой метод 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)?
1 ответ
Я использовал API Monitor на экранной клавиатуре Windows 8, и он действительно использует SendInput. После дальнейшего расследования я обнаружил, что вам нужно разбить символ Unicode UTF-32 на его суррогатную пару 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)));
}