First Character of SendInput blocked in applicatio

2019-08-30 02:53发布

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

0条回答
登录 后发表回答