5

我正在使用此代码为线程中的托盘图标设置动画(icon1 和 icon2 在 .res 文件中):

while AnimationPending do
begin
    TrayIcon.Icon.Handle := LoadIcon(hInstance,'icon1');
    Sleep(300);
    TrayIcon.Icon.Handle := LoadIcon(hInstance,'icon2');
    Sleep(300);
end;

我担心如果我在循环中执行它可能会造成内存泄漏,因为 icon1/2 会重新加载。

代码是否会造成内存泄漏,或者在循环中使用是否安全?

4

1 回答 1

9

你在打电话LoadIcon。这将返回所谓的共享图标。这在DestroyIcon. 成为共享图标的后果之一是您不需要调用DestroyIcon.

只需为使用以下函数创建的图标和光标调用DestroyIcon : CreateIconFromResourceEx(如果在没有LR_SHARED标志的情况下调用)、CreateIconIndirectCopyIcon。请勿使用此功能破坏共享图标。只要加载它的模块仍在内存中,共享图标就有效。以下函数获取共享图标。

  • 加载图标
  • LoadImage(如果您使用LR_SHARED标志)
  • CopyImage(如果您使用LR_COPYRETURNORG标志并且 hImage 参数是共享图标)
  • CreateIconFromResource
  • CreateIconFromResourceEx(如果您使用LR_SHARED标志)

那么,这与您的代码有何关系?好吧,当你写

TrayIcon.Icon.Handle := LoadIcon(hInstance,'icon1');

您正在分配给对象的Handle属性TIcon。如果该TIcon对象已经包含一个图标,则该图标将在被新图标替换之前被销毁。那是因为TIcon拥有其图标句柄的所有权。所有这一切都意味着上面的代码行导致了DestroyIcon对共享图标的调用。这是 MSDN 告诉你不要做的,但实际上它是良性的。没什么好担心的。

现在,即使您使用的是返回非共享图标的函数,例如CreateIconIndirect,您的代码也不会泄漏图标句柄。这是因为TIcon该类拥有图标句柄的所有权。

但是由于您使用的是共享图标,因此甚至不可能泄漏这些句柄。不能破坏的对象,不能泄露!

还有几点:

  1. 我个人不会LoadIcon像那样一遍又一遍地打电话。我会在程序启动时调用它两次并记住共享图标句柄。然后我会使用这些句柄分配给TrayIcon.Icon.Handle.
  2. 当您打电话时,LoadIcon您无法控制返回的图标的大小。我认为您可能会得到一个大图标而不是小图标。这需要在显示之前缩放到小图标大小。创建通知区域图标时,您应该确保它们SM_CXSMICONSM_CYSMICON大小排列。
于 2013-03-21T21:36:24.327 回答