0

所以我有一个适用于游戏的应用程序。在程序的一个阶段,它单击文本字段,输入一些文本,然后单击其他一些内容。

现在的问题是,有时输入的第一个字符被阻止。也就是说,如果我在文本字段中输入"This is a test" ,则会出现以下内容"his is a test"。它总是第一个消失的字符。将代码更改为仅打印 1 个字符后,当您在 windows 输入字段中输入无效字符时,我会听到经典的 windows 'bing' 声音。然而,我的所有角色都不是无效的。

无论如何,当我改变程序点击文本字段的方式时,这一切都开始发生了。在它移动光标之前,然后模拟一次点击。现在它只是模拟点击而不接触光标。

我设法为所有文本框解决了这个问题,除了以下情况:我的代码的一部分多次重新点击同一个文本框(所以它点击它,输入文本,做其他事情,点击同一个文本框,输入文字...等)。问题是第一次输入文本时,第一个字符永远不会丢失,随后的条目很有可能丢失第一个字符(但有时它们不是(可能有 5% 的时间))。

在每次点击和输入文本之间,会有延迟,我已经做了很长时间的实验(这涉及在 TypeInfo 中发送的击键之间的延迟)。这似乎不是时间问题。

以下是所有相关代码:

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

在以下代码中,xPos 和 yPos 是相对于我希望单击的屏幕的坐标。同时删除SetForegroundWindowInternal(ctrl_handle)导致第一个字符始终不会出现在所有文本字段中。代码取自: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);
    }
  }
}

这是在 main 中调用上述代码的方式:

ClickTarget(hwnd, ....);
TypeInfo("This is a test");
Sleep(...); //Some sleep or delay here
4

0 回答 0