![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Получение иконок типов файлов - как сделать быстрее?
kami © (2005-11-26 14:52:00)Написал такой код:
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. Получение всех зарегистрированных расширений из реестра проходит почти моментально, а вот само получение иконок - очень долго, на мой взгляд.
Как можно ускорить этот процесс? Может, есть другие ф-и получения иконки без наличия самого файла, которые будут работать быстрее? (нужна пара "расширение файла"-"иконка") ?
kami (2005-11-26 21:26:00) [1]Eraser © (26.11.05 20:15) [5]
будет различный для различных процессов
Именно это я и имел ввиду, что нельзя однозначно сказать, что иконка №5 будет (допустим) от .folder, все зависит от того, когда ее затребуют.
> Читай MSDN.
Сперва именно его и читаю. Вот что упустил - так это что системный список именно создаетсядля конкретногопроцесса (думал, что он один на всех). Каюсь, грешен :)
Видимо, придется смириться, ну да ладно - уже все переделал под эту особенность :)
Спасибо.
Eraser (2005-11-26 20:25:00) [2]
> kami © (26.11.05 19:16) [4]
Более того, ты можешь добавлять своииконки в системный список иконок своего процесса.
Eraser (2005-11-26 20:15:00) [3]
> 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.
kami (2005-11-26 19:16:00) [4]Eraser © (26.11.05 15:16) [1]
Поясни, пожалуйста.
Ну, получение хендла системного ImageList понятно (хотя, несовсем, но разберусь).
Сейчас сделал тестовую программку, так она выдает, что изначально в ImageList всего 4 иконки, а потом, при загрузке иконки конкретного типа файла, она добавляется в список. То есть, в системномсписке иконок у них нет фиксированного индекса, по которому в любой момент можно было бы обратиться, и более того - даже наличие иконки необязательно ? Как-то это ... нездОрово. -\
kami (2005-11-26 15:34:00) [5]Eraser © (26.11.05 15:16) [1]
Точно !!!
Давно пытался найти, как получается системный ImageList, но не нашел, где.
Спасибо!!!
Lamer@fools.ua (2005-11-26 15:26:00) [6]Попробуйте убрать SHGFI_USEFILEATTRIBUTESиз
const Flag.
Eraser (2005-11-26 15:16:00) [7]
> 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;