Имитация OnKeyDown, OnKeyUp, OnKeyPress с помощью PostMessage - PullRequest
0 голосов
/ 27 марта 2019

Мне нужно смоделировать ввод пользователя в текстовое поле WebBrowser (без обнаружения в качестве бота).Все соответствующие события JavaScript должны быть подняты.Если я отправляю только WM_CHAR, то нажатие клавиши вверх / вверх не вызывает события.Но когда я отправляю WM_KEYDOWN, WM_CHAR, WM_KEYUP, персонаж пишется 3 раза.Если я отправляю только WM_KEYDOWN, то событие нажатия клавиши не вызывается (но событие нажатия клавиши вызывается даже без WM_CHAR).Если я отправляю только WM_KEYUP, то события клавиш вверх / вниз не возникают.Также отправка символов кириллицы без использования WM_CHAR при активной английской клавиатуре не работает.Итак, как сделать это правильно, чтобы написать символ только один раз и вызвать все эти события?

    [DllImport("User32.dll", CharSet = CharSet.Unicode)]
    static extern int PostMessage(IntPtr hWnd, int uMsg, IntPtr wParam, IntPtr lParam);

    [DllImport("User32.dll", CharSet = CharSet.Unicode)]
    static extern int PostMessage(IntPtr hWnd, int uMsg, int wParam, IntPtr lParam);

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

    public const Int32 WM_CHAR = 0x0102;
    public const Int32 WM_KEYDOWN = 0x0100;
    public const Int32 WM_KEYUP = 0x0101;

void SendCharacter(char character, IntPtr hWnd)
{
    var key = new IntPtr(character);
    var scanKey = new IntPtr((int)ConvertCharToVirtualKey(character));
    PostMessage(hWnd, WM_KEYDOWN, scanKey , IntPtr.Zero);
    PostMessage(hWnd, WM_CHAR, key, IntPtr.Zero);
    PostMessage(hWnd, WM_KEYUP, scanKey , IntPtr.Zero);
}

public static Keys ConvertCharToVirtualKey(char ch) {
    short vkey = VkKeyScan(ch);
    Keys retval = (Keys)(vkey & 0xff);
    int modifiers = vkey >> 8;
    if ((modifiers & 1) != 0) retval |= Keys.Shift;
    if ((modifiers & 2) != 0) retval |= Keys.Control;
    if ((modifiers & 4) != 0) retval |= Keys.Alt;
    return retval;
}

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern short VkKeyScan(char ch);

Похоже, что нормальная типизация заставляет lParam иметь значения, такие как 1966081 для WM_KEYDOWN и WM_CHAR и 3223191553для WM_KEYUP но при каждом запуске приложения они немного отличаются.При вставке этих значений один из 3 повторяющихся символов исчезал.


Обновление

Рабочая версия:

void SendCharacter(char character, IntPtr hWnd)
{
    //hWnd = textBox1.Handle;

    var k = (uint)(int) ConvertCharToVirtualKey(character);

    uint repeatCount = 0;
    uint scanCode = k;
    uint extended = 0;
    uint context = 0;
    uint previousState = 0;
    uint transition = 1;

    uint lParamDown = repeatCount
        | (scanCode << 16)
        | (extended << 24)
        | (context << 29)
        | (previousState << 30)
        | (transition << 31);

    previousState = 1;

    uint lParamUp = repeatCount
        | (scanCode << 16)
        | (extended << 24)
        | (context << 29)
        | (previousState << 30)
        | (transition << 31);

    var ipKey = (IntPtr)(int)k;
    var ipLParamDown = unchecked((IntPtr)(int)lParamDown);
    var ipLParamUp = unchecked((IntPtr) (int) lParamUp);

    PostMessage(hWnd, WM_KEYDOWN, ipKey, ipLParamDown);
    PostMessage(hWnd, WM_CHAR, new IntPtr(character), IntPtr.Zero);
    PostMessage(hWnd, WM_KEYUP, ipKey, ipLParamUp);
}


public static Keys ConvertCharToVirtualKey(char ch) {
    short vkey = VkKeyScan(ch);
    Keys retval = (Keys)(vkey & 0xff);
    int modifiers = vkey >> 8;
    if ((modifiers & 1) != 0) retval |= Keys.Shift;
    if ((modifiers & 2) != 0) retval |= Keys.Control;
    if ((modifiers & 4) != 0) retval |= Keys.Alt;
    return retval;
}

Бит transition должен быть 0 дляWM_KEYDOWN в соответствии с MSDN, но это был повторяющийся символ несколько раз, если я не установил его на 1. Все еще жду ответа, как это должно быть сделано правильно.

...