【问题标题】:Threaded loading of icons in DelphiDelphi中图标的线程加载
【发布时间】:2012-07-09 11:18:51
【问题描述】:

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

我已使用此处找到的解决方案: Can 48x48 or 64x64 icons be obtained 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;

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

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

【问题讨论】:

  • 显示您目前所获得的信息,以便我们提供帮助...
  • 你已经添加了代码,但是你没有调用CoInitialize。该文档明确指出您必须这样做。你在上面的评论中说你已经这样做了。您是否意识到对CoInitialize 的调用必须从调用SHGetFileInfo 的线程进行?
  • TThread 构造函数在主线程中运行!
  • 这意味着你必须在执行部分调用 CoInitialize。
  • @LURD 是对的。您需要在线程中初始化 com。这意味着内部执行。

标签: delphi icons delphi-2009


【解决方案1】:

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

【讨论】:

  • 您接受了答案。然后不接受。有问题吗?
【解决方案2】:

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

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

Synchronize and Queue with Parameters

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

【讨论】:

  • 我几乎 100% 确定这不是线程代码问题。我有一些简单对象的简单列表,其中包含文件名和 TIcon。我已经尝试为每个对象创建一个线程,以及上面创建线程的位置,并在需要时手动提供对象。无论我如何从线程中调用 GetIconFromFile,它最终都会给我错误的图标。如果我从主线程进行调用,一切都很好...... ??
  • 哦,只是为了好玩,我尝试将 GetIconFromFile 包装在 TCriticalSection 中。这没有任何区别......
【解决方案3】:

尝试移动这个:

GetIconFromFile(Item.FFilename, I, SHIL_EXTRALARGE);

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

【讨论】:

  • 这会破坏使用线程的全部目的,不是吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-04
  • 2011-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-29
相关资源
最近更新 更多