だから私はゲームで動作するアプリケーションを持っています。プログラムのある段階で、テキスト フィールドをクリックし、テキストを入力してから、別のものをクリックします。
問題はこれです。最初に入力した文字がブロックされることがあります。つまり、テキスト フィールドに「This is a test」と入力すると、「his is a test」と表示されます。消えるのは常に最初の文字です。1 文字のみを出力するようにコードを変更すると、Windows の入力フィールドに無効な文字を入力したときに聞こえる従来の Windows の「ビング」サウンドが聞こえます。ただし、私の文字はどれも無効ではありません。
とにかく、これはすべて、プログラムがテキスト フィールドをクリックする方法を変更したときに起こり始めました。カーソルを移動する前に、クリックをシミュレートします。現在は、カーソルに触れずにクリックをシミュレートするだけです。
次のシナリオを除いて、すべてのテキストボックスでこの問題を修正することができました:コードの一部が同じテキストボックスを複数回再クリックします(そのため、それをクリックし、テキストを入力し、他のことを行い、同じテキストボックスをクリックし、入力しますテキスト...など)。問題は、テキストが初めて入力され、最初の文字が欠落することはなく、後続のエントリでは最初の文字が欠落する可能性が非常に高いことです (ただし、そうでない場合もあります (おそらく 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);
}
}
}
これは、上記のコードがメインで呼び出される方法です。
ClickTarget(hwnd, ....);
TypeInfo("This is a test");
Sleep(...); //Some sleep or delay here