2009-10-28 49 views
4

我想獲得一個C#WPF應用程序與使用WM_COPYDATA在C中編寫的另一個應用程序進行通信。的C應用程序試圖按以下方式發送一個結構:WM_COPYDATA消息的編組結構

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來解釋字節數組,並且工作得很好。但現在我正在嘗試以一種更清潔的方式來實現,而這只是無效。

回答

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,我只是忘了用它更新的版本。

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; 
};