mfc的CTreeCtrl控件实现windows的资源管理器

         记录这个文章没别的意思就是当做是学习笔记,没什么技术含量,因为测试其他功能需要在界面上面方便把东西拷贝到电脑上面,使用需要在测试工程里面直接把windows的资源管理器展示出来,这个东西以前做过,但是代码丢了很久,mfc只是测试的时候用一下,基本没有去细挖,所以这次记录一下代码,这个也简单的显示了一些系统图标。

没什么东西直接上主要代码(系统自己带的代码能不上就不上了)。

BOOL Cwp8MtpTestDlg::OnInitDialog()
{
	CDialog::OnInitDialog();
//设置目录树样式
	DWORD dwStyle = GetWindowLong(m_pcTreeCtrl.m_hWnd,GWL_STYLE);
	dwStyle |= TVS_HASBUTTONS|TVS_HASLINES|TVS_LINESATROOT;
	SetWindowLong(m_pcTreeCtrl.m_hWnd,GWL_STYLE,dwStyle);
	//绑定图标链表
	m_pcTreeCtrl.SetImageList(CFileIcon::GetSysImgList(), TVSIL_NORMAL); 
	m_hPCTreeRoot = m_pcTreeCtrl.InsertItem(_T("我的电脑"),1,1);
	GetLogicalDrives(m_hPCTreeRoot);//获取本地驱动器加载到目录树
	GetDriveDir(m_hPCTreeRoot);	//获取驱动器下一级文件夹到目录树
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}
// 获取盘符到目录树,作为根目录下一级节点
void Cwp8MtpTestDlg::GetLogicalDrives(HTREEITEM hRoot)
{
	size_t szAllDrivesStrings = GetLogicalDriveStrings(0,NULL);	//获取驱动器字符长度
	WCHAR* pDriveStrings = new WCHAR[szAllDrivesStrings + sizeof(_T(""))];//定义字符串存储驱动器字符pDriveStrings
	GetLogicalDriveStrings((DWORD)szAllDrivesStrings,pDriveStrings);//获取驱动器字符到pDriveStrings
	//截取单个驱动器字符出来添加到目录树上
	//定义临时字符指针指向驱动器字符信息
	//(为了最后可以释放驱动器字符串方便,如果直接移动字符串指针,
	//后面调用delete释放字符串资源的时候会报错)
WCHAR* pTempDrive = pDriveStrings;
	size_t szDriveString = wcslen(pTempDrive);
	while(szDriveString>0)
	{
		m_pcTreeCtrl.InsertItem(pTempDrive,2,2,hRoot);//加载解析后的一个驱动器信息到目录树
		pTempDrive += szDriveString + 1;
		szDriveString = wcslen(pTempDrive);
	}
	delete pDriveStrings;
}
// 获取驱动器下一级目录到目录树上显示
void Cwp8MtpTestDlg::GetDriveDir(HTREEITEM hRoot)
{
	HTREEITEM hChild = m_pcTreeCtrl.GetChildItem(hRoot);//获取根节点下的第一个盘符节点
	while(hChild)
	{
		//获取查找路径
		CString strText = m_pcTreeCtrl.GetItemText(hChild);
		if(strText.Right(1) != _T("\\"))
		{
			strText += _T("\\");
		}
strText += _T("*.*");
		CFileFind fileFind;
		BOOL bContinue = fileFind.FindFile(strText);
		CString tempPath;
		while(bContinue)
		{
			bContinue = fileFind.FindNextFile();
			//不是[.]或[..]的时候,加载到目录树
			if(!fileFind.IsDots())
			{
				if (fileFind.IsDirectory())
				{//加载不同的图标
					m_pcTreeCtrl.InsertItem(fileFind.GetFileName(),3,4,hChild);
				}
else
				{
					tempPath = strText;
					int index = tempPath.Find(_T("*.*"));
					tempPath.Delete(index,3); 
					int iIcon = CFileIcon::GetSysIcon(tempPath+fileFind.GetFileName());//获取文件图标
					m_pcTreeCtrl.InsertItem(fileFind.GetFileName(),iIcon,iIcon,hChild);
				}
			}
		}
		//到下一个驱动器
		hChild = m_pcTreeCtrl.GetNextItem(hChild,TVGN_NEXT);
	}
}
// 根据目录树中任一节点获取其所有子目录
void Cwp8MtpTestDlg::AddSubDir(HTREEITEM hParent)
{
	//因为每次节点展开都执行了添加,为了避免重复,所以需要先删除	
	DelTreeItemChildes(hParent);

	CString strPath = GetFullPath(hParent);
	if(strPath.Right(1) != _T("\\"))
	{
		strPath += _T("\\");
	}
	strPath += _T("*.*");
	CFileFind fileFind;
	BOOL bContinue = fileFind.FindFile(strPath);
	CString tempPath;
	while(bContinue)
	{bContinue = fileFind.FindNextFile(); 
		if(!fileFind.IsDots())
		{
			if (fileFind.IsDirectory())
			{
				m_pcTreeCtrl.InsertItem(fileFind.GetFileName(),3,4,hParent);
			}
			else
			{
				tempPath = strPath;
				int index = tempPath.Find(_T("*.*"));
				tempPath.Delete(index,3); 
				int iIcon = CFileIcon::GetSysIcon(tempPath+fileFind.GetFileName());//获取文件图标
				m_pcTreeCtrl.InsertItem(fileFind.GetFileName(),iIcon,iIcon,hParent);
			}
		}
	}
}
//删除hParent节点下面的 所有的子节点,但是不删除hParent节点
void Cwp8MtpTestDlg::DelTreeItemChildes(HTREEITEM hParent)
{
	HTREEITEM hCurrent = m_pcTreeCtrl.GetChildItem(hParent);
	HTREEITEM hNext = hCurrent;
	while (hCurrent != NULL)
	{
		hNext = m_pcTreeCtrl.GetNextItem(hCurrent, TVGN_NEXT);
		m_pcTreeCtrl.DeleteItem(hCurrent);
		hCurrent = hNext;
	}
}
// 获取某节点的文件路径
CString Cwp8MtpTestDlg::GetFullPath(HTREEITEM hCurrent)
{
	CString strTemp = _T("");
	CString strFullPath = _T("");
	while(hCurrent != m_hPCTreeRoot)
	{
		//从当前节点找起,依次找出其父节点,到根节点结束
		strTemp = m_pcTreeCtrl.GetItemText(hCurrent);
		if(strTemp.Right(1) != _T("\\"))
			strTemp += _T("\\");
		strFullPath = strTemp + strFullPath;
		hCurrent = m_pcTreeCtrl.GetParentItem(hCurrent);
	}
	return strFullPath;
}
void Cwp8MtpTestDlg::OnTvnItemexpandedPcTree(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMTREEVIEW pNMTreeView = reinterpret_cast(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	TVITEM item = pNMTreeView->itemNew;				//获取当前展开节点
	//如果当前展开节点为根节点,则返回
	if(item.hItem == m_hPCTreeRoot)
		return;
	//轮训展开节点的每个子节点,加载文件目录信息到子节点上
	HTREEITEM hChild = m_pcTreeCtrl.GetChildItem(item.hItem);
	while(hChild!=NULL)
	{
		AddSubDir(hChild);
		hChild = m_pcTreeCtrl.GetNextItem(hChild,TVGN_NEXT);
	}
	*pResult = 0;
}

 

下面就是实现的获取系统图标的CFileIcon类

CFileIcon.h

#pragma once

class CFileIcon
{
public:
	CFileIcon(void);
	~CFileIcon(void);
	static CImageList* GetSysImgList();
	static int GetSysIcon(const CString &filePath);
private:
	static CImageList* m_img;
	static int m_imageid;
	static int m_videoid;
	static int m_musicid;
};


接下来是cpp文件

#include "FileIcon.h"

CImageList* CFileIcon::m_img = NULL;
int CFileIcon::m_imageid = 0;
int CFileIcon::m_videoid = 0;
int CFileIcon::m_musicid = 0;

CFileIcon::CFileIcon(void)
{

}

CFileIcon::~CFileIcon(void)
{
}
CImageList* CFileIcon::GetSysImgList()
{
	if (NULL == m_img)
	{
		m_img = new CImageList();
		m_img->Create(GetSystemMetrics(SM_CXSMICON),   
			GetSystemMetrics(SM_CYSMICON),   
			ILC_COLOR24,60,60); 
		//Shell32.Dll 图标资源对照表,这里面的图标很不准
		//所以打算只使用 我的电脑,磁盘,文件夹这里图片
		m_img->SetBkColor(GetSysColor(COLOR_WINDOW)); 
		//默认图标 无扩展名的
m_img->Add(ExtractIcon(AfxGetApp()->m_hInstance,_T("shell32.dll"),1));//0
		//我的电脑
		m_img->Add(ExtractIcon(AfxGetApp()->m_hInstance,_T("shell32.dll"),15));//1
		//磁盘
		m_img->Add(ExtractIcon(AfxGetApp()->m_hInstance,_T("shell32.dll"),8));//2
		//文件夹闭合
		m_img->Add(ExtractIcon(AfxGetApp()->m_hInstance,_T("shell32.dll"),3));//3
		//文件夹打开
		m_img->Add(ExtractIcon(AfxGetApp()->m_hInstance,_T("shell32.dll"),4));//4
	}
	   
	return m_img;
}
int CFileIcon::GetSysIcon(const CString &filePath)
{
	int iIcon = 0;
	int pos = filePath.ReverseFind('.');
	CString extenlName = _T("");
	if(pos != -1)
	{
		extenlName = filePath.Mid(pos+1,filePath.GetLength() - pos-1);
	}
	extenlName.MakeUpper();

	if ((_T("BMP")==extenlName)||(_T("JPG")==extenlName)||
		(_T("JPEG")==extenlName)||(_T("PNG")==extenlName)||(_T("GIF")==extenlName))
	{// 图片
if (0 == m_imageid)
		{
			SHFILEINFO fileInfo;
			SHGetFileInfo(filePath,0,&fileInfo,sizeof(&fileInfo),SHGFI_ICON|SHGFI_DISPLAYNAME);
			m_imageid = m_img->Add(fileInfo.hIcon);
		}
		iIcon = m_imageid;
	}
	else if ((_T("AVI")==extenlName)||(_T("RMVB")==extenlName)||(_T("FLV")==extenlName)||
		(_T("RM")==extenlName)||(_T("ASF")==extenlName)||(_T("DIVX")==extenlName)||
		(_T("MPG")==extenlName)||(_T("MPEG")==extenlName)||(_T("MPE")==extenlName)||
		(_T("WMV")==extenlName)||(_T("MP4")==extenlName)||(_T("MKV")==extenlName)||(_T("VOB")==extenlName))
	{// 视频
if (0 == m_videoid)
		{
			SHFILEINFO fileInfo;
			//这个函数可以拿很多图标,只是这个链表会有重复,还没好的处理方式
			//暂时只做了图片 音乐 视频的
			SHGetFileInfo(filePath,0,&fileInfo,sizeof(&fileInfo),SHGFI_ICON|SHGFI_DISPLAYNAME);
			m_videoid = m_img->Add(fileInfo.hIcon);
		}
		iIcon = m_videoid;
	}
else if ((_T("CD")==extenlName)||(_T("OGG")==extenlName)||(_T("MP3")==extenlName)||
		(_T("MP3")==extenlName)||(_T("WMA")==extenlName)||(_T("WAV")==extenlName)||
		(_T("VQF")==extenlName)||(_T("PRO")==extenlName)||(_T("REAL")==extenlName)||
		(_T("APE")==extenlName)||(_T("MODULE")==extenlName)||(_T("MIDI")==extenlName))
	{// 音乐
if (0 == m_musicid)
		{
			SHFILEINFO fileInfo;
			SHGetFileInfo(filePath,0,&fileInfo,sizeof(&fileInfo),SHGFI_ICON|SHGFI_DISPLAYNAME);
			m_musicid = m_img->Add(fileInfo.hIcon);
		}
		iIcon = m_musicid;
	}
	return iIcon;
}


代码都有注释,主要是我不想下次再来查找这个东西的实现,太烦人了所以,记录一下,也供大家参考。

事实上网上有很多实现很漂亮的一些这个东西,但是我要的是简单,所以那些代码我感觉都太麻烦了,又不想要几个文本所以加上了一些图标。

你可能感兴趣的:(mfc的CTreeCtrl控件实现windows的资源管理器)