[RESOLVED] SendMessage for a game
Hi,
I'm part of a MMORPG gaming community. Some time ago I decided to write a very simple but useful tool for the players. Let me tell you how should it work ideally. As a generic MMORPG one of its parts is levelling up, namely just holding down right mouse button while your character kills monsters around it. You can even put something on your right mouse button and go outside, but unfortunately you will have to buy a new mouse quite often then. It would be very good to hide the game and let players browsing Internet while their character is levelling up. So, this is an abstract algorithm of my application actions:
1. User starts the procedure by hitting a "start" key
2. Hide the game window and send a right mouse button signal to it
3. User does whatever he wants, e.g. doing his homework on PC, but nothing should stop the right mouse button signal in the game window
4. User stops the procedure by hitting a "stop" key
5. Restore the game window and stop "holding" right mouse button in it
This tool is legit, it's not a bot, because the levelling is not the most important part of the game. Also, the game has an anti-cheat system.
So, I divided my task to few small functions and started to write them, but I have problems with it. I was trying to test a part which should send right mouse button signals if user presses a key. Assuming that hMU is the valid handle to the game window, this is my WndProc
Code:
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYDOWN:
{
if (wParam == VK_F11)
{
SendMessage(hMU, WM_RBUTTONDOWN, 0, 0);
}
else if (wParam == VK_F12)
{
SendMessage(hMU, WM_RBUTTONUP, 0, 0);
}
break;
}
default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return 0;
}
The problem is that nothing happens when I press F11 or F12. Neither PostMessage, SendMessage, nor SendInput worked for me (I used SendInput for testing only, it's definitely not what I need for my application). Why it is so, what should I do for reaching my goal? I'm using GNU C compiler.
Any help will be greatly appreciated. Thank you!
P.S. I'm sorry for my English which is far from good, and also I'm sorry for the lenght of my post, however I tried to make it smaller.
Re: SendMessage for a game
Quote:
Originally Posted by
PointToZero
The problem is that nothing happens when I press F11 or F12. Neither PostMessage, SendMessage, nor SendInput worked for me ...
How did you test it? Did you debug this code?
Re: SendMessage for a game
Quote:
Originally Posted by
VictorN
How did you test it? Did you debug this code?
Yes, I ran the game, then run this code. I pressed F11/F12 while my application window was on top, but nothing changed in the game.
Re: SendMessage for a game
"run" and "debug" are two absolutely different things!
Re: SendMessage for a game
Quote:
Originally Posted by
VictorN
"run" and "debug" are two absolutely different things!
I'm sorry, now I got what you mean. The handle to the game window is correct, Spy++ showed the same. This code works perfectly with notepad:
Code:
HWND hMU = FindWindow(NULL, "Untitled - Notepad");
hMU = FindWindowEx(hMU, NULL, "EDIT", NULL);
The game window has several child windows, they all are "EDIT"s. I tried to loop through them using EnumChildWindows, each time sending both WM_RBUTTONDOWN and WM_RBUTTONUP, but each time I was getting the click outside the game, on the line that divides desktop from taskbar.
Re: SendMessage for a game
Re: SendMessage for a game
I recently created a similar tool for a friend of mine. I used PostMessage() instead of SendMessage().
I wish I could give a good reference but I had to lose myself in google to find the information I was looking for and eventually just looked at enough examples.
I think you need to give your mouseclick some coordinates. Try something like this:
Code:
int mouseX = 200;
int mouseY = 100;
PostMessage(hMU, WM_LBUTTONDOWN, 0, MAKELPARAM(mouseX,mouseY))
Victor, I also tried to put this through a debugger without an LPARAM to see what would happen. I stepped through it until reaching the PostMessage call but had no idea what I was looking for....What sort of thing should you see that is out of the ordinary from the debugger?
Re: SendMessage for a game
Quote:
Originally Posted by
Austin.Soucy
I recently created a similar tool for a friend of mine. I used PostMessage() instead of SendMessage().
I wish I could give a good reference but I had to lose myself in google to find the information I was looking for and eventually just looked at enough examples.
I think you need to give your mouseclick some coordinates. Try something like this:
Code:
int mouseX = 200;
int mouseY = 100;
PostMessage(hMU, WM_LBUTTONDOWN, 0, MAKELPARAM(mouseX,mouseY))
Victor, I also tried to put this through a debugger without an LPARAM to see what would happen. I stepped through it until reaching the PostMessage call but had no idea what I was looking for....What sort of thing should you see that is out of the ordinary from the debugger?
Thanks, but unfortunately this didn't work either. I checked in Spy++ if the message reaches the window, and yes, it does.
Re: SendMessage for a game
Re: SendMessage for a game
Quote:
Originally Posted by
Marc G
This is how I modified my WndProc according to your advice:
Code:
if (wParam == VK_F11)
{
SetWindowPos(hMU, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
INPUT input;
memset(&input, 0, sizeof(INPUT));
input.type = INPUT_MOUSE;
input.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
SendInput(1, &input, sizeof(INPUT));
}
The code worked because of SetWindowPos, but I don't need the game window to be HWND_TOP all the time. When I added this line to the end of my if statement, it stopped to work:
Code:
SetWindowPos(hMU, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW);
Re: SendMessage for a game
Yes, sorry my mistake. The window should be focussed for SendInput.
Are you sure you are giving the correct coordinates to your postmessage mouse messages? Are you sure the coordinates you send are in client coordinates?
Are you sure you are posting them to the correct child window of the target window, if any child windows?
Re: SendMessage for a game
Quote:
Originally Posted by
Marc G
Yes, sorry my mistake. The window should be focussed for SendInput.
Are you sure you are giving the correct coordinates to your postmessage mouse messages? Are you sure the coordinates you send are in client coordinates?
Are you sure you are posting them to the correct child window of the target window, if any child windows?
Yes, I'm sure the coordinates are correct, I also tried ScreenToClient:
Code:
POINT pt;
pt.x = 100;
pt.y = 100;
ScreenToClient(hMU, &pt);
SendMessage(hMU, WM_RBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
SendMessage(hMU, WM_RBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
The window I'm trying to post the messages is the main game window. It has seven or eight child windows, and when I tried to call the above function for each of them, I got a popup menu like Edit controls have on my desktop.
Re: SendMessage for a game
Quote:
Originally Posted by
PointToZero
Yes, I'm sure the coordinates are correct, I also tried ScreenToClient:
Code:
POINT pt;
pt.x = 100;
pt.y = 100;
ScreenToClient(hMU, &pt);
SendMessage(hMU, WM_RBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
SendMessage(hMU, WM_RBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
The window I'm trying to post the messages is the main game window. It has seven or eight child windows, and when I tried to call the above function for each of them, I got a popup menu like Edit controls have on my desktop.
You are using WM_RBUTTONDOWN, don't you need WM_LBUTTONDOWN?
Try looping through the child windows and storing them in HWND hWnd[10]; Then use PostMessage() to send a WM_LBUTTONDOWN to each child window one at a time with coords like 100x100(something that will not extend outside the window you need it, you can always adjust later).
When you detect the click in the window you want it take note of the array index you are on. Change your code to focus on that index and then play with your X and Y to aim your shot.
1 Attachment(s)
Re: SendMessage for a game
Quote:
Originally Posted by
Austin.Soucy
You are using WM_RBUTTONDOWN, don't you need WM_LBUTTONDOWN?
Try looping through the child windows and storing them in HWND hWnd[10]; Then use PostMessage() to send a WM_LBUTTONDOWN to each child window one at a time with coords like 100x100(something that will not extend outside the window you need it, you can always adjust later).
When you detect the click in the window you want it take note of the array index you are on. Change your code to focus on that index and then play with your X and Y to aim your shot.
Yes, I need to send right mouse button click. So, I followed your advice and modified a little my code:
Code:
HWND handles[10];
int i;
BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) { return (BOOL)(handles[i++] = hwnd); }
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
...
case WM_KEYDOWN:
{
if (wParam == VK_F11)
{
EnumChildWindows(hMU, EnumChildProc, 0);
i = 0;
}
else if (wParam == VK_F12)
{
POINT pt;
pt.x = 100;
pt.y = 100;
ScreenToClient(hMU, &pt);
SendMessage(handles[i], WM_RBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
SendMessage(handles[i++], WM_RBUTTONUP, 0, MAKELPARAM(pt.x, pt.y));
}
else if (wParam == VK_F1)
{
char index[2];
sprintf(index, "%d", i);
MessageBox(NULL, index, NULL, 0);
}
break;
...
Then I run it and pressed F11 so it found all child windows of the game. Then I was pressing F12 for each of them, but each time I received a click outside the game. I've attached the screenshot of it. I was clicking around that place, but I couldn't call the same menu!
Re: SendMessage for a game
Quote:
Originally Posted by
PointToZero
ScreenToClient(hMU, &pt);
Try passing your child windows to this before the click.
Code:
ScreenToClient(handles[i], &pt);
You can also use ShowWindow() to maximize your window and then work with screen coords(probably not the best way, but it works).
EDIT: How do you find hMU?
if you are using this like in your previous post it might be a source for error.
Code:
HWND hMU = FindWindow(NULL, "Untitled - Notepad");
hMU = FindWindowEx(hMU, NULL, "EDIT", NULL);
you should only need
Code:
HWND hMU = FindWindow(NULL, "APP TITLE");
and then find the child windows normally with EnumChildWindow
Re: SendMessage for a game
Quote:
Originally Posted by
Austin.Soucy
Try passing your child windows to this before the click.
Code:
ScreenToClient(handles[i], &pt);
You can also use ShowWindow() to maximize your window and then work with screen coords(probably not the best way, but it works).
EDIT: How do you find hMU?
if you are using this like in your previous post it might be a source for error.
Code:
HWND hMU = FindWindow(NULL, "Untitled - Notepad");
hMU = FindWindowEx(hMU, NULL, "EDIT", NULL);
you should only need
Code:
HWND hMU = FindWindow(NULL, "APP TITLE");
and then find the child windows normally with EnumChildWindow
I'm sorry, I forgot to change the first parameter of ScreenToClient, as you mentioned. Now the same popup menu appears at 100:100 of Desktop window.
This is how I find hMU:
Code:
HWND hMU = FindWindow("MU", "Mu Online");
I used Spy++ and my code on the game window, and they both detected same handle value for the game. When I change class name to NULL, it works too. Could the anticheat prevent my attempts to click, probably with a global mouse hook?
Re: SendMessage for a game
Unfortunately I am stumped at this point...I tried :(
If you are using the correct HWND and passing correct client coords I see no reason that it should not work. Maybe if you post your full code we can defer to someone that has more knowledge than I do. Also, perhaps a screenshot of the game? Is this a full-screen game or windowed?
Re: SendMessage for a game
Quote:
Originally Posted by
Austin.Soucy
Unfortunately I am stumped at this point...I tried :(
If you are using the correct HWND and passing correct client coords I see no reason that it should not work. Maybe if you post your full code we can defer to someone that has more knowledge than I do. Also, perhaps a screenshot of the game? Is this a full-screen game or windowed?
Thank you for efforts! This is the full code of how I test Send/PostMessage. If you want to take a look at the whole project (I mean, everything except this PostMessage), I can post it too, because the code is compact.
Code:
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYDOWN:
{
HWND hMU = FindWindow("MU", "InsaniaMU");
if (wParam == VK_F11)
{
PostMessage(hMU, WM_RBUTTONDOWN, 0, MAKELPARAM(200, 200));
}
else if (wParam == VK_F12)
{
PostMessage(hMU, WM_RBUTTONUP, 0, MAKELPARAM(200, 200));
}
break;
}
default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(WNDCLASSEX);
wndclass.style = 0;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = NULL;
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)COLOR_3DSHADOW;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = "WINDOWCLASS";
wndclass.hIconSm = NULL;
RegisterClassEx(&wndclass);
CreateWindow("WINDOWCLASS", "123", WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 10, 10, 100, 100, NULL, NULL, hInstance, NULL);
MSG Msg;
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return 0;
}
The game can be full-screen or windowed, it depends on the setting. I was testing the code above with a windowed game. It said the game screenshot is too large, so there's the link to photobucket, hopefully it won't be treated as an advertisement: http://i1135.photobucket.com/albums/...ttozero/mu.jpg
Thanks!
Re: SendMessage for a game
So, yesterday I found the solution. Maybe it's ugly now, but that's only because I don't know yet what exactly each of my SendMessages do. I just used Spy++ on the game window and caught all the messages it received when I hovered the mouse over it and pressed and released the right mouse button. I tried to send the caught messages into the game window from my program, and finally got my program working.
Code:
void OnRMouseButtonDown(void)
{
WINDOWPOS wp = {hMU, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE};
SendMessage(hMU, WM_SETCURSOR, (WPARAM)hMU, MAKELPARAM(HTCLIENT, WM_MOUSEMOVE));
SendMessage(hMU, WM_MOUSEACTIVATE, (WPARAM)hMU, MAKELPARAM(HTCLIENT, WM_RBUTTONDOWN));
SendMessage(hMU, WM_WINDOWPOSCHANGING, 0, (LPARAM)&wp);
SendMessage(hMU, WM_NCPAINT, 1, 0);
SendMessage(hMU, WM_WINDOWPOSCHANGED, 0, (LPARAM)&wp);
SendMessage(hMU, WM_ACTIVATEAPP, 1, 0);
SendMessage(hMU, WM_NCACTIVATE, 1, 0);
SendMessage(hMU, WM_ACTIVATE, WA_CLICKACTIVE, 0);
SendMessage(hMU, WM_SETFOCUS, 0, 0);
SendMessage(hMU, WM_SETCURSOR, (WPARAM)hMU, MAKELPARAM(1, WM_RBUTTONDOWN));
PostMessage(hMU, WM_RBUTTONDOWN, 2, 0x1530279);
}
void OnRMouseButtonUp(void)
{
PostMessage(hMU, WM_RBUTTONUP, 0, 0x1530279);
SendMessage(hMU, WM_CAPTURECHANGED, 0, 0);
}
Therefore, if you have a task similar to what I had, use Spy++ and repeat all the messages you caught with it.
Thank you all!