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。共有アイコンであることの結果の1つは、を呼び出す必要がないことですDestroyIcon

次の関数で作成されたアイコンとカーソルに対してのみDestroyIconを呼び出す必要があります: CreateIconFromResourceExLR_SHAREDフラグなしで呼び出された場合)、CreateIconIndirect、およびCopyIcon。この機能を使用して共有アイコンを破棄しないでください。共有アイコンは、それがロードされたモジュールがメモリに残っている限り有効です。次の関数は、共有アイコンを取得します。

  • LoadIcon
  • LoadImage ( LR_SHAREDフラグを使用する場合)
  • CopyImageLR_COPYRETURNORGフラグを使用し、hImageパラメーターが共有アイコンである場合)
  • CreateIconFromResource
  • CreateIconFromResourceEx ( LR_SHAREDフラグを使用する場合)

では、これはあなたのコードとどのように関係していますか?さて、あなたが書くとき

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

Handleオブジェクトのプロパティに割り当てていTIconます。そのTIconオブジェクトにすでにアイコンが含まれている場合、そのアイコンは新しいアイコンに置き換えられる前に破棄されます。これTIconは、アイコンハンドルの所有権があるためです。これはすべて、上記のコード行がDestroyIcon共有アイコンの呼び出しになることを意味します。これはMSDNがやらないように言っていることですが、実際には良性であることがわかります。心配する必要はありません。

これで、非共有アイコンを返す関数を使用している場合でも、たとえばCreateIconIndirect、コードがアイコンハンドルをリークすることはありません。これは、TIconクラスがアイコンハンドルの所有権を引き継ぐためです。

ただし、共有アイコンを使用しているため、これらのハンドルをリークすることさえできません。破壊できないもの、漏れないもの!

さらにいくつかのポイント:

  1. 私は個人的にLoadIconそのように何度も何度も電話することはありません。プログラムの起動時に2回呼び出し、共有アイコンのハンドルを覚えています。次に、それらのハンドルを使用してに割り当てTrayIcon.Icon.Handleます。
  2. 電話をかけるLoadIconと、返されるアイコンのサイズをあまり制御できません。小さいアイコンではなく、大きいアイコンが表示される可能性があると思います。そして、それは表示する前に小さなアイコンサイズに拡大縮小する必要があります。通知領域のアイコンを作成するときはSM_CXSMICONSM_CYSMICONサイズ別になっていることを確認する必要があります。
于 2013-03-21T21:36:24.327 に答える