C# 向 C++ 发送消息WinProc

发布于 2024-08-29 11:40:41 字数 783 浏览 5 评论 0原文

我需要将一个字符串从 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

逐鹿 2024-09-05 11:40:41

对于 C++ LPWSTRLPSTR 参数,您需要在 DllImport 中使用 C# StringBuilder

对于 C++ LPCWSTRLPCSTR 参数,您需要在 DllImport 中使用 C# string

For C++ LPWSTR or LPSTR parameters you need to use the C# StringBuilder in your DllImport.

For C++ LPCWSTR or LPCSTR parameters you need to use the C# string in your DllImport.

流年已逝 2024-09-05 11:40:41

确保您的 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文