winForms Interop - C#:WndProc() 和 IntPtr 类型 - 如何正确处理它?IntPtr

本文关键字:IntPtr 类型 正确处理 Interop WndProc winForms | 更新日期: 2023-09-27 17:56:16

我有WndProc(Message m)覆盖。这显然被称为很多。假设我希望将某些消息标记为"已处理"。所以我应该将Result设置为 1。但Result财产是IntPtr.执行m.Result = new IntPtr(1)时会发生什么?每次调用都会为一个Int32值分配内存?如果我创建一个静态IntPtr变量并将其设置为 new IntPtr(1) 会发生什么?

最正确的方法是什么?

然后我想m.LParam与已知值进行比较。它也IntPtr,我可以通过多种方式做到这一点:

if (m.LParam == (IntPtr)0x0001) ...
if ((int)m.LParam == 0x0001) ...
if (m.LParam == myStaticIntPtr1) ...

这种比较的成本是多少?在高于 3 期间,低水平会发生什么? Message类型不是一次性的。所以我认为我可以安全地省略将其传递给base.WndProc(),对吗?当我只想丢弃消息时,不需要对它执行任何操作?

奖励问题:我不确定,但我想我已经在 pinvoke.net 上看到了 DllImport MSDN 文档中存在的 IntPtr 更改为仅 int s。 可能吗?行得通吗?会发生什么?隐式转换?

顺便说一句,IntPtr是托管类型,对吧?因此,如果我不调用非托管代码或使用一次性类型 - 不需要释放任何东西?

winForms Interop - C#:WndProc() 和 IntPtr 类型 - 如何正确处理它?IntPtr

IntPtr 是一种值类型,不会产生任何内存分配 - 它要么在堆栈上,要么是另一种类型的内存结构的一部分。在 C# 中,new运算符同时用于值和引用类型,如果您来自C++背景,这可能会令人困惑。您甚至可以写new int(),并且不会有任何分配。

此外,将其强制转换为Int32int 在 C# 中)可能会产生错误的结果 - 在 64 位进程中,它将是一个Int64的大小(您可以检查IntPtr.Size)。

简而言之,比较的成本可以忽略不计 - 这与比较两个整数相同。如果这样可以提高可读性,您可以将IntPtr保留在静态字段中,但您不必担心内存。

以下内容是等效的:

  • new IntPtr(1)
  • (IntPtr)1 - 有一个显式强制转换运算符将其转换为上述构造函数

此类型存在的原因是在处理非托管 API 时抽象出指针的大小,因此您可以从 32 位和 64 位进程 P/Invoke 到 Win32 中。