Keyboard input via SendInput (Win32 API) doesnt work, hardware one does - windows

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.

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));
}

Related

Unable to execute interrupt function

Using Mplab ide 5.10 and xc8 compiler for the pic18f4550 I am unable to get the code to get into the interrupt function the goal is to get J to count up in the background until something trigger it to output a value in the lcd. Currently only the lcd display the first message and using ICD 3 the value of J does not change and does not look like the program runs the interrupt function at all
#define _XTAL_FREQ 48000000
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include "lcd.h"
unsigned char j, output = 0, i, outchar;
char buffer[2] = " ";
char Message[ ] = "Hands Position ";
void interrupt timer0_isr();
void lcd_write_cmd(unsigned char cmd);
void lcd_write_data(unsigned char data);
void lcd_strobe(void); // Generate the E pulse
void lcd_init(void);
void interrupt timer0_ISR() // Timer0 Interrupt Service Routine (ISR)
{
if (INTCONbits.TMR0IF) // TMR0IF:- Timer0 Overflow Interrupt Flag Bit
{
TMR0H = 0x48; // Timer0 start value = 0x48E5 for 1 second
TMR0L = 0xE5;
PORTCbits.RC1 = !PORTCbits.RC1; /* external timing check - toggle every 1ms */
if (j <= 4) { //limit up to 7
j++; // Increase count by 1
PORTB = j; // Output to Demultiplexer
} else {
j = 0; // Reset count aftwr it hit 7
PORTB = j; // Output to Demultiplexer
}
INTCONbits.TMR0IF = 0; // Reset TMR0IF at interrupt end
}
}
void main(void) // Main Function
{
ADCON1 = 0x0F;
CMCON = 0x07;
RCONbits.IPEN = 1; // Bit7 Interrupt Priority Enable Bit
INTCONbits.GIEH = 1; // Bit7 Global Interrupt Enable bit
INTCONbits.GIEL = 0; /* turn on low & high interrupts */
T0CONbits.TMR0ON = 1; // Turn on timer
T0CON = 0b00000111; // bit7:0 Stop Timer0
// bit6:0 Timer0 as 16 bit timer
// bit5:0 Clock source is internal
// bit4:0 Increment on lo to hi transition on TOCKI pin
// bit3:0 Prescaler output is assigned to Timer0
// bit2-bit0:111 1:256 prescaler
INTCON2 = 0b10000100; // bit7 :PORTB Pull-Up Enable bit
// 1 All PORTB pull-ups are disabled
// bit2 :TMR0 Overflow Int Priority Bit
// 1 High Priority
TMR0H = 0x48; // Initialising TMR0H
TMR0L = 0xE5; // Initialising TMR0L for 1 second interrupt
INTCONbits.TMR0IE = 1; // bit5 TMR0 Overflow Int Enable bit
INTCONbits.TMR0IF = 0; // bit2 TMR0 Overflow Int Flag bit
// 0 TMR0 register did not overflow
TRISC = 0; /* all outputs */
TRISAbits.TRISA5 = 1; // RA5 is the check for signal from input Multiplexer.
TRISAbits.TRISA0 = 0; // RA0, RA1 & RA2 output to arduino
TRISAbits.TRISA1 = 0;
TRISAbits.TRISA2 = 0;
TRISD = 0x00; // PortD connects to Demultiplexer
TRISB = 0;
lcd_init(); // LCD init
lcd_write_cmd(0x80); // Cursor set at line 1 positon 1
for (i = 0; i < 16; i++) {
outchar = Message[i]; // Store Message in outchar
lcd_write_data(outchar); // Display Message
}
__delay_ms(100);
PORTD = 0x00; // Clear PortD
PORTB = 0;
j = 0; // Start count from 0
while (1) // Main Process
{
if (PORTAbits.RA5 == 1) { // If RA3 detect a signal
switch (j) { // Switch case to determine hand position & output to RA0, RA1 & RA2 to transmit to arduino
case(0):
output = 10;
PORTAbits.RA0 = 0;
PORTAbits.RA1 = 0;
PORTAbits.RA2 = 0;
break;
case(1):
output = 20;
PORTAbits.RA0 = 1;
PORTAbits.RA1 = 0;
PORTAbits.RA2 = 0;
break;
case(2):
output = 30;
PORTAbits.RA0 = 0;
PORTAbits.RA1 = 1;
PORTAbits.RA2 = 0;
break;
case(3):
output = 40;
PORTAbits.RA0 = 1;
PORTAbits.RA1 = 1;
PORTAbits.RA2 = 0;
break;
case(4):
output = 50;
PORTAbits.RA0 = 0;
PORTAbits.RA1 = 0;
PORTAbits.RA2 = 1;
break;
}
lcd_write_cmd(0xC0); // Cursor set at line 2 positon 1
sprintf(buffer, "%d", output); // Convert numbers to character
for (i = 0; i < 2; i++)
lcd_write_data(buffer[i]); // Display Hand Position
}
}
}

How activate cmd.exe window's "Scroll mode" via a Win-32 API function?

In the cmd.exe window there is a status called "Scroll mode". At this site there is a description of how to activate it; via keyboard: Alt-Space, then Edit, then scroLl; or via mouse: right-click on the title bar, then select Edit and Scroll.
My question is simple: what Win-32 API function is used to activate this status?
I reviewed the SetConsoleMode function, but it does not manage this mode (nor anyone of the rest of console functions). I searched the web looking for "cmd.exe scroll mode", but no one of the multiple results refers to this mode...
After some digging and tests, it "seems" that this behaviour is not exposed by any public API function. While someone find a non obvious way (or still better an obvious one), this workaround can be used
#define _WIN32_WINNT 0x0500
#include <windows.h>
#define SC_SCROLL 0xFFF3
int main(void) {
HWND hWnd;
// Search current console
if (!(
hWnd = GetConsoleWindow()
)) return 1;
// Set scroll mode
if (
SendMessage(
hWnd
, WM_SYSCOMMAND
, (WPARAM) SC_SCROLL
, (LPARAM) NULL
) != 0
) return 2;
// Done
return 0;
}
edited to adapt to comments
To disable the scroll, we only need a Enter, Esc or Ctrl-C key press
#define _WIN32_WINNT 0x0500
#include <windows.h>
#define KEYEVENTF_KEYDOWN 0
int main(void) {
INPUT ip;
// Keyboard input structure initialize
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0;
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
// Control key down
ip.ki.wVk = VK_CONTROL;
ip.ki.dwFlags = KEYEVENTF_KEYDOWN;
SendInput( 1, &ip, sizeof(INPUT) );
// C key down
ip.ki.wVk = 'C';
ip.ki.dwFlags = KEYEVENTF_KEYDOWN;
SendInput( 1, &ip, sizeof(INPUT) );
// C key up
ip.ki.wVk = 'C';
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput( 1, &ip, sizeof(INPUT) );
// Control key up
ip.ki.wVk = VK_CONTROL;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput( 1, &ip, sizeof(INPUT) );
// Done
return 0;
}
This code sends a Ctrl+C, but you can not indicate the target of the keypress. To avoid problems from focus loss it is probably better to send the Esc directly to the window
#define _WIN32_WINNT 0x0500
#include <windows.h>
int main(void) {
int KEY = VK_ESCAPE;
unsigned int lParamKeyDown = 0;
unsigned int lParamKeyUp = 0;
HWND hWnd;
// Search current console
if (!(
hWnd = GetConsoleWindow()
)) return 1;
// Configure lParam for key down event
lParamKeyDown |= 1;
lParamKeyDown |= 1 << 24;
lParamKeyDown |= MapVirtualKey(KEY, 0) << 16;
// Configure lParam for key up event
lParamKeyUp |= 1 << 30;
lParamKeyUp |= 1 << 31;
lParamKeyUp |= MapVirtualKey(KEY, 0) << 16;
// Send the key
SendMessage( hWnd, WM_KEYDOWN, KEY, lParamKeyDown );
SendMessage( hWnd, WM_KEYUP, KEY, lParamKeyUp );
// Done
return 0;
}

A program that "press" the x button N times

I wonder if it is possible to create a program, using notepad and command prompt in windows, that acts like my fingers on the keyboard. I think the best way to explain what I mean is with an example.
for(i = 0; i < N; i++)
{
"press key x"
"wait 3 seconds"
}
So basically I want a program that acts as if I was hitting the x button every third second, a total of N times. If the answer is yes, it is possible, could you recommend a site, pdf or similar from where I could learn how to write such a program.
I hope that I have made myself clear, if there is anything in my question that should be improved, please let me know.
AutoHotKey is a nice option.
Here's a sample script:
Loop, 3
{
send, xxxxx
Sleep, 3000
}
For Windows, you can look into keybd_event and SendInput APIs for keyboard input, and Sleep for waiting.
For example, with keybd_event
for(i = 0; i < N; i++)
{
keybd_event((BYTE)VkKeyScan(L'x'), MapVirtualKey(VkKeyScan(L'x'), MAPVK_VK_TO_VSC), 0, 0);
keybd_event((BYTE)VkKeyScan(L'x'), MapVirtualKey(VkKeyScan(L'x'), MAPVK_VK_TO_VSC), KEYEVENTF_KEYUP, 0);
Sleep(3000);
}
With SendInput:
INPUT inputs[1];
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wVk = VkKeyScan(L'x');
inputs[0].ki.wScan = MapVirtualKey(VkKeyScan(L'x'), MAPVK_VK_TO_VSC);
inputs[0].ki.time = 0;
inputs[0].ki.dwExtraInfo = 0;
for(i = 0; i < N; i++)
{
inputs[0].ki.dwFlags = 0;
SendInput(1, inputs, sizeof(INPUT));
input.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, inputs, sizeof(INPUT));
Sleep(3000);
}

Not getting ack after sending xmodem frame

I have a device connected to serial port and waiting for a file to be transmited using xmodem protocol.
I have tried constructing a message using in xmodem format and sending it, however I'm not getting the expected ACK for the transfer.
Bellow are the relevant bits of code:
Format of XMODEM message:
struct xmodem_packet
{
uint8_t start;
uint8_t block;
uint8_t block_neg;
uint8_t payload[128];
uint16_t crc;
};
Opening and configuring port:
HANDLE portHandler = CreateFile(L"COM9", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
DCB config = { 0 };
COMMTIMEOUTS timeout = { 0 };
// Configure
config.DCBlength = sizeof(config);
GetCommState(portHandler, &config);
config.BaudRate = CBR_115200;
config.ByteSize = 8;
config.StopBits = ONESTOPBIT;
config.Parity = NOPARITY;
SetCommState(portHandler, &config);
timeout.ReadIntervalTimeout = 50;
timeout.ReadTotalTimeoutConstant = 50;
timeout.ReadTotalTimeoutMultiplier = 50;
timeout.WriteTotalTimeoutConstant = 50;
timeout.WriteTotalTimeoutMultiplier = 10;
SetCommTimeouts(portHandler, &timeout);
Prepare module for XMODEM transfer:
DWORD toRead = 1;
DWORD wasWriten = 0;
DWORD wasRead = 0;
char responce = 0;
WriteFile(portHandler, "set load xmodem\n", 3+4+6+3, &wasWriten, NULL);
WriteFile(portHandler, "\n", 2, &wasWriten, NULL); // Doesn't work without this
Construct XMODEM frame
xmodem_frame frame;
frame.start = SOH;
frame.block = 0;
frame.block_neg = 0;
memcpy(frame.payload, "test_data", 128);
swap16(crc16(frame.payload, sizeof(frame.payload)));
Send frame and look for ACK:
WriteFile(portHandler, &frame, sizeof(frame), &wasWriten, NULL);
ReadFile(portHandler, &responce, toRead, &wasRead, NULL);
if (responce == 6)
std::cout << "ACK was recieved";
else
std::cout << "ACK wasn't recieved";
I was expecting to get an ACK, however "ACK wasn't recieved" is always printed.

SendInput() for keyboard - only uppercase

Quite funny. I just asked few minutes ago here SendInput() for keyboard - only lowercase, how to send letters upper case. The solution was to send shift before letter. But after turning shift on I can't turn it off...
I'm trying hard with KEYEVENTF_KEYUP flag like this:
INPUT Input = { 0 };
Input.type = INPUT_KEYBOARD;
Input.mi.dwFlags = KEYEVENTF_EXTENDEDKEY;
Input.ki.wVk = VK_LSHIFT;
SendInput( 1, &Input, sizeof( INPUT ) );
Input.type = INPUT_KEYBOARD;
Input.mi.dwFlags = KEYEVENTF_EXTENDEDKEY;
Input.ki.wVk = 'A';
SendInput( 1, &Input, sizeof( INPUT ) );
Input.type = INPUT_KEYBOARD;
Input.mi.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY;
Input.ki.wVk = VK_LSHIFT;
SendInput( 1, &Input, sizeof( INPUT ) );
Input.type = INPUT_KEYBOARD;
Input.mi.dwFlags = KEYEVENTF_EXTENDEDKEY;
Input.ki.wVk = 'A';
SendInput( 1, &Input, sizeof( INPUT ) );
but it seems to not work at all. It always sends AA.
Thanks.
The problem was with
Input.mi.dwFlags
it should be
Input.ki.dwFlags
thanks to rodrigo.
Another way is to use KEYEVENTF_SCANCODE flag. Then we have to scan our char using VkKeyScan() - http://msdn.microsoft.com/en-us/library/windows/desktop/ms646329(v=vs.85).aspx, which gives us virtual key code in low byte and state (shift, ctrl etc.) in high byte.
Due to using scan codes we have to map our virtual code to scan code by using MapVirtualKey() with MAPVK_VK_TO_VSC value, MSDN says:
uCode is a virtual-key code and is translated into a scan code. If it
is a virtual-key code that does not distinguish between left- and
right-hand keys, the left-hand scan code is returned. If there is no
translation, the function returns 0.
and then pass it to the wScan field of the Input.ki structure, because according to MSDN if we use scan codes it ignores wVk and uses wScan, MSDN says:
If specified, wScan identifies the key and wVk is ignored.
Therefore the code can look something like this:
INPUT Event = { 0 };
const SHORT key = VkKeyScan('a');
const UINT mappedKey = MapVirtualKey( LOBYTE( key ), 0 );
// Press shift key
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE;
Event.ki.wScan = MapVirtualKey( VK_LSHIFT, 0 );
SendInput( 1, &Event, sizeof( Event ) );
// upper case 'A' (press down)
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE;
Event.ki.wScan = mappedKey;
SendInput( 1, &Event, sizeof( Event ) );
// release 'A'
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
Event.ki.wScan = mappedKey;
SendInput( 1, &Event, sizeof( Event ) );
// Release shift key
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
Event.ki.wScan = MapVirtualKey( VK_LSHIFT, 0 );
SendInput( 1, &Event, sizeof( Event ) );
const SHORT key1 = VkKeyScan('a');
const UINT mappedKey1 = MapVirtualKey( LOBYTE( key1 ), 0 );
// lower case 'a' (press down)
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE;
Event.ki.wScan = mappedKey1;
SendInput( 1, &Event, sizeof( Event ) );
// release 'a'
Event.type = INPUT_KEYBOARD;
Event.ki.dwFlags = KEYEVENTF_SCANCODE;
Event.ki.wScan = mappedKey1;
SendInput( 1, &Event, sizeof( Event ) );
If I have said something wrong, please correct me.
Thanks for this! It was very helpful in debugging my code. Here is my final version for those who need it.
void Type(const char* text) {
INPUT ip[4] = {};
for (; *text; text++) {
int startInput = 1; // Assume 1 keyup and keydown pair.
int nInputs = 2;
if (HIBYTE(VkKeyScan(*text)) == 1) { // Set up SHIFT key and release
startInput = 0;
nInputs = 4;
ip[0].type = INPUT_KEYBOARD;
ip[0].ki.dwFlags = KEYEVENTF_SCANCODE;
ip[0].ki.wScan = MapVirtualKey(VK_LSHIFT, 0);
ip[3] = ip[0];
ip[3].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
}
ip[1].type = INPUT_KEYBOARD; // Set up key and release
ip[1].ki.wScan = MapVirtualKey(LOBYTE(VkKeyScan(*text)), 0);
ip[1].ki.dwFlags = KEYEVENTF_SCANCODE;
ip[2] = ip[1];
ip[2].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
SendInput(nInputs, &ip[startInput], sizeof(INPUT));
Sleep(100);
}
}

Resources