SendInput не будет отправлять базовый Unicode в некоторые окна - PullRequest
0 голосов
/ 19 мая 2018

У меня проблема с этим проектом в C #: при использовании функции WinAPI SendInput

    /// <summary>
    /// Sends Unicode (UTF16) string to foreground window.
    /// </summary>
    /// <param name="inputString">String to be sent to foreground window.</param>
    internal static void Send(string inputString)
    {
        if (inputString == string.Empty)
        { return; }

        char[] chars = inputString.ToCharArray();
        INPUT[] pInputs = new INPUT[chars.Length * 2];

        for (int i = 0; i < chars.Length; i++)
        {
            UInt16 unicode = chars[i];
            pInputs[i * 2] = new INPUT();
            pInputs[i * 2].type = INPUT_KEYBOARD;
            pInputs[i * 2].ki.wVk = 0;
            pInputs[i * 2].ki.wScan = unicode;
            pInputs[i * 2].ki.dwFlags = KEYEVENTF_UNICODE;
            pInputs[i * 2].ki.time = 0;
            pInputs[i * 2].ki.dwExtraInfo = SetMessageExtraInfo(IntPtr.Zero);

            pInputs[i * 2 + 1] = new INPUT();
            pInputs[i * 2 + 1].type = INPUT_KEYBOARD;
            pInputs[i * 2 + 1].ki.wVk = 0;
            pInputs[i * 2 + 1].ki.wScan = unicode;
            pInputs[i * 2 + 1].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
            pInputs[i * 2 + 1].ki.time = 0;
            pInputs[i * 2 + 1].ki.dwExtraInfo = SetMessageExtraInfo(IntPtr.Zero);
        }
        uint nSent = SendInput((uint)chars.Length * 2, pInputs, Marshal.SizeOf(typeof(INPUT)));
        if (nSent == 0)
        {
            Debug.WriteLine("SendInput error " + GetLastError().ToString()); // error 87 : "The parameter is incorrect."
        }
    }

В настольных приложениях, таких как Notepad или VS, код работает нормально, но в других он не работает с простымиАнглийский алфавит и пунктуация.Строка типа «íáó» со специальными символами работает явно / универсально, а строка типа «Моя машина» - нет.Очевидно, что значения utf-16 для символов в «My car» низкие, менее 100;Значения á и í составляют 225 и 237 соответственно.Казалось бы, поверхностная разница.Кто-нибудь знает способ получения регулярных английских писем для отправки в виде Unicode в произвольные окна с помощью SendInput?

1 Ответ

0 голосов
/ 19 мая 2018

Это не документация по MSDN, но при использовании KEYEVENTF_UNICODE, если для заданной кодовой точки Unicode требуется использование суррогатов UTF-16, вам необходимо отправить оба суррогата без KEYEVENTF_KEYUP, затем отправить обоих суррогатов с KEYEVENTF_KEYUP.Код, который вы показали, совсем не учитывает суррогаты UTF-16, он отправляет входные данные для каждого суррогата независимо друг от друга.Два суррогата должны быть одновременно «вниз», а затем «вверх» одновременно.

Вместо этого попробуйте что-нибудь более подобное (основываясь на предыдущем ответе , который я написал длята же проблема в C ++):

/// <summary>
/// Sends Unicode (UTF16) string to foreground window.
/// </summary>
/// <param name="inputString">String to be sent to foreground window.</param>
internal static void Send(string inputString)
{
    if (string.IsNullOrEmpty(inputString))
    { return; }

    char[] chars = inputString.ToCharArray();
    int len = chars.Length;
    INPUT[] pInputs = new INPUT[len * 2];

    UInt32 ExtraInfo = GetMessageExtraInfo();

    int i = 0, idx = 0;
    while (i < len)
    {
        UInt16 ch = chars[i++];

        if ((ch < 0xD800) || (ch > 0xDFFF))
        {
            pInputs[idx] = new INPUT();
            pInputs[idx].type = INPUT_KEYBOARD;
            pInputs[idx].ki.wVk = 0;
            pInputs[idx].ki.wScan = ch;
            pInputs[idx].ki.dwFlags = KEYEVENTF_UNICODE;
            pInputs[idx].ki.time = 0;
            pInputs[idx].ki.dwExtraInfo = ExtraInfo;
            ++idx;

            pInputs[idx] = new INPUT();
            pInputs[idx].type = INPUT_KEYBOARD;
            pInputs[idx].ki.wVk = 0;
            pInputs[idx].ki.wScan = ch;
            pInputs[idx].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
            pInputs[idx].ki.time = 0;
            pInputs[idx].ki.dwExtraInfo = ExtraInfo;
            ++idx;
        }
        else
        {
            UInt16 ch2 = chars[i++];

            pInputs[idx] = new INPUT();
            pInputs[idx].type = INPUT_KEYBOARD;
            pInputs[idx].ki.wVk = 0;
            pInputs[idx].ki.wScan = ch;
            pInputs[idx].ki.dwFlags = KEYEVENTF_UNICODE;
            pInputs[idx].ki.time = 0;
            pInputs[idx].ki.dwExtraInfo = ExtraInfo;
            ++idx;

            pInputs[idx] = new INPUT();
            pInputs[idx].type = INPUT_KEYBOARD;
            pInputs[idx].ki.wVk = 0;
            pInputs[idx].ki.wScan = ch2;
            pInputs[idx].ki.dwFlags = KEYEVENTF_UNICODE;
            pInputs[idx].ki.time = 0;
            pInputs[idx].ki.dwExtraInfo = ExtraInfo;
            ++idx;

            pInputs[idx] = new INPUT();
            pInputs[idx].type = INPUT_KEYBOARD;
            pInputs[idx].ki.wVk = 0;
            pInputs[idx].ki.wScan = ch;
            pInputs[idx].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
            pInputs[idx].ki.time = 0;
            pInputs[idx].ki.dwExtraInfo = ExtraInfo;
            ++idx;

            pInputs[idx] = new INPUT();
            pInputs[idx].type = INPUT_KEYBOARD;
            pInputs[idx].ki.wVk = 0;
            pInputs[idx].ki.wScan = ch2;
            pInputs[idx].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
            pInputs[idx].ki.time = 0;
            pInputs[idx].ki.dwExtraInfo = ExtraInfo;
            ++idx;
        }
    }

    uint nSent = SendInput((uint)pInputs.Length, pInputs, Marshal.SizeOf(typeof(INPUT)));
    if (nSent == 0)
    {
        Debug.WriteLine("SendInput error " + GetLastError().ToString());
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...