Structuring structures from WM_COPYDATA messages

I am trying to get a WPF C # application to communicate with another application written in C using WM_COPYDATA. Appendix C tries to send the structure as follows:

typedef struct { int x; int y; char str[40]; double d; char c; } DATASTRUCT; 

In my C # application, I defined the structure as follows:

 [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] public struct DATASTRUCT { public int x; public int y; [MarshalAs(UnmanagedType.LPStr, SizeConst=40)] public string s; public double d; public char c; }; 

And the code for receiving the WM_COPYDATA message is as follows:

 private void Window_Loaded(object sender, RoutedEventArgs e) { hwndSource = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle); hwndSource.AddHook(new HwndSourceHook(WndProc)); } private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { if (msg == 0x4A) { DATASTRUCT data = (DATASTRUCT)Marshal.PtrToStructure(lParam, typeof(DATASTRUCT)); this.updateText(data); handled = true; } return (IntPtr)0; } 

I get messages from application C, but all the data in the structure is gibberish. Before that, I was able to manually extract the byte array from the lParam pointer, and then use System.BitConverter and System.Text.Encoding.ACII to interpret the byte array, and this worked pretty well. But now I'm trying to make it cleaner, and it just doesn't work.

+4
source share
2 answers

After a long search for the answer to this question, I realized that I was missing a VERY important step. I feel like an idiot, but here is the answer to my own question.

The C # structure should look like this:

 [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] public unsafe struct DataStruct { public int x; public int y; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=40)] public string s; public double d; public char c; }; 

And another structure needs to be defined to receive WM_COPYDATA information. It looks like this:

 [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] public unsafe struct CopyDataStruct { public IntPtr dwData; public int cbData; public IntPtr lpData; } 

And the WndProc method should be changed so that it looks like this:

 private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { if (msg == 0x4A) { CopyDataStruct cps = (CopyDataStruct)Marshal.PtrToStructure(lParam, typeof(CopyDataStruct)); DataStruct data = (DataStruct)Marshal.PtrToStructure(cps.lpData, typeof(DataStruct)); updateText(data); handled = true; } return (IntPtr)0; } 

I used CopyDataStruct in my previous working solution, and I just forgot to use it in a newer version.

+6
source

Part of the problem is that the str member must be ByValTStr, not LPSTR, since it is a string array of strings. Try the following definition

 [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] public struct DATASTRUCT { public int x; public int y; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=40)] public string s; public double d; public char c; }; 
+2
source

All Articles