Game Development Reference
As mentioned earlier, we pass the WM_COPYDATA identifier into the SendMessage()
method. In order to do so, we need to define the WM_COPYDATA identifier because
Microsoft.NET does not natively recognize its value.
private const int WM_COPYDATA = 0x4A;
The following two lines of code show the P/Invoke signature for the SendMessage()
method that is located in user32.dll .
private extern static int SendMessage(IntPtr handle, int msg, int param, ref
In order to send a data pointer to another process, we need to allocate a global
block of memory that is not managed by the garbage collector. We can do this by
calling Marshal.AllocCoTaskMem() . It will return a pointer to an allocated block of
memory that can now have contents copied into it. A subsequent call to Marshal.Copy()
can copy a byte array to that location in memory.
byte dataToSend = new byte;
IntPtr dataPointer = Marshal.AllocCoTaskMem(dataToSend.Length);
Marshal.Copy(dataToSend, 0, dataPointer, dataToSend.Length);
Just like using WM_COPYDATA in an unmanaged application, we need to instantiate a
COPYDATASTRUCT instance and specify the data that we will be sending to the receiv-
COPYDATASTRUCT copyData = new COPYDATASTRUCT();
copyData._dataType = IntPtr.Zero;
copyData._dataSize = dataToSend.Length;
copyData._dataPointer = dataPointer;
The next few lines of code show the call to SendMessage() . You can get an unmanaged
handle ( HWND ) to any managed Form in .NET by accessing the Handle property. You
need to find out the handle of the target form, which again is not natively sup-
ported by .NET, although you can use a function like FindWindow() to help you out.
You will have to tap into P/Invoke for this one too. The example and library on the
Companion Web site show how to do this.
IntPtr target = TargetForm.Handle;
IntPtr sender = YourForm.Handle;
int result = SendMessage(target, WM_COPYDATA, sender.ToInt32(), ref copyData);
// Successful if result is 0