Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.12.11;
Скачать: CL | DM;

Вниз

Получение иконок типов файлов - как сделать быстрее?   Найти похожие ветки 

 
kami ©   (2005-11-26 14:52) [0]

Написал такой код:

var
 Strings:TStringList;
const
 StepLoadIcons=30;

procedure TfmMain.FillExtList;
const
 Flag=SHGFI_ICON or SHGFI_LARGEICON or SHGFI_USEFILEATTRIBUTES;
var
 r:TRegistry;
 i:integer;
 s:string;
 fi: _SHFILEINFOA;
begin
 Strings.BeginUpdate;
 r:=TRegistry.Create(KEY_READ);
 r.RootKey:=HKey_Classes_Root;
 r.OpenKey("",false);
 r.GetKeyNames(Strings);
 r.Free;

 i:=Strings.Count-1;
 While Strings.Strings[i][1]<>"." do
   begin
     Strings.Delete(i); // удалили все до последнего зарегистрированного
     dec(i);            // типа файла
   end;
 fmLoading.ProgressBar1.Max:=Strings.Count-1;
 fmLoading.ProgressBar1.Step:=StepLoadIcons;

 i:=1;// потому что нулевой элемент имеет имя "/"
 CoInitialize(nil);
 repeat
   s:=Strings.Strings[i];
   if (i mod StepLoadIcons)=0 then  
     begin      // если убрать отображение прогресса, то загрузка становится всего на 3-5 с. быстрее
       fmLoading.lbDescription.Caption:="Загружается : иконка "+s;
       fmLoading.ProgressBar1.StepIt;
       Application.ProcessMessages;
     end;
   ZeroMemory(@fi, SizeOf(fi));
   SHGetFileInfo(@s[1], FILE_ATTRIBUTE_NORMAL, fi, SizeOf(fi),Flag);// тормоза возникают (скорее всего) именно здесь
   ImageList_AddIcon(ImageList.Handle,fi.hIcon);
   inc(i);
 until i=Strings.Count;

 Strings.EndUpdate;
 CoUninitialize;
end;


Этот код выполняется при запуске программы, и отрабатывает секунд за 20-30 при первом запуске, при последующих (наверное, из-за буферизации) секунд за 7-10. Получение всех зарегистрированных расширений из реестра проходит почти моментально, а вот само получение иконок - очень долго, на мой взгляд.
 Как можно ускорить этот процесс? Может, есть другие ф-и получения иконки без наличия самого файла, которые будут работать быстрее? (нужна пара "расширение файла"-"иконка") ?


 
Eraser ©   (2005-11-26 15:16) [1]


> kami ©   (26.11.05 14:52)

Всё гораздо проще )
Получить список всех зарегистрированых иконок можно так
   ilIcons.Handle := SHGetFileInfo(PChar(""),
     0,
     FileInfo,
     SizeOf(TSHFileInfo),
     SHGFI_ADDOVERLAYS or
     SHGFI_ICON or SHGFI_SMALLICON or
     SHGFI_SYSICONINDEX);
, где
ilIcons: TImageList.
не забудь предварительно поставить ilIcons.ShareImages := true;<.CODE>
Чтобы потом получить доступ к нужной иконки - просто бери её индекс и обращайся к нужному элементу в ilIcons.

       SHGetFileInfo(PChar(ListItem.Caption),
           FILE_ATTRIBUTE_NORMAL,
           FileInfo,
           SizeOf(TSHFileInfo),
           SHGFI_USEFILEATTRIBUTES or
           SHGFI_ICON or SHGFI_SMALLICON or
           SHGFI_TYPENAME or
           SHGFI_SYSICONINDEX or SHGFI_ADDOVERLAYS);
...
 ListItem.ImageIndex := FileInfo.iIcon;


 
Lamer@fools.ua ©   (2005-11-26 15:26) [2]

Попробуйте убрать SHGFI_USEFILEATTRIBUTES из const Flag.


 
kami ©   (2005-11-26 15:34) [3]

Eraser ©   (26.11.05 15:16) [1]

Точно !!!
Давно пытался найти, как получается системный ImageList, но не нашел, где.

Спасибо!!!


 
kami ©   (2005-11-26 19:16) [4]

Eraser ©   (26.11.05 15:16) [1]

Поясни, пожалуйста.
Ну, получение хендла системного ImageList понятно (хотя, несовсем, но разберусь).
Сейчас сделал тестовую программку, так она выдает, что изначально в ImageList всего 4 иконки, а потом, при загрузке иконки конкретного типа файла, она добавляется в список. То есть, в системном списке иконок у них нет фиксированного индекса, по которому в любой момент можно было бы обратиться, и более того - даже наличие иконки необязательно ? Как-то это ... нездОрово. -\


 
Eraser ©   (2005-11-26 20:15) [5]


> kami ©   (26.11.05 19:16) [4]


>  То есть, в системном списке иконок у них нет фиксированного
> индекса, по которому в любой момент можно было бы обратиться,
>  и более того - даже наличие иконки необязательно ?

Фиксированный индекс как раз таки есть, но только он будет различный для различных процессов.
Once you have a handle to a system image list, you can use the Image List API to manipulate it like any other image list. Because system image lists are created on a per-process basis, you should treat them as read-only objects. Writing to a system image list may overwrite or delete one of the system images, making it unavailable or incorrect for the remainder of the process.


Читай MSDN.


 
Eraser ©   (2005-11-26 20:25) [6]


> kami ©   (26.11.05 19:16) [4]

Более того, ты можешь добавлять свои иконки в системный список иконок своего процесса.


 
kami ©   (2005-11-26 21:26) [7]

Eraser ©   (26.11.05 20:15) [5]
будет различный для различных процессов

Именно это я и имел ввиду, что нельзя однозначно сказать, что иконка №5 будет (допустим) от .folder, все зависит от того, когда ее затребуют.

> Читай MSDN.

Сперва именно его и читаю. Вот что упустил - так это что системный список именно создается для конкретного процесса (думал, что он один на всех). Каюсь, грешен :)

Видимо, придется смириться, ну да ладно - уже все переделал под эту особенность :)
Спасибо.



Страницы: 1 вся ветка

Текущий архив: 2005.12.11;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.036 c
2-1132921845
brownrat
2005-11-25 15:30
2005.12.11
доступ к компоненте другой программы


2-1132703422
SergP
2005-11-23 02:50
2005.12.11
Update одной таблицы из другой.


2-1133111316
Volfram
2005-11-27 20:08
2005.12.11
TDrawGrid


3-1130055239
ViktorZ
2005-10-23 12:13
2005.12.11
Ошибки не выдает ,но и не делает того, что надо


14-1132411904
QwertyKz
2005-11-19 17:51
2005.12.11
Microsoft Jet Непонятная ошибка