我现在已经在互联网上搜索了大约5个小时,如果我能找到答案,我会被诅咒。我发现这个问题在我旅途中的多个地方都没有得到答复。
我愿意使用能够产生与文件当前图标叠加相关的远程信息的任何语言。下面的图片展示了我正在谈论的叠加。
答案 0 :(得分:0)
procedure GetOverlayIconInfo(const AFileName: UnicodeString; out AIconFileName: UnicodeString; out AIconIndex: Integer);
const
sShellIconOverlayIdentifiers = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers';
sShell32 = 'shell32.dll';
sImageres = 'imageres.dll';
procedure RegCheck(AStatus: DWORD);
begin
if AStatus = ERROR_SUCCESS then Exit;
SetLastError(AStatus);
RaiseLastOSError;
end;
function GetNextOverlayIconHandlerName(AKey: HKEY; AIndex: Integer): UnicodeString;
var
Status: DWORD;
Len: DWORD;
begin
Len := 256;
while True do
begin
SetLength(Result, Len - 1);
Status := RegEnumKeyExW(AKey, AIndex, PWideChar(Result), Len, nil, nil, nil, nil);
case Status of
ERROR_SUCCESS:
begin
SetLength(Result, Len);
Exit;
end;
ERROR_MORE_DATA: Len := Len * 2;
ERROR_NO_MORE_ITEMS:
begin
Result := '';
Exit;
end
else
RegCheck(Status);
end;
end;
end;
function GetOverlayIconHandlerCLSID(AKey: HKEY; const AName: UnicodeString): TCLSID;
var
Key: HKEY;
Status: DWORD;
Len: DWORD;
Size: DWORD;
CLSID: UnicodeString;
begin
RegCheck(RegOpenKeyExW(AKey, PWideChar(AName), 0, KEY_READ, Key));
try
Len := 256;
while True do
begin
SetLength(CLSID, Len);
Size := Len * SizeOf(WideChar);
Status := RegQueryValueExW(Key, nil, nil, nil, PByte(PWideChar(CLSID)), @Size);
case Status of
ERROR_SUCCESS:
begin
SetLength(CLSID, (Size div SizeOf(WideChar)) - 1);
Result := StringToGUID(CLSID);
Exit;
end;
ERROR_MORE_DATA: Len := (Size div SizeOf(WideChar));
else
RegCheck(Status);
end;
end;
finally
RegCloseKey(Key);
end;
end;
procedure GetOverlayIconInfo(const AOverlayHandlerCLSID: TCLSID; out AIconFileName: UnicodeString; out AIconIndex: Integer);
var
Unknown: IUnknown;
ShellIconOverlayIdentifier: IShellIconOverlayIdentifier;
Flags: DWORD;
begin
OleCheck(CoCreateInstance(AOverlayHandlerCLSID, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IUnknown, Unknown));
try
OleCheck(Unknown.QueryInterface(IID_IShellIconOverlayIdentifier, ShellIconOverlayIdentifier));
try
SetLength(AIconFileName, MAX_PATH);
AIconFileName[1] := #0;
AIconIndex := 0;
Flags := 0;
OleCheck(ShellIconOverlayIdentifier.GetOverlayInfo(PWideChar(AIconFileName), Length(AIconFileName), AIconIndex, Flags));
AIconFileName := PWideChar(AIconFileName);
if Flags and ISIOI_ICONFILE <> 0 then
begin
if Flags and ISIOI_ICONINDEX = 0 then
AIconIndex := 0;
end
else
begin
AIconFileName := '';
AIconIndex := 0;
end;
finally
ShellIconOverlayIdentifier := nil;
end;
finally
Unknown := nil;
end;
end;
function GetSystem32Dir: UnicodeString;
begin
SetLength(Result, MAX_PATH);
OleCheck(SHGetFolderPathW(0, CSIDL_SYSTEM, 0, SHGFP_TYPE_CURRENT, PWideChar(Result)));
Result := PWideChar(Result) + '\';
end;
var
FileInfo: TSHFileInfoW;
OverlayIconIndex: Integer;
Key: HKEY;
Index: Integer;
SubKeyName: UnicodeString;
CLSID: TCLSID;
begin
AIconFileName := '';
AIconIndex := 0;
// first off all we get overlay icon index of file
ZeroMemory(@FileInfo, SizeOf(FileInfo));
if SHGetFileInfoW(PWideChar(AFileName), 0, FileInfo, SizeOf(FileInfo), SHGFI_OVERLAYINDEX or SHGFI_ICON) = 0 then
RaiseLastOSError;
DestroyIcon(FileInfo.hIcon);
OverlayIconIndex := (FileInfo.iIcon shr 24) and $0000000F;
// now we enum all overlay icon handlers in the system
if RegOpenKeyExW(HKEY_LOCAL_MACHINE, PWideChar(sShellIconOverlayIdentifiers), 0, KEY_READ, Key) = ERROR_SUCCESS then
try
Index := 0;
while True do
begin
SubKeyName := GetNextOverlayIconHandlerName(Key, Index);
if SubKeyName = '' then Break;
try
// create an instance of current overlay icon handler
CLSID := GetOverlayIconHandlerCLSID(Key, SubKeyName);
// and get information about overlay icon implemented by current overlay icon handler
GetOverlayIconInfo(CLSID, AIconFileName, AIconIndex);
// is our overlay icon implemented by current overlay icon handler?
// if yes we found all information we are looking for
if SHGetIconOverlayIndexW(PWideChar(AIconFileName), AIconIndex) = OverlayIconIndex then
Exit;
except
end;
Inc(Index);
end;
finally
RegCloseKey(Key);
end;
// our overlay icon is not implemented by any of overlay icon handler
// lets use heuristic
AIconFileName := '';
AIconIndex := 0;
// I AM NOT FULLY SURE!!!
case OverlayIconIndex of
1: // share overlay
begin
if IsWindowsVistaOrLater then
begin
AIconFileName := GetSystem32Dir + sImageres;
AIconIndex := 164;
end
else
begin
AIconFileName := GetSystem32Dir + sShell32;
AIconIndex := 29;
end;
end;
2: // link overlay
begin
if IsWindowsVistaOrLater then
begin
AIconFileName := GetSystem32Dir + sImageres;
AIconIndex := 163;
end
else
begin
AIconFileName := GetSystem32Dir + sShell32;
AIconIndex := 30;
end;
end;
3: // default overlay
begin
if IsWindowsVistaOrLater then
begin
AIconFileName := GetSystem32Dir + sImageres;
AIconIndex := 157;
end
end;
4: // slow overlay
begin
if IsWindowsVistaOrLater then
begin
AIconFileName := GetSystem32Dir + sImageres;
AIconIndex := 169; // NOT SURE!!!
end
else
begin
AIconFileName := GetSystem32Dir + sShell32;
AIconIndex := 31;
end;
end;
end;
end;