2012-01-13 10 views
1

私が使用しているSHGetFileInfoW関数に問題があります。SHGetFileInfoW関数の代入

スタートアップ(初期化)時に最初の読み取りが非常に遅く、100msを消費します。

MSDNでは、プロセスがスタックされる可能性があるため、メインスレッドではなくスレッドから読み込む必要があります。

もしあれば、私はアイコンを読むためにいくつかの他の機能を使いたいです。

別のこと。どのように大きなアイコンを読むことが可能です、現在私は32x32(SHGFI_LARGEICON)まで読むことができます

ありがとう!

実際のコード:

procedure TForm1.LoadIcons; 
var 
    Info:  TShFileInfo; 
    Icon:  TIcon; 
    Flags: UINT; 
    FileName: PAnsiChar; 

begin 
    FileName := '.txt'; 
    Flags := SHGFI_USEFILEATTRIBUTES or SHGFI_ICON or SHGFI_LARGEICON; 
    Icon := TIcon.Create; 
    try 
    SHGetFileInfo(FileName, FILE_ATTRIBUTE_NORMAL, Info, 
     SizeOf(Info), Flags); 
    Icon.Handle := Info.hIcon; 
    Image1.Picture.Assign(Icon); 
    Image1.Refresh; 
    finally 
    DestroyIcon(Info.hIcon); 
    Icon.Free; 
    end; 
end; 
+1

スレッドで実行するだけです。また、起動時にすべてのアイコンを読み込まず、必要に応じて読むだけです。 AsyncCallsは仕事をかなり簡単に完了させるでしょう。 –

+1

問題が初期読み込みにあります。私が最初のアイコンを読むとき、私は80 + msを過ごす。次の20個のアイコンを読むと、別の20msを消費します。 私はAsyncCallsでこれを読んでいます(他のトピックでこれについて議論しました)、それはうまく動作しますが、スピードを上げたいと思っています。 –

+0

実際のコードを表示してください。 –

答えて

3

レジストリから、指定されたファイルの拡張子についてDefaultIconを見つけ、ExtractIconExを使用することができます。 Here is an example

それはSHGetFileInfo

EDITよりも高速だ場合、私は知らない。私は(サンプルから)拡張からアイコンを取得する部分を抽出している

。 実際には非常に高速です。より多く最適化することができます。

// find the icon for a certain file extension in the registry 
function TForm1.RegistryIconExtraction(Extension : string): integer; 
var 
    RegKey : TRegistry; 
    IconPos : integer; 
    AssocAppInfo : string; 
    ExtractPath, FileName : string; 
    IconHandle, PLargeIcon, PSmallIcon : HICON; 
    AnIcon : TIcon; 

begin 
    Result := 0; // default icon 

    if Extension[1] <> '.' then Extension := '.' + Extension; 

    RegKey := TRegistry.Create(KEY_READ); 
    try 
    // KEY_QUERY_VALUE grants permission to query subkey data. 
    RegKey.RootKey := HKEY_CLASSES_ROOT; // set folder for icon info lookup 
    if RegKey.OpenKeyReadOnly(Extension) then // extension key exists? 
    try 
     AssocAppInfo := RegKey.ReadString(''); // read app key 
     RegKey.CloseKey; 
    except 
     Exit; 
    end; 
    if ((AssocAppInfo <> '') and // app key and icon info exists? 
     (RegKey.OpenKeyReadOnly(AssocAppInfo + '\DefaultIcon'))) then 
    try 
     ExtractPath := RegKey.ReadString(''); // icon path 
     RegKey.CloseKey; 
    except 
     Exit; 
    end; 
    finally 
    RegKey.Free; 
    end; 

    // IconPos after comma in key ie: C:\Program Files\Winzip\Winzip.Exe,0 
    // did we get a key for icon, does IconPos exist after comma seperator? 
    If ((ExtractPath <> '') and (pos(',', ExtractPath) <> 0)) then 
    begin 

    // Filename in registry key is before the comma seperator 
    FileName := Copy(ExtractPath, 1, Pos(',', ExtractPath) - 1); 
    // extract the icon Index from after the comma in the ExtractPath string 
    try 
     IconPos := StrToInt(copy(ExtractPath, Pos(',', ExtractPath) + 1, 
     Length(ExtractPath) - Pos(',', ExtractPath) + 1)); 
    except 
     Exit; 
    end; 

    IconHandle := ExtractIconEx(PChar(FileName), IconPos, PLargeIcon, PSmallIcon, 1); 

    If (PLargeIcon <> 0) then 
    begin 
     AnIcon := TIcon.Create; 
     AnIcon.Handle := PLargeIcon; 

     Image1.Picture.Assign(AnIcon); 
     Image1.Refresh; 

     AnIcon.Free; 
    end; 

    DestroyIcon(PLargeIcon); 
    DestroyIcon(PSmallIcon); 
    end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    t1, t2: DWORD; 
begin 
    t1 := GetTickCount; 
    RegistryIconExtraction('.txt'); 
    t2 := GetTickCount; 
    Memo1.Lines.Add(IntToStr(t2-t1)); 
end; 

EDIT2:サンプルコードは今ビスタ/ Win7のUACに準拠して は(私は、コードビットを修正しました)。

+0

これは私が必要とするものの解決策ではありません。この関数は、exeまたはdllからアイコンを抽出し、私は拡張機能で動作しません。 –

+1

この例をもう一度見てください... – kobik

+0

UACをオンにしてWin7でこれを試しましたか? HKEY_CLASSES_ROOTを定期的に読むためには、ユーザー特権をAdminに昇格させる必要があります。これは私がレジストリから直接読むことができない理由です。 これ以外の場合、これは有限の解決策になります。 –

関連する問題