Sending Windows Events from one app to another
-
Is it possible to send windows events from one application to another? To be more specific I want one application to make the other application believe that the user just clicked its "ok" or "cancel" button eventhough the mouse didn't move at all. The problem is that the two applications can't communicate with each other via any IPC etc. Can we make use of windows hooks here? If so how? Any ideas or comments would be greatly appreciated. Thanks Regards, Zahid
-
Is it possible to send windows events from one application to another? To be more specific I want one application to make the other application believe that the user just clicked its "ok" or "cancel" button eventhough the mouse didn't move at all. The problem is that the two applications can't communicate with each other via any IPC etc. Can we make use of windows hooks here? If so how? Any ideas or comments would be greatly appreciated. Thanks Regards, Zahid
Try using DDE or register a custom event with unique ID, then broadcast the message from one application to all the windows. only your other application will then process it. regards, Prakash. The World is getting smaller and so are the people.
-
Is it possible to send windows events from one application to another? To be more specific I want one application to make the other application believe that the user just clicked its "ok" or "cancel" button eventhough the mouse didn't move at all. The problem is that the two applications can't communicate with each other via any IPC etc. Can we make use of windows hooks here? If so how? Any ideas or comments would be greatly appreciated. Thanks Regards, Zahid
Generally, in a dialog-based application, the Ok button has an ID IDOK attached to it. CDialog class has a default handler for a click of this button. If the application in question has this handler implemented or overwritten, you can simulate the clicks of the default Ok and Cancel buttons by sending a WM_COMMAND message. The default identifiers, which MFC recognizes, are IDOK and IDCANCEL. See WM_COMMAND reference for details. The other method (MFC style) would be to access the dialog window through a HWDN and FromHandle method of CDialog. Then use UpdateData and PostQuitMessage member methods to terminate the dialog window, or alternatively call the default OnOK handler, which does the same things. -Antti Keskinen ---------------------------------------------- The definition of impossible is strictly dependant on what we think is possible.
-
Generally, in a dialog-based application, the Ok button has an ID IDOK attached to it. CDialog class has a default handler for a click of this button. If the application in question has this handler implemented or overwritten, you can simulate the clicks of the default Ok and Cancel buttons by sending a WM_COMMAND message. The default identifiers, which MFC recognizes, are IDOK and IDCANCEL. See WM_COMMAND reference for details. The other method (MFC style) would be to access the dialog window through a HWDN and FromHandle method of CDialog. Then use UpdateData and PostQuitMessage member methods to terminate the dialog window, or alternatively call the default OnOK handler, which does the same things. -Antti Keskinen ---------------------------------------------- The definition of impossible is strictly dependant on what we think is possible.
I liked your idea very much but the problem is that I want it work for other buttons on the Dialog as well that I don't know the ID for. Infact I don't have access to the source code of the target application whose buttons I want to press. So I can't write any handlers in there. Secondly I tried simulating a mouse click by doing mouse_event(MOUSEEVENTF_LEFTDOWN, 50, 50, 0, 0); mouse_event(MOUSEEVENTF_LEFTUP, 50, 50, 0, 0); which kind of works but sends messages to the self application and not the target one (since the x,y coordinates are relative to the current window). Back to the send WM_COMMAND message you talked about? What kind of message do I need to send inorder to simulate a mouse click. Since I don't know what the names of the Messages the target application handles in its code I probably can't send it Button_Click messages, so it has to be mouse_click and also how do I determine the 1st hWnd argument....right now I am doing a broadcast? Thanks. Regards, Zahid
-
I liked your idea very much but the problem is that I want it work for other buttons on the Dialog as well that I don't know the ID for. Infact I don't have access to the source code of the target application whose buttons I want to press. So I can't write any handlers in there. Secondly I tried simulating a mouse click by doing mouse_event(MOUSEEVENTF_LEFTDOWN, 50, 50, 0, 0); mouse_event(MOUSEEVENTF_LEFTUP, 50, 50, 0, 0); which kind of works but sends messages to the self application and not the target one (since the x,y coordinates are relative to the current window). Back to the send WM_COMMAND message you talked about? What kind of message do I need to send inorder to simulate a mouse click. Since I don't know what the names of the Messages the target application handles in its code I probably can't send it Button_Click messages, so it has to be mouse_click and also how do I determine the 1st hWnd argument....right now I am doing a broadcast? Thanks. Regards, Zahid
According to the Platform SDK Reference, when a button is clicked, it will send a BN_CLICKED notification to it's parent. This notification is packed to a WM_COMMAND message. In order to simulate a mouse click, you must send WM_LBUTTONDOWN or WM_RBUTTONDOWN, depending which mouse button you'd like to simulate. These messages carry with them position information in a POINT structure. The structure's coordinates are relative to the target window's upper-left corner. However, the mouse message must be sent to the button window, which then sends a BN_CLICKED message to it's parent. If you do not have access the source code at all, then one option is to create an enumeration function to enumerate through all the child windows of a dialog. Buttons are, in fact, standard windows with a class name of "Button", if they are default buttons. When doing the enumeration, you can compare the class name of the window and it's caption to determine the correct button. Say, a button which reads 'Click me', would have a class name of "Button" and a window text of "Click me". The enumeration could be implemented by using a while-loop in accordance with a GetNextWindow function call. Here's a half-pseudo code on how to implement it:
// We assume that you have a pointer to the CWnd class of the dialog (dlgPointer)
// We first get the top level child window
CWnd* pChildWnd = dlgPointer->GetTopWindow();// We now have the first child window, so let's start the enumeration loop
while (true)
{
TCHAR buffer[40];
CString strCaption = "";// Does this window match ?
::GetClassName(pChildWnd->m_hWnd, (LPTSTR) &buffer[0], 39)
pChildWnd->GetWindowText(strCaption);if ( strstr(buffer, "Button") && strCaption.Find("Click me") != -1 )
{
// We have a match, so do something
break;
}pChildWnd = pChildWnd->GetNextWindow();
// Did we run out of child windows ?
if ( pChildWnd == NULL )
break;}
After obtaining the CWnd pointer of the desired button window, use
CWnd::SendMessage
to post a WM_LBUTTONDOWN message to -
According to the Platform SDK Reference, when a button is clicked, it will send a BN_CLICKED notification to it's parent. This notification is packed to a WM_COMMAND message. In order to simulate a mouse click, you must send WM_LBUTTONDOWN or WM_RBUTTONDOWN, depending which mouse button you'd like to simulate. These messages carry with them position information in a POINT structure. The structure's coordinates are relative to the target window's upper-left corner. However, the mouse message must be sent to the button window, which then sends a BN_CLICKED message to it's parent. If you do not have access the source code at all, then one option is to create an enumeration function to enumerate through all the child windows of a dialog. Buttons are, in fact, standard windows with a class name of "Button", if they are default buttons. When doing the enumeration, you can compare the class name of the window and it's caption to determine the correct button. Say, a button which reads 'Click me', would have a class name of "Button" and a window text of "Click me". The enumeration could be implemented by using a while-loop in accordance with a GetNextWindow function call. Here's a half-pseudo code on how to implement it:
// We assume that you have a pointer to the CWnd class of the dialog (dlgPointer)
// We first get the top level child window
CWnd* pChildWnd = dlgPointer->GetTopWindow();// We now have the first child window, so let's start the enumeration loop
while (true)
{
TCHAR buffer[40];
CString strCaption = "";// Does this window match ?
::GetClassName(pChildWnd->m_hWnd, (LPTSTR) &buffer[0], 39)
pChildWnd->GetWindowText(strCaption);if ( strstr(buffer, "Button") && strCaption.Find("Click me") != -1 )
{
// We have a match, so do something
break;
}pChildWnd = pChildWnd->GetNextWindow();
// Did we run out of child windows ?
if ( pChildWnd == NULL )
break;}
After obtaining the CWnd pointer of the desired button window, use
CWnd::SendMessage
to post a WM_LBUTTONDOWN message toThanks for detailed reply Antti. It worked!! I had to implement the whole thing in WIN32 API since the SendMessage took only 3 parameters in MFC and not the window pointer. Also I used WM_LBUTTONDOWN followed by WM_LBUTTONUP to simulate a mouse click. Regards, Zahid