可能是一个菜鸟问题但是互操作不是我的优点之一。
除了限制重载次数之外,还有任何理由我应该声明我的DllImports:
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam);
并像这样使用它们:
IntPtr lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(formatrange));
Marshal.StructureToPtr(formatrange, lParam, false);
int returnValue = User32.SendMessage(_RichTextBox.Handle, ApiConstants.EM_FORMATRANGE, wParam, lParam);
Marshal.FreeCoTaskMem(lParam);
而不是创建目标重载:
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, ref FORMATRANGE lParam);
使用它像:
FORMATRANGE lParam = new FORMATRANGE();
int returnValue = User32.SendMessage(_RichTextBox.Handle, ApiConstants.EM_FORMATRANGE, wParam, ref lParam);
by ref重载最终会更容易使用,但我想知道是否存在我不知道的缺点。
修改
到目前为止,有很多很棒的信息。
@P爸爸:你有一个基于抽象(或任何)类的结构类的例子吗?我将签名改为:
[DllImport("user32.dll", SetLastError = true)]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, [In, Out, MarshalAs(UnmanagedType.LPStruct)] CHARFORMAT2 lParam);
没有In
,Out
和MarshalAs
SendMessage(我的测试中的EM_GETCHARFORMAT)失败。以上示例效果很好,但如果我将其更改为:
[DllImport("user32.dll", SetLastError = true)]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, [In, Out, MarshalAs(UnmanagedType.LPStruct)] NativeStruct lParam);
我收到一个System.TypeLoadException,指出CHARFORMAT2格式无效(我会尝试在这里捕获它)。
例外:
无法从程序集“CC.Utilities,Version = 1.0.9.1212,Culture = neutral,PublicKeyToken = 111aac7a42f7965e”加载类型“CC.Utilities.WindowsApi.CHARFORMAT2”,因为格式无效。
NativeStruct类:
public class NativeStruct
{
}
我已尝试abstract
,添加了StructLayout
属性等,我得到了同样的例外。
[StructLayout(LayoutKind.Sequential)]
public class CHARFORMAT2: NativeStruct
{
...
}
修改
我没有按照常见问题解答,我问了一个可以讨论但没有得到积极回答的问题。除此之外,这个帖子中还有很多有见地的信息。所以我会把它留给读者投票给答案。第一个到10个以上的投票将是答案。如果在两天(太平洋标准时间12/17)没有答案符合这一点,我将添加我自己的答案,总结线程中的所有美味知识: - )
再次编辑:
我撒了谎,接受了P爸爸的回答,因为他是那个男人并得到了很大的帮助(他也有一只可爱的小猴子:-P)
答案 0 :(得分:15)
答案 1 :(得分:3)
我有一些有趣的案例,参数类似于ref Guid parent
,相应的文档说:
“指向指定父级的GUID的指针。传递空指针以使用 [插入一些系统定义的项目] 。”
如果null
(或IntPtr.Zero
参数IntPtr
)确实是无效参数,那么您可以使用ref
参数 - 可能更好,因为它是更清楚你需要通过什么。
如果null
是有效参数,则可以传递ClassType
而不是ref StructType
。引用类型(class
)的对象作为指针传递,它们允许null
。
答案 2 :(得分:2)
不,你不能重载SendMessage并使wparam参数成为int。这将使您的程序在64位版本的操作系统上失败。它必须是一个指针,IntPtr,blittable引用或out或ref值类型。重载out / ref类型也不错。
答案 3 :(得分:1)
我没有看到任何缺点。
对于简单类型和简单结构,副词通常就足够了。
如果结构具有可变大小或者您想要进行自定义处理,则应该优先使用IntPtr。
答案 4 :(得分:1)
使用ref
比手动操作指针更简单且更不容易出错,因此我认为没有充分理由不使用它...使用ref
的另一个好处是你没有担心释放非托管分配的内存