Use WM_COPYDATA to send data between processes
I wish to send text between processes. I have found lots of examples of this but none that I can get working. Here is what I have so far:
for the sending part:
COPYDATASTRUCT CDS;
CDS.dwData = 1;
CDS.cbData = 8;
CDS.lpData = NULL;
SendMessage(hwnd, WM_COPYDATA , (WPARAM)hwnd, (LPARAM) (LPVOID) &CDS);
the receiving part:
case WM_COPYDATA:
COPYDATASTRUCT* cds = (COPYDATASTRUCT*) lParam;
I dont know how to construct the COPYDATASTRUCT
, I have just put something in that seems to work. When debugging the WM_COPYDATA
case is executed, but again I dont know what to do with the COPYDATASTRUCT
.
I would like to send text between the two processes.
As you can probably tell I am just starting out, I am using GNU GCC Compiler in Code::Blocks, I am trying to avoid MFC and dependencies.
Solution 1:
For an example of how to use the message, see http://msdn.microsoft.com/en-us/library/ms649009(VS.85).aspx. You may also want to look at http://www.flounder.com/wm_copydata.htm.
The dwData
member is defined by you. Think of it like a data type enum that you get to define. It is whatever you want to use to identify that the data is a such-and-such string.
The cbData
member is the size in bytes of the data pointed to by lpData
. In your case, it will be the size of the string in bytes.
The lpData
member points to the data you want to copy.
So, to transfer a single string....
LPCTSTR lpszString = ...;
COPYDATASTRUCT cds;
cds.dwData = 1; // can be anything
cds.cbData = sizeof(TCHAR) * (_tcslen(lpszString) + 1);
cds.lpData = lpszString;
SendMessage(hwnd, WM_COPYDATA, (WPARAM)hwnd, (LPARAM)(LPVOID)&cds);
Then, to receive it....
COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)lParam;
if (pcds->dwData == 1)
{
LPCTSTR lpszString = (LPCTSTR)(pcds->lpData);
// do something with lpszString...
}
Solution 2:
Use the following code.
//Message Sender Class( for the demonstration purpose put the following code in //button click event)
CString strWindowTitle= _T("InterProcessCommunicationExample");
CString dataToSend =_T("Originate from Windows");
LRESULT copyDataResult;
CWnd *pOtherWnd=CWnd::FindWindowW(NULL, strWindowTitle);
if(pOtherWnd)
{
COPYDATASTRUCT cpd;
cpd.dwData=0;
cpd.cbData=dataToSend.GetLength();
//cpd.cbData=_tcslen(dataToSend)+1;
cpd.lpData=(void*)dataToSend.GetBuffer(cpd.cbData);
AfxMessageBox((LPCTSTR)cpd.lpData);
//cpd.lpData=(void*)((LPCTSTR)cpd.cbData);
copyDataResult=pOtherWnd->SendMessage(WM_COPYDATA,(WPARAM)AfxGetApp()->m_pMainWnd->GetSafeHwnd(),(LPARAM) &cpd);
dataToSend.ReleaseBuffer();
}
else
{
AfxMessageBox(L"Hwllo World");
}
//Message Receiver Process
BOOL CMessageReceiverClass::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
CString copiedData=(LPCTSTR)(pCopyDataStruct->lpData);
AfxMessageBox((LPCTSTR)(pCopyDataStruct->lpData));
// return CDialog::OnCopyData(pWnd, pCopyDataStruct);
return TRUE;
}
Solution 3:
That's not really an answer but useful hint when debugging SendMessage(WM_COPYDATA...
Well Microsoft Spy++ might really come in handy. You may find it here:
c:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\spyxx_amd64.exe
c:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\spyxx.exe
- Test that it's working on the target process(window) [ctrl+f,Windows].
- Second set message filter on WM_COPYDATA. ... and
- 'View\Always on top' is also really handy.
Happy C++'ing - especially in C# that API can be real 'fun'. ;)