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”的转换函数存在 @ErnestoJorgeBitmap::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 对象泄漏的主要内容,如果未能解决你的问题,请参考以下文章