So I have an application that works with a game. At one stage in the program, it clicks on a text field, enters some text then clicks some other stuff.
Now the issue is this, sometimes the first character typed is blocked. That is, if I am typing "This is a test" into the text field, the following appears "his is a test". Its always the first character that disappears. Upon changing the code to only print 1 character, I hear the classic windows 'bing' sound that you hear when you enter invalid characters into a windows input field. None of my characters are invalid however.
Anyway, this all started happening when I changed the way my program clicks on the text fields. Before it would move the cursor, then simulate a click. Now it simply simulates a click without touching the cursor.
I managed to fix this issue for all textboxes except in the following scenario: one part of my code reclicks on the same text box more than once (so it clicks on it, enters text, does other stuff, clicks on same text box, enters text...etc). The issue is the first time the text is entered, the first character is never missing, subsequent entries have a really high chance of having first character missing (but sometimes they aren't (5% of the time maybe)).
Between each click and the entering of text, there are delays and i've made these very long to experiment (this involves delays in between key strokes sent in TypeInfo). It does not appear to be a timing issue.
Here is all relevant code:
//Types string to stdout as physical keyboard strokes
void TypeInfo(const string info) {
breakableSleep(250);
INPUT ip;
ip.type = INPUT_KEYBOARD;
ip.ki.time = 0;
ip.ki.wVk = 0;
ip.ki.dwExtraInfo = 0;
//Loop through champion name and type it out
for (size_t i = 0; i < info.length(); ++i) {
ip.ki.dwFlags = KEYEVENTF_UNICODE;
ip.ki.wScan = info[i];
SendInput(1, &ip, sizeof(INPUT));
//Prepare a keyup event
ip.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
breakableSleep(250);
}
In following code, xPos and yPos are coords relative to screen I wish to click. Also removing SetForegroundWindowInternal(ctrl_handle) causing the first character to ALWAYS not appear for all text fields. Code is taken from: http://www.cplusplus.com/forum/windows/63948/
// Clicks target
void ClickTarget(HWND hwnd, int x, int y, int cols, int rows, int xoffset, int yoffset) {
//X and Y positions to click
int xPos = x + (cols / 2) + xoffset;
int yPos = y + (rows / 2) + yoffset;
POINT win_coords = { xPos, yPos };
POINT ctrl_coords = { xPos, yPos };
ScreenToClient(hwnd, &win_coords);
HWND ctrl_handle = hwnd;
ScreenToClient(ctrl_handle, &ctrl_coords);
//Before we click, set foreground window to object we want to click
SetForegroundWindowInternal(ctrl_handle);
LPARAM lParam = MAKELPARAM(ctrl_coords.x, ctrl_coords.y);
SendMessage(ctrl_handle, WM_LBUTTONDOWN, MK_LBUTTON, lParam);
SendMessage(ctrl_handle, WM_LBUTTONUP, 0, lParam);
}
//Use 'hack' to set foreground window of another process
void SetForegroundWindowInternal(HWND hWnd) {
if (!::IsWindow(hWnd)) return;
BYTE keyState[256] = { 0 };
//to unlock SetForegroundWindow we need to imitate Alt pressing
if (::GetKeyboardState((LPBYTE)&keyState))
{
if (!(keyState[VK_MENU] & 0x80))
{
::keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
}
}
::SetForegroundWindow(hWnd);
if (::GetKeyboardState((LPBYTE)&keyState))
{
if (!(keyState[VK_MENU] & 0x80))
{
::keybd_event(VK_MENU, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}
}
}
This is how the above code is called in main:
ClickTarget(hwnd, ....);
TypeInfo("This is a test");
Sleep(...); //Some sleep or delay here