学习心得:控件之Tree Control (仿系统目录树视图)

本文介绍了Windows外壳名字空间的概念,包括外壳名字空间的定义、PIDL路径以及相关API如SHGetSpecialFolderLocation和SHGetFileInfo的使用。此外,还讨论了如何利用这些知识来仿造系统目录树视图,提供了在VS2005环境下实现的代码示例。
摘要由CSDN通过智能技术生成

 一、几个概念(摘)

1.外壳名字空间:

 在WINDOWS中又叫外壳名字空间(Shell Name Space).外壳名字空间是Windows下的标准文件系统,它大大扩展了Dos文件系统,形成了以“桌面”(Desktop)为根的单一的文件系统树,原有的C盘、D盘等目录树变成“我的电脑”这一外壳名字空间子树的下一级子树,而像“控制面板”、“回收站”、“网上邻居”等应用程序及“打印机”等设备也被虚拟成了外壳名字空间中的节点。另外,与DOS中物理存储只能和文件系统项一一对应这一点不同的是,一个实际目录在外壳名字空间中可以表现为不同的项。例如“我的文档”与“C:/MyDocuments”其实都指向“C:/My Documents”目录,但它们在外壳名字空间中是不同的项。

2. 外壳名字空间下的路径: PIDL

PIDL是一个元素类型为ITEMIDLIST结构的数组,数组中元素的个数是未知的,但紧接着数组末尾的必是一个双字节的零。每个数组元素代表了外壳名字空间树中的一层(即一个文件夹或文件),数组中的前一元素代表的是后一元素的父文件夹。由此可见, PIDL实际上就是指向一块由若干个顺序排列的ITEMIDLIST结构组成、并在最后有一个双字节零的空间的指针。所以PIDL的类型就被Windows定义为ITEMIDLIST结构的指针。

 PIDL亦有“绝对路径”与“相对路径”的概念。表示“相对路径”的PIDL只有一个ITEMIDLIST结构的元素,用于标识相对于父文件夹的“路径”;表示“绝对路径”的PIDL(简称为“绝对PIDL”)有若干个ITEMIDLIST结构的元素,第一个元素表示外壳名字空间根文件夹(“桌面”)下的某一子文件夹A,第二个元素则表示文件夹A下的某一子文件夹B,其余依此类推。这样绝对PIDL就通过保存一条从“桌面”下的直接子文件夹或文件的绝对PIDL与相对PIDL是相同的,而其他的文件夹或文件的相对PIDL就只是其绝对PIDL的最后一部分了。由于所有的PIDL都是从桌面下的某一个子文件夹开始的,所以对于桌面本身来说,它的PIDL数组显然一个元素都没有。这样就只剩下PIDL数组最后的那个双字节的零了。所以,“桌面”的PIDL就是一个16位的零。

二、几个API

1.HRESULT SHGetSpecialFolderLocation(      
    HWND hwndOwner,
    int nFolder,                                 //CSIDL
    LPITEMIDLIST *ppidl               //返回CSIDL所对应的绝对PIDL(输出)
);

2.DWORD_PTR SHGetFileInfo(      
    LPCTSTR pszPath,                      //uFlags含SHGFI_PIDL时为绝对PIDL(输入)
    DWORD dwFileAttributes,          //绝对PIDL所对应文件的 file attribute flags (输出)
    SHFILEINFO *psfi,                       //返回file information
    UINT cbFileInfo,                          //SHFILEINFO结构大                                                                 UINT uFlags                                //指定你所要获取的信息
);       //该函数返回系统HIMAGELIST


说明:

typedef struct _SHFILEINFO {
  HICON hIcon;                                                
  int iIcon;                                                         //图标索引
  DWORD dwAttributes;                                 //文件属性
  TCHAR szDisplayName[MAX_PATH];    // 显示名称 
  TCHAR szTypeName[80];                          //文件类型:一个值对应一个二进制位
} SHFILEINFO;

uFlags  :SHGFI_DISPLAYNAME  | SHGFI_TYPENAME :psfi返回中包含显示名称和文件类型 (其他类推)

3.HRESULT SHGetDesktopFolder(
  IShellFolder** ppshf                          //f返回桌面IShellFolder接口   
);

IShellFolder的几个方法:

(1).BingToObject 获取子文件夹的IShellFolder接口                                                                   

(2).EnumObject获取IEnumIDList ,IEnumIDList ->Next方法获取子文件的相对PIDL(详见MSDN)

(3)GetAttributesOf获取文件属性

注意事项:参数中是绝对PIDL还是相对PIDL。SHGet绝对,IShellFolder相对。PIDL用IMalloc接口开辟空间

三、仿系统目录树

注:本程序在VS2005编译通过(存在小Bug:树节点的加号要展开后才显示,待修改)。

下面是原码

//  BrowseSysTreeDlg.h : 头文件
//

#pragma  once
#include 
" afxcmn.h "


//  CBrowseSysTreeDlg 对话框
class  CBrowseSysTreeDlg :  public  CDialog
{
// 构造
public:
    CBrowseSysTreeDlg(CWnd
* pParent = NULL);    // 标准构造函数


// 对话框数据
    enum { IDD = IDD_BROWSESYSTREE_DIALOG };

    
protected:
    
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

//添加
protected:
    HTREEITEM CreateFolderNode(LPITEMIDLIST lpPidl,HTREEITEM hParent);
    BOOL AttachFolders(HTREEITEM hNode);
    
void FreeNode(HTREEITEM hNode);


// 实现
protected:
    HICON                               m_hIcon;
    CTreeCtrl        m_ctrlTree;
    CImageList        m_imageList;
    IMalloc
*        m_pMalloc;

    
// 生成的消息映射函数
    virtual BOOL OnInitDialog();
    afx_msg 
void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg 
void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()

public:
    afx_msg 
void OnNMDblclkSysTree(NMHDR *pNMHDR, LRESULT *pResult);
public:
    afx_msg 
void OnTvnItemexpandingSysTree(NMHDR *pNMHDR, LRESULT *pResult);
public:
    afx_msg 
void OnDestroy();
}
;

 

//  BrowseSysTreeDlg.cpp : 实现文件
//

#include 
" stdafx.h "
#include 
" BrowseSysTree.h "
#include 
" BrowseSysTreeDlg.h "
#include 
" shlobj.h "

#ifdef _DEBUG
#define  new DEBUG_NEW
#endif


//  用于应用程序“关于”菜单项的 CAboutDlg 对话框

class  CAboutDlg :  public  CDialog
{
public:
    CAboutDlg();

// 对话框数据
    enum { IDD = IDD_ABOUTBOX };

    
protected:
    
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
    DECLARE_MESSAGE_MAP()
}
;

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值