得到“桌面”及其下的子目录: unit BrowseTreeView;interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ShlObj,ComCtrls;type PTreeViewItem=^TTreeViewItem; TTreeViewItem=record ParentFolder:IShellFolder; //节点对应的文件夹的父文件夹的IShellFolder接口 Pidl,FullPidl:PItemIDList; //节点对应的文件夹的相对和绝对项目标识符列表 HasExpanded:Boolean;//节点是否展开 end; TForm1 = class(TForm) TreeView1: TTreeView; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure TreeView1Expanding(Sender: TObject; Node: TTreeNode; var AllowExpansion: Boolean); private { Private declarations } FItemList:TList; procedure SetTreeViewImageList; procedure FillTreeView(Folder:IShellFolder;FullPIDL:PItemIDList;ParentNode:TTreeNode); public { Public declarations } end;var Form1: TForm1;implementation{$R *.DFM} uses ActiveX,ComObj,ShellAPI,CommCtrl; //以下是几个对项目标识符进行操作的函数procedure DisposePIDL(ID:PItemIDList); var Malloc:IMalloc; begin if ID= nil then Exit; OLECheck(SHGetMalloc(Malloc)); Malloc.Free(ID); end;function CopyItemID(ID:PItemIDList):PItemIDList; var Malloc:IMalloc; begin Result:=nil; OLECheck(SHGetMalloc(Malloc)); if Assigned(ID) then begin Result:=Malloc.Alloc(ID^.mkid.cb+sizeof(ID^.mkid.cb)); CopyMemory(Result,ID,ID^.mkid.cb+sizeof(ID^.mkid.cb)); end; end;function NextPIDL(ID:PItemIDList):PItemIDList; begin result:=id; Inc(PChar(result),id^.mkid.cb); end;function GetPIDLSize(ID:PItemIDList):Integer; begin result:=0; if Assigned(ID) then begin result:=sizeof(ID^.mkid.cb); while ID^.mkid.cb <> 0 do begin Inc(result,ID^.mkid.cb); ID:=NextPIDL(ID); end; end; end;function CreatePIDL(Size:Integer):PItemIDList; var Malloc:IMalloc; HR:HResult; begin result:=nil; HR:=SHGetMalloc(Malloc); if Failed(HR) then Exit; try Result:=Malloc.Alloc(Size); if Assigned(Result) then FillChar(Result^,Size,0); finally end; end;function ConcatPIDLs(ID1,ID2:PItemIDList):PItemIDList; var cb1,cb2:Integer; begin if Assigned(ID1) then cb1:=GetPIDLSize(ID1)-sizeof(ID1^.mkid.cb ) else cb1:=0; cb2:=GetPIDLSize(ID2); result:=CreatePIDL(cb1+cb2); if Assigned(Result) then begin if Assigned(ID1) then CopyMemory(Result,ID1,cb1); CopyMemory(PChar(Result)+cb1,ID2,cb2); end; end; //将二进制表示的项目标识符列表转换成有可识的项目名function GetDisplayName(Folder:IShellFolder;PIDL:PItemIDList;ForParsing:Boolean):String; var StrRet:TStrRet; P:PChar; Flags:Integer; begin result:=''; if ForParsing then Flags:=SHGDN_FORPARSING else Flags:=SHGDN_NORMAL; Folder.GetDisplayNameOf(pidl,flags,StrRet); case StrRet.uType of STRRET_CSTR: SetString(Result,StrRet.cStr,StrLen(StrRet.cStr)); STRRET_OFFSET: begin P:[email protected][StrRet.uOffset-sizeof(PIDL.mkid.cb)]; SetString(Result,P,PIDL.mkid.cb-StrRet.UOffset); end; end; end;function GetIcon(PIDL:PItemIDList;Open:Boolean):Integer; const IconFlag=SHGFI_PIDL or SHGFI_SYSICONINDEX or SHGFI_SMALLICON; var FileInfo:TSHFileInfo; Flags:Integer; begin if Open then Flags:=IconFlag or SHGFI_OPENICON else Flags:=IconFlag; SHGetFileInfo(PChar(PIDL),0,FileInfo,sizeof(TSHFileInfo),Flags); result:=FileInfo.iIcon; end; //获得每个文件夹在系统中的图标
procedure GetItemIcons(FullPIDL:PItemIDList;TreeNode:TTreeNode); begin with TreeNode do begin ImageIndex:=GetIcon(FullPIDL,False); SelectedIndex:=GetIcon(FullPIDL,True); end; end; //获得系统的图标列表procedure TForm1.SetTreeViewImageList; var imagelist:thandle; fileinfo:tshfileinfo; begin imagelist:=shgetfileinfo(Pchar('c:\'),0,fileinfo,sizeof(tshfileinfo),shgfi_sysiconindex or shgfi_smallicon); if imagelist<>0 then treeview_setimagelist(treeview1.handle,imagelist,0); end; //生成文件夹管理树procedure TForm1.FillTreeView(Folder:IShellFolder;FullPIDL:PItemIDList;ParentNode:TTreeNode); var TreeViewItem:PTreeViewItem; EnumIDList:IEnumIDList; PIDLs,FullItemPIDL:PItemIDList; NumID:LongWord; ChildNode:TTreeNode; Attr:Cardinal; begin try OLECheck(Folder.EnumObjects(Handle,SHCONTF_FOLDERS,EnumIDList)); while EnumIDList.Next(1,PIDls,NumID)=S_OK do begin FullItemPIDL:=ConcatPIDLs(FullPIDL,PIDLs); TreeViewItem:=New(PTreeViewItem); TreeViewItem.ParentFolder:=Folder; TreeViewItem.Pidl:=CopyItemID(PIDLs); TreeViewItem.FullPidl:=FullItemPIDL; TreeViewItem.HasExpanded:=False; FItemList.Add(TreeViewItem); ChildNode:=TreeView1.Items.AddChildObject(ParentNode,GetDisplayName(Folder,PIDLs,False),TreeViewItem); GetItemIcons(FullItemPIDL,ChildNode); Attr:=SFGAO_HASSUBFOLDER or SFGAO_FOLDER; Folder.GetAttributesOf (1,PIDLs,Attr); if Bool(Attr and(SFGAO_HASSUBFOLDER or SFGAO_FOLDER)) then if Bool(Attr and SFGAO_FOLDER) then if Bool(Attr and SFGAO_HASSUBFOLDER) then ChildNode.HasChildren:=True; end; except // 你可在此处对异常进行处理 end; end;procedure TForm1.FormDestroy(Sender: TObject); var I:Integer; begin try for I:=0 to FItemList.Count-1 do begin DisposePIDL(PTreeViewItem(FItemList[i]).PIDL); DisposePIDL(PTreeViewItem(FItemList[i]).FullPIDL); end; FItemList.Clear; FItemList.Free; except end; end;procedure TForm1.FormCreate(Sender: TObject); var Folder:IshellFolder; begin SetTreeViewImageList; OLECheck(ShGetDesktopFolder(Folder)); FItemList:=Tlist.Create; FillTreeView(folder,nil,nil);end;procedure TForm1.TreeView1Expanding(Sender: TObject; Node: TTreeNode; var AllowExpansion: Boolean); var tVItem:PTreeViewItem; SHFolder:IShellFolder; begin TVItem:=PTreeViewItem(Node.Data); if TVItem.HasExpanded then Exit; OLECheck(TVItem.ParentFolder.BindToObject(TVItem^.Pidl,Nil,IID_IShellFolder,Pointer(SHFolder))); FillTreeView(SHFolder,TVItem^.FullPidl,Node); Node.AlphaSort; TVItem^.HasExpanded:=True;end;end.
要引用 shlobj : function GetDesktopFolder: string; var Buffer: PChar; begin Result := ''; GetMem(Buffer, MAX_PATH); try if ShGetSpecialFolderPath(Application.Handle,Buffer, CSIDL_DESKTOP, False) then SetString(Result, Buffer, StrLen(Buffer)); finally FreeMem(Buffer); end; end; 或者 也要引用shlobj function GetDesktopDir: string; var Buffer: PChar; ItemIDList: PItemIDList; ShellMalloc: IMalloc; begin Result := ''; if (ShGetMalloc(ShellMalloc) = S_OK) and (ShellMalloc <> nil) then begin Buffer := ShellMalloc.Alloc(MAX_PATH); try if SHGetSpecialFolderLocation(Application.Handle, CSIDL_DESKTOP, ItemIDList) = S_OK then if SHGetPathFromIDList(ItemIDList,Buffer) then SetString(Result, Buffer, StrLen(Buffer)); finally ShellMalloc.Free(Buffer); end; end; end;
利用Api函数,利用他们就可以轻松简单的获取这些特殊系统目录。 Function SHGetSpecialFolderLocation(hwndOwner: HWND; nFolder: Integer; var ppidl: PItemIDList): HResult; stdcall; Function SHGetPathFromIDList(pidl: PItemIDList; pszPath: PChar): BOOL;stdcall; 其中由nFolder参数指定的就是各个特殊系统目录: CSIDL_DESKTOP:毫无疑问这就是桌面; CSIDL_DRIVERS:我的电脑; CSIDL_FAVORITES:收藏夹; CSIDL_STARTUP:开始菜单; CSIDL_NETWORK:网上邻居; 还有很多,你可以查阅一下Delphi的Win32 Api函数的帮助文件,不过在帮助文件下的这些参数也不是很全,像收藏夹帮助文件里面就没有,你可以查阅一下它的头文件:shlobj.pas。 下面我就利用这两个函数取得桌面的路径(在win98和win2000下都可以使用): uses shlobj; var pitem:PITEMIDLIST; s:string; begin shGetSpecialFolderLocation(handle,CSIDL_DESKTOP,pitem); setlength(s,100); shGetPathFromIDList(pitem,pchar(s)); end; 在字符串s中存储的就是桌面的路径值。简单吧!
unit BrowseTreeView;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ShlObj,ComCtrls;type
PTreeViewItem=^TTreeViewItem;
TTreeViewItem=record
ParentFolder:IShellFolder;
//节点对应的文件夹的父文件夹的IShellFolder接口
Pidl,FullPidl:PItemIDList;
//节点对应的文件夹的相对和绝对项目标识符列表
HasExpanded:Boolean;//节点是否展开
end;
TForm1 = class(TForm)
TreeView1: TTreeView;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure TreeView1Expanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean); private
{ Private declarations }
FItemList:TList;
procedure SetTreeViewImageList;
procedure FillTreeView(Folder:IShellFolder;FullPIDL:PItemIDList;ParentNode:TTreeNode); public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.DFM}
uses
ActiveX,ComObj,ShellAPI,CommCtrl;
//以下是几个对项目标识符进行操作的函数procedure DisposePIDL(ID:PItemIDList);
var
Malloc:IMalloc;
begin
if ID= nil then Exit;
OLECheck(SHGetMalloc(Malloc));
Malloc.Free(ID);
end;function CopyItemID(ID:PItemIDList):PItemIDList;
var
Malloc:IMalloc;
begin
Result:=nil;
OLECheck(SHGetMalloc(Malloc));
if Assigned(ID) then
begin
Result:=Malloc.Alloc(ID^.mkid.cb+sizeof(ID^.mkid.cb));
CopyMemory(Result,ID,ID^.mkid.cb+sizeof(ID^.mkid.cb));
end;
end;function NextPIDL(ID:PItemIDList):PItemIDList;
begin
result:=id;
Inc(PChar(result),id^.mkid.cb);
end;function GetPIDLSize(ID:PItemIDList):Integer;
begin
result:=0;
if Assigned(ID) then
begin
result:=sizeof(ID^.mkid.cb);
while ID^.mkid.cb <> 0 do
begin
Inc(result,ID^.mkid.cb);
ID:=NextPIDL(ID);
end;
end;
end;function CreatePIDL(Size:Integer):PItemIDList;
var
Malloc:IMalloc;
HR:HResult;
begin
result:=nil;
HR:=SHGetMalloc(Malloc);
if Failed(HR) then Exit;
try
Result:=Malloc.Alloc(Size);
if Assigned(Result) then
FillChar(Result^,Size,0);
finally
end;
end;function ConcatPIDLs(ID1,ID2:PItemIDList):PItemIDList;
var
cb1,cb2:Integer;
begin
if Assigned(ID1) then
cb1:=GetPIDLSize(ID1)-sizeof(ID1^.mkid.cb )
else
cb1:=0;
cb2:=GetPIDLSize(ID2);
result:=CreatePIDL(cb1+cb2);
if Assigned(Result) then
begin
if Assigned(ID1) then
CopyMemory(Result,ID1,cb1);
CopyMemory(PChar(Result)+cb1,ID2,cb2);
end;
end;
//将二进制表示的项目标识符列表转换成有可识的项目名function GetDisplayName(Folder:IShellFolder;PIDL:PItemIDList;ForParsing:Boolean):String;
var
StrRet:TStrRet;
P:PChar;
Flags:Integer;
begin
result:='';
if ForParsing then
Flags:=SHGDN_FORPARSING
else
Flags:=SHGDN_NORMAL;
Folder.GetDisplayNameOf(pidl,flags,StrRet);
case StrRet.uType of
STRRET_CSTR:
SetString(Result,StrRet.cStr,StrLen(StrRet.cStr));
STRRET_OFFSET:
begin
P:[email protected][StrRet.uOffset-sizeof(PIDL.mkid.cb)];
SetString(Result,P,PIDL.mkid.cb-StrRet.UOffset);
end;
end;
end;function GetIcon(PIDL:PItemIDList;Open:Boolean):Integer;
const
IconFlag=SHGFI_PIDL or SHGFI_SYSICONINDEX or SHGFI_SMALLICON;
var
FileInfo:TSHFileInfo;
Flags:Integer;
begin
if Open then
Flags:=IconFlag or SHGFI_OPENICON
else
Flags:=IconFlag;
SHGetFileInfo(PChar(PIDL),0,FileInfo,sizeof(TSHFileInfo),Flags);
result:=FileInfo.iIcon;
end;
//获得每个文件夹在系统中的图标
procedure GetItemIcons(FullPIDL:PItemIDList;TreeNode:TTreeNode);
begin
with TreeNode do
begin
ImageIndex:=GetIcon(FullPIDL,False);
SelectedIndex:=GetIcon(FullPIDL,True);
end;
end;
//获得系统的图标列表procedure TForm1.SetTreeViewImageList;
var
imagelist:thandle;
fileinfo:tshfileinfo;
begin
imagelist:=shgetfileinfo(Pchar('c:\'),0,fileinfo,sizeof(tshfileinfo),shgfi_sysiconindex or shgfi_smallicon);
if imagelist<>0 then
treeview_setimagelist(treeview1.handle,imagelist,0);
end;
//生成文件夹管理树procedure TForm1.FillTreeView(Folder:IShellFolder;FullPIDL:PItemIDList;ParentNode:TTreeNode);
var
TreeViewItem:PTreeViewItem;
EnumIDList:IEnumIDList;
PIDLs,FullItemPIDL:PItemIDList;
NumID:LongWord;
ChildNode:TTreeNode;
Attr:Cardinal;
begin
try
OLECheck(Folder.EnumObjects(Handle,SHCONTF_FOLDERS,EnumIDList));
while EnumIDList.Next(1,PIDls,NumID)=S_OK do
begin
FullItemPIDL:=ConcatPIDLs(FullPIDL,PIDLs);
TreeViewItem:=New(PTreeViewItem);
TreeViewItem.ParentFolder:=Folder;
TreeViewItem.Pidl:=CopyItemID(PIDLs);
TreeViewItem.FullPidl:=FullItemPIDL;
TreeViewItem.HasExpanded:=False;
FItemList.Add(TreeViewItem);
ChildNode:=TreeView1.Items.AddChildObject(ParentNode,GetDisplayName(Folder,PIDLs,False),TreeViewItem);
GetItemIcons(FullItemPIDL,ChildNode);
Attr:=SFGAO_HASSUBFOLDER or SFGAO_FOLDER;
Folder.GetAttributesOf (1,PIDLs,Attr);
if Bool(Attr and(SFGAO_HASSUBFOLDER or SFGAO_FOLDER)) then
if Bool(Attr and SFGAO_FOLDER) then
if Bool(Attr and SFGAO_HASSUBFOLDER) then
ChildNode.HasChildren:=True;
end;
except
// 你可在此处对异常进行处理
end;
end;procedure TForm1.FormDestroy(Sender: TObject);
var
I:Integer;
begin
try
for I:=0 to FItemList.Count-1 do
begin
DisposePIDL(PTreeViewItem(FItemList[i]).PIDL);
DisposePIDL(PTreeViewItem(FItemList[i]).FullPIDL);
end;
FItemList.Clear;
FItemList.Free;
except
end;
end;procedure TForm1.FormCreate(Sender: TObject);
var
Folder:IshellFolder;
begin
SetTreeViewImageList;
OLECheck(ShGetDesktopFolder(Folder));
FItemList:=Tlist.Create;
FillTreeView(folder,nil,nil);end;procedure TForm1.TreeView1Expanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
var
tVItem:PTreeViewItem;
SHFolder:IShellFolder;
begin
TVItem:=PTreeViewItem(Node.Data);
if TVItem.HasExpanded then Exit;
OLECheck(TVItem.ParentFolder.BindToObject(TVItem^.Pidl,Nil,IID_IShellFolder,Pointer(SHFolder)));
FillTreeView(SHFolder,TVItem^.FullPidl,Node);
Node.AlphaSort;
TVItem^.HasExpanded:=True;end;end.
function GetDesktopFolder: string;
var
Buffer: PChar;
begin
Result := '';
GetMem(Buffer, MAX_PATH);
try
if ShGetSpecialFolderPath(Application.Handle,Buffer, CSIDL_DESKTOP, False) then
SetString(Result, Buffer, StrLen(Buffer));
finally
FreeMem(Buffer);
end;
end; 或者
也要引用shlobj
function GetDesktopDir: string;
var
Buffer: PChar;
ItemIDList: PItemIDList;
ShellMalloc: IMalloc;
begin
Result := '';
if (ShGetMalloc(ShellMalloc) = S_OK) and (ShellMalloc <> nil) then
begin
Buffer := ShellMalloc.Alloc(MAX_PATH);
try
if SHGetSpecialFolderLocation(Application.Handle, CSIDL_DESKTOP, ItemIDList) = S_OK then
if SHGetPathFromIDList(ItemIDList,Buffer) then
SetString(Result, Buffer, StrLen(Buffer));
finally
ShellMalloc.Free(Buffer);
end;
end;
end;
var ppidl: PItemIDList): HResult; stdcall; Function SHGetPathFromIDList(pidl: PItemIDList; pszPath: PChar): BOOL;stdcall; 其中由nFolder参数指定的就是各个特殊系统目录: CSIDL_DESKTOP:毫无疑问这就是桌面; CSIDL_DRIVERS:我的电脑; CSIDL_FAVORITES:收藏夹; CSIDL_STARTUP:开始菜单; CSIDL_NETWORK:网上邻居; 还有很多,你可以查阅一下Delphi的Win32 Api函数的帮助文件,不过在帮助文件下的这些参数也不是很全,像收藏夹帮助文件里面就没有,你可以查阅一下它的头文件:shlobj.pas。 下面我就利用这两个函数取得桌面的路径(在win98和win2000下都可以使用): uses shlobj; var
pitem:PITEMIDLIST;
s:string;
begin
shGetSpecialFolderLocation(handle,CSIDL_DESKTOP,pitem);
setlength(s,100);
shGetPathFromIDList(pitem,pchar(s));
end; 在字符串s中存储的就是桌面的路径值。简单吧!
程序组,最近文档,发送到,开始菜单,启动等,有时可能需要取得这些文件夹
的真正路径。
一种方法是通过读注册表文件,存放在HKEY_CURRENT_USER根下,目录为:
Software\MicroSoft\Windows\CurrentVersion\Explorer
可看到在shell folder段中存放着上述文件夹所对应的实际物理目录,至于如何
读注册表的操作不再给出,请自行解决。
另一种方法是调用shell函数可以得到相应的目录,但是不是所有在shell folder
目录下的文件夹都可以获得,请注意。
function GetSpecialFolderDir(const folderid:integer):string;
var
pidl:pItemIDList;
buffer:array [ 0..255 ] of char ;
begin
//取指定的文件夹项目表
SHGetSpecialFolderLocation( application.Handle , folderid, pidl);
SHGetPathFromIDList(pidl, buffer); //转换成文件系统的路径
result:=strpas(buffer);
end;其中:folderid可以取下面的值:但是请注意,有些是虚的文件夹,不是文件系统
的一部分,所以用SHGetPathFromIDList是取不出路径的,但是在此也列出了。打'*'
号的为不是真正的文件系统,应该用作它用。
CSIDL_BITBUCKET * 回收站
CSIDL_CONTROLS * 控制面板
CSIDL_DESKTOP * 桌面
CSIDL_DESKTOPDIRECTORY 桌面目录 //如C:\WINDOWS\Desktop
CSIDL_DRIVES * 我的电脑
CSIDL_FONTS 字体 //如C:\WINDOWS\FONTS
CSIDL_NETHOOD 网上邻居目录 //如C:\WINDOWS\NetHood
CSIDL_NETWORK * 网上邻居
CSIDL_PERSONAL 我的文档 //如C:\My Documents
CSIDL_PRINTERS * 打印机
CSIDL_PROGRAMS 程序组 //如C:\WINDOWS\Start Menu\Programs
CSIDL_RECENT 最近文档 //如C:\WINDOWS\Recent
CSIDL_SENDTO 发送到 //如C:\WINDOWS\SentTo
CSIDL_STARTMENU 开始菜单 //如C:\WINDOWS\Start Menu
CSIDL_STARTUP 启动 //如C:\WINDOWS\启动
CSIDL_TEMPLATES 模版 //如C:\WINDOWS\ShellNew