📄 jclshell.pas
字号:
if Succeeded(SHGetDesktopFolder(DesktopFolder)) then
DesktopFolder.ParseDisplayName(0, nil, WidePath, CharsParsed, Result, Attr);
end;
function PathToPidlBind(const FileName: string; out Folder: IShellFolder): PItemIdList;
var
Attr, Eaten: ULONG;
PathIdList: PItemIdList;
DesktopFolder: IShellFolder;
Path, ItemName: TUnicodePath;
begin
Result := nil;
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, PChar(ExtractFilePath(FileName)), -1, Path, MAX_PATH);
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, PChar(ExtractFileName(FileName)), -1, ItemName, MAX_PATH);
if Succeeded(SHGetDesktopFolder(DesktopFolder)) then
begin
if Succeeded(DesktopFolder.ParseDisplayName(0, nil, Path, Eaten, PathIdList,
Attr)) then
begin
if Succeeded(DesktopFolder.BindToObject(PathIdList, nil, IID_IShellFolder,
Pointer(Folder))) then
begin
if Failed(Folder.ParseDisplayName(0, nil, ItemName, Eaten, Result, Attr)) then
begin
Folder := nil;
Result := DriveToPidlBind(FileName, Folder);
end;
end;
PidlFree(PathIdList);
end
else
Result := DriveToPidlBind(FileName, Folder);
end;
end;
function PidlBindToParent(IdList: PItemIdList; out Folder: IShellFolder; out Last: PItemIdList): Boolean;
var
Path: string;
begin
Last := nil;
Path := PidlToPath(IdList);
Last := PathToPidlBind(Path, Folder);
Result := Last <> nil;
if Last = nil then
Folder := nil;
end;
function PidlCompare(Pidl1, Pidl2: PItemIdList): Boolean;
var
L: Integer;
begin
Result := False;
L := PidlGetLength(Pidl1);
if L = PidlGetLength(Pidl2) then
Result := CompareMem(Pidl1, Pidl2, L);
end;
function PidlCopy(Source: PItemIdList; out Dest: PItemIdList): Boolean;
var
L: Integer;
begin
Result := False;
Dest := Source;
if Source <> nil then
begin
L := PidlGetLength(Source) + 2;
if SHAllocMem(Pointer(Dest), L) then
begin
Move(Source^, Dest^, L);
Result := True;
end;
end;
end;
function PidlFree(var IdList: PItemIdList): Boolean;
var
Malloc: IMalloc;
begin
Result := False;
if IdList = nil then
Result := True
else
begin
if Succeeded(SHGetMalloc(Malloc)) and (Malloc.DidAlloc(IdList) > 0) then
begin
Malloc.Free(IdList);
IdList := nil;
Result := True;
end;
end;
end;
function PidlGetDepth(Pidl: PItemIdList): Integer;
var
P: PItemIdList;
begin
Result := 0;
if Pidl <> nil then
begin
P := Pidl;
while (P^.mkId.cb <> 0) and (Result < MAX_PATH) do
begin
Inc(Result);
P := PItemIdList(@P^.mkId.abID[P^.mkId.cb - 2]);
end;
end;
if Result = MAX_PATH then
Result := -1;
end;
function PidlGetLength(Pidl: PItemIdList): Integer;
var
P: PItemIdList;
I: Integer;
begin
Result := 0;
if Pidl <> nil then
begin
I := 0;
P := Pidl;
while (P^.mkId.cb <> 0) and (I < MAX_PATH) do
begin
Inc(I);
Inc(Result, P^.mkId.cb);
P := PItemIdList(@P^.mkId.abID[P^.mkId.cb - 2]);
end;
if I = MAX_PATH then
Result := -1;
end;
end;
function PidlGetNext(Pidl: PItemIdList): PItemIdList;
begin
Result := nil;
if (Pidl <> nil) and (Pidl^.mkid.cb <> 0) then
begin
Result := PItemIdList(@Pidl^.mkId.abID[Pidl^.mkId.cb - 2]);
if Result^.mkid.cb = 0 then
Result := nil;
end;
end;
function PidlToPath(IdList: PItemIdList): string;
begin
SetLength(Result, MAX_PATH);
if SHGetPathFromIdList(IdList, PChar(Result)) then
StrResetLength(Result)
else
Result := '';
end;
function StrRetFreeMem(StrRet: TStrRet): Boolean;
begin
Result := False;
if StrRet.uType = STRRET_WSTR then
Result := SHFreeMem(Pointer(StrRet.pOleStr));
end;
function StrRetToString(IdList: PItemIdList; StrRet: TStrRet; Free: Boolean): string;
begin
case StrRet.uType of
STRRET_WSTR:
begin
Result := WideCharToString(StrRet.pOleStr);
if Free then
SHFreeMem(Pointer(StrRet.pOleStr));
end;
STRRET_OFFSET:
if IdList <> nil then
Result := PChar(IdList) + StrRet.uOffset
else
Result := '';
STRRET_CSTR:
Result := StrRet.cStr;
else
Result := '';
end;
end;
//=== ShortCuts / Shell link =================================================
procedure ShellLinkFree(var Link: TShellLink);
begin
PidlFree(Link.IdList);
end;
const
IID_IShellLink: TGUID = { IID_IShellLinkA }
(D1:$000214EE; D2:$0000; D3:$0000; D4:($C0,$00,$00,$00,$00,$00,$00,$46));
function ShellLinkCreateSystem(const Link: TShellLink; const Folder: Integer;
const FileName: string): HRESULT;
var
Path: string;
Pidl: PItemIDList;
begin
Result := E_INVALIDARG;
SetLength(Path, MAX_PATH);
if Succeeded(SHGetSpecialFolderLocation(0, Folder, Pidl)) then
begin
Path := PidltoPath(Pidl);
if Path <> '' then
begin
StrResetLength(Path);
Result := ShellLinkCreate(Link, PathAddSeparator(Path) + FileName);
end;
end;
end;
function ShellLinkCreate(const Link: TShellLink; const FileName: string): HRESULT;
var
ShellLink: IShellLink;
PersistFile: IPersistFile;
LinkName: TUnicodePath;
begin
Result := CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER,
IID_IShellLink, ShellLink);
if Succeeded(Result) then
begin
ShellLink.SetArguments(PChar(Link.Arguments));
ShellLink.SetShowCmd(Link.ShowCmd);
ShellLink.SetWorkingDirectory(PChar(Link.WorkingDirectory));
ShellLink.SetPath(PChar(Link.Target));
ShellLink.SetDescription(PChar(Link.Description));
ShellLink.SetHotkey(Link.HotKey);
ShellLink.SetIconLocation(PChar(Link.IconLocation), Link.IconIndex);
PersistFile := ShellLink as IPersistFile;
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, PChar(FileName), -1,
LinkName, MAX_PATH);
Result := PersistFile.Save(LinkName, True);
end;
end;
function RtdlLoadMsiFuncs:Boolean;
begin
Result:=False;
if LoadModule(rtdlMsiLibHandle,MSILIB) then
begin
if not Assigned(RtdlMsiGetShortcutTarget) then
RtdlMsiGetShortcutTarget:=GetModuleSymbol(rtdlMsiLibHandle,'MsiGetShortcutTargetA');
if not Assigned(RtdlMsiGetComponentPath) then
RtdlMsiGetComponentPath:=GetModuleSymbol(rtdlMsiLibHandle,'MsiGetComponentPathA');
Result:=(Assigned(RtdlMsiGetShortcutTarget)) and (Assigned(RtdlMsiGetComponentPath));
end;
end;
function ShellLinkResolve(const FileName: string; var Link: TShellLink): HRESULT;
const
MAX_FEATURE_CHARS = 38; // maximum chars in MSI feature name
var
ShellLink: IShellLink;
PersistFile: IPersistFile;
LinkName: TUnicodePath;
Buffer: string;
Win32FindData: TWin32FindData;
FullPath: string;
ProductGuid: array [0..38] of Char;
FeatureID: array [0..MAX_FEATURE_CHARS] of Char;
ComponentGUID: array [0..38] of Char;
TargetFile: array [0..MAX_PATH] of Char;
PathSize: DWORD;
TargetResolved: Boolean;
begin
Result := CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER,
IID_IShellLink, ShellLink);
if Succeeded(Result) then
begin
TargetResolved := False;
// Handle MSI style shortcuts without invoking the Windows installer if
// the feature was set to "Install on first use"
if RtdlLoadMsiFuncs then
begin
FillChar(ProductGuid, SizeOf(ProductGuid), #0);
FillChar(FeatureID, SizeOf(FeatureID), #0);
FillChar(ComponentGuid, SizeOf(ComponentGuid), #0);
FillChar(TargetFile, SizeOf(TargetFile), #0);
if RtdlMsiGetShortcutTarget(PAnsiChar(FileName), ProductGuid, FeatureID, ComponentGuid) = ERROR_SUCCESS then
begin
PathSize := MAX_PATH + 1;
RtdlMsiGetComponentPath(ProductGuid, ComponentGuid, TargetFile, @PathSize);
if TargetFile <> '' then
begin
Link.Target := TargetFile;
TargetResolved := True;
end;
end;
end;
PersistFile := ShellLink as IPersistFile;
// PersistFile.Load fails if the filename is not fully qualified
FullPath := ExpandFileName(FileName);
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, PChar(FullPath), -1, LinkName, MAX_PATH);
Result := PersistFile.Load(LinkName, STGM_READ);
if Succeeded(Result) then
begin
Result := ShellLink.Resolve(0, SLR_ANY_MATCH);
if Succeeded(Result) then
begin
SetLength(Buffer, MAX_PATH);
if not TargetResolved then
begin
ShellLink.GetPath(PChar(Buffer), MAX_PATH, Win32FindData, SLGP_SHORTPATH);
Link.Target := PChar(Buffer);
end;
ShellLink.GetArguments(PChar(Buffer), MAX_PATH);
Link.Arguments := PChar(Buffer);
ShellLink.GetShowCmd(Link.ShowCmd);
ShellLink.GetWorkingDirectory(PChar(Buffer), MAX_PATH);
Link.WorkingDirectory := PChar(Buffer);
ShellLink.GetDescription(PChar(Buffer), MAX_PATH);
Link.Description := PChar(Buffer);
ShellLink.GetIconLocation(PChar(Buffer), MAX_PATH, Link.IconIndex);
Link.IconLocation := PChar(Buffer);
ShellLink.GetHotkey(Link.HotKey);
ShellLink.GetIDList(Link.IdList);
end;
end;
end;
end;
function ShellLinkIcon(const Link: TShellLink): HICON; overload;
var
LocExt: string;
Info: TSHFileInfo;
begin
Result := 0;
LocExt := LowerCase(ExtractFileExt(Link.IconLocation));
// 1. See if IconLocation specifies a valid icon file
if (LocExt = '.ico') and (FileExists(Link.IconLocation)) then
begin
{ TODO : Implement loading from an .ico file }
end;
// 2. See if IconLocation specifies an executable
if Result = 0 then
begin
if (LocExt = '.dll') or (LocExt = '.exe') then
Result := ExtractIcon(0, PChar(Link.IconLocation), Link.IconIndex);
end;
// 3. See if target specifies a file
if Result = 0 then
begin
if FileExists(Link.Target) then
Result := ExtractIcon(0, PChar(Link.Target), Link.IconIndex);
end;
// 4. See if the target is an object
if Result = 0 then
begin
if Link.IdList <> nil then
begin
FillChar(Info, SizeOf(Info), 0);
if SHGetFileInfo(PChar(Link.IdList), 0, Info, SizeOf(Info), SHGFI_PIDL or SHGFI_ICON) <> 0 then
Result := Info.hIcon;
end;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -