图1 程序运行结果 TForm1 = class(TForm) TreeView1: TTreeView; procedure FormDestroy(Sender: TObject); procedure FormCreate(Sender: TObject); procedure TreeView1Expanding(Sender: TObject; Node: TTreeNode; var AllowExpansion: Boolean); private FItemList: TList; procedure SetTreeViewImageList; procedure FillTreeView(Folder: IShellFolder; FullPIDL: PItemIDList; ParentNode: TTreeNode); 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, lStrLen(StrRet.cStr)); STRRET_OFFSET: begin P := @PIDL.mkid.abID[StrRet.uOffset - sizeof(PIDL.mkid.cb)]; SetString(Result, P, PIDL.mkid.cb - StrRet.uOffset); end; STRRET_WSTR: Result := StrRet.pOleStr; 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.
图1 程序运行结果 TForm1 = class(TForm) TreeView1: TTreeView; procedure FormDestroy(Sender: TObject); procedure FormCreate(Sender: TObject); procedure TreeView1Expanding(Sender: TObject; Node: TTreeNode; var AllowExpansion: Boolean); private FItemList: TList; procedure SetTreeViewImageList; procedure FillTreeView(Folder: IShellFolder; FullPIDL: PItemIDList; ParentNode: TTreeNode); 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, lStrLen(StrRet.cStr)); STRRET_OFFSET: begin P := @PIDL.mkid.abID[StrRet.uOffset - sizeof(PIDL.mkid.cb)]; SetString(Result, P, PIDL.mkid.cb - StrRet.uOffset); end; STRRET_WSTR: Result := StrRet.pOleStr; 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.
Delphi6的Samples页面有这样的控件,也有源码,但是你得搜索一下Delphi的安装目录。
自己做解码,得累s.
当然,我要的是ACDSee 的缩略图浏览
To Musicwind:
我装 Delphi 6.0 了,我要的不是那个,那个我早就作出来了
To lance:
我学VB时,也做过,和你一样,但我……
????????????
我的电脑已经不装VB了……
那个控件好象outlook什么的,等我回去查查。