Мне нужно смоделировать ввод пользователя в текстовое поле 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. Все еще жду ответа, как это должно быть сделано правильно.