20

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.

Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164
Charles Gargent
  • 1,797
  • 2
  • 13
  • 19

3 Answers3

24

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...
}
Tadmas
  • 6,238
  • 3
  • 39
  • 31
  • I know that second link (to flounder.com) uses MFC, which you're not using, but I included it merely to illustrate that you should consider passing more than just a simple string. – Tadmas Mar 15 '10 at 23:49
  • 1
    Thanks, I got it working. Although I had to change the first line to LPTSTR lpszString because I got this error: invalid conversion from `const void*' to `void*' – Charles Gargent Mar 16 '10 at 09:29
  • This link is very helpful: http://code.msdn.microsoft.com/windowsdesktop/CppSendWMCOPYDATA-f75bc681/ – pcunite Feb 09 '12 at 06:13
  • 1
    I might be late to the party, but can you explain why you are casting &cds to LPVOID? – Sossenbinder Jul 12 '16 at 11:47
  • 1
    @Sossenbinder That's fair - I guess it's not really necessary since `cds` would be on the stack. There are two reasons the cast is there: (1) It was there in the question. (2) The cast makes sure it's a far pointer, which would be important for 16-bit code: if `cds` was in the data segment instead of the stack segment, it could be a near pointer. The extra cast is mostly a relic of history now, I suppose. – Tadmas Jul 12 '16 at 14:45
3
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;
}
Dila Gurung
  • 1,726
  • 21
  • 26
  • 1
    This is the correct solution for the MFC applications. Otherwise, the target application doesn't respond to the "OnCopyData" callback function. – Bandula Dharmadasa May 21 '20 at 11:46
1

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
  1. Test that it's working on the target process(window) [ctrl+f,Windows].
  2. Second set message filter on WM_COPYDATA. ... and
  3. 'View\Always on top' is also really handy.

Happy C++'ing - especially in C# that API can be real 'fun'. ;)

Un Peu
  • 131
  • 3
  • 13