Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame

IPC Demo Image

Recently I have seen numerous postings on the message board asking about options for inter-process communication.  One of the many techniques available is the standard SendMessage function with the WM_COPYDATA message.  There seems to be very few samples available regarding this so I decided to write one.  Once I got into this, I found two other samples : Paul DiLascia's TRACEWIN project in the MSJ and Spy in the SDK samples.  At least, now Codeguru.com will have its own.:)

To use WM_COPYDATA, SendMessage is called as follows :

SendMessage( hwReceiver, WM_COPYDATA, (WPARAM) hwSender, (LPARAM) pData ); 

The actual data passed in the LPARAM argument (pData) is a pointer to a data structure that is defined as follows :

typedef struct {
    DWORD dwData;  // a 32-bit data item passed to the receiver
    DWORD cbData;  // the size in bytes of the data pointed to be lpData
    PVOID lpData;  // pointer to the data passed to the receiver or null } COPYDATASTRUCT; 

Note that SendMessage must be used, PostMessage can not be.  Also, as stated in the docs about WM_COPYDATA, the receiving process should consider the data received to be read-only and valid only during the processing of the message.

My little demo project illustrated above takes data from one dialog-based app and sends it to a second one.  It just so happens that they are two instances of the same app but this was done to simplify downloading and building of the project. 

Following is the code used to send the message.  In this case, the data consists of a text string, the line to display it on, and the foreground and background colors to display it in.  The data is loaded into my custom message structure (MsgCmd) and then loaded into the COPYDATASTRUCT.

int CIpcSendDlg::SendIpcMsg( int cmd, int line, COLORREF fgclr,
                             COLORREF bgclr, ccp txt ) {
    MsgCmd msg;

    msg.command = cmd;
    msg.line = line;
    msg.fgcolor = fgclr;
    msg.bgcolor = bgclr;
    strcpy( msg.text, txt, MSGCMD_TEXTSIZE );


    cds.dwData = 0;
    cds.cbData = sizeof( msg );
    cds.lpData = &msg;

   return ::SendMessage( m_hWndRecv, WM_COPYDATA,
                         (WPARAM) m_hWnd, (LPARAM) &cds ); }

Following is part of the code that handles the message in the receiving dialog.  There are three commands it can receive : display a text line, terminate, and a timing command.

BOOL CIpcRecvDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pData) {
    // if size doesn't match we don't know what this is

    if( pData->cbData == sizeof( MsgCmd ) )
        MsgCmd msg;
        memcpy( &msg, pData->lpData, sizeof( MsgCmd ) );

        // process the message

        return TRUE;
    return CDialog::OnCopyData(pWnd, pData); }

While WM_COPYDATA can be used to used for IPC, as illustrated by this demo, it is not without some caveats.  Among them are : a handle to the receiving window must be acquired and SendMessage must be used which means that the message must be processed by the receiver before the sending process continues.

There is a system menu option that allows one to test the performance of the WM_COPYDATA message transmission.  On my 300 MHz PII 10000 messages were sent in 0.377 seconds on NT v4.0 SP3.  What is more interesting is that on 98 the time was 2.104 seconds for 10000 messages.  I guess this illustrates that NT has a much faster context switch than 98.  I would judge the performance to be adequate for many applications but not necessarily all, especially on 98.

Points of note concerning this demo are : starting up the app causes it to start another copy of itself.  The first app becomes the sender and the second becomes the receiver.  Mutexes are used to determine which app is which and to prevent additional instances.  Exiting the sender causes it to pass a terminate message to the receiver so both will shut down at the 'same' time.  Since I don't much like the registry, I have used my own little profile handling class (CProfile) to save the positions of the windows when they terminate and to restore them when they initialize.  The profile (IpcDemo.ini) is stored in the system's %WINDIR%.  Feel free to delete it if you want.  A batch file called _makeme.bat is included so that downloaders can quickly build the app from the command line.  The batch file requires an 'r' argument for a release build and a 'd' argument for a debug build.  The executable will be placed in objrel or objdbg respectively.  I have placed the following comment in the code modules '//@tabs=4' in the naive hope that intelligent code editors will recognize this and adjust their tabstops accordingly.  I hope to develop one (using code from this site, of course :) that will.

In the spirit of code reuse, Norm Alomond's CLabel class is used to display text in the receiver dialog, James R. Twine's CColorPickerCB class was used to select colors in the sender dialog, and my own CElapsed high resolution timer class was used for timing.  All of these are described in articles on this site.

This code was developed using Visual C++ v5.0 on NT v4.0 SP3. and it has been tested on 98.

Download demo project - 24 KB


  • Great! This was just what I was looking for. :)

    Posted by Legacy on 03/12/2003 08:00am

    Originally posted by: Keri

    Easy to understand and well-presented

  • It will work if your application is launched from the same location

    Posted by Legacy on 10/03/2002 07:00am

    Originally posted by: AlexeyK

    Looks good... But I would like to note that it will work correct if your application is launched from the same location. If I have two copies of one application and they are is in the different folders, then it will not work correct. For example, the application C:\SomeFolder_1\program.exe and C:\SomeFolder_2\program.exe. Every of them will have its own counter, cause the executable images are different.

    • So What?

      Posted by Rick on 11/27/2014 04:45pm

      This article was a demonstration of using the WM_COPYDATA message. It was not a demonstration of locating other applications. Please note the caveat mentioned : "a handle to the receiving window must be acquired ..." Also, this application was specifically written to send a message to another instance of ITSELF. In other words, your comment is completely irrelevant for this sample as it was presented.

    • Cheers!

      Posted by chilly32 on 05/16/2005 02:50pm

      That was a cumbersome implementation indeed. You can find a much refined one here: www.neatcpp.com/NCLiteDXDoc.html

  • WM_COPYDATA with C#

    Posted by Legacy on 10/15/2001 07:00am

    Originally posted by: rick

    Help guys !

    how do i receive WM_COPYDATA messages using C# ?

  • Well a new Message format for me....

    Posted by Legacy on 08/06/2001 07:00am

    Originally posted by: Sajjad

    Hello All,
    This is a new thing that i found out.
    Same method to send data among Windows i followes is some thing like this.....

    HWND ChildHwnd;

    ::SendMessage (ChildHwnd, WM_DATA, 0, (LPARAM)MessagePtr);

    WM_DATA is my own Message.

    It worked.
    Well any comments on it..
    May be i missed some thing, that i couldn't remember....

    Well, try it on.

    • Nope, it just won't work.

      Posted by chilly32 on 05/16/2005 02:48pm

      You cannot send data this way into another process, only within your own process. Your data pointer belongs to the creating process, and it cannot be shared that way with other processes, i.e. it won't be valid. Another WM_COPYDATA example: www.neatcpp.com/NCLiteDXDoc.html

  • Must same application

    Posted by Legacy on 03/28/2001 08:00am

    Originally posted by: Tum_tum

    I think COPYDATA must use in same application, and not use to control other applcation example notepad.

  • How to transfer data?

    Posted by Legacy on 02/14/2001 08:00am

    Originally posted by: Damir Tenisheff

    In the artcle there is a good example of using the WM_COPYDATA message. But one question:
    While in
    typedef struct tagCOPYDATASTRUCT {
    ULONG_PTR dwData;
    DWORD cbData;
    PVOID lpData;

    lpData points to the data in the local address space of the sender - how I can read this data in the receiver's address space?

  • Translation to Visual Basic

    Posted by Legacy on 12/11/2000 08:00am

    Originally posted by: Roger Taylor


    At about the time this artical was being written i was doing the same thing becasue i wanted a way of sending data to an external process on a machine that did not have tcp/ip installed. sounds strange i know but hey wha a gonna do!!!!

    anyway, if any of ya are interested you can see my version of it at

  • WM_COPYDATA to Notepad application

    Posted by Legacy on 11/14/2000 08:00am

    Originally posted by: Vincenzo Catania

    I used the WM_COPYDATA to send a strings to Notepad but
    it doesn't work! Why ??

  • how to use WM_COPYDATA with j++

    Posted by Legacy on 11/09/2000 08:00am

    Originally posted by: Justin

    How do you use WM_COPYDATA with j++ because all the types are then ints.

  • How can I copy text into MS word?

    Posted by Legacy on 11/03/2000 08:00am

    Originally posted by: Li Zhigang

    How can I use WM_COPYDATA or Clipboard to copy text into
    MS Word?

  • Loading, Please Wait ...

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date