我有一个c ++应用程序,它使用SendNotifyMessage
将 CB_FINDSTRINGEXACT 重定向到C#代码。现在,我想将其更改为 WM_COPYDATA ,但我无法使其正常工作。
C ++代码:
static LRESULT CALLBACK GetMsgHookCallback(int code, WPARAM wparam, LPARAM lparam){
if (code >= 0)
{
UINT msg = 0;
UINT msg2 = 0;
msg = RegisterWindowMessage("WILSON_HOOK_GETMSG");
msg2 = RegisterWindowMessage("WILSON_HOOK_GETMSG_PARAMS");
HWND dstWnd = (HWND)GetProp(GetDesktopWindow(), "WILSON_HOOK_HWND_GETMSG");
MSG* pMsg = (MSG*)lparam;
if (msg != 0 && pMsg->message != msg && pMsg->message != msg2)
{
if (pMsg->message == CB_ADDSTRING)
{
SendNotifyMessage(dstWnd, msg, (WPARAM)pMsg->hwnd, pMsg->message);
SendNotifyMessage(dstWnd, msg2, pMsg->wParam, pMsg->lParam); //plus more code...
现在,由于我的目的是阅读pMsg->lParam
中的字符串而我无法使其从c#侧*开始工作,我试图以这种方式使用WM_COPYDATA:
SendNotifyMessage(dstWnd, msg, (WPARAM)pMsg->hwnd, pMsg->message);
SendNotifyMessage(dstWnd, msg2, pMsg->wParam, pMsg->lParam);
// Added code
CString *message = (CString*)pMsg->lParam;
COPYDATASTRUCT cpd;
cpd.dwData = 0;
cpd.cbData = message->GetLength();
cpd.lpData = (void*)message->GetBuffer(cpd.cbData);
::SendMessage(dstWnd, WM_COPYDATA, (WPARAM)pMsg->hwnd, (LPARAM)&cpd);
SendNotifyMessage(dstWnd, WM_COPYDATA, (WPARAM)pMsg->hwnd, (LPARAM)&cpd);
但是,我从未在c#application *中收到任何 WM_COPYDATA 。
这是C#部分:
int CB_FINDSTRINGEXACT = 0x0158;
public const Int32 WM_COPYDATA = 0x4A;
private void test(IntPtr Handle, IntPtr Message, IntPtr wParam, IntPtr lParam)
{
if (Message.ToInt32() == CB_FINDSTRINGEXACT)
{
String one = Marshal.PtrToStringAuto(lParam); // This gives accessviolationexception
String dos = Marshal.PtrToStringAnsi(lParam); // returns empty string
Console.WriteLine("SOMETHING RECEIVED: "+one+". dos: "+dos+". tres: "+lParam.ToString()); // last part is only an intptr
}
if (Message.ToInt32() == WM_COPYDATA) // never true
Console.WriteLine("COPYDATA: ");
}
我已经尝试了很多解决方案,但我似乎都没有。如何在c#函数中从c ++中读取lParam(真的是一个String)?我想得到这个字符串。
EDIT1:
我尝试了几种方法让WM_COPYDATA正常工作,但没有成功。他们在这里:
// Test 1: c# never receives anything
COPYDATASTRUCT* copy_data = (COPYDATASTRUCT*)(pCwpStruct->lParam);
SendMessage(dstWnd, WM_COPYDATA, (WPARAM)pCwpStruct->hwnd, (LPARAM)©_data);
SendNotifyMessage(dstWnd, WM_COPYDATA, (WPARAM)pCwpStruct->hwnd, (LPARAM)©_data);
// Test 2: c# never receives anything
LPCTSTR lpszString = (LPCTSTR)pCwpStruct->lParam;
COPYDATASTRUCT cds;
cds.dwData = 0;
cds.cbData = sizeof(TCHAR)* (_tcslen(lpszString) + 1);
cds.lpData = (PVOID)lpszString;
SendMessage(dstWnd, WM_COPYDATA, (WPARAM)pCwpStruct->hwnd, (LPARAM)(LPVOID)&cds);
SendNotifyMessage(dstWnd, WM_COPYDATA, (WPARAM)pCwpStruct->hwnd, (LPARAM)&cds);
答案 0 :(得分:0)
有许多更正的评论,但它消失了,不知道为什么。我遵循了一些建议并解决了它。这是最终的代码:
C ++:
LPCTSTR lpszString = (LPCTSTR)pCwpStruct->lParam;
COPYDATASTRUCT cds;
cds.dwData = 0;
cds.cbData = sizeof(TCHAR)* (_tcslen(lpszString) + 1);
cds.lpData = (PVOID)lpszString;
SendMessage(dstWnd, WM_COPYDATA, (WPARAM)pCwpStruct->hwnd, (LPARAM)(LPVOID)&cds);
请注意,我已将 SendNotifyMessage 更改为 SendMessage 。这是我能让它发挥作用的唯一方式。
在c#应用程序中:
public override void ProcessWindowMessage(ref System.Windows.Forms.Message m)
{
if (m.Msg == WM_COPYDATA)
{
COPYDATASTRUCT cds;
cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
if (cds.cbData > 0)
{
byte[] data = new byte[cds.cbData];
Marshal.Copy(cds.lpData, data, 0, cds.cbData);
System.Text.Encoding unicodeStr = System.Text.Encoding.ASCII;
char[] myString = unicodeStr.GetChars(data);
string returnText = new string(myString); // Here is the info
}
...