Using SendMessage to enter text into an edit contr

2019-01-19 07:35发布

问题:

I want to set up text in edit box programatically in other program, which is a game app and using directX, but running in window mode. I'm doing this:

HWND hWnd = FindWindow(NULL,"Game");
HWND edit = FindWindowEx(hWnd, NULL, "Edit", NULL);

SendMessage(edit, WM_CHAR, (TCHAR) 'H', 0);
SendMessage(edit, WM_CHAR, (TCHAR) 'E', 0);
SendMessage(edit, WM_CHAR, (TCHAR) 'L', 0);
SendMessage(edit, WM_CHAR, (TCHAR) 'L', 0);
SendMessage(edit, WM_CHAR, (TCHAR) 'O', 0);

this not working for me.... but some how once worked. I think I misunderstood something, maybe it must focus on edit control, then set cursor then paste text and then disable focus... I realy don't know much...please save my time and nervs, tell me how to make it working....

I tried this too, and not working:

SendMessage(hwnd, WM_SETTEXT, NULL, (LPARAM)"text");

hwnd is correct, but text is not updated... it send to correct handle, but not updated.... I think I need somehow to focus or update, once it updated successful, but I didnt realized what happened...so code worked once, but no more working... why one time it worked?

回答1:

Your question is money! Seriously. Let's say a little bird told me what's the game you are interested at (starts with an S). I've spent a few hours myself on this problem and I've had some success, so I'll share it with you.

There's a tool named Spy++ (from Microsoft) that let's you watch messages that are sent to a window/class. This is great for debugging because it allows you to monitor the messages that are sent to the EDIT box when a key is pressed on your keyboard, so you can find out the exact calls and parameters that are send to the game to simulate this operation.

Use spy++ to open the game process, and once you are in Game's login window you will see that spy++ reports several threads opened in this process, but only one thread is going to have 3 EDIT boxes. That is the thread you are interested at!

Also notice that neither of the EDIT boxes have caption, so the following code will never work:

HWND edit = FindWindowEx(hWnd, NULL, "Edit", NULL);

and by the way, always make sure that FindWindowEx() returns something valid, else how would you know that it succeeded finding the edit box?

What you should do instead is:

HWND edit = FindWindowEx(hWnd, NULL, "", NULL);
if (!edit)
{
    // report error
}

And this will find the first EDIT box. This box corresponds to the username box. The game uses 3 PostMessage() calls to simulate a key press, and not SendMessage() as you were trying:

// "..." means you need to find out the other parameters
PostMessage(edit, WM_KEYDOWN, ...); 
PostMessage(edit, WM_CHAR, ...); 
PostMessage(edit, WM_KEYUP, ...); 

Spy++ will reveal what the other parameters are, don't worry. You will probably spend some time figuring out how the last parameter of the call is built (because it's a mask).

I haven't been able to send keys to the game if it was minimized or without focus. You will have to figure this one out. For testing purposes, use can use SetForegroundWindow(window_hwnd); and some more stuff to focus the window.



回答2:

Look for the source code to Autoit. Autoit is able to send keys/mouse to just about anything. When newer versions of Kaspersky Anti Virus are installed, it messes with SendMessage|SendInput type things between processes.

Edit: For the folks who point out that Autoit is a huge lump of code to dig through to accomplish this task:

Autoit is able to send input to background apps that do not want to see injected input. It is not a trivial task easily done. There are games out there that do not want to see any scripted input of any form and they go out of their way to prevent it. Also, there are AV solutions in the wild that block inter-process input injection. Autoit somehow works around the blocks in a lot of cases.