0

I have a task where I need to put some mouse clicks on web form displayed in browser, and also do some keyboard input, as fill the text box with numbers or make sequence of pressing down arrows in order to get choice in combo box.

Window handlers I have, coordinates where click too, it works fine for me (very simple function):

 extern "C" __declspec(dllexport) void __stdcall PutSingleClick(unsigned hwnd, int x, int y) { SendMessage(((HWND) hwnd), WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y)); SendMessage(((HWND) hwnd), WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(x, y)); } 

My problem appears while I try to send keyboard input, as for example by calling:

extern "C" __declspec(dllexport) void __stdcall PutKeystrokeDown(int times) { INPUT ip; ip.type = INPUT_KEYBOARD; ip.ki.time = 0; ip.ki.wVk = 0; ip.ki.dwExtraInfo = 0; ip.ki.wScan = VK_DOWN; for(int i = 0; i < times; i++) { ip.ki.dwFlags = KEYEVENTF_SCANCODE; SendInput(1, &ip, sizeof(INPUT)); ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP; SendInput(1, &ip, sizeof(INPUT)); } ip.ki.dwFlags = KEYEVENTF_SCANCODE; ip.ki.wScan = VK_RETURN; SendInput(1, &ip, sizeof(INPUT)); ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP; SendInput(1, &ip, sizeof(INPUT)); } 

After calling this function nothing done, only in input buffer remains strange character (" ´ " [akcent, dead character] in my case).

While I try to catch what happens by Spy++, mouse events (clicks) are spied correctly (when generated both manually and by program), but keyboard ones not - either program or manual.

While I try utility On screen keyboard (common part of Windows), it works as good as hardware keyboard (numbers was inputed, chosen value are changed....), but no messages is generated.

Any idea how emulate hardware keystrokes and put sequence where I need?

Thanks a lot.

1
  • You are doing it wrong. Use UI Automation. Commented Aug 21, 2015 at 21:58

1 Answer 1

5

VK_DOWN and VK_RETURN are virtual keys, not scan codes. As such, when calling SendInput(), use the ip.ki.wVk field instead of the ip.ki.wScan field, and get rid of the KEYEVENTF_SCANCODE flag:

extern "C" __declspec(dllexport) void __stdcall PutKeystrokeDown(int times) { INPUT ip = {0}; ip.type = INPUT_KEYBOARD; ip.ki.wVk = VK_DOWN; for(int i = 0; i < times; i++) { ip.ki.dwFlags = 0; SendInput(1, &ip, sizeof(INPUT)); ip.ki.dwFlags = KEYEVENTF_KEYUP; SendInput(1, &ip, sizeof(INPUT)); } ip.ki.dwFlags = 0; ip.ki.wVk = VK_RETURN; SendInput(1, &ip, sizeof(INPUT)); ip.ki.dwFlags = KEYEVENTF_KEYUP; SendInput(1, &ip, sizeof(INPUT)); } 

However, you shouldn't call SendInput() to send multiple input events individually like this. It defeats the purpose of using SendInput() vs keybd_event(), with none of the benefits. Instead, you should send all of the events at one time in a single call to SendInput() by using an array, eg:

#include <vector> extern "C" __declspec(dllexport) void __stdcall PutKeystrokeDown(int times) { INPUT ip = {0}; ip.type = INPUT_KEYBOARD; ip.ki.wVk = VK_DOWN; std::vector<INPUT> ips; ips.reserve((times*2)+2); for(int i = 0; i < times; i++) { ip.ki.dwFlags = 0; ips.push_back(ip); ip.ki.dwFlags = KEYEVENTF_KEYUP; ips.push_back(ip); } ip.ki.dwFlags = 0; ip.ki.wVk = VK_RETURN; ips.push_back(ip); ip.ki.dwFlags = KEYEVENTF_KEYUP; ips.push_back(ip); SendInput(ips.size(), &ips[0], sizeof(INPUT)); } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.