!
does not exist in the virtual key codes of Win32. Is there a way I could use keybd_event()
, or anything else, to simulate a keyboard entry leading to !
?
It's my first time making a bot to spam in a Discord casino (private).
!
does not exist in the virtual key codes of Win32. Is there a way I could use keybd_event()
, or anything else, to simulate a keyboard entry leading to !
?
It's my first time making a bot to spam in a Discord casino (private).
Since keybd_event()
has been superseded by SendInput()
, I suggest that you use that instead.
With SendInput()
, you send a number of INPUT
structures. You can send mouse input, keyboard input, and hardware input. I'll show how to send keyboard input.
Keyboard input can be sent using scan codes - or Unicode characters. I'll use Unicode. Finding the Unicode character for something you don't know is usually as easy as: https://www.google.com/search?q=unicode+exclamation+mark and you'll get the answer, like U+0021 for !
, which can be encoded as \u0021
in Unicode strings in C++.
I'll start by inheriting the INPUT
structure to make it simpler to instantiate it:
#include <Windows.h>
#include <iostream>
#include <stdexcept>
#include <vector>
struct mINPUT : INPUT {
mINPUT() : INPUT{} {} // make sure it's clean if default constructed.
// this constructor prepares the structure for different kinds of input:
mINPUT(DWORD type) : INPUT{type} {
switch (type) {
case INPUT_MOUSE:
// use mi.
break;
case INPUT_KEYBOARD:
// use ki.
ki.dwFlags = KEYEVENTF_UNICODE; // we'll use unicode
break;
case INPUT_HARDWARE:
// use hi.
break;
}
}
};
// helper functions to create `mINPUT` structures from Unicode values:
mINPUT key_down(char16_t unicode_char) {
mINPUT rv{INPUT_KEYBOARD};
rv.ki.wScan = unicode_char;
return rv;
}
mINPUT key_up(char16_t unicode_char) {
mINPUT rv{INPUT_KEYBOARD};
rv.ki.dwFlags |= KEYEVENTF_KEYUP;
rv.ki.wScan = unicode_char;
return rv;
}
// Helper functions to check UTF16 surrogate ranges
bool is_surrogate(char16_t code_unit) {
return code_unit >= 0xD800 && code_unit <= 0xDFFF;
}
bool is_high_surrogate(char16_t code_unit) {
return code_unit >= 0xD800 && code_unit <= 0xDBFF;
}
bool is_low_surrogate(char16_t code_unit) {
return code_unit >= 0xDC00 && code_unit <= 0xDFFF;
}
// A helper structure to prepare a sequence of events
struct Inputs {
UINT cInputs() const { return static_cast<UINT>(inputs.size()); }
LPINPUT pInputs() { return inputs.data(); }
int cbSize() const { return static_cast<int>(sizeof(INPUT)); }
// A helper function to add down+up events for a string:
void add_string(const char16_t* str) {
while (*str) {
char16_t ch = *str++;
if (is_surrogate(ch)) {
char16_t first = ch;
char16_t second = *str++;
if (!is_high_surrogate(first) || !is_low_surrogate(second))
throw std::runtime_error("Broken UTF16 surrogate pair");
inputs.push_back(key_down(first));
inputs.push_back(key_down(second));
inputs.push_back(key_up(first));
inputs.push_back(key_up(second));
} else {
inputs.push_back(key_down(ch));
inputs.push_back(key_up(ch));
}
}
}
UINT Send() { // Send the stored events
return SendInput(cInputs(), pInputs(), cbSize());
}
std::vector<mINPUT> inputs;
};
int main() {
std::cout << "Switch to Notepad or some other app taking input" << std::endl;
Sleep(5000); // in 5 seconds, you should see the input
Inputs x; // Create an event container
// Add events for a full string including exclamation marks in two
// different formats:
x.add_string(u"Hello world!!! or \u0021\u0021\u0021 ");
x.add_string(u"This is something with surrogate pairs: ");
// Send the events:
UINT rv = x.Send();
std::cout << "Sent " << rv << " events\n";
}
If everything goes according to plan, it will send 134
events and you should see the exclamation mark and other characters appear in any app you have active if it's capable of receiving keyboard input and displaying the result, like Notepad or Visual Studio - so be careful where you place the cursor.