So, I have an application that works with the game. At one stage of the program, he clicks on a text field, enters some text, then clicks some other material.
Now the problem is this, sometimes the first character typed is locked. That is, if I type "This is a test" in the text box, "his test" appears. Its always the first character that disappears. After changing the code to print only 1 character, I hear the sound of the classic βbingβ sound that you hear when you enter invalid characters in the Windows input field. However, none of my characters are valid.
In any case, it all started when I changed the way my program clicks on text fields. Before he moves the cursor, then simulate a click. Now it simply simulates a click without touching the cursor.
I managed to fix this problem for all text fields, with the exception of the following scenario: one part of my code redraws several times in the same text field (so that it clicks on it, enters text, does other things, clicks on the same text box, enters text ... etc.). The problem is the first text input, the first character is never skipped, subsequent entries have a really high probability of the absence of the first character (but sometimes they are not (maybe in 5% of cases)).
There are delays between each mouse click and text input, and I experimented for a very long time (this is due to the delays between keystrokes that were sent to TypeInfo). This does not seem to be a problem of time.
Here is all the 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 the following code, xPos and yPos are the coordinates relative to the screen I want to click. Also removing SetForegroundWindowInternal (ctrl_handle) , as a result of which the first character is ALWAYS not displayed for all text fields. Code 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); } } }
Here's how this code is called basically:
ClickTarget(hwnd, ....); TypeInfo("This is a test"); Sleep(...); //Some sleep or delay here