1

タスク マネージャーを使用して動的に作成されたコントロールを監視していたところ、ImageList を使用して TreeView を作成するたびに、ツリーを破棄して再度作成するたびにGDI オブジェクトの数が 4 ずつ増加することがわかりました。ただし、ListView には問題はありませんでした。

TVS_CHECKBOXESは状態イメージの問題を知っており、すでに状態イメージリストを破棄していましたが、実装しました:

ImageList_Destroy(TreeView_SetImageList(GetHandle(), nullptr, TVSIL_NORMAL));

そして今、リソースリークはなくなりました。

これまでのところ、次の場合は手動で画像をクリーンアップする必要があるようですWM_DESTROY:

Button_SetImageList() - Have to set it to switch it to `BUTTON_IMAGELIST.himl=BCCL_NOGLYPH` to clear it.
TreeView_SetImageList(LVILS_STATE) - if you set it or used `TVS_CHECKBOXES`
TreeView_SetImageList(LVILS_NORMAL) - if you set it
BM_SETIMAGE and STM_SETIMAGE - destroy your own but also set to NULL and destroy returned handle to get rid of potential hidden bitmap handle if different handle than your own.

しかし、ListViewは異なります。それは設計によるものですか、それともWM_DESTROY次のようなものを先に進める必要がありますか:

ImageList_Destroy(ListView_SetImageList(GetHandle(), nullptr, LVSIL_STATE));
ImageList_Destroy(ListView_SetImageList(GetHandle(), nullptr, LVSIL_SMALL));
ImageList_Destroy(ListView_SetImageList(GetHandle(), nullptr, LVSIL_NORMAL));

WM_NCDESTROYTreeView の使用は遅すぎることに注意してください。

4

2 に答える 2

3

この点で、2 つのコントロールは矛盾しています。

ツリー コントロールは、与えられたイメージリストの所有権を取得しないため、それを解放する責任はユーザーにあります。

ウィンドウ スタイルを設定しない限り、リストビュー コントロール所有権を取得します。LVS_SHAREIMAGELISTS

ツリー コントロールにも関連する癖があることに注意してください。スタイルを設定すると、TVS_CHECKBOXES作成していなくても、状態のイメージ リストを解放する責任があります。

于 2021-09-18T02:40:20.807 に答える
1

あなたが見ているのは、文書化された動作です。

TreeView の場合:

TVM_SETIMAGELIST メッセージ
TreeView_SetImageList マクロ

ツリー ビュー コントロールは、このメッセージで指定されたイメージ リストを破棄しません。不要になったイメージ リストは、アプリケーションで破棄する必要があります。

としても:

ツリー ビュー コントロール ウィンドウのスタイル

絶え間ない 説明
TVS_CHECKBOXES バージョン 4.70。ツリー ビュー コントロールの項目のチェック ボックスを有効にします。チェック ボックスは、画像がアイテムに関連付けられている場合にのみ表示されます。このスタイルに設定すると、コントロールは DrawFrameControl を効果的に使用して、2 つの画像を含む状態の画像リストを作成および設定します。状態の画像 1 はチェックされていないボックスで、状態の画像 2 はチェックされているボックスです。状態イメージをゼロに設定すると、チェック ボックスが完全に削除されます。詳細については、状態イメージ インデックスの操作を参照してください。

バージョン 5.80。アイテムに画像が関連付けられていない場合でも、チェック ボックスを表示します。ツリー ビュー コントロールがこのスタイルで作成されると、スタイルは削除できません。代わりに、コントロールを破棄し、代わりに新しいコントロールを作成する必要があります。ツリー ビュー コントロールを破棄しても、チェック ボックスの状態のイメージ リストは破棄されません。明示的に破棄する必要があります。ツリー ビュー コントロールにTVM_GETIMAGELISTメッセージを送信して、状態イメージ リストへのハンドルを取得します。次に、イメージ リストを で破棄しImageList_Destroyます。

このスタイルを使用する場合は、ツリービュー コントロールを作成した後、ツリーを設定する前にTVS_CHECKBOXESスタイルを設定する必要があります。SetWindowLongそうしないと、タイミングの問題によっては、チェックボックスがチェックされていないように見えることがあります。

ListView との比較:

LVM_SETIMAGELIST メッセージ
ListView_SetImageList マクロ

LVS_SHAREIMAGELISTSスタイルが設定されていない限り、リスト ビュー コントロールが破棄されると、現在のイメージ リストが破棄されます。このメッセージを使用して 1 つのイメージ リストを別のイメージ リストに置き換える場合、アプリケーションは現在のイメージ リスト以外のすべてのイメージ リストを明示的に破棄する必要があります。

于 2021-09-18T02:40:31.510 に答える