4

WM_COPYDATA を使用して C で記述された別のアプリケーションと通信する C# WPF アプリケーションを取得しようとしています。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 メンバーがインライン文字列配列であるため、LPSTR ではなく ByValTStr である必要があることです。次の定義を試してください

[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 に答える