classtreectrl.cpp
来自「深入浅出Visual C++入门进阶与应用实例 随书光盘 作者 何志丹」· C++ 代码 · 共 272 行
CPP
272 行
// ClassTreeCtrl.cpp : implementation file
//
#include "ClassTreeCtrl.h"
#include "stdafx.h"
#include "Resource.h"
#include "ModifyClassTreeNode.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CClassTreeCtrl
CClassTreeCtrl::CClassTreeCtrl()
{
m_bReadOnly = false;
m_pMainData = NULL;
m_pWndAcceptMessage = NULL ;
}
CClassTreeCtrl::~CClassTreeCtrl()
{
}
BEGIN_MESSAGE_MAP(CClassTreeCtrl, CTreeCtrl)
//{{AFX_MSG_MAP(CClassTreeCtrl)
ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
ON_COMMAND(ID_ADDNODE, OnAddnode)
ON_COMMAND(ID_DELETE_NODE, OnDeleteNode)
ON_COMMAND(ID_MODIFY_NODE, OnModifyNode)
ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged)
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CClassTreeCtrl message handlers
//根据数据分成子树
bool CClassTreeCtrl::InitTree(HTREEITEM hParentItem, CClassTreeNodeData * pTreeNodeData)
{
if(NULL == pTreeNodeData)
return false;
HTREEITEM hItem = InsertItem(pTreeNodeData->m_strText,hParentItem);
SetItemData(hItem,(DWORD)pTreeNodeData->m_nID);
//递归分成子树
for(int i = 0 ; i < pTreeNodeData->m_pSubNode.GetSize() ; i++ )
{
CClassTreeNodeData * pSubTreeNode = pTreeNodeData->m_pSubNode[i] ;
if(NULL == pSubTreeNode)
{
ASSERT(false);
continue;
}
InitTree(hItem,pSubTreeNode);
}
return true;
}
//根据关联数据分成树
bool CClassTreeCtrl::InitTree()
{
if(!InitTree(TVI_ROOT,&m_pMainData->m_ClassTreeRoot))
return false ;
if(NULL != m_pMainData)
{
CClassTreeNodeData * pCurTreeNodeData = m_pMainData->GetCurTreeNode() ;
if(NULL != pCurTreeNodeData )
{
HTREEITEM hSelectItem = GetItemByID(GetRootItem(),pCurTreeNodeData->m_nID );
SelectItem(hSelectItem);
}
}
return true ;
}
void CClassTreeCtrl::OnRclick(NMHDR* pNMHDR, LRESULT* pResult)
{
if(m_bReadOnly)//如果为只读不能弹出菜单
return ;
CPoint pt(0, 0);
::GetCursorPos(&pt);
ScreenToClient (&pt);
UINT nFlags;
HTREEITEM hNewSel = HitTest(pt, &nFlags);//右键击中节点
if(NULL == hNewSel)
return ;
//选中此节点
SelectItem(hNewSel);
CMenu menu;
HINSTANCE hOldInstance = AfxGetResourceHandle();
AfxSetResourceHandle(g_hInstance);
menu.LoadMenu(IDR_RBUTTONMENU);
AfxSetResourceHandle(hOldInstance);
CMenu * pMenu = menu.GetSubMenu(0);
if(NULL == GetParentItem(hNewSel))
{//根节点不能删除
pMenu->DeleteMenu(ID_DELETE_NODE,MF_BYCOMMAND);
}
ClientToScreen(&pt);
pMenu->TrackPopupMenu(TPM_CENTERALIGN| TPM_RIGHTBUTTON,pt.x,pt.y,this);
*pResult = 0;
}
void CClassTreeCtrl::OnAddnode()
{
HTREEITEM hItem = GetSelectedItem();
if(NULL == hItem)
return ;//此限制有必要吗?
//让用户输入相关信息
int nParentID = GetItemData(hItem);
CString strText = "新节点";
CString strDir = "";
CModifyClassTreeNodeDlg dlg;
dlg.SetMainData(m_pMainData);
do
{
if(!dlg.GetNewTreeNode(strText,strDir,nParentID))
return ;
CString strMess ;
if(m_pMainData->CanAddTreeNode(strText,nParentID,strDir,strMess))
break;
else
AfxMessageBox(strMess); //非法数据重新输入
}while(true);
if(NULL == m_pMainData)
{
ASSERT(false);
return ;
}
int nID ;
if(!m_pMainData->AddTreeNode(strText,nParentID,strDir,nID))
return ;//刷新内存及数据库中的内容
//更新树控件的内容
hItem = GetItemByID(GetRootItem(),nParentID);//当前节点不一定是新节点的父节点
hItem = InsertItem(strText,hItem);
SetItemData(hItem,nID);
SelectItem(hItem);
}
void CClassTreeCtrl::OnDeleteNode()
{
HTREEITEM hItem = GetSelectedItem();
if(NULL == hItem)
return ;
int nID = GetItemData(hItem);
if(NULL == m_pMainData)
{
ASSERT(false);
return ;
}
if(!m_pMainData->DeleteTreeNode(nID))//从内存及数据库中删除数据
return ;
DeleteItem(hItem);//删除树迭件的节点
}
void CClassTreeCtrl::OnModifyNode()
{
HTREEITEM hItem = GetSelectedItem();//选中节点
if(NULL == hItem)
return ;
int nID = GetItemData(hItem);
HTREEITEM hParentItem = GetParentItem(hItem);//选中节点的父节点
if(NULL == hParentItem)
return ;
int nParentID = GetItemData(hParentItem);
CString strText = GetItemText(hItem);//当前节点的内容
CClassTreeNodeData* pTreeNode = m_pMainData->GetTreeNodeByID(nID);
ASSERT(NULL != pTreeNode);
CString strDir = pTreeNode->m_strDirName;
//让用户输入相关信息
CModifyClassTreeNodeDlg dlg;
dlg.SetMainData(m_pMainData);
do
{
if(!dlg.GetNewTreeNode(strText,strDir,nParentID))
return ;
CString strMess ;
if(m_pMainData->CanEditTreeNode(nID,strText,nParentID,strDir,strMess))
break;
else//给用户提示,好让用户重新输入
AfxMessageBox(strMess);
}while(true);
if(NULL == m_pMainData)
{
ASSERT(false);
return ;
}
if(!m_pMainData->EditTreeNode(nID,strText,strDir,nParentID))
return ;//更新内存及数据库中的数据
//更新树迭件的信息(全部删除,重新生成)
DeleteAllItems();
InitTree(TVI_ROOT,&m_pMainData->m_ClassTreeRoot);
hItem = GetItemByID(GetRootItem(),nID);
SelectItem(hItem);
}
HTREEITEM CClassTreeCtrl::GetItemByID(HTREEITEM hParentID,int nID)
{
if(NULL == hParentID)
return NULL;
int iData = GetItemData(hParentID);
if(nID == iData)
return hParentID ;
//递归
HTREEITEM hItem = GetChildItem(hParentID);
while(NULL != hItem)
{
HTREEITEM hFindItem = GetItemByID(hItem,nID);
if(NULL != hFindItem)
return hFindItem;
hItem = GetNextSiblingItem(hItem);
}
return NULL;
}
void CClassTreeCtrl::PreSubclassWindow()
{
//失去焦点的时候,也可清楚的看到那个节点被选中
ModifyStyle(NULL,TVS_SHOWSELALWAYS);
CTreeCtrl::PreSubclassWindow();
}
CMainData* CClassTreeCtrl::SetMainData(CMainData *pData)
{
m_pMainData = pData ;
return m_pMainData ;
}
void CClassTreeCtrl::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
HTREEITEM hNewItem = pNMTreeView->itemNew.hItem ;
if(NULL == hNewItem)
return ;
DWORD uID = GetItemData(hNewItem);
if(NULL == m_pWndAcceptMessage)
return ;
m_pWndAcceptMessage->SendMessage(WM_USER_CLASSTREE_ITEMCHANGED,(WPARAM)uID,NULL);
*pResult = 0;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?