2012-07-09 74 views
4

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

我已经用在这里找到了解决办法: Can 48x48 or 64x64 icons be obtained from the Vista Shell?

这工作得很好,如果不是在一个线程中运行。 只要我把它放在一个线程中,一些图标就不会被“提取”,或者是某种通用图标。 我甚至尝试序列化线程(使它们obsolote,实际上),但它产生相同的结果。

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

/拉尔斯

编辑: 增加了一些非常基本的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; 

此不作任何diffenrence。 我仍然得到了一些通用的图标(只有当这种被称为一个线程,虽然)

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; 
+0

显示你得到的沙发,所以我们可以帮助... – whosrdaddy 2012-07-09 11:38:51

+0

那么,没有太多显示。我有链接示例中的过程。我尝试了不同的线程方法,但每个人都给出相同的(错误的)结果。 – 2012-07-09 12:22:45

+0

api调用返回了哪些错误?你是否初始化COM? – 2012-07-09 12:24:17

回答

2

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

+0

你接受了答案。然后不被接受。有问题吗? – 2012-07-10 06:48:07

+0

Nonono ...只是不小心再次点击复选标记... – 2012-07-10 18:14:48

+0

好的。感谢你的接纳! – 2012-07-10 19:27:09

0

也许你可以简化你的线程代码使用在2009年德尔福

的物品,其给出了一些例子和背景资料介绍,TThread.Queue方法是在这里:

Synchronize and Queue with Parameters

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

+0

我几乎100%肯定它不是线程代码问题。我有一个简单的对象列表,它包含一个文件名和一个TIcon。我已经尝试为每个对象创建一个线程,并在上面创建线程,并在需要时手动添加对象。无论我如何从线程中调用GetIconFromFile,它最终都会给我错误的图标。如果我从主线程调用,一切都很好......? – 2012-07-09 18:20:43

+0

哦,只是为了好玩,我试着在TCriticalSection中封装GetIconFromFile。这并没有什么区别...... – 2012-07-09 18:25:33

-1

尝试移动此:

GetIconFromFile(Item.FFilename, I, SHIL_EXTRALARGE); 

synchronize块。使用SHGetFileInfo()后,您应该致电DestroyIcon()

+1

这将打败使用线程的整个目的,不是吗? – 2012-07-10 04:14:42