Click here to Skip to main content
15,867,453 members
Articles / Desktop Programming / MFC
Article

Sending a message to the Main Frame Window of Another Application, given only the Process Handle

Rate me:
Please Sign up or sign in to vote.
3.62/5 (12 votes)
8 Dec 1999 219.5K   1   73   28
Explains how to send a message between windows when you only have the Process handle

In order to send a message to another process, it is necessary to know the handle of the receiving window. However, if that process is created using CreateProcess or opened using OpenProcess, only the handles of the process and of it's main thread are known.

It is normally possible to find the window, if the title is known, simply by enumerating all windows and searching for the right window. When the name is unknown however, it is a little more complex to get its handle.

In order to find that handle it is, however, possible to scan all top-level windows and compare each window process Id with the Id received from the CreateProcess or the OpenProcess function. Please take note that not all Windows messages can be sent between processes. It is why use WM_COPYDATA is recommended.

Finally, remember that the message will need to be sent to the Main Frame. If it is intended for a child window ( a CView-derived class, for example ), it should be sent to the Main Frame, and then redirected in the target application.

In a private communication with a Senior Support Engineer at Microsoft, it has been noted that there is no guarantee that a process has any windows at all. It is also possible that a process has more than one window. Even if you get the correct window, it must know about and be able to handle the message being sent. A window always has a process, but a process can have zero to any number of windows, so there is no way to make a correlation between a process and a particular window.

I personally recommand a lot of care when using this method. However, this technique is working well in my projects, and I now use it for all inter-process communication. Furthermore, since I have included my code in several different projects, I have found only two problems with this code:

  1. The Process must have finished it's initialization. This can be verified with the following call made before the call to SendMessage :
    WaitForInputIdle( ProcessInfo.hProcess, INFINITE );
  2. The Process must be receiving its messages. In order to go around this problem, I place my calls to SendMessageToProcess in a while loop, which waits to the receiving application to send back a WM_COPYDATA message confirming reception.

To add a function that send a message to a Process, perfoms the steps listed bellow. NOTE: These steps assume that the name of the CWinApp-derived object is CMyWinApp.

  1. Add the Following members to the declaration of CMyWinApp in MYWINAPP.H:
    public:
    	void SendMessageToProcess(LPPROCESS_INFORMATION lpProcessInformation, 
    	                          UINT Msg, WPARAM wParam, LPARAM lParam);
    protected:
    	static BOOL CALLBACK EnumWindowCallBack(HWND hwnd, LPARAM lParam);
  2. Define the CMyWinApp::SendMessageToProcess function.
    void CMyWinApp:: SendMessageToProcess(LPPROCESS_INFORMATION lpProcessInformation, 
                                          UINT Msg, WPARAM wParam, LPARAM lParam)
    {
    	FINDWINDOWHANDLESTRUCT fwhs;
    	fwhs.ProcessInfo = lpProcessInformation;
    	fwhs.hWndFound  = NULL;
    
    	EnumWindows ( EnumWindowCallBack, (LPARAM)&fwhs ) ;
    
    	SendMessage ( fwhs.hWndFound, Msg, wParam, lParam );
    }
  3. Define the CMyWinApp::EnumWindowCallBack function.
    BOOL CALLBACK CMyWinApp::EnumWindowCallBack(HWND hwnd, LPARAM lParam) 
    { 
    	FINDWINDOWHANDLESTRUCT * pfwhs = (FINDWINDOWHANDLESTRUCT * )lParam; 
    	DWORD ProcessId; 
    	CString Title; 
    	GetWindowThreadProcessId ( hwnd, &ProcessId ); 
    
    	// note: In order to make sure we have the MainFrame, verify that the title 
    	// has Zero-Length. Under Windows 98, sometimes the Client Window ( which doesn't 
    	// have a title ) is enumerated before the MainFrame 
    
    	CWnd::FromHandle( hwnd )->GetWindowText(Title);
    	if ( ProcessId  == pfwhs->ProcessInfo->dwProcessId && Title.GetLength() != 0) 
    	{ 
    		pfwhs->hWndFound = hwnd; 
    		return false; 
    	} 
    	else 
    	{ 
    		// Keep enumerating 
    		return true; 
    	} 
    }

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralIf you have the code of both projects Pin
Martin-Pierre Frenette17-Oct-01 9:25
Martin-Pierre Frenette17-Oct-01 9:25 
QuestionFINDWINDOWHANDLESTRUCT ? Pin
18-Jan-01 0:07
suss18-Jan-01 0:07 
AnswerRe: FINDWINDOWHANDLESTRUCT ? Pin
7-May-01 1:14
suss7-May-01 1:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.