2010-04-16 39 views
4

我需要從C#發送一個字符串到C++ WindowProc。與此有關的SO有許多相關的問題,但沒有一個答案適用於我。這裏的情況:C#發送消息到C++ WinProc

PInvoke: 
[DllImport("user32", CharSet = CharSet.Auto)] 
public extern static int SendMessage(IntPtr hWnd, uint wMsg, IntPtr wParam, string lParam); 

C#: 
string lparam = "abc"; 
NativeMethods.User32.SendMessage(handle, ConnectMsg, IntPtr.Zero, lparam); 

C++: 
API LRESULT CALLBACK HookProc (int code, WPARAM wParam, LPARAM lParam) 
{  
    if (code >= 0) 
    { 
     CWPSTRUCT* cwp = (CWPSTRUCT*)lParam; 
       ... 
     (LPWSTR)cwp->lParam <-- BadPtr 
       ... 
    } 

    return ::CallNextHookEx(0, code, wParam, lParam); 
} 

我已經嘗試了一些不同的東西,編組字符串作爲LPSTR,LPWSTR,還試圖從非託管內存中創建一個IntPtr,並與Marshal.WriteByte寫它。

指針是C++端的正確內存位置,但數據不在那裏。我錯過了什麼?

回答

2

對於C++ LPWSTRLPSTR參數您需要在您的DllImport中使用C#StringBuilder

對於C++ LPCWSTRLPCSTR參數您需要在您的DllImport中使用C#string

+0

你能舉個例子嗎? – Nayan 2010-04-16 14:33:53

1

確保您的SendMessage調用以預期的同步方式進行,並且您的NativeMethods類映射正確的Win32調用(發送與PostMessage。)如果這不正確,可能您的郵件是在C++端進行處理,您已經離開了C#方法的範圍,並且在堆棧上創建的任何局部變量都消失,導致您的指針變得糟糕。

跨線程調用的堆棧和堆注意事項:線程有自己的堆棧但共享堆。一個線程中堆棧分配的變量在另一個線程中不可見。字符串類型是.NET中的一個奇怪的鴨子。它是一個Object引發的引用類型,但在代碼中看起來和感覺就像是一個值類型。所以也許傳遞一個指向堆分配數據的指針應該可以工作。這就是StringBuilder作爲堆分配參考類型進來的地方。

+0

我肯定使用SendMessage,所以我不應該在處理完消息之前回到C#。 – jaws 2010-04-16 14:41:21

+0

這是一個跨線程調用?線程有自己的堆棧,但共享堆。一個線程中堆棧分配的變量在另一個線程中不可見。字符串類型是.NET中的一個奇怪的鴨子。它是Object派生的,引用類型,但看起來和感覺像是一個值類型。所以傳遞一個指向堆分配數據的指針應該可以工作。也許這就是StringBuilder進來的地方。 – 2010-04-16 14:52:53

+0

是的,它是跨線程的,它總是有意義的。 – jaws 2010-04-16 15:00:05