4

我正在尝试让 C# WPF 应用程序与使用 WM_COPYDATA 用 C 编写的另一个应用程序进行通信。C 应用程序正在尝试发送一个结构,如下所示:

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

在我的 C# 应用程序中,我定义了一个结构如下:

[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 来解释字节数组,并且效果很好。但现在我正试图以一种更清洁的方式来做这件事,但它不起作用。

4

2 回答 2

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,我只是忘记在较新的版本中使用它。

于 2009-10-28T16:51:14.343 回答
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;
};
于 2009-10-28T15:18:01.533 回答