Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.216.186.164] |
|
Сообщ.
#1
,
|
|
|
Никак не могу найти простого примера получения иконки файла с помощью IExtractIcon. Может у кого найдется примерчик?
|
Сообщ.
#2
,
|
|
|
Обязательно IExtractIcon?
SHGetFileInfo не подойдет? Недавно FAQ пополнился на этот счет: Ассоциированные с файлом иконки. Тут ещё что-то есть: http://stackoverflow.com/questions/3032435/delphi-shell-iextracticon-usage-and-result |
Сообщ.
#3
,
|
|
|
Спасибо, но нужно именно IExtractIcon
Добавлено Цитата Lumen @ Тут ещё что-то есть: все это видено много раз... не ясно, что с этим огрызком кода делать. |
Сообщ.
#4
,
|
|
|
Цитата shershen @ Может у кого найдется примерчик? А в чём проблема-то? Цитата MSDN To use IExtractIcon to retrieve an object's icon, do the following: 1. Get a pointer to the IShellFolder interface of the folder that contains the object. 2. Call IShellFolder::GetUIObjectOf with the pointer to an item identifier list (PIDL) of the object and the interface ID of IExtractIcon (IID_IExtractIcon). The folder creates an object to handle the icon extraction, and returns the object's IExtractIcon interface pointer. 3. Call IExtractIcon::GetIconLocation to retrieve the icon's location. 4. Call IExtractIcon::Extract to retrieve the icon's handle. Примеры на Delphi по работе с интерфейсами оболочки можно глянуть тут или тут. Не IExtractIcon, конечно, но принципы можно посмотреть. |
Сообщ.
#5
,
|
|
|
Есть вот такой странный код на билдере, работает немного кривенько, но чем богаты... может кто не сочтет за труд перевести на дельфи?
typedef void (WINAPI *fnILFree)(LPCITEMIDLIST); static fnILFree MSILFree = NULL; typedef LPITEMIDLIST (WINAPI *fnILClone)(LPCITEMIDLIST); static fnILClone MSILClone = NULL; typedef LPITEMIDLIST (WINAPI *fnILFindLastID)(LPCITEMIDLIST); static fnILFindLastID MSILFindLastID = NULL; typedef BOOL (WINAPI *fnILRemoveLastID)(LPCITEMIDLIST); static fnILRemoveLastID MSILRemoveLastID = NULL; typedef UINT (WINAPI *fnPrivateExtractIcons)(LPCTSTR, int, int, int, HICON*, UINT*, UINT, UINT); static fnPrivateExtractIcons MSPrivateExtractIcons = NULL; typedef UINT (WINAPI *fnPickIcon)(HWND, WCHAR*, UINT, int*); static fnPickIcon MSPickIcon = NULL; HICON EGGetIcon(WCHAR *file, UINT iconSize) { HICON icon = NULL, tmpIcon = NULL; IShellFolder *deskFolder = NULL; IShellFolder *appObject = NULL; LPITEMIDLIST pidlLocal = NULL; LPITEMIDLIST pidlRelative = NULL; IExtractIcon *extractIcon = NULL; WCHAR iconLocation[MAX_PATH]; int iconIndex = 0; UINT iconFlags = 0; HRESULT hr; if (MSILFree == NULL) MSILFree = (fnILFree)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), (LPCSTR)155); // MSILFree = (fnILFree)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), "ILFree"); if (MSILClone == NULL) MSILClone = (fnILClone)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), (LPCSTR)18); // MSILClone = (fnILClone)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), "ILClone"); if (MSILFindLastID == NULL) MSILFindLastID = (fnILFindLastID)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), (LPCSTR)16); // MSILFindLastID = (fnILFindLastID)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), "ILFindLastID"); if (MSILRemoveLastID == NULL) MSILRemoveLastID = (fnILRemoveLastID)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), (LPCSTR)17); // MSILRemoveLastID = (fnILRemoveLastID)GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), "ILRemoveLastID"); hr = SHGetDesktopFolder(&deskFolder); if (FAILED(hr)) return icon; hr = deskFolder->ParseDisplayName(NULL, NULL, file, NULL, &pidlLocal, NULL); if (FAILED(hr)) { deskFolder->Release(); return icon; } pidlRelative = MSILClone(MSILFindLastID(pidlLocal)); MSILRemoveLastID(pidlLocal); hr = deskFolder->BindToObject(pidlLocal, NULL, IID_IShellFolder, (void**)&appObject); if (FAILED(hr)) { deskFolder->Release(); MSILFree(pidlLocal); return icon; } MSILFree(pidlLocal); hr = appObject->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST*)&pidlRelative, IID_IExtractIcon, NULL, (void**)&extractIcon); if (FAILED(hr)) { deskFolder->Release(); appObject->Release(); MSILFree(pidlRelative); return icon; } MSILFree(pidlRelative); hr = extractIcon->GetIconLocation(0, iconLocation, MAX_PATH, &iconIndex, &iconFlags); if (FAILED(hr)) { deskFolder->Release(); appObject->Release(); return icon; } if (iconSize == 16) hr = extractIcon->Extract(iconLocation, iconIndex, &tmpIcon, &icon, MAKELONG(32, 16)); else hr = extractIcon->Extract(iconLocation, iconIndex, &icon, &tmpIcon, MAKELONG(iconSize, 16)); if (SUCCEEDED(hr)) { DestroyIcon(tmpIcon); } extractIcon->Release(); appObject->Release(); deskFolder->Release(); return icon; } |
Сообщ.
#6
,
|
|
|
uses Windows,ShlObj; function EGGetIcon(FileName:PChar; iconSize:Integer):HICON; var tmpIcon:HICON; deskFolder,appObject:IShellFolder; pidlLocal, pidlRelative: PItemIDList; extractIcon:IExtractIcon; iconLocation:array[0..MAX_PATH-1] of Char; iconIndex:integer; pchEaten,dwAttrib,iconFlags:Cardinal; hr:HRESULT; begin Result:=0; if FAILED(SHGetDesktopFolder(deskFolder)) then exit; if FAILED(deskFolder.ParseDisplayName(0, nil, FileName, pchEaten, pidlLocal, dwAttrib)) then exit; pidlRelative := ILClone(ILFindLastID(pidlLocal)); ILRemoveLastID(pidlLocal); hr := deskFolder.BindToObject(pidlLocal, nil, IID_IShellFolder, appObject); ILFree(pidlLocal); if FAILED(hr) then exit; hr := appObject.GetUIObjectOf(0, 1, pidlRelative, IID_IExtractIconW, nil,extractIcon); ILFree(pidlRelative); if FAILED(hr) then exit; if FAILED(extractIcon.GetIconLocation(0, iconLocation, MAX_PATH, iconIndex, iconFlags)) then exit; if (iconSize = 16) then hr := extractIcon.Extract(iconLocation, iconIndex, tmpIcon, Result, MAKELONG(32, 16)) else hr := extractIcon.Extract(iconLocation, iconIndex, Result, tmpIcon, MAKELONG(iconSize, 16)); if SUCCEEDED(hr) then DestroyIcon(tmpIcon); end; procedure TForm1.Button1Click(Sender: TObject); var icon:HICON; begin icon:=EGGetIcon('C:\WINDOWS\MEDIA\ding.wav',32); Image1.Picture.Icon.Handle:=icon end; |
Сообщ.
#7
,
|
|
|
Krid, спасибо большое.
Теперь другой вопрос, почему IExtractIcon::Extract на некоторые файлы возвращает S_FALSE? В Мсдн написано "The icon location and index are the same values returned by the IExtractIcon::GetIconLocation method. If IExtractIcon::Extract function returns S_FALSE, these values must specify an icon file name and index that form legal parameters for a call to ExtractIcon. " , но как-то это мне не сильно помогло... |
Сообщ.
#8
,
|
|
|
Если Extract возвращает S_FALSE, то это означает, что значения iconLocation и iconIndex (полученные в GetIconLocation) - валидны и определяют имя файла с иконкой и индекс (порядковый номер) этой иконки в файле. В этом случае проводник сам извлекает иконку либо по этим данным (передав их, например в ExtractIcon), либо из кэша (если иконка там есть).
Ну а если возвращается S_OK, то в принципе происходит тоже самое, но iconLocation и iconIndex могут быть не валидны и кэш иконок проводника может не использоваться (что несколько замедляет работу для большого кол-ва файлов). Иконки тут извлекает соотв. само приложение (т.е. метод Extract). Вобщем-то всё зависит от флагов и от установленых расширений оболочки, реализующих интерфейс IExtractIcon для конкретных файлов. Кстати, возвращаемое Extract'ом значение нужно (и важно) тому, кто пишет такие расширения. А тебе в данном случае абсолютно без разницы, что возвращает Extract. Иконку ты всё равно получишь Результат вызова Extract'а по сути просто показывает, какие внутренние механизмы были использованы для получения иконки. |
Сообщ.
#9
,
|
|
|
Цитата Krid @ Иконку ты всё равно получишь Так я бы и не парился, если бы так и было, так ведь не получаю, пусто в иконках. |
Сообщ.
#10
,
|
|
|
Так это не ошибка. Видимо для этого файла нет иконок там, где Extract их ищет - ни в самом файле, ни в кэше, ни в реестре, etc. Так что напрасно паришься. Это - by design
Ну а если тебе обязательно нужна иконка - бери дефолтную для этого типа файлов (через ExtractAssociatedIcon(EX)/SHGetFileInfo/etc.) |
Сообщ.
#11
,
|
|
|
Теперь, пожалуй, все ясно Спасибо
|