从 WM_COPYDATA 消息编组结构

发布于 2024-08-09 08:58:31 字数 1212 浏览 12 评论 0原文

我正在尝试让 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 来解释该字节数组,效果非常好。但现在我试图以更干净的方式做到这一点,但它不起作用。

I am trying to get a C# WPF application to communicate with another application written in C using WM_COPYDATA. The C app is trying to send a struct as follows:

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

In my C# app I have defined a struct 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 to receive 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 am receiving messages from the C application, but all the data in the struct is gibberish. Previous to this I was able to manually extract an array of bytes from the lParam pointer and then use System.BitConverter and System.Text.Encoding.ACII to interpret the byte array, and that worked pretty well. But now I am trying to do it in a cleaner way and it's just not working.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

幸福%小乖 2024-08-16 08:58:31

经过很长时间寻找这个问题的答案,我意识到我错过了非常重要的一步。我觉得自己像个白痴,但这是我自己问题的答案。

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

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

The C# struct 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 struct must be defined to receive the WM_COPYDATA info. 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 to look 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 was using the CopyDataStruct in my previous working solution, and I just forgot to use it in the newer version.

薄情伤 2024-08-16 08:58:31

部分问题在于 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;
};

Part of the problem is that the str member needs to be a ByValTStr not a LPSTR since it's an inlined string array. 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;
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文