gpt4 book ai didi

c# - SendMessage 中的误导参数类型 (... IntPtr wParam ...)

转载 作者:行者123 更新时间:2023-11-28 05:09:40 24 4
gpt4 key购买 nike

在处理 What's wrong with this unmanaged code in C#? 中描述的问题时我偶然发现了参数 wParam 及其类型 IntPtr for SendMessage 功能。

原始函数的代码是这样的

var length = (int)SendMessage(hWnd, WindowMessage.WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);
var buff = new char[length + 1];
var iptr = Marshal.AllocHGlobal(buff.Length * sizeof(char));
SendMessage(hWnd, WindowMessage.WM_GETTEXT, (IntPtr)(length + 1), iptr);
Marshal.Copy(iptr, buff, 0, length + 1);
Marshal.FreeHGlobal(iptr);

我不喜欢 allocation 和 Copy 部分,所以我尝试用

var length = 1 + (int)SendMessage(hWnd, WindowMessage.WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);
var buffer = new char[length];
var bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
var lengthHandle = GCHandle.Alloc(length, GCHandleType.Pinned);
SendMessage(hWnd, WindowMessage.WM_GETTEXT, lengthHandle.AddrOfPinnedObject(), bufferHandle.AddrOfPinnedObject());
bufferHandle.Free();
lengthHandle.Free();

事实证明,这是行不通的,因为参数 wParam 不是指针(可以从它的 IntPtr 类型得出结论)。

关于WM_GETTEXT消息的具体描述可以在MSDN上找到(感谢 SO 社区指出这一点)这导致我们遵循以下代码

var length = 1 + (int)SendMessage(hWnd, WindowMessage.WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);
var buffer = new char[length];
var bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
SendMessage(hWnd, WindowMessage.WM_GETTEXT, (IntPtr)length, bufferHandle.AddrOfPinnedObject());
bufferHandle.Free();

是否有针对特定消息专门化或缩小范围的 SendMessage 函数的库或签名集合?

不要误会我的意思,PInvoke 已经通过将此功能提供给托管世界做了很多工作,我很欣赏这一点,但是单一方法的多用途性质使其更难使用。

最佳答案

您可以从 PInvoke page 复制它们, 但请注意,我经常必须修改 PInvoke 定义(它们通常是面向 32 位的,因此他们经常假设 sizeof(IntPtr) == sizeof(int),这是非常错误的!,或者他们使用“过时的”ANSI API,但现在应该始终使用 Unicode API...举个例子,在链接页面中,SendMessage[MarshalAs(UnmanagedType.LPStr) ] string lParam 使用的是 ANSI API,而带有 Int32 wParam 的将在 64 位上中断)

您的代码可以更改为:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, StringBuilder lParam);

var length = (int)SendMessage(hWnd, WindowMessage.WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);
var sb = new StringBuilder(length + 1);
SendMessage(hWnd, WindowMessage.WM_GETTEXT, (IntPtr)sb.Capacity, sb);
string str = sb.ToString();

利用 pinvoke 子系统“支持”StringBuilder 来编码字符串这一事实。

关于c# - SendMessage 中的误导参数类型 (... IntPtr wParam ...),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43778985/

24 4 0
文章推荐: c++ - 如何为 GraphicsItem 创建自定义属性并在 QPropertyAnimation 中使用它
文章推荐: c++ - Windows 上的 Cmake,加载静态库
文章推荐: css 和 div - parent 对 child 的属性
文章推荐: html - FireFox 中表格周围的
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com