COPYDATASTRUCT (Structures)
Last changed: shipr on StackOverflow-76.14.214.109

.
Summary
COPYDATASTRUCT messages may be used to send structured data between processes. In the example given, a 64-bit C# application receives a message from a 32-bit C++ DLL. The COPYDATASTRUCT structure shown works even between architectures.

C# Definition:

[StructLayout(LayoutKind.Sequential)]
struct COPYDATASTRUCT
{
     public IntPtr dwData;
     public int cbData;
     public IntPtr lpData;
}

const int WM_COPYDATA = 0x004A;

VB.NET Definition:

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

User-Defined Field Types:

None.

Documentation

// 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.
[StructLayout(LayoutKind.Sequential)]
struct COPYDATASTRUCT
{
     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; }
}

// Allocate a pointer to int 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 int from the global heap.
public static void IntPtrFree(IntPtr preAllocated)
{
     if (IntPtr.Zero == preAllocated) throw (new NullReferenceException("Go Home"));
     Marshal.FreeHGlobal(preAllocated); preAllocated = IntPtr.Zero;
}

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

// 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)
         break;
         if (MessageType.FV_RUBBERBAND_GEORECT_MSG == pData.Type
         && this.messageId == pData.MessageId)
         {
         this.Simulation.WeatherArea.N = new LatLong(this.ctrlLatitudeN.Latitude = pData.NW_Latitude, LL.Latitude);
         this.Simulation.WeatherArea.W = new LatLong(this.ctrlLongitudeW.Longitude = pData.NW_Longitude, LL.Longitude);
         this.Simulation.WeatherArea.S = new LatLong(this.ctrlLatitudeS.Latitude = pData.SE_Latitude, LL.Latitude);
         this.Simulation.WeatherArea.E = new LatLong(this.ctrlLongitudeE.Longitude = pData.SE_Longitude, LL.Longitude);
         NativeWindow.SetForegroundWindow(this.Handle);
         return;
         }
         else if (MessageType.FV_RUBBERBAND_GEORECT_CANCELED == pData.Type)
         {
         // Message overwritten by another attempt to get it
         return;
         }

         break;
     }

     base.WndProc(ref m);
}