Last changed: shipr on StackOverflow-

COPYDATASTRUCT messages may be used to send structured data between processes.

Two examples are included here.

The first sends an arbitrary structure (called txStruct) to another process.

In the second, a 64-bit C# application receives a message from a 32-bit C++ DLL.

Note that the COPYDATASTRUCT messaging capability shown can work even between differing memory architectures.

C# Definition:

   public IntPtr dwData;    // Any value the sender chooses.  Perhaps its main window handle?
   public int cbData;       // The count of bytes in the message.
   public IntPtr lpData;    // The address of the message.

const int WM_COPYDATA = 0x004A;

VB.NET Definition:

<StructLayout(LayoutKind.Sequential)> _
   Public dwData As IntPtr
   Public cdData As Integer
   Public lpData As IntPtr
End Structure

User-Defined Field Types:



C# Structures:

// The COPYDATASTRUCT describes the data that is passed.
// The message is routed via the receiving process's window handle.
// The first field, dwData, may contain anything the sender wishes; it is the equivalent of System.Object sender in an EventHandler.
// The count of bytes is given in cbData.
// And the data itself is pointed to by lpData.
   public IntPtr dwData;
   public int cbData;
   public IntPtr lpData;

// The data may be of any agreed-upon form.
// The Pack parameter to the structure gives the padding between fields.
// Here Pack = 1 is used because the original data was created in a 32-bit C++ DLL and no padding was used.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct GEORECT
   // The string is included inline in the data.
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
   public string Falconview;                   // "FALCONVIEW"

   public MessageType Type { get; set; }           // MessageType.FV_RUBBERBAND_GEORECT_MSG (3)
   public int MessageId { get; set; }
   public double NW_Latitude { get; set; }
   public double NW_Longitude { get; set; }
   public double SE_Latitude { get; set; }
   public double SE_Longitude { get; set; }

C# Global memory allocation

// Allocate a pointer to an arbitrary structure on the global heap.
public static IntPtr IntPtrAlloc<T>(T param)
   IntPtr retval = Marshal.AllocHGlobal(Marshal.SizeOf(param));
   Marshal.StructureToPtr(param, retval, false);
   return retval;

// Free a pointer to an arbitrary structure from the global heap.
public static void IntPtrFree(ref IntPtr preAllocated)
   if (IntPtr.Zero == preAllocated)
     throw (new NullReferenceException("Go Home"));
   preAllocated = IntPtr.Zero;

C# Example 1 - send data:

// An example of sending a message containing a txStruct.
public SendMessage()
   IntPtr buffer = IntPtrAlloc(txStruct);
   copyData.dwData = IntPtr.Zero;
   copyData.lpData = buffer;
   copyData.cbData = Marshal.SizeOf(txStruct);
   IntPtr copyDataBuff = IntPtrAlloc(copyData);
   SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, copyDataBuff);
   IntPtrFree(ref copyDataBuff);
   IntPtrFree(ref buffer);

C# Example 2 - receive data:

// Receive a COPYDATASTRUCT message from FalconView
// containing a geocoordinate rectangle
protected override void WndProc(ref Message m)
   switch (m.Msg)
     case (int)WM.COPYDATA:
       var msg = Marshal.PtrToStructure<COPYDATASTRUCT>(m.LParam);
       var pData = Marshal.PtrToStructure<GEORECT>(msg.lpData);

       if (pData.Falconview != FalconShu.FALCONVIEW)

       if (MessageType.FV_RUBBERBAND_GEORECT_MSG == pData.Type
         && this.messageId == pData.MessageId)
         this.Simulation.WeatherArea.N = pData.NW_Latitude;
         this.Simulation.WeatherArea.W = pData.NW_Longitude;
         this.Simulation.WeatherArea.S = pData.SE_Latitude;
         this.Simulation.WeatherArea.E = pData.SE_Longitude;
       else if (MessageType.FV_RUBBERBAND_GEORECT_CANCELED == pData.Type)
         // Message overwritten by another attempt to get it


   base.WndProc(ref m);