System.Drawing.Bitmap.GetHicon() 上的 GDI 对象泄漏

Posted

技术标签:

【中文标题】System.Drawing.Bitmap.GetHicon() 上的 GDI 对象泄漏【英文标题】:GDI Object leak on System.Drawing.Bitmap.GetHicon() 【发布时间】:2021-06-20 10:08:06 【问题描述】:

我见过类似的问题,但没有一个能满足我的情况。

我正在修复 C++ Windows 窗体应用程序上的 GDI 对象泄漏。

这是它抛出的异常:

GDI+ 中出现一般错误。在 System.Drawing.Bitmap.GetHicon()

这是发生崩溃的那一行的GetHicon 调用:

this->notifyIcon1->Icon=Icon->FromHandle(((Bitmap^)imgsApp->Images[0])->GetHicon());

在这里做了一些阅读之后,在https://docs.microsoft.com/en-us/dotnet/api/system.drawing.icon.fromhandle?view=net-5.0 上,我看到我需要调用DestroyIcon() 以释放图标句柄(不确定这里的措辞是否正确),但我在这样做时遇到了麻烦熟悉 Windows 窗体。

【问题讨论】:

您链接到的文档字面上显示了使用DestroyIcon() 的示例。 Bitmap::GetHIcon() 的文档也是如此 相关/复制:Icon.FromHandle: should I Dispose it, or call DestroyIcon? 【参考方案1】:

试试这个:

IntPtr iconHandle = ((Bitmap^)imgsApp->Images[0])->GetHicon();
Icon ^newIcon = Icon::FromHandle(iconHandle);
this->notifyIcon1->Icon = (Icon^) newIcon->Clone();
newIcon->Dispose();
DestroyIcon((HICON)iconHandle.ToPointer());

每Icon.FromHandle: should I Dispose it, or call DestroyIcon?:

结论:Icon.FromHandle之后,ownHandle字段为false,因此Dispose/FromHandle不会调用DestroyIcon

因此:如果您使用 Icon.FromHandle 创建一个图标,您将不得不 Dispose() 该图标以及调用 DestroyIcon,正如备注部分所述

【讨论】:

我看到你做了什么,这应该可以工作,但是我得到:标识符“tempManagedRes”未定义。我想这必须在此之前定义? 感谢您的更新。在您的示例中初始化的 iconHandle 在第一行获取 HICON,但是在调用 DestroyIcon(iconHandle) 时会导致以下错误:没有合适的从“System::IntPtr”到“HICON”的转换函数存在 @ErnestoJorge Bitmap::GetHIcon() 返回 IntPtr 而不是 HICON(分别是 struct HICON__*void*,具体取决于 STRICT 是否启用)。您必须调用DestroyIcon() 的实际 Win32 API C 声明,而不是它的 PInvoke 版本。您将不得不使用类型转换,例如 DestroyIcon((HICON)iconHandle);(我不使用 Managed C++)。 类型转换的结果相同,因为没有从 IntPtr 到 HICON 的转换。这与文档link 不匹配,因为他们调用destroyIcon(newIcon->Handle) 并且在我的代码中执行此操作也会导致“没有合适的转换”。如果Bitmap::GetHicon() 返回一个 IntPtr,文档如何调用DestroyIcon()?一旦发现其他内容,我将继续研究并更新。 @ErnestoJorge Icon::Handle 也是 IntPtr。该文档显示的是 C# 中的代码示例,而不是 C++ 中的代码示例(C# 中没有 -> 运算符),其中 DestroyIcon() 是通过使用 IntPtr 参数的 PInvoke 调用的。在 C++ 中,尝试使用IntPtr::ToPointer(),例如:DestroyIcon((HICON)iconHandle.ToPointer());

以上是关于System.Drawing.Bitmap.GetHicon() 上的 GDI 对象泄漏的主要内容,如果未能解决你的问题,请参考以下文章