MFC 树形控件CTreeCtrl显示文件路径及文件

2023-11-12

在上篇文章中简单讲述了"MFC单文档分割窗口显示图片",但是我想实现的是左边显示图片的路径,右边显示图片的情况,所以这里需要讲述如何使用控件List Control和Tree Control.
    CListCtrl(列表控件):可以用大图标、小图标、列表、报表四种不同方式显示一组信息.
    CTreeCtrl(树形控件):用树结构显示一组信息,并能反映这些信息的层次关系.
首先声明:该文章主要是数字图形处理知识并结合liujiannan_1987的上传资源讲述,在此感谢该作者:
http://download.csdn.net/download/liujiannan_1987/1528908

一.CTreeCtrl显示文件路径

第一部分 新建项目名为"TreeShow"的MFC基于对话框的应用程序.
资源视图中修改对话框IDD_TREESHOW_DIALOG,删除"TODO"和按钮,从工具箱中添加Tree Control(左)和List Control控件,设置CTreeCtrl的ID为IDC_TREE,属性Scroll(启动水平垂直滚动)、Horizontal Scroll(具有水平滚动)、Transparent(透明背景)为True.设置CListCtrl的ID为IDC_LIST.如下图:

第二部分 调用"项目"->"类向导"添加成员变量.
在类向导中选择类名"CTreeViewDlg","成员变量"中添加变量:
(控件ID-类型-成员)IDC_LIST-CListCtrl-m_list、IDC_TREE-CTreeCtrl-m_tree.
添加自定义受保护变量:CImageList-m_ImageList、HTREEITEM-m_hRoot.添加后XXXDlg.h中显示如下:

public:
	CListCtrl m_list;        //列表控件 IDC_LIST
	CTreeCtrl m_tree;        //树形控件 IDC_TREE
protected:
	CImageList m_ImageList;  //图像列表(相同大小图像集合) 
	HTREEITEM m_hRoot;       //句柄 CTreeCtrl的根结点"我的电脑"

第三部分 调用"项目"->"类向导"添加方法.
1.在类导向中选择类名"CTreeShowDlg","方法"中点击"添加方法"公有函数void GetLogicalDrives(HTREEITEM hParent).具体代码如下:

//函数功能:获取驱动器 参数:路径名                       
void CTreeShowDlg::GetLogicalDrives(HTREEITEM hParent)
{
	//获取系统分区驱动器字符串信息
	size_t szAllDriveStrings = GetLogicalDriveStrings(0,NULL);           //驱动器总长度
	char *pDriveStrings = new char[szAllDriveStrings + sizeof(_T(""))];  //建立数组
	GetLogicalDriveStrings(szAllDriveStrings,pDriveStrings);
	size_t szDriveString = strlen(pDriveStrings);                        //驱动大小
	while(szDriveString > 0)
	{
		m_tree.InsertItem(pDriveStrings,hParent);       //在父节点hParent下添加盘符
		pDriveStrings += szDriveString + 1;             //pDriveStrings即C:\ D:\ E:\盘
		szDriveString = strlen(pDriveStrings);
	}
}

其中DWORD GetLogicalDriveStrings(DWORD nBuffer,LPTSTR lpBuffer)是Win32 API中获取系统分区信息函数,获取字符,其中包含当前所有逻辑驱动器的根驱动器路径,nBuffer是缓冲区大小,lpBuffer是逻辑驱动器名称字串.该函数将所有盘符信息以lpBuffer返回,如A:\<null>C:\<null>D:\<null><null>两个NULL终止.
此时如修改CTreeShowDlg::OnInitDialog()函数,添加相应代码能显示如下(该部分代码后面3将详细讲述):

2.同理通过"类向导"添加公有函数void GetDriveDir(HTREEITEM hParent)具体代码如下:

//函数功能:获取驱动盘符下所有子项文件夹
void CTreeShowDlg::GetDriveDir(HTREEITEM hParent)
{
	HTREEITEM hChild = m_tree.GetChildItem(hParent);   //获取指定位置中的子项
	while(hChild)                                      
	{
		CString strText = m_tree.GetItemText(hChild);  //检索列表中项目文字
		if(strText.Right(1) != "\\")                   //从右边1开始获取从右向左nCount个字符
			strText += _T("\\");
		strText += "*.*";
		//将当前目录下文件枚举并InsertItem树状显示
		CFileFind file;                                       //定义本地文件查找
	    BOOL bContinue = file.FindFile(strText);              //查找包含字符串的文件
		while(bContinue)
		{
            bContinue = file.FindNextFile();                  //查找下一个文件
			if(file.IsDirectory() && !file.IsDots())          //找到文件为内容且不为点"."
		        m_tree.InsertItem(file.GetFileName(),hChild); //添加盘符路径下树状文件夹
		}
		GetDriveDir(hChild);                                  //递归调用
		hChild = m_tree.GetNextItem(hChild,TVGN_NEXT);        //获取树形控件TVGN_NEXT下兄弟项
	}
}

其中CTreeCtrl::GetNextItem(HTREEITEM hItem,UINT nCode)是MFC中树形控件和列表控件用来获取下一项,常用来遍历.参数hItem是一个tree项的句柄,nCode一个用来指示与hItem的关系的类型的标志.上述代码用到TVGN_NEXT来获取下一个兄弟项.详见GetNextItem.
通过AfxMessageBox(strText)打桩输出,可以发现它获取的路径为"C:\*.*",然后为"$360Section\*.*"依次递归遍历;再通过GetNextItem(hChild,TVGN_NEXT)循环输出下一个兄弟项"D:\*.*",递归D盘子项;再到兄弟项E盘等.这就是该部分代码实现的功能.添加相应代码显示如下(该部分代码后面3将详细讲述):

3.修改TreeShowDlg.cpp中BOOL CTreeShowDlg::OnInitDialog()初始化函数才能实现显示,添加代码如下:

BOOL CTreeShowDlg::OnInitDialog()
{
	...
	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	m_ImageList.Create(32,32,ILC_COLOR32,10,30);     //创建图像序列CImageList对象 
	m_list.SetImageList(&m_ImageList,LVSIL_NORMAL);  //为树形控件设置图像序列   
	m_tree.ModifyStyle(NULL,TVS_HASBUTTONS|TVS_HASLINES|TVS_LINESATROOT|TVS_EDITLABELS);
    m_hRoot = m_tree.InsertItem("我的电脑");         //插入根节点
	GetLogicalDrives(m_hRoot);                      //自定义函数 获取驱动
	GetDriveDir(m_hRoot);                           //自定义函数 获取驱动子项
	m_tree.Expand(m_hRoot,TVE_EXPAND);              //展开或折叠子项列表 TVE_EXPAND展开列表 
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

(1).BOOLCImageList::Create( int cx, int cy, UINT nFlags, int nInitial, int nGrow )函数初始化图像列表并绑定对象.cx定义图像的宽度32像素,cy定义图象的高度32像素,nFlags确定建立图像列表的类型ILC_COLOR32 32位真彩,nInitial用来确定图像列表包含的图像数量,nGrow用来确定图像列表可控制的图像数量(增加容量时至少增加nGrow个单位).
(2).CImageList* SetImageList( CImageList *pImageList, intnImageListType )此成员函数来设置一个tree view控件的常规或状态图像控制列表.参数pImageList为指向图像列表的标识,如果pImageList为NULL则所有的图像都将从树控制中被清除;nImageListType为图像列表设置的类型,TVSIL_NORMAL 设置正常图像列,其中包括选中和非选中两种图标.
(3).ModifyStyle(DWORD dwRemove,DWORD dwAdd,UINT nFlags=0)修改窗口风格.dwRemove指定修改时要删除的窗风格,dwAdd指定修改时将要增加的窗口风格,也可以调用Win32 API函数SetWindowLong设置指定窗口属性.

DWORD dwStyle = GetWindowLong(m_tree.m_hWnd,GWL_STYLE);
dwStyle |= TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT;
SetWindowLong(m_tree.m_hWnd,GWL_STYLE,dwStyle);

再调用InsertItem插入根节点"我的电脑",通过GetLogicalDrives(m_hRoot)显示驱动器盘符树状信息,GetDriveDir(m_hRoot)显示驱动子项文件夹信息.Expand是展开"我的电脑"列表,否则默认为折叠状.

 二.显示子项下文件夹并添加文件夹图标

通过上面的讲述我们可以发现只是实现了展开盘符下一层的路径文件夹,但是继续下去的文件夹如何展开,下面将讲述,但不将继续叙述其中的函数功能.
第四部分 实现子项的孩子文件夹显示
1.打开"项目"->"类导向"->选择"CTreeShowDlg"类->"方法"中添加方法:CString GetFullPath(HTREEITEM hCurrent).具体代码如下:

//函数功能:获取树项目全根路径
CString CTreeShowDlg::GetFullPath(HTREEITEM hCurrent)
{
	CString strTemp;
	CString strReturn = "";
	while(hCurrent != m_hRoot)
	{
		strTemp = m_tree.GetItemText(hCurrent);    //检索列表中项目文字
		if(strTemp.Right(1) != "\\")
			strTemp += "\\";
		strReturn = strTemp  + strReturn;        
		hCurrent = m_tree.GetParentItem(hCurrent); //返回父项目句柄
	}
	return strReturn;
}

2.同理,添加方法:void AddSubDir(HTREEITEM hParent).该函数添加子目录,调用GetFullPath()获取全路径.具体代码如下:

//函数功能:添加子目录
void CTreeShowDlg::AddSubDir(HTREEITEM hParent)
{
	CString strPath = GetFullPath(hParent);     //获取全路径
	if(strPath.Right(1) != "\\")
		strPath += "\\";
	strPath += "*.*";
	CFileFind file;
	BOOL bContinue = file.FindFile(strPath);    //查找包含字符串的文件
	while(bContinue)
	{
		bContinue = file.FindNextFile();        //查找下一个文件
		if(file.IsDirectory() && !file.IsDots())
		    m_tree.InsertItem(file.GetFileName(),hParent);
	}
}

3."项目"->"类导向"->选择"CTreeShowDlg"类->"命令"中选择"IDC_TREE"对象ID->双击消息"TVN_ITEMEXPANDED",并添加成员函数void CTreeShowDlg::OnItemexpandedTree(NMHDR *pNMHDR, LRESULT *pResult).具体代码如下:

//函数功能:展开事件函数
void CTreeShowDlg::OnItemexpandedTree(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);

	// TODO: 在此添加控件通知处理程序代码
	TVITEM item = pNMTreeView->itemNew;                  //发送\接受关于树形视图项目信息
	if(item.hItem == m_hRoot)
		return;
    HTREEITEM hChild = m_tree.GetChildItem(item.hItem);  //获取指定位置中的子项
	while(hChild)
	{
		AddSubDir(hChild);                               //添加子目录
		hChild = m_tree.GetNextItem(hChild,TVGN_NEXT);   //获取树形控件TVGN_NEXT下兄弟项
	}
	*pResult = 0;
}

运行结果如下:

第五部分 添加文件夹图标
具体方法如下:找到文件夹32*32ICON图标,保存到工程的res目录下.然后在Resource View资源视图中,右键点击Icon节点,在右键菜单中选择“Add Resource..",弹出“Add Resource”对话框从左边“Resource type”列表中选择“Icon”,点击右边的“Import...”按钮即可导入.设置图标为IDI_ICON1.同时修改OnInitDialog()函数:
HICON hIcon = theApp.LoadIcon(IDI_ICON1);        //图标句柄
m_ImageList.Add(hIcon);                          //图标添加到图像序列
访问图标时m_hRoot = m_tree.InsertItem("我的电脑",0,0);为第一张ICON图标.推荐Bruce_Zeng文章"MFC树形控件(CTreeCtrl)用法".但是我没有成功,可能是获取大小时有图标会越界.

三.CListCtrl显示文件夹中文件

第六部分 调用CListCtrl显示文件夹中文件
"项目"->"类导向"->选择"CTreeShowDlg"类->"命令"中选择"IDC_TREE"对象ID->双击消息"TVN_SELCHANGED"生成成员函数:void CTreeShowDlg::OnSelchangedTree(NMHDR *pNMHDR, LRESULT *pResult),通过如下代码显示在CListCtrl中.

//函数功能:选中事件显示图标
void CTreeShowDlg::OnSelchangedTree(NMHDR *pNMHDR, LRESULT *pResult)
{
	//LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	m_list.DeleteAllItems();
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	TVITEM item = pNMTreeView->itemNew;
	if(item.hItem == m_hRoot)
		return;
	CString str = GetFullPath(item.hItem);
    if(str.Right(1) != "\\")
	   str += "\\";
	str += "*.*";
	CFileFind file;
	BOOL bContinue = file.FindFile(str);
	while(bContinue)
	{
		bContinue = file.FindNextFile();
		if(!file.IsDirectory() && !file.IsDots())
		{
		    SHFILEINFO info;
			CString temp = str;
			int index = temp.Find("*.*");
			temp.Delete(index,3);
		    SHGetFileInfo(temp + file.GetFileName(),0,&info,sizeof(&info),SHGFI_DISPLAYNAME | SHGFI_ICON);
		    int i = m_ImageList.Add(info.hIcon);
		    m_list.InsertItem(i,info.szDisplayName,i);
		}
	}
	*pResult = 0;
}

该部分代码希望读者自己详细阅读,非常不错的一段代码,完全转自liujiannan_1987的上传资源.运行结果如下:

四.总结

个人感觉该文章还不错,主要是结合自己数字图像处理知识,希望文章能够对大家有所帮助,同时如果文章中有错误或不足之处,还请大家海涵.同时感谢liujiannan_1987你上传的资源.最近有些忙,过后还将完成图标等工作及下篇"左边显示路径,右边显示图片".该文章资源下载地址:http://download.csdn.net/detail/eastmount/6917799

(By:Eastmount 2014-2-13夜1点 原创:http://blog.csdn.net/eastmount)

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MFC 树形控件CTreeCtrl显示文件路径及文件 的相关文章

  • Matlab:尝试将 SCRIPT XXX 作为函数执行的解决方案

    Matlab 尝试将 SCRIPT XXX 作为函数执行的解决方案 最近在做图像处理小实验的过程中遇到了无比沙雕的情况 被自己佛了 最近真的智商不在线 或者没在线过 先描述一下问题 在Matlab中调用直方图均衡化函数histeq 但是出现
  • 数字图像处理扭曲效果——挤压效果

    挤压效果 挤压效果是将图像向内挤压 产生收缩变形 挤压效果的实现可以看成是数学极坐标的一种体现 将当前像素点 图像正中心点和过中心点的水平线这三要素画出一个极坐标 然后根据用户指定的挤压度 在当前点与中心点所连的直线上映射出一个像素点 最后
  • 镜头选型——景深计算

    正在上传 重新上传取消 1 概述 先看两个例子 拍摄花 昆虫等照片时 背景拍的比较模糊 突出被拍物 但当拍摄纪念照 风景等照片时 却会把背景拍摄得和被拍对象一样清晰 这两者就是不同景深 前者为浅景深 拍摄聚焦到被拍物上 只能拍清一小段距离
  • 【OpenCV】噪声的添加和过滤

    1 简介 下面简单介绍两种图像噪声 即椒盐噪声和高斯噪声 1 椒盐噪声 椒盐噪声也称脉冲噪声 它是一种随机出现的白点或者黑点 可能是亮的区域有黑色像素或是在暗的区域有白色像素 或是两者皆有 图像模拟添加椒盐噪声是通过 随机获取像素点 并设置
  • 【图像处理】彩色直方图均衡

    sourcePic imread D Images pic loc 1870358810205041517 jpg m n o size sourcePic grayPic rgb2gray sourcePic figure imshow
  • MFC VS2012对话框背景填图

    这是使用VS 2012编写MFC对话框程序的教程 主要是关于图片处理方面的操作 这些在MFC游戏 图片处理 软件编写中是经常要用到的知识 一 创建项目 文件 新建项目 MFC应用程序 该页面使用 基于对话框 完成即可 注意 取消 使用Uni
  • MATLAB—GUI新手入门教程

    GUI界面基本操作 1 GUI界面介绍 2 各个控件的使用方法 2 1 1 按钮 2 1 2 滑动条 2 1 3 文本框 2 1 4 单选框和复选框和切换按钮 2 1 5 弹出式菜单和列表框 2 1 6 按钮组 2 1 7 菜单编辑器 常见
  • 二、图像二值化方法(python)---阈值全局固定、大津法

    文章目录 阈值全局固定 利用python实现阈值全局固定时的二值化 效果图 大津法OTSU 利用Python实现大津法 效果图如下 图像二值化也叫做图像阈值化处理 通过设定某个阈值为门限 把多灰度级的图像转化为仅仅有两个极端的灰度级 0和2
  • 一种简单快速有效的低照度图像增强方法

    一种简单快速有效的低照度图像增强方法 一 本文介绍的是一种比较实用并且去阴影效果很好的方法 选自2004年Tao的一篇论文 名称是 An Integrated Neighborhood Dependent Approach for Nonl
  • 20分钟,使用Amazon SageMaker快速搭建属于自己的AIGC应用

    真火 作为最近一段时间人工智能领域内的顶流之一 AIGC AI Generated Content 早已火爆出圈 频登各大互联网平台热搜 cite 微软亚洲研究院官方微博 这段时间以来 基于深度学习的内容生成在图像 视频 语音 音乐 文本等
  • 【图像处理】CvArr、Mat、CvMat、IplImage、BYTE转换

    一 Mat 类型 矩阵类型 Matrix 在openCV中 Mat是一个多维的密集数据数组 可以用来处理向量和矩阵 图像 直方图等等常见的多维数据 Mat有3个重要的方法 1 Mat mat imread const String file
  • 数学形态学滤波学习

    一 概述 数学形态学是建立在集合论基础上了一门学科 具体在图像处理领域 它把形态学和数学中的集合论结合起来 描述二值或灰度图像中的形态特征 来达到图形处理的目的 形态学主要是通过结构元素和图像的相互作用对图像进行拓补变换从而获得图像结构信息
  • 数字图像处理-小波变换小白解释基本原则

    内容完全转载 小波理论的基本概念及概述 第二版 欢迎阅读此份关于小波变换的入门教程 小波变换是一个相对较新的概念 其出现大约是在20世纪80年代 但是有关于它的文章和书籍却不少 这其中大部分都是由数学专业人士写给其他同行看的 不过 仍然有大
  • 【图像处理】去雾算法

    真正了解了什么叫最简单的就是最美好的 真正的好文章不需要大堆公式堆积显得充实 而是最最平实的思想 这篇文章的 原文PDF PPT 感兴趣的可以了解一下 这篇文章的目的就是以最简单的思路将图像达到去雾效果 用Matlab编了一下 效果图特别好
  • 图像边缘检测——一阶微分算子 Roberts、Sobel、Prewitt、Kirsch、Robinson(Matlab实现)

    图像边缘一般指图像的灰度变化率最大的位置 成因主要如下 1 图像灰度在表面法向变化不连续 2 图像中物体在空间上的深度不一致 3 在光滑的表面上颜色不一致 4 图像中物体的光影 边缘检测指的是从图像中检测边缘点和边缘段 并且描述边缘方向的过
  • 【数字图像处理】三.MFC实现图像灰度、采样和量化功能详解

    本文主要讲述基于VC 6 0 MFC图像处理的应用知识 主要结合自己大三所学课程 数字图像处理 及课件进行讲解 主要通过MFC单文档视图实现显示BMP格式图片 并通过Bitmap进行灰度处理 图片采样和量化功能 个人认为对初学者VC 6 0
  • 数字图像处理 在小波域中分析信号和图像

    一 简述 小波变换是用于分析特征在不同尺度上变化的数据的数学工具 对于信号 特征可以是随时间变化的频率 瞬态或缓慢变化的趋势 对于图像 特征包括边缘和纹理 小波变换主要是为了解决傅立叶变换的局限性而创建的 傅立叶分析是将信号分解为特定频率的
  • 【数字图像处理】图像形态学算法C语言实现(图像卷积,膨胀,腐蚀,开运算,闭运算,顶帽,黑帽,雕版,锐化)

    文章目录 一 图像卷积 1 图像卷积 2 数字信号处理中的卷积 3 数字图像处理中的卷积 二 图像卷积实现各种形态学运算 腐蚀 膨胀 形态学梯度 开运算 闭运算 顶帽 黑帽 雕版 锐化 li conv c main c 三 效果展示 原图
  • CListCtrl:如何保持滚动位置?

    我有一个 CListCtrl 报告样式 我可以在其中清除列表并在某些时间重新填充它 我想在执行此操作时保持垂直滚动位置 我发现有几种看起来很有前途的方法 EnsureVisible GetScrollPos SetScrollPos Get
  • CListCtrl 用鼠标选择多行

    There is a CListCtrl with SetExtendedStyle LVS EX GRIDLINES LVS EX FULLROWSELECT a single selection is false I want to b

随机推荐