简介:
将树中的每一个项目作为数据库中的一条记录(ACCESS2000),将程序启动时,对数据库进行读操作;创建树的各个项目时,是对数据库进行读操作,每次的读取,都是在可是查寻符合条件的记录,并将其一一添加到树中!
实现方法:
准备:
使用ACCESS2000,创建一个数据库,名字为City.mdb(我们将制作一个关于省与市的树,特别适合通讯录);在数据库中创建一表,表名为TreeItem,字段内容与类型如下图:
ID: 索引号码(可有,可无)
Name: 项目名称(必须)
ParentItem: 父项名称(必须)
SecNum: 电话区号(可有,可无)
输入一些原始数据.数据库已经准备好,那我们就进行实地的编程阶段.
程序实现:
创建一个基于对话框的工程---TreeData
一.ADO的引入和初始化
由于在程序中,我使用了ADO来连接和操作数据库,所以要进行以下操作:
1.在Stdafx.h中添加引作ADO的代码:
//-------------------------------------------- #import "c:/program files/common files/system/ado/msado15.dll" / no_namespace / rename("EOF","adoEOF") //-------------------------------------------- |
2.在TreeData.h中声明两个私有变量:
public: _ConnectionPtr m_pTreeConn;//连接创建 private: CString TreeConnString;//连接字符串 |
3.在CTreeDataApp的构造函数CTreeDataApp中添加如下代码:
//------------------------------------------- m_TreeConnString=_T("Provider=Microsoft.Jet.OLEDB.4.0;") _T("Data Source=DataBase//City.mdb;"); //------------------------------------------- |
4.在CTreeDataApp的初始化函数中添加如下代码:
//-------COM初始化-------------------------------- AfxOleInit(); /******************连接通讯录数据库********************/ HRESULT hRes; try { hRes=m_pTreeConn.CreateInstance(_T("ADODB.Connection")); m_pTreeConn->ConnectionTimeout = 8; //连接ACCESS2000 hRes=m_pTreeConn->Open(_bstr_t((LPCTSTR) m_strTelDataSource), _T(""),_T(""),adModeUnknown); } catch(_com_error e)///捕捉异常 { CString errormessage; errormessage.Format(_T("连接TelBook.mdb数据库失败!/r/n错误信息:%s"),e.ErrorMessage()); AfxMessageBox(errormessage);///显示错误信息 return FALSE; }二.Recordset的创建:
1.在CTreeDataDlg.h中声明变量:
//------------------------------------------ private: HRESULT hRes; _RecordsetPtr m_TreeRecordset; //用于创建一个查询记录集 //------------------------------------------ public: CImageList m_TreeBootImage; //Tree的图标 | 2. (1).在对话框窗口中添加一个TreeCtrl控件,一个ComboExe控件; TreeCtrl的风格设置如下图;
(2).导入一个BMP文件,做为Tree的项目图标(TreeBoot.bmp),将其ID设置为IDB_TreeBootImage;
(3).在向导中,为三个控件添加连接对象.
3.在CTreeDataDlg中右击,选择添加一个成员函数
TreeAddTree(bool Ta): void CBusinessView::TreeAddTree(bool Ta) { //--------------Tree控件操作变量------------------------ TVINSERTSTRUCT tvInsert; HTREEITEM hParent; //------------------------------------------------ tvInsert.hParent = NULL; tvInsert.hInsertAfter = NULL; tvInsert.item.mask = TVIF_TEXT; //-----------------创建图象标签---------------------------- m_TreeBootImage.Create ( IDB_TreeBootImage,20,1,ILC_COLOR8); m_ctrlTree.SetImageList ( &m_TreeBootImage,TVSIL_NORMAL ); m_ctrlTree.SetTextColor (RGB(7,145,13)); //--------添加根目录---------------------------------------- tvInsert.item.pszText = _T("中国"); hParent = m_ctrlTree.InsertItem(&tvInsert); //---------------添加子目录------------------------------- TreeAddSubTree("中国","1",hParent); //---------------------展开Tree目录------------------ m_ctrlTree.Expand(hParent,TVE_EXPAND); } | 4.添加一个COM变量到CString变量的转换函数:
//-----------------实现了VARIANT类型的值转换成CString类型-------------- CString CBusinessView::VariantToCString(VARIANT var) { CString strValue; _variant_t var_t; _bstr_t bst_t; time_t cur_time; CTime time_value; COleCurrency var_currency; switch(var.vt) { case VT_EMPTY:strValue=_T("");break; case VT_UI1:strValue.Format ("%d",var.bVal);break; case VT_I2:strValue.Format ("%d",var.iVal );break; case VT_I4:strValue.Format ("%d",var.lVal);break; case VT_R4:strValue.Format ("%f",var.fltVal);break; case VT_R8:strValue.Format ("%f",var.dblVal);break; case VT_CY: var_currency=var; strValue=var_currency.Format(0); break; case VT_BSTR: var_t=var; bst_t=var_t; strValue.Format ("%s",(const char*)bst_t); break; case VT_NULL: strValue=_T(""); break; case VT_DATE: cur_time=var.date; time_value=cur_time; strValue=time_value.Format("%A,%B%d,%Y"); break; case VT_BOOL: strValue.Format ("%d",var.boolVal ); break; default: strValue=_T(""); break; } return strValue; } | 5.同样的方法添加另外一个成员函数
TreeAddSubTree(CString ParTree,CString strChildTree,HTREEITEM hPartItem):
此成员函数是一个递归函数.
if (strChildTree!="0") { //----------------使用到的变量进行定义---------- _RecordsetPtr m_pTreeRecordset; //用于创建一个查询记录集 _variant_t vChild; //--------------Tree控件操作变量------------------------ HTREEITEM hCurrent; //---------------------------------------------- CString strSQL,strCurItem; //----------------------------------------------- strSQL="SELECT * FROM TreeItem where ParentItem like ''%" ; strSQL=strSQL+ParTree+"%''"; try { HRESULT hTRes; hTRes = m_pTreeRecordset.CreateInstance(_T("ADODB.Recordset")); if (SUCCEEDED(hTRes)) { //---------------------------------------------------- hTRes = m_pTreeRecordset->Open((LPTSTR)strSQL.GetBuffer(130), _variant_t((IDispatch *)(((CBusinessApp*)AfxGetApp())->m_pTreeConnection),true), adOpenDynamic,adLockPessimistic,adCmdText); if(SUCCEEDED(hTRes)) { TRACE(_T("连接成功!/n")); //------------------------------------------ m_pTreeRecordset->MoveFirst(); if (!(m_pTreeRecordset->adoEOF)) {
while(!m_pTreeRecordset->adoEOF) { hCurrent = m_ctrlTree.InsertItem((LPCTSTR)(_bstr_t)/ (m_pTreeRecordset->GetCollect("Name")), hPartItem, NULL); //---------------将内容添加到City的Combo控件中------------------ m_ctrlComboCity.AddString(VariantToCString(m_pTreeRecordset->GetCollect("Name"))); if (TreeSumRecordCount(VariantToCString/ (m_pTreeRecordset->GetCollect("Name")))>0) { TreeAddSubTree(VariantToCString(m_pTreeRecordset->GetCollect("Name")), (VariantToCString(m_pTreeRecordset->GetCollect("Name"))), hCurrent); }
if (!(m_pTreeRecordset->adoEOF)) { m_pTreeRecordset->MoveNext(); } } } //--------------------------------------- } } } catch(_com_error e)///捕捉异常 { CString errormessage; MessageBox("创建City记录集失败!",ParTree+strChildTree); } } | 6.添加一个求当前项子项串的成员函数
ReturnTreeChilds(CString strCurItem): 此成员函数也是递归函数.
//----------------提取当前所选择项的子项文本所组成的字符串------------------------ CString CTreeDataDlg::ReturnTreeChilds(CString strCurItem) { CString strTreeChildren;//记录子项文本所组成的字符串 if (TreeSumRecordCount(strCurItem) > 0) { //--------------------进入递归运算--------------------- _RecordsetPtr m_pTreeRecordset; //用于创建一个查询记录集 _variant_t vCur; CString strSQL; //----------------------------------------------- strSQL="SELECT * FROM TreeItem where ParentItem like ''%" ; strSQL=strSQL+strCurItem+"%''"; try { HRESULT hTRes; hTRes = m_pTreeRecordset.CreateInstance(_T("ADODB.Recordset")); if (SUCCEEDED(hTRes)) { //---------------------------------------------------- hTRes = m_pTreeRecordset->Open((LPTSTR)strSQL.GetBuffer(130), _variant_t((IDispatch *)(((CTreeDataApp*)AfxGetApp())->m_pTreeConn),true), adOpenDynamic,adLockPessimistic,adCmdText); if(SUCCEEDED(hTRes)) { TRACE(_T("连接成功!/n")); //------------------------------------------ m_pTreeRecordset->MoveFirst(); vCur=(m_pTreeRecordset->GetCollect("Name")); if (TreeSumRecordCount(VariantToCString(vCur))>=0) { while(!m_pTreeRecordset->adoEOF) { vCur=(m_pTreeRecordset->GetCollect("Name")); strTreeChildren+=(",''"+VariantToCString(vCur)+"''"); if (TreeSumRecordCount(VariantToCString(vCur))!=0) { strTreeChildren+=ReturnTreeChilds(VariantToCString(vCur)); } if (!(m_pTreeRecordset->adoEOF)) { m_pTreeRecordset->MoveNext(); } } } //--------------------------------------- } } } catch(_com_error e)///捕捉异常 { CString errormessage; AfxMessageBox("创建ChildTree记录集失败!"+strCurItem); } } return strTreeChildren; } | 7.处理TreeCtrl控件的点击(OnClick)和改变选择项(SelchangedTree)事件:
void CTreeDataDlg::OnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; //-------------------------------------------------------- hTreeCurrent=m_ctrlTree.GetSelectedItem (); hTreeParent=m_ctrlTree.GetParentItem(m_ctrlTree.GetSelectedItem ()); //-------------------树型控件的图标更改--------- m_ctrlTree.SetItemImage(hTreeCurrent,1,true ); //---------------------------------------------- TreeCurrent="''"+m_ctrlTree.GetItemText(hTreeCurrent)+"''"; TreeParent=m_ctrlTree.GetItemText (hTreeParent); //---------------------处理ListTree中的相应显示内容-------------- //-------------提取树中当前项及其子项的内容------ hTreeCurrent=m_ctrlTree.GetSelectedItem (); m_strEdit=TreeCurrent+ReturnTreeChilds(m_ctrlTree.GetItemText(hTreeCurrent)); UpdateData(false);//子项内容显示到Edit控件中 //--------------------------------------------------- *pResult = 0; } void CTreeDataDlg::OnClickTree1(NMHDR* pNMHDR, LRESULT* pResult) { //-------------------树型控件的图标还原--------- m_ctrlTree.SetItemImage(hTreeCurrent,0,true ); //---------------------------------------------- *pResult = 0; } | 三.在BOOL CTreeDataDlg::OnInitDialog()中添加以下代码: TreeAddTree();
本文效果图:
总结:
这个程序主要是在数据库中进行操作,主干是两个递归成员函数;对于递归,让你自己来理解吧!
|