使用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;
这不会造成任何不同。 我仍然得到一些通用图标(只有在线程中调用它时)
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 :(得分:2)
SHGetFileInfo
的文档指定在调用函数之前必须初始化COM。由于COM初始化是每个线程,因此需要在线程中初始化COM。这意味着从该帖子的CoInitialize
方法调用CoInitializeEx
或Execute
。
答案 1 :(得分:0)
也许您可以使用Delphi 2009中引入的TThread.Queue方法来简化线程代码。
提供一些示例和背景信息的文章在这里:
Synchronize and Queue with Parameters
TThread.Queue是非阻塞的。这允许为所有图标顺序创建后台工作线程,然后让它们异步加载。
答案 2 :(得分:-1)
尝试移动它:
GetIconFromFile(Item.FFilename, I, SHIL_EXTRALARGE);
进入synchronize
区块。使用SHGetFileInfo()
后,您应该致电DestroyIcon()。