我正在尝试使用WM_COPYDATA将C#WPF应用程序与使用C编写的另一个应用程序进行通信。 C app正在尝试按如下方式发送结构:
typedef struct
{
int x;
int y;
char str[40];
double d;
char c;
} DATASTRUCT;
在我的C#app中,我定义了一个结构如下:
[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;
};
接收WM_COPYDATA消息的代码如下:
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;
}
我正在从C应用程序接收消息,但结构中的所有数据都是乱码。在此之前,我能够从lParam指针手动提取一个字节数组,然后使用System.BitConverter和System.Text.Encoding.ACII来解释字节数组,这非常有效。但是现在我试图以更清洁的方式做到这一点而且它只是不起作用。
答案 0 :(得分:6)
经过很长一段时间寻找这个问题的答案,我意识到我错过了一个非常重要的步骤。我觉得自己像个白痴,但这是我自己问题的答案。
C#结构应该如下所示:
[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;
};
必须定义另一个结构来接收WM_COPYDATA信息。它看起来像这样:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public unsafe struct CopyDataStruct
{
public IntPtr dwData;
public int cbData;
public IntPtr lpData;
}
WndProc方法应该改为:
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;
}
我在之前的工作解决方案中使用了CopyDataStruct,我只是忘了在较新版本中使用它。
答案 1 :(得分:2)
部分问题是str成员需要是ByValTStr而不是LPSTR,因为它是一个内联字符串数组。请尝试以下定义
[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;
};