Implement the Windows folder management tree with Delphi

xiaoxiao2021-03-06  14

Second, the implementation principle

The implementation of the Windows folder management tree is essentially traversal for Windows Namespaces. Each folder in the name space provides an ISHELLFOLDER interface, and the way to traverse the name is:

1) Call the SHGETDESKTOPFolder function to get the ISHELLFOLDER interface of the desktop folder, the desktop folder is the root node of the folder management tree.

2) The enumobjects member function of the obtained ISHELLFOLDER interface is called to list the child folder.

3) Call the BindtoBject member function of iShellfolder to get the iShellFolder interface of the subfolder.

4) Repeat steps 2), 3) list all subfolders under a folder, only to the obtained ISHELLFOLDER interface as NIL.

The following explains several major functions that will be used, they define in the SHLOBJ unit:

1) Function ShgetDesktopFolder (VAR PPSHF: ishellfolder): HRESULT;

This function gets the ISHELLFOLDER interface of the desktop folder through PPSHF.

2) Function ishellfolder.enumObjects (hwndowner: hwnd; grfflags: dword;

Out enumidlist: ienumidlist): HRESULT;

This function obtains a IEnumIdList interface, which can list the contents of the folder corresponding to the ISHELLFOLDER interface by calling the interface of the interface, and the type of content is specified by grfflags. We need to list the subfolders, so the value of Grfflags is specified as Shcontf_folders. HWndowner is a handle of the main window.

3) Function ishellfolder.bindtoObject (PIDL: PitemidList; PBCReServed: Pointer;

Const riid: tiid; out ppvout: Pointer: hResult;

This function gets an ISHELLFOLDER interface of a subfolder that is returned by PPVout. PIDL is a pointer to the element identifier list, and Windows 95/98 uses an element identifier and an element identifier list to identify objects in the namespace, which are similar to file names and paths. It is necessary to point out that when PIDL is passed to the Shell API function, it must be a member function relative to the ISHELLFOLDER interface relative to the desktop folder, and should be relative to the corresponding folder corresponding to the interface. path. PBCReServed should be specified as NIL, and RIID should be specified as IID_ISHELLFOLDER.

Other functions can be found in "Win32 Programmer's Reference" provided by Delphi.

Third, the program list

The following source code is implemented in Windows 98 and is tested in the Windows2000 beta (shown in Figure 1), and interested readers can rewrite them into Delphi components for common use.

Unit BrowsetreeView;

Interface

Uses

Windows, Messages, Sysutils, Classes, Graphics, Controls, Forms, Dialogs,

SHLOBJ, COMCTRLS;

Type

PTreeViewItem = ^ TtreeViewItem

TTREEVIEWITEM = Record

ParentFolder: iShellFolder; / / The ISHELLFOLDER interface of the parent folder of the corresponding folder

PIDL, FULLPIDL: PitemidList; // The relative and absolute item identity list of the corresponding folder, whether the list isxpanded: Boolean; // Whether the contact is expanded

END;

Figure 1 Program operation results

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

// The following is a function of a few of the project identifier

Procedure Disposepidl (ID: PitemidList);

VAR

Malloc: IMALLOC;

Begin

IF id = nil dam

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).

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;

// Convert binary representation of the item identity list into an identifiable project name

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_SYSICIONINDEX 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;

// Get the icon of each folder in the system

Procedure GetItemicons (Fullpidl: PitemidList; Treenode: Ttreenode);

Begin

With treenode do

Begin

ImageIndex: = Geticon (FullPIDL, FALSE);

SELECTEDINDEX: = Geticon (fullpidl, true);

END;

END;

/ / Get the system's icon list

Procedure TFORM1.SETTREEVIEWIMAGELIST;

VAR

ImageList: thandle;

FileInfo: Tshfileinfo; Begin

ImageList: = shGetfileinfo (Pchar ('C: /'), 0, FileInfo,

Sizeof (TshfileInfo), SHGFI_SYSICIONINDEX or SHGFI_SMALLICON;

IF imagelist <> 0 THEN

TreeView_setimagelist (TreeView1.Handle, Imagelist, 0);

END;

/ / Generate a folder management tree

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.getaTributesof (1, PIDLS, ATTR);

if Bool (attr and (sfgao_hassubfolder or sfgao_folder) THEN

if Bool (attr and sfgao_folder)

IF Bool (attr and sfgao_hassubfolder) THEN

Childnode.haschildren: = true;

END;

Except

/ / You can process an exception here

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 the exit;

Olecheck (TVItem.ParentFolder.BindToObject (TVItem ^ .pidl,

NIL, IID_ID_ILLFOLDER, POINTER (SHFOLDER));

FillTreeView (Shfolder, TVItem ^ .FullPidl, Node);

Node.alphas.

TVitem ^ .hasexpanded: = true;

END;

End.

转载请注明原文地址:https://www.9cbs.com/read-48659.html

New Post(0)