1

这是我将文件名及其关联图标添加到 virtualtreeview 的简单代码

  PFileInfoRec = ^TFileInfoRec;
  TFileInfoRec = record
    strict private
      vFullPath: string;
      vFileName: string;
      vFileIcon: hIcon;
    public
      constructor Create(const FullPath: string);
      property FullPath: string read vFullPath;
      property FileNam : string read vFileName;
      property FileIcon: hIcon read vFileIcon;
  end;

在我使用 shGetFileInfo Api 获得图标句柄之后

procedure TMainFrm.VSTGetImageIndex(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
  var Ghosted: Boolean; var ImageIndex: Integer);
var
  FileInfo: PFileInfoRec;
  Icon: TIcon;
begin
  FileInfo := Sender.GetNodeData(Node);
  Icon := TIcon.Create;
  try
    Icon.Handle := FileInfo.FileIcon;
      if Kind in [ikNormal , ikSelected] then
      begin
        if Column = 1 then ImageIndex := ImageList.AddIcon(Icon);
      end;
  finally
    Icon.Free; //here the probelme
  end;
end;

删除 Icon.Free 时让我感到困惑的是什么;代码工作正常文件添加了图标,但是当免费的 TIcon 对象添加图标失败!任何人向我解释这段代码有什么问题?

我在这里先向您的帮助表示感谢...

4

1 回答 1

1

首先,你必须停止打电话ImageList.AddIconOnGetImageIndex我不会详细重复该建议,而只是将您引荐给您之前的问题

至于这里发生了什么,这就是正在发生的事情:

  1. 您创建一个图标句柄,vFileIcon.
  2. 然后,您将该图标的所有权传递给TIcon实例。
  3. 您释放图标实例,这反过来又删除了图标句柄。
  4. 下次您调用OnGetImageIndex时,图标句柄vFileIcon指的是已销毁的句柄,因此您使用该图标的尝试自然会失败。

将此图标添加到图像列表的最简单方法实际上是使用ImageList_AddIcon而不是创建TIcon实例。

FileInfo := Sender.GetNodeData(Node);
ImageList_AddIcon(ImageList.Handle, FileInfo.FileIcon);

当实例被销毁时,可以使用 aTIcon而不会销毁句柄。TIcon调用ReleaseHandle以告知TIcon实例它不再拥有图标句柄。

Icon := TIcon.Create;
try
  Icon.Handle := SomeIconHandle;
  SomeImageIndex := ImageList.AddIcon(Icon);
  Icon.ReleaseHandle;
finally
  //because ReleaseHandle was called, this no longer destroys the icon handle
  Icon.Free;
end;
于 2012-06-23T15:23:39.273 回答