Delphi中图标的线程加载



使用Delphi 2009,尝试制作一个启动器。为了让它"敏捷",我真的很想在后台线程中加载图标。

我使用了此处的解决方案:48x48或64x64图标可以从Vista Shell中获得吗?

如果不在线程中运行,这会很好地工作。一旦我把它放在线程中,一些图标就不会被"提取",或者是某种通用图标。我甚至尝试过序列化线程(实际上使它们变成obsolate),但它产生了相同的结果。

因此,问题是:如何在线程中加载图标(具有与链接示例相同的可用选项)?

/Lars

编辑:在GetIconFromFile 中添加了一些非常基本的错误检查

if SHGetFileInfo( PChar( aFile ),
                FILE_ATTRIBUTE_NORMAL,
                SFI,
                SizeOf( TSHFileInfo ),
                SHGFI_ICON
                  or SHGFI_LARGEICON
                  or SHGFI_SHELLICONSIZE
                  or SHGFI_SYSICONINDEX
                  or SHGFI_TYPENAME
                  or SHGFI_DISPLAYNAME ) <> 0 then
begin
  if not Assigned( aIcon ) then
    aIcon := TIcon.Create;
  aImgList := GetImageListSH( SHIL_FLAG );
  aIndex := SFI.iIcon;
  if aImgList <> 0 then
    aIcon.Handle := ImageList_GetIcon( aImgList, aIndex, ILD_NORMAL );
end;

这没什么区别。我仍然得到一些通用图标(不过只有在线程中调用它时)

第2版:线程代码(非常简单):

procedure TIconLoader.Execute;
var
  Item : TGridItem;
  I : TIcon;
begin
  inherited;
  while not terminated do
  begin
    Item := nil;
    if assigned(FOnNeedGridItem) then
    begin
      Synchronize(
          procedure
          begin
            FOnNeedGridItem(Self, Item);
          end
      );
    end;
    if assigned(Item) then
    begin
      GetIconFromFile(Item.FFilename, I, SHIL_EXTRALARGE);
      Synchronize(
          procedure
          begin
            Item.SetIcon(I);
          end
      );
//      I.Free;
    end
    else
      Terminate;
  end;
end;

SHGetFileInfo的文档指定在调用函数之前必须初始化COM。由于COM初始化是按线程进行的,因此需要在线程中初始化COM。这意味着从线程的Execute方法调用CoInitializeCoInitializeEx

也许您可以通过使用Delphi 2009中引入的TThread.Queue方法来简化线程代码。

这里有一篇文章给出了一些例子和背景信息:

与参数同步和排队

TThread.Queue是非阻塞的。这允许按顺序为所有图标创建后台工作线程,然后让它们异步加载。

尝试移动这个:

GetIconFromFile(Item.FFilename, I, SHIL_EXTRALARGE);

进入CCD_ 5块。并且应该在使用SHGetFileInfo()之后调用DestroyIcon()。

最新更新