【问题标题】:virtualtreeview add icon failvirtualtreeview 添加图标失败
【发布时间】:2012-06-25 14:03:39
【问题描述】:

这是我将文件名及其关联图标添加到 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 对象添加图标失败!任何人向我解释 这段代码有什么问题??

提前感谢您的帮助...

【问题讨论】:

  • @S.FATEH,首先,VirtualTreeView 不需要class record,除非您具有需要记录构造函数和属性的特定功能。您需要一个简单的packed record。其次,在设计时将那个图标加载到TImageList,然后在运行时只在OnGetImageIndex中设置它的ImageIndex。其他都不需要。
  • 我错过了“使用 shGetFileInfo 获取图标句柄”部分。您应该在应用程序启动时将所需的图像加载到TImageList。然后将vFileIcon字段设置为Integer,并将其设置为指向该文件对应图像的Index。最后,在OnGetImageIndex 中使用 vFileIcon 来告诉 VirtualTreeView 为该文件显示哪个图标。基本上,您需要检查您的逻辑,因为必须以特定方式使用 VirtualTreeView。
  • LightBulb 这正是我所做的记录在另一个单元中,是的,还有另一个功能,我在上面添加的代码用于说明,对不起我的床英语:)...

标签: delphi icons virtualtreeview


【解决方案1】:

首先,您必须停止在OnGetImageIndex 中调用ImageList.AddIcon。我不会详细重复这些建议,只是将您推荐给your previous question

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

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

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

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

TIcon 实例被销毁时,可以使用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;

【讨论】:

  • 我的回答的最后一部分告诉你如何做到这一点
  • 大卫赫弗南感谢 Icon.ReleaseHandle;这正是我需要像魅力一样工作:)
  • 你明白每次OnGetImageIndex运行都加图标是站不住脚的吗?
  • 好的,我明白了,下次我会使用 OnInitNode 事件
  • 但在调用Invalidate 方法和RepaintNode 时似乎没有发生OnInitNode 事件,所以我无法在运行时刷新图标...
猜你喜欢
  • 2023-03-20
  • 2021-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-03
相关资源
最近更新 更多