记录这个文章没别的意思就是当做是学习笔记,没什么技术含量,因为测试其他功能需要在界面上面方便把东西拷贝到电脑上面,使用需要在测试工程里面直接把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;
}
代码都有注释,主要是我不想下次再来查找这个东西的实现,太烦人了所以,记录一下,也供大家参考。
事实上网上有很多实现很漂亮的一些这个东西,但是我要的是简单,所以那些代码我感觉都太麻烦了,又不想要几个文本所以加上了一些图标。