分类:
2008-10-13 16:55:13
按数据库记录构建树控件
作者:
代码运行效果图如下:
简介:
将树中的每一个项目作为数据库中的一条记录(ACCESS2000),将程序启动时,对数据库进行读操作;创建树的各个项目时,是对数据库进行读操作,每次的读取,都是在可是查寻符合条件的记录,并将其一一添加到树中!
实现方法:
准备:
使用ACCESS2000,创建一个数据库,名字为City.mdb(我们将制作一个关于省与市的树,特别适合通讯录);
在数据库中创建一表,表名为TreeItem,字段内容与类型如下图:
ID: 索引号码(可有,可无) Name: 项目名称(必须) ParentItem: 父项名称(必须) SecNum: 电话区号(可有,可无) |
输入一些原始数据.数据库已经准备好,那我们就进行实地的编程阶段.
程序实现:
创建一个基于对话框的工程---TreeData
//-------------------------------------------- #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的创建:
//------------------------------------------ private: HRESULT hRes; _RecordsetPtr m_TreeRecordset; //用于创建一个查询记录集 //------------------------------------------ public: CImageList m_TreeBootImage; //Tree的图标2. (1).在对话框窗口中添加一个TreeCtrl控件,一个ComboExe控件; TreeCtrl的风格设置如下图;
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();总结:
这个程序主要是在数据库中进行操作,主干是两个递归成员函数;对于递归,让你自己来理解吧!