`
445822357
  • 浏览: 749533 次
文章分类
社区版块
存档分类
最新评论

MFC——CTreeCtrl数据的处理:如何将数据和逻辑分开?

 
阅读更多

CTreeCtrl是windows界面开发中经常用到,也是windows系统中经常见到的一种控件,比如文件夹目录,那就是一个典型的应用,不过,很多资料中,对于CTreeCtrl的数据的处理,存在一些问题。我们可以先看下面的代码:

void CFileTreeCtrl::InitTreeCtrl(const CString& strDir, HTREEITEM hItem)
{
	CFileFind finder;
	CString strFindDir = strDir;
	strFindDir += _T("\\*.*");
	BOOL bWorking = finder.FindFile(strFindDir);
	while(bWorking)
	{
		HTREEITEM hItemTmp;
		bWorking = finder.FindNextFile();
		if(finder.IsDirectory() && !finder.IsDots())
		{
			CString szFileName = finder.GetFileName();
			CString strNextDir = finder.GetFilePath();
			SHFILEINFO sfi;
			SHGetFileInfo(strNextDir+_T("\\"), 0, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX|SHGFI_DISPLAYNAME);
			TV_INSERTSTRUCT TCItem;
			ZeroMemory(&TCItem,sizeof(TV_INSERTSTRUCT));
			
			TCItem.hInsertAfter = TVI_LAST;
			TCItem.item.mask           = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_STATE|TVIF_SELECTEDIMAGE;
			TCItem.item.pszText        = sfi.szDisplayName;
			TCItem.item.iImage         = sfi.iIcon;
			TCItem.item.iSelectedImage = sfi.iIcon;
			TCItem.item.lParam  = 0;

			if(hItem == NULL)
			{
				TCItem.hParent = m_hRoot;
				//hItemTmp = InsertItem(szFileName, m_hRoot);
				hItemTmp = InsertItem(&TCItem);
			}
			else
			{
				TCItem.hParent = hItem;
				//hItemTmp = InsertItem(szFileName, hItem);
				hItemTmp = InsertItem(&TCItem);
			}
			
			TCHAR* pData = new TCHAR[strNextDir.GetLength()];
			lstrcpy(pData, (LPCTSTR)strNextDir);
			SetItemData(hItemTmp, (DWORD_PTR)pData);
			InitTreeCtrl(strNextDir, hItemTmp);
		}
	}
	Expand(m_hRoot,TVE_EXPAND);
	finder.Close();
}


这种写法是比较常见的,这样写有什么问题呢?首先数据和逻辑混在一起;其次,每刷新一次,都要重新读取目录一次;再次,就是扩展性不好。这里是读取一个指定目录,那如果目录数据来源于数据库呢,又或者来源于服务程序?

所以,网上搜的资料,可以参考,可以借鉴,更要深入的思考和优化。

都提倡设计模式,但是说一套,做一套,并不是一个好的方式。有的人说起来一套套的,似乎这也会,那也懂,但是写的东西不是有内存泄露,就是导致程序异常。对于这种数据和逻辑混淆在一起的情况,其实大有存在。

先看看下面的代码:

int CFileTreeCtrl::InitData(int parentId, HTREEITEM hItem)
{
	COprMySql OprMySql;
	BOOL bFlag=FALSE;
	TFile* temp;

	int nData = m_file[parentId];
	if (nData == 1)
	{
		Expand(hItem,TVE_EXPAND);
		temp = m_fileData[parentId];
		((CDlgUpFile*)(GetParent()))->m_EditPath.SetWindowText(temp->url);
		return 1;
	}

	vector<TFile> tFile;
	tFile.empty();
	vector<TFile>::iterator iter;
	
	char strtemp[20];

	OprMySql.QueryFileSqlByParentId(tFile, parentId);

	for(iter=tFile.begin(); iter!=tFile.end(); iter++)
	{
		temp = new TFile();
		*temp = *iter;

		TV_INSERTSTRUCT TCItem;
		ZeroMemory(&TCItem,sizeof(TV_INSERTSTRUCT));
			
		TCItem.hInsertAfter = TVI_LAST;
		TCItem.item.mask           = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_STATE|TVIF_SELECTEDIMAGE;
		TCItem.item.pszText        = temp->name.GetBuffer();
		//TCItem.item.iImage         = sfi.iIcon;
		//TCItem.item.iSelectedImage = sfi.iIcon;
		TCItem.item.lParam  = temp->id;

		TCItem.hParent = hItem;
		InsertItem(&TCItem);

		m_fileData[temp->id] = temp;

	}

	OprMySql.Close();

	m_file[parentId] = 1;

	Expand(hItem,TVE_EXPAND);

	temp = m_fileData[parentId];
	((CDlgUpFile*)(GetParent()))->m_EditPath.SetWindowText(temp->url);

	return 0;
}


这段代码是从数据库获取目录信息,参数parentId,是表示选中的级数,一般默认加载一级的,当选中某个的时候,就在查询数据库获取它的子项,在这里做了一个标记,m_file[parentId],第一次从数据库获取后,就设置m_file[parentId]=1,同时保存节点的信息m_fileData[temp->id] = temp。

而如果换成一个目录的话,只需要把这一句:OprMySql.QueryFileSqlByParentId(tFile, parentId);里的函数查询数据库,改成本地文件路径的数据。

这是初始的数据,当有增加和删除操作的时候,也一样。同时更新数据库和map的数据就好。

同样的道理,对于CListCtrl里的数据也是如此。

转载请注明原创链接:http://blog.csdn.net/wujunokay/article/details/13278131

分享到:
评论

相关推荐

    VS2010_MFC_CTreeCtrl的创建、使用、添加节点图标的测试例子

    代码包含CTreeCtrl的基本创建方法: 1、创建带图标的树,参考函数SetTree; 2、鼠标点击树节点的动作,参考函数OnTvnSelchangedTree1; 仅供参考学习所用,如觉得有用,请多分享链接。

    MFC CTreeCtrl保存xml与读取

    在VS2010下可编译运行,MFC CtreeCtrl 保存为.xml格式,提供 bool LoadXmlFile&#40;CTreeCtrl& m_tree, string& szFileName&#41; 函数保存MFC CtreeCtrl,并提供 bool CreateXmlFile&#40;CTreeCtrl& m_tree, string& ...

    CTreectrl控件选择性选中节点

    同事给的一个资源,自己稍作修改以满足自己的需要。一来传播经典二来留作日后自己使用。

    MFC拖放树控件CTreeCtrl源码

    MFC树控件CTreeCtrl的拖放操作源码,方便快捷高效

    MFC CTreeCtrl控件使用例子

    MFC树形结构的常用方法使用例子,包括对树形节点的添加,删除,查找,遍历,排序,在节点中绑定资源等。

    mfc ctreectrl 中节点拖动的实现

    简单实现下ctreectrl控件上节点的移动,可选作参考。

    MFC CTREECTRL AND GRID

    MFC CTREECTRL AND GRID

    MFC CListBox及CTreeCtrl具有复选框功能

    简单的使用 CListCtrl 与CTreeCtrl 使其具有复选框功能

    MFC 重绘CListCtrl、CTreeCtrl的滚动条

    这是我见过、用过的最好的一个有关重绘CListCtrl滚动条的代码。...资源中外面的两个代码文件我只是将源程序中加载应用中的资源改为加载本地资源而已,在此感谢http://www.vckbase.com/index.php/wv/1595的Nobita。

    VS2008 MFC下支持拖拽的CtreeCtrl控件

    看到网上一些支持拖拽的CTreeCtrl控件代码,改进了一些,希望对大家有所帮助,代码里有一部分注释,可以支持节点随意拖拽或者仅支持父节点拖拽功能。

    MFC 重绘CListCtrl、CTreeCtrl的滚动条.rar

    MFC 重绘CListCtrl、CTreeCtrl的滚动条,实现了添加滑动条控件的背景重绘,完全和控件完美的结合在一起,用当前的控件可以直接应用到你的项目进行二次开发,非常好的资源。

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

    该资源主要是结合http://blog.csdn.net/eastmount/article/details/19120567文章,使用MFC树形控件CTreeCtrl左边显示我的电脑不同盘符下文件夹,双击路径能显示该文件夹下文件图标.是关于树形控件比较好的资源,含注释.

    VC6.0 MFC CListCtrl BUTTON CTreeCtrl源码

    原创VC6.0 MFC应用程序源码,包含CListCtrl BUTTON CTreeCtrl等控件的使用,还有CImageList的使用,自定义结构体的方法,包含冒泡排序升序降序排列,关于学生班级的信息显示,姓名学号语数英分数总分等内容,最终将...

    CTreeCtrl添加.删除节点

    CTreeCtrl的功能.如移动.添加.删除节点 CTreeCtrl添加删除节点

    01_CTreeCtrl_控件_MFC界面_

    MFC中TreeCtrl用法示例,采用对话框应用程序编程,MFC下TreeCtrl控件的使用方法,图标添加方法,图标动态改变等

    CtreeCtrl checkbox 显示隐藏

    一个ctreectrl控制checkbox显示、隐藏的代码,有兴趣可以关注下。声明:此程序来源于网络,经本人部分修改。

    VC++ MFC树控件(CTreeCtrl)的入门应用实例

    VC++ MFC树控件(CTreeCtrl)的入门应用实例 能实现树控件的插入,删除一个结点,删除全部结点,树控件样式的改变,(树连线,字体,背景颜色的改变)等操作。实现了root添加多个父结点,每个父结点添加多个子结点,最后...

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

    简介:自幼受贵州大山的熏陶,养成了诚实质朴的性格。经过寒窗苦读,考入BIT,为完成自己的教师梦,放弃IT、航天等工作,成为贵财一名大学教师,并想把自己所学所感真

    带复选框的CTreeCtrl响应复选消息

    带复选框的CTreeCtrl响应复选消息,点击时同时设置其父项和子项,能够自能判断。

    自定义皮肤树控件(CTreeCtrl)

    对CTreeCtrl进行继承,添加了自定义滚动条样式,背景图片,鼠标经过子项样式,对展开时+-图标进行自定义,并保持了对原有功能的完全继承,其中很多资源参考网络

Global site tag (gtag.js) - Google Analytics