4

使用Delphi 2009,尝试做一个启动器。为了让它“活泼”,我真的很想在后台线程中加载图标。

我使用了此处找到的解决方案: Can 48x48 or 64x64 icons be getting from the Vista Shell?

如果不在线程中运行,这可以正常工作。一旦我把它放在一个线程中,一些图标就不是“获取”的,或者是某种通用图标。我什至尝试序列化线程(实际上使它们过时),但它产生了相同的结果。

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

/拉尔斯

编辑:在 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;

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

Edit2:线程代码(非常简单):

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;
4

3 回答 3

2

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

于 2012-07-10T06:23:08.107 回答
0

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

一篇提供一些示例和背景信息的文章在这里:

使用参数同步和排队

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

于 2012-07-09T17:50:41.327 回答
-1

尝试移动这个:

GetIconFromFile(Item.FFilename, I, SHIL_EXTRALARGE);

synchronize块。你应该在使用后调用DestroyIcon()SHGetFileInfo()

于 2012-07-10T01:25:49.490 回答