⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dirtree.cpp

📁 在VC编程环境下
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

	说明:本类在编写时参考了Code Jockey所写的MFC扩展类CShellTree,
		  特此说明。

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
//////////////////////////////////////////////////////////////////////
#include "fclstd.h"
#include "DirTree.h"
#include <shellapi.h>

//////////////////////////////////////////////////////////////////////
// 构造函数和析构函数
//////////////////////////////////////////////////////////////////////

CDirTree::CDirTree()
{
	m_strCurDir[0] = '\0';
}

CDirTree::~CDirTree()
{
}
////////////////////////////////////////////////////////////////////////////
BOOL CDirTree::Create(CFBWnd* pParent,UINT nID)
{
	if(pParent == NULL)return FALSE;

	DWORD style = WS_VISIBLE| WS_CHILD| TVS_HASLINES | TVS_LINESATROOT |
					TVS_HASBUTTONS | TVS_SHOWSELALWAYS |
					CCS_NOPARENTALIGN|CCS_NODIVIDER|CCS_NORESIZE;

	return CFBTreeView::Create(pParent,style,nID);
}
/////////////////////////////////////////////////////////////////////////////////////////////
BOOL CDirTree::OnCreate()
{
    SHFILEINFO		sfi;
    LPSHELLFOLDER	lpsf=NULL;	//IShellFolder 接口指针
    LPITEMIDLIST	lpi=NULL;		//ITEMIDLIST 结构指针
    HRESULT			hr;
    TV_SORTCB		tvscb;		//TV_SORTCB 结构

	//得到系统图像列表(系统图标)
    HIMAGELIST himl = (HIMAGELIST)SHGetFileInfo((LPCSTR)"C:\\", 
                                           0,
                                           &sfi, 
                                           sizeof(SHFILEINFO), 
                                           SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
	//拷贝之
	HIMAGELIST him = ImageList_Duplicate(himl);
    //将这个个图像列表分配给TreeCtrl 
    if (him)
		SetImageList(him);
	//图像列表背景透明
	ImageList_SetBkColor(him,CLR_NONE);

    // 得到桌面文件夹
    hr=SHGetDesktopFolder(&lpsf);

    if (SUCCEEDED(hr))
    {
       FillDirTree(lpsf,NULL,TVI_ROOT);//拼接目录树
       lpsf->Release();// 释放IShellFolder接口指针.
    }

	//排序
    tvscb.hParent     = TVI_ROOT;			//父节点
    tvscb.lParam      = 0;					//自定义
    tvscb.lpfnCompare = SortCBProc;			//回调函数
	SortChildrenCB(&tvscb);					//排序
    
	//展开根项目
	HTREEITEM hItem;
	hItem = GetRoot();
	Expand(hItem,TVE_EXPAND);

	return TRUE;
}
/****************************************************************************
*
*    函数: TreeViewCmpProc(LPARAM, LPARAM, LPARAM)
*
*    用途:  排列目录树的回叫函数 
*
****************************************************************************/
int CALLBACK CDirTree::SortCBProc(LPARAM lparam1, LPARAM lparam2, LPARAM lparamSort)
{
    LPTVITEMDATA lptvid1=(LPTVITEMDATA)lparam1;
    LPTVITEMDATA lptvid2=(LPTVITEMDATA)lparam2;
    HRESULT   hr;

    hr = lptvid1->lpsfParent->CompareIDs(0,lptvid1->lpi,lptvid2->lpi);

    if (FAILED(hr))
       return 0;

    return (short)SCODE_CODE(GetScode(hr));
}
/****************************************************************************
*
*  函数: FillDirTree( LPSHELLFOLDER lpsf,
*                     LPITEMIDLIST  lpifq,
*                     HTREEITEM     hParent)
*
*  用途: 拼装目录树
*
*  参数: lpsf         - IShellFolder 接口指针.
*		 lpifq        - TreeCtrl 的项目 ID 列表指针 (指向一个 ITEMIDLIST 结构).
*		 hParent      - 父节点
*
****************************************************************************/
void CDirTree::FillDirTree(LPSHELLFOLDER lpsf,LPITEMIDLIST lpifq,HTREEITEM hParent)
{
    TV_ITEM         tvi;            // TreeCtrl 项目的 TV_ITEM 结构.
    TV_INSERTSTRUCT tvins;          // TreeCtrl 插入项目的 TV_INSERTSTRUCT 结构.
    HTREEITEM       hPrev = NULL;   // 上一个添加项目的句柄.
    LPSHELLFOLDER   lpsf2=NULL;		//第二个 IShellFolder 接口指针
    LPENUMIDLIST    lpe=NULL;		//IEnumIDList接口指针
    LPITEMIDLIST    lpi=NULL, lpiTemp=NULL, lpifqThisItem=NULL;
    LPTVITEMDATA    lptvid=NULL;
    LPMALLOC        lpMalloc=NULL;//IMalloc 指针
    ULONG           ulFetched;
    UINT            uCount=0;//计数
    HRESULT         hr;
    char            szBuff[_MAX_PATH];
    HWND            hwnd = GetParent(m_hWnd);//父窗口句柄

    // 分配 shell 内存对象. 
    hr = SHGetMalloc(&lpMalloc);
    if (FAILED(hr))
       return;

    // 得到 IShellFolder 接口的 IEnumIDList 对象.
    hr = lpsf->EnumObjects(hwnd, SHCONTF_FOLDERS /*| SHCONTF_NONFOLDERS */| SHCONTF_INCLUDEHIDDEN, &lpe);

    if (SUCCEEDED(hr))//如果成功
    {
        while (S_OK == lpe->Next(1, &lpi, &ulFetched))
        {
            ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER;//属性: 文件夹和子文件夹
            lpsf->GetAttributesOf(1, (const struct _ITEMIDLIST **)&lpi, &ulAttrs);

            if (ulAttrs & SFGAO_FOLDER)//如果是文件夹
            {
                tvi.mask= TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
                if (ulAttrs & SFGAO_HASSUBFOLDER)//如果是子文件夹
                {
                    tvi.cChildren=1;
                    tvi.mask |= TVIF_CHILDREN;
                }
                        
                //为 ITEMDATA 结构分配内存
                lptvid = (LPTVITEMDATA)lpMalloc->Alloc(sizeof(TVITEMDATA));
                if (!lptvid)//如果失败
                    goto Done;
				
                if (!GetName(lpsf, lpi, SHGDN_NORMAL, szBuff))//得到文件夹名
                    goto Done;

                tvi.pszText    = szBuff;
                tvi.cchTextMax = _MAX_PATH;
                lpifqThisItem = ConcatPidls(lpifq, lpi);
      
                //拷贝 ITEMIDLIST 结构
                lptvid->lpi = CopyITEMID(lpMalloc, lpi);
   
		 	    tvi.iImage = GetItemIcon(lpifqThisItem, SHGFI_PIDL | 
									  SHGFI_SYSICONINDEX | 
									  SHGFI_SMALLICON);
   
				tvi.iSelectedImage = GetItemIcon(lpifqThisItem, SHGFI_PIDL | 
                                      SHGFI_SYSICONINDEX | 
                                      SHGFI_SMALLICON |
                                      SHGFI_OPENICON);
   
                lptvid->lpsfParent = lpsf;    //保存父文件夹
                lpsf->AddRef();

                lptvid->lpifq = ConcatPidls(lpifq, lpi);
   
                tvi.lParam = (LPARAM)lptvid;
	 		    //插入项目   
                tvins.item         = tvi;
                tvins.hInsertAfter = hPrev;
                tvins.hParent      = hParent;
                hPrev = InsertItem(&tvins);
             }
             // 释放内存.
             lpMalloc->Free(lpifqThisItem);  
             lpifqThisItem=0;
         }

         lpMalloc->Free(lpi); 
         lpi=0;
    }

Done://打扫战场, 释放内存.
 
    if (lpe)  
        lpe->Release();
    if (lpi && lpMalloc)           
        lpMalloc->Free(lpi);
    if (lpifqThisItem && lpMalloc) 
        lpMalloc->Free(lpifqThisItem);  

    if (lpMalloc) 
        lpMalloc->Release();
}
/****************************************************************************
*
*	FUNCTION:	TunnelTree(LPTSTR szFindPath)
*
*	PURPOSE:	Too crude to explain, just use it
*
*	WARNING:	Only works if you use the default PopTree()
*				Not guaranteed to work on any future or existing
*				version of windows. Use with caution. Pretty much
*				ok if you're using on local drives
*
****************************************************************************/

void CDirTree::TunnelTree(LPCTSTR szFindPath)
{
	HTREEITEM subNode = GetRoot();
	LPTSTR szPathHop;
	char szPath[_MAX_PATH];
	char drive[_MAX_DRIVE];
	char dir[_MAX_DIR];
	char fname[_MAX_FNAME];
	char ext[_MAX_EXT];
	char delimiter[]="\\";
	int i = 0;

	//CSHFileInfo checkPath(szFindPath);
	//if(!checkPath.Exist())
	//	return;

	ZeroMemory(szPath,_MAX_PATH);
	lstrcpy(szPath,szFindPath);
	i = lstrlen(szPath);
	if(szPath[i-1] != '\\')
	{
		szPath[i] = '\\';
		szPath[i+1] = '\0';
	}

	_splitpath(szPath,drive,dir,fname,ext);

	//search the drive first
	szPathHop=drive;
	subNode = GetChildItem(subNode);

	if(subNode)
	{
		if(SearchTree(subNode,szPathHop, SHELL_DRIVE))
		{

			//break down subfolders and search
			char *p=strtok(dir,delimiter);
			while(p)
			{
				subNode = (HTREEITEM)SendMessage(m_hWnd, TVM_GETNEXTITEM, TVGN_CARET, 0);
				subNode = GetChildItem(subNode);
				if(SearchTree(subNode,p, SHELL_FOLDER))
					p=strtok(NULL,delimiter);
				else
					p=NULL;
			}
		}
	}
}

//===========================================================================
/****************************************************************************
*
*	FUNCTION:	SearchTree(	HTREEITEM treeNode,
*							LPTSTR szSearchName )
*
*	PURPOSE:	Too crude to explain, just use it
*
*	WARNING:	Only works if you use the default PopulateTree()
*				Not guaranteed to work on any future or existing
*				version of windows. Use with caution. Pretty much
*				ok if you're using on local drives
*
****************************************************************************/
bool CDirTree::SearchTree(HTREEITEM treeNode,
							LPTSTR szSearchName,
							FindAttribs attr)
{
	LPTVITEMDATA	lptvid;  //Long pointer to TreeView item data
	LPSHELLFOLDER	lpsf2=NULL;
	char	drive[_MAX_DRIVE];
	char	dir[_MAX_DIR];
	char	fname[_MAX_FNAME];
	char	ext[_MAX_EXT];
	bool	bRet=false;
	HRESULT	hr;
	char	szPath[_MAX_PATH];
	ZeroMemory(szPath,_MAX_PATH);
	LPTSTR	szCompare = szPath;

	strupr(szSearchName);
	while(treeNode && bRet==false)
	{
		lptvid=(LPTVITEMDATA)GetItemData(treeNode);
		if (lptvid && lptvid->lpsfParent && lptvid->lpi)
		{
			hr=lptvid->lpsfParent->BindToObject(lptvid->lpi,
					 0,IID_IShellFolder,(LPVOID *)&lpsf2);
			if (SUCCEEDED(hr))
			{
				ULONG ulAttrs = SFGAO_FILESYSTEM;
				lptvid->lpsfParent->GetAttributesOf(1, (const struct _ITEMIDLIST **)&lptvid->lpi, &ulAttrs);
				if (ulAttrs & (SFGAO_FILESYSTEM))
				{
					if(SHGetPathFromIDList(lptvid->lpifq,szCompare))
					{
						switch(attr)
						{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -