如何取得...

解决方案 »

  1.   

    得到“桌面”及其下的子目录:
    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.
      

  2.   

    要引用 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;
      

  3.   

    利用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中存储的就是桌面的路径值。简单吧!
      

  4.   

    相关资料:如何取得某些特殊文件夹路径在Windows 下有很多的特殊含义的文件夹,如桌面,网上邻居,字体,我的文档,
    程序组,最近文档,发送到,开始菜单,启动等,有时可能需要取得这些文件夹
    的真正路径。
    一种方法是通过读注册表文件,存放在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