C# 向 C++ 发送消息WinProc
我需要将一个字符串从 C# 发送到 C++ WindowProc。 SO 有很多与此相关的问题,但没有一个答案对我有用。情况如下:
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++ 端的正确内存位置,但数据不存在。我缺少什么?
I need to send a string from C# to a C++ WindowProc. There are a number of related questions on SO related to this, but none of the answers have worked for me. Here's the situation:
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);
}
I've tried a number of different things, Marshalling the string as LPStr, LPWStr, also tried creating an IntPtr from unmanaged memory, and writing to it with Marshal.WriteByte.
The pointer is the correct memory location on the C++ side, but the data isn't there. What am I missing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对于 C++
LPWSTR
或LPSTR
参数,您需要在 DllImport 中使用 C#StringBuilder
。对于 C++
LPCWSTR
或LPCSTR
参数,您需要在 DllImport 中使用 C#string
。For C++
LPWSTR
orLPSTR
parameters you need to use the C#StringBuilder
in your DllImport.For C++
LPCWSTR
orLPCSTR
parameters you need to use the C#string
in your DllImport.确保您的 SendMessage 调用以预期的同步方式发生,并且您的 NativeMethods 类映射正确的 Win32 调用(Send 与 PostMessage)。如果这不正确,则可能是在 C++ 上处理消息时最后,您已经离开了 C# 方法的范围,并且在堆栈上创建的任何局部变量都消失了,从而导致了错误的指针。
跨线程调用的堆栈和堆注意事项:线程有自己的堆栈,但共享堆。一个线程中的堆栈分配变量在另一线程中不可见。字符串类型在 .NET 中是一种奇怪的东西。它是一个对象派生的引用类型,但看起来和感觉起来都像代码中的值类型。因此,也许传递一个指向堆分配数据的指针应该可行。这就是 StringBuilder 作为堆分配引用类型的用武之地。
Make sure that your SendMessage call is occurring in the expected, synchronous manner and that your NativeMethods class maps the proper Win32 call (Send vs. PostMessage.) If this isn't correct it's possible that by the time your message is processed on the C++ end, you've left the scope of your C# method and any local variables created on the stack are gone resulting in your bad pointer.
Stack and heap considerations for cross-thread calls: Threads have their own stacks but share the heap. Stack-allocated variables in one thread will not be visible in another. The string type is an odd duck in .NET. It is an Object-derived, reference type but made to look and feel like a value type in code. So perhaps passing a pointer to heap-allocated data ought to work. That's where StringBuilder, as a heap-allocated reference type, comes in.