Слои оверлея
Модератор: motyara
-
- Автор программы
- Сообщения: 3432
- Зарегистрирован: Пт окт 12, 2007 3:26 pm
Слои оверлея
Разыскивается код на Delphi/C++Builder, позволяющий получить у системы оверлейные слои значков. Буду очень признателен за конкретную помощь по данному вопросу.
-
- Охотник за багами
- Сообщения: 21
- Зарегистрирован: Чт фев 26, 2009 11:04 pm
-
- Автор программы
- Сообщения: 3432
- Зарегистрирован: Пт окт 12, 2007 3:26 pm
-
- Охотник за багами
- Сообщения: 21
- Зарегистрирован: Чт фев 26, 2009 11:04 pm
Re: Слои оверлея
Объясните пожалуйста что конкретно нужно, а то я не понял смысла чего надо сделать. С оверлеями не работал и только понял из описания, что это маленький значок типа стрелочки, рисуемый поверх ярлыков, к примеру.
-
- Автор программы
- Сообщения: 3432
- Зарегистрирован: Пт окт 12, 2007 3:26 pm
Насколько мне известно, оверлейный слой работает именно по такому принципу - накладывается поверх какой-либо иконки. Если запросить у ОС индекс иконки файла, то иконка соответствующая индексу (расположенная в системном ImageList'е) не будет содержать оверлейных слоев. Если же запросить не индекс, а саму иконку (получить ее как объект), то ОС выдаст ее с уже наложенными оверлейными слоями (сейчас именно такой принцип и используется в программе). Меня интересует способ получения непосредственно чего-то вроде "индекса слоя". Было бы замечательно если бы некий код примера содержал следующие фазы:
1. получение индекса иконки файла (впрочем эта фаза-то у меня есть),
2. получение индекса оверлейного слоя для этого файла,
3. прорисовка результирующей иконки на canvas какого-либо объекта через функцию DrawIconEx или какую-либо другую (в данном случае можно было бы наложить оверлейный слой на любую другую иконку, индекс которой известен).
1. получение индекса иконки файла (впрочем эта фаза-то у меня есть),
2. получение индекса оверлейного слоя для этого файла,
3. прорисовка результирующей иконки на canvas какого-либо объекта через функцию DrawIconEx или какую-либо другую (в данном случае можно было бы наложить оверлейный слой на любую другую иконку, индекс которой известен).
-
- Охотник за багами
- Сообщения: 21
- Зарегистрирован: Чт фев 26, 2009 11:04 pm
Re: Слои оверлея
Код: Выделить всё
код удалил. смотрите ниже
Последний раз редактировалось admini Ср дек 09, 2009 1:40 pm, всего редактировалось 2 раза.
-
- Автор программы
- Сообщения: 3432
- Зарегистрирован: Пт окт 12, 2007 3:26 pm
Первый вариант (при SHGFI_ADDOVERLAYS) как раз и использован в программе на данный момент - получение иконки с объединенными слоями. А вот насчет второго варианта проблема... переменная overlayIndex вместо номера иконки слоя получает значение -1. Возможно я при компиляции делаю что-то не так, но именно такой исход и получался у меня всегда ранее... Удается ли при тестировании получить другие результаты?
-
- Охотник за багами
- Сообщения: 21
- Зарегистрирован: Чт фев 26, 2009 11:04 pm
Re: Слои оверлея
хммм. мистика какая то. дома код работает а на работе тоже возвращает -1, а SHGetIconOverlayIndex всегда какое-то странное значение - 8. погляжу еще в чем дело и можно уточнить а зачем разделять иконки и оверлеи когда сразу отрисовывать?
-
- Автор программы
- Сообщения: 3432
- Зарегистрирован: Пт окт 12, 2007 3:26 pm
Отделение иконки от оверлейного слоя нужно для случаев когда например установлены несистемные иконки каталогов, но при этом должны быть отображены оверлеи (чтобы не получалось месиво из иконок, ведь оверлейные слои всегда по умолчанию налагаются на системные иконки каталогов). Да и с точки зрения памяти явно рациональнее получать не готовую иконку как объект, а лишь однобайтовый индекс оверлейного слоя (да и с прорисовкой оверлейных иконок при входе в каталог получается не так как хотелось, ведь каждый раз производится перечитывание всех иконок без кэширования).
И кстати я обратил внимание на тот факт, что если пройтись по полученному ImageList'у напрямую (прорисовывать все иконки от нулевой по очереди), то необходимых оверлейных среди существующих нет (хотя некоторые другие оверлейные все-таки есть). Отсюда напрашивается вывод что может быть система выдает не системный ImageList, а какой-то его урезанный аналог?
И кстати я обратил внимание на тот факт, что если пройтись по полученному ImageList'у напрямую (прорисовывать все иконки от нулевой по очереди), то необходимых оверлейных среди существующих нет (хотя некоторые другие оверлейные все-таки есть). Отсюда напрашивается вывод что может быть система выдает не системный ImageList, а какой-то его урезанный аналог?
-
- Охотник за багами
- Сообщения: 21
- Зарегистрирован: Чт фев 26, 2009 11:04 pm
Re: Слои оверлея
Код: Выделить всё
код удалил. смотрите ниже
Последний раз редактировалось admini Сб дек 12, 2009 1:23 pm, всего редактировалось 2 раза.
-
- Охотник за багами
- Сообщения: 21
- Зарегистрирован: Чт фев 26, 2009 11:04 pm
Re: Слои оверлея
Кстати информация - придурки из MS убрали оверлеи у расшаренных папок в Win7 и поэтому данная функа не работает для расшаренных папок (вернет -1) но анрил как то отрисовывает с объединенными оверлеями...
-
- Охотник за багами
- Сообщения: 21
- Зарегистрирован: Чт фев 26, 2009 11:04 pm
Re: Слои оверлея
Код: Выделить всё
код удалил. смотрите ниже
Последний раз редактировалось admini Сб дек 12, 2009 1:23 pm, всего редактировалось 1 раз.
-
- Охотник за багами
- Сообщения: 21
- Зарегистрирован: Чт фев 26, 2009 11:04 pm
Re: Слои оверлея
В общем теперь всё работает. Если уже пробовали предыдущий код, то удалите его и пробуйте этот
Требования: Windows 2000 или выше и не забывать юзать CoInitializeEx где необходимо.
Требования: Windows 2000 или выше и не забывать юзать CoInitializeEx где необходимо.
Код: Выделить всё
uses
ActiveX, ShlObj, ShLwApi, CommCtrl;
const
IID_IShellIconOverlay: TGUID = (
D1:$7D688A70; D2:$C613; D3:$11D0; D4:($99, $9B, $00, $C0, $4F, $D6, $55, $E1));
IID_IShellIconOverlayManager: TGUID = (
D1:$F10B5E34; D2:$DD3B; D3:$42A7; D4:($AA, $7D, $2F, $4E, $C5, $4B, $B0, $9B));
CLSID_CFSIconOverlayManager: TGUID = (
D1:$63B51F81; D2:$C868; D3:$11D0; D4:($99, $9C, $00, $C0, $4F, $D6, $55, $E1));
type
IShellIconOverlayManager = interface
['{F10B5E34-DD3B-42A7-AA7D-2F4EC54BB09B}']
function GetFileOverlayInfo(pwszPath: LPCWSTR; dwAttrib: DWORD;
var iIndex: Integer; dwFlags: DWORD): HRESULT; stdcall;
function GetReservedOverlayInfo(pwszPath: LPCWSTR; dwAttrib: DWORD;
var iIndex: Integer; dwFlags: DWORD; iReservedID: Integer): HRESULT; stdcall;
function RefreshOverlayImages(dwFlags: DWORD): HRESULT; stdcall;
function LoadNonloadedOverlayIdentifiers(): HRESULT; stdcall;
function OverlayIndexFromImageIndex(iImage: Integer;
var iIndex: Integer; fAdd: BOOL): HRESULT; stdcall;
end;
const
SIOM_OVERLAYINDEX = 1;
SIOM_ICONINDEX = 2;
SIOM_RESERVED_SHARED = 0;
SIOM_RESERVED_LINK = 1;
SIOM_RESERVED_SLOWFILE = 2;
const
SHGFI_ICON = $000000100;
SHGFI_DISPLAYNAME = $000000200;
SHGFI_TYPENAME = $000000400;
SHGFI_ATTRIBUTES = $000000800;
SHGFI_ICONLOCATION = $000001000;
SHGFI_EXETYPE = $000002000;
SHGFI_SYSICONINDEX = $000004000;
SHGFI_LINKOVERLAY = $000008000;
SHGFI_SELECTED = $000010000;
SHGFI_LARGEICON = $000000000;
SHGFI_SMALLICON = $000000001;
SHGFI_OPENICON = $000000002;
SHGFI_SHELLICONSIZE = $000000004;
SHGFI_PIDL = $000000008;
SHGFI_USEFILEATTRIBUTES = $000000010;
SHGFI_ADDOVERLAYS = $000000020;
SHGFI_OVERLAYINDEX = $000000040;
type
_SHFILEINFOW = packed record
hIcon: HICON;
iIcon: Integer;
dwAttributes: DWORD;
szDisplayName: array [0..MAX_PATH-1] of WideChar;
szTypeName: array [0..79] of WideChar;
end;
function SHGetFileInfoW(pszPath: LPCWSTR; dwFileAttributes: DWORD;
var psfi: _SHFILEINFOW; cbFileInfo, uFlags: UINT): DWORD; stdcall; external 'SHELL32.DLL';
function QueryShlObjIconOverlayIndex(filePath: PWideChar; var iIndex: Integer): Boolean;
var
pathBuf: PWideChar;
desktopFolder, folder: IShellFolder;
folderID, fileID: PItemIDList;
shellIconOverlay: IShellIconOverlay;
overlayIndex, overlayIconIndex: Integer;
begin
Result := False;
iIndex := -1;
if not PathFileExistsW(filePath) then Exit;
GetMem(pathBuf, (lstrlenW(filePath) + 1) shl 1);
try
lstrcpyW(pathBuf, filePath);
StrTrimW(pathBuf, '\');
PathRemoveFileSpecW(pathBuf);
SHGetDesktopFolder(desktopFolder);
if not Assigned(desktopFolder) then Exit;
try
desktopFolder.ParseDisplayName(0, nil,
pathBuf, PULONG(nil)^, folderID, PULONG(nil)^);
if not Assigned(folderID) then Exit;
try
desktopFolder.BindToObject(folderID, nil, IID_IShellFolder, folder);
if not Assigned(folder) then Exit;
try
lstrcpyW(pathBuf, PathFindFileNameW(filePath));
StrTrimW(pathBuf, '\');
folder.ParseDisplayName(0, nil,
pathBuf, PULONG(nil)^, fileID, PULONG(nil)^);
if not Assigned(fileID) then Exit;
try
folder.QueryInterface(IID_IShellIconOverlay, shellIconOverlay);
if not Assigned(shellIconOverlay) then Exit;
try
shellIconOverlay.GetOverlayIndex(fileID, overlayIndex);
shellIconOverlay.GetOverlayIconIndex(fileID, overlayIconIndex);
if (overlayIndex >= overlayIconIndex) then
iIndex := overlayIndex - 1
else
iIndex := overlayIconIndex;
finally
shellIconOverlay := nil;
end;
finally
CoTaskMemFree(fileID);
end;
finally
folder := nil;
end;
finally
CoTaskMemFree(folderID);
end;
finally
desktopFolder := nil;
end;
finally
FreeMem(pathBuf);
end;
Result := True;
end;
function QueryReservedIconOverlayIndex(iReservedID: Integer; var iIndex: Integer): Boolean;
var
shellIconOverlayManager: IShellIconOverlayManager;
begin
Result := False;
CoCreateInstance(CLSID_CFSIconOverlayManager, nil,
CLSCTX_INPROC_SERVER, IID_IShellIconOverlayManager, shellIconOverlayManager);
if not Assigned(shellIconOverlayManager) then Exit;
try
shellIconOverlayManager.GetReservedOverlayInfo(nil, 0, iIndex, SIOM_ICONINDEX, iReservedID);
finally
shellIconOverlayManager := nil;
end;
Result := True;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
filePath: WideString;
shfi: _SHFILEINFOW;
hImgList: integer;
overlayIndex: Integer;
begin
filePath := StringToOleStr(Edit1.Text);
FillChar(shfi, SizeOf(shfi), 0);
hImgList := SHGetFileInfoW(PWideChar(filePath), 0,
shfi, SizeOf(shfi), SHGFI_SMALLICON or SHGFI_SYSICONINDEX or SHGFI_ATTRIBUTES);
QueryShlObjIconOverlayIndex(PWideChar(filePath), overlayIndex);
if (overlayIndex < 0) and (shfi.dwAttributes and SFGAO_SHARE <> 0) then
QueryReservedIconOverlayIndex(SIOM_RESERVED_SHARED, overlayIndex);
Refresh();
ImageList_Draw(hImgList, shfi.iIcon, Canvas.Handle, 200, 100, ILD_TRANSPARENT);
ImageList_Draw(hImgList, overlayIndex, Canvas.Handle, 200, 100, ILD_TRANSPARENT);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
FileInitIcons(True);
end;
Последний раз редактировалось admini Сб дек 12, 2009 1:23 pm, всего редактировалось 1 раз.
-
- Автор программы
- Сообщения: 3432
- Зарегистрирован: Пт окт 12, 2007 3:26 pm
-
- Охотник за багами
- Сообщения: 21
- Зарегистрирован: Чт фев 26, 2009 11:04 pm
Re: Слои оверлея
Я решил еще проанализировать ситуацию в плане документированности функций и рекомендаций из MSDN и оформить все в одном примере. Работает также начиная с вин2000. Думаю это наиболее подходящий вариант.
У вас нет необходимых прав для просмотра вложений в этом сообщении.