classtreenodedata.cpp
来自「深入浅出Visual C++入门进阶与应用实例 随书光盘 作者 何志丹」· C++ 代码 · 共 1,113 行 · 第 1/2 页
CPP
1,113 行
// ClassTreeNodeData.cpp: implementation of the CClassTreeNodeData class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ClassTreeNodeData.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//==================================================================//
// CClassTreeNodeData //
//==================================================================//
CClassTreeNodeData::CClassTreeNodeData()
{
m_pParentNode = NULL ;
}
CClassTreeNodeData::~CClassTreeNodeData()
{
for(int i = m_arContentData.GetSize() -1 ; i>= 0 ; i-- )
{
CArticleData * pData = m_arContentData[i];
ASSERT(NULL != pData);
delete pData ;
}
m_arContentData.RemoveAll();
for(i = m_pSubNode.GetSize() -1 ; i >= 0 ; i-- )
{
CClassTreeNodeData * pTreeNode = m_pSubNode[i];
ASSERT(NULL != pTreeNode);
delete pTreeNode ;
}
m_pSubNode.RemoveAll() ;
}
bool CClassTreeNodeData::ReadFromDB()
{
CArray<CClassTreeNodeData*,CClassTreeNodeData*> pNodeDatas;
if(!ReadFromClassTreeTable(pNodeDatas))
return false;
CArray<CArticleData *,CArticleData *> pContentDatas;
if(!ReadFromArticleTable(pContentDatas))
return false;
//建立两者之间的关系
for(int i = pNodeDatas.GetSize()-1 ; i >= 0 ; i--)
{
CClassTreeNodeData * pNodeData = pNodeDatas[i] ;
ASSERT(NULL != pNodeData);
for(int j = pContentDatas.GetSize() -1 ; j >= 0 ; j--)
{
CArticleData * pContentData = pContentDatas[j];
ASSERT(NULL != pContentData);
if(pNodeData->m_nID == pContentData->m_forumid)
{
pNodeData->m_arContentData.Add(pContentData);
pContentDatas.RemoveAt(j);
}
}
}
//将没有联系的CContentData,从内存中删除
ASSERT(0 == pContentDatas.GetSize());
for(i = 0 ; i < pContentDatas.GetSize() ; i++ )
delete pContentDatas[i] ;
pContentDatas.RemoveAll();
return true;
}
bool CClassTreeNodeData::ReadFromClassTreeTable(CArray<CClassTreeNodeData*,CClassTreeNodeData*>& pNodeDatas)
{
pNodeDatas.RemoveAll();
CClassSet rsRoot(CDB::GetDefaultDB());
//寻找根结点
rsRoot.m_strFilter = "ParentID=-1" ;
rsRoot.Open();
ASSERT(1 == rsRoot.GetRecordCount());//有且只能有一个根节点
if(rsRoot.GetRecordCount() == 0)
{
rsRoot.Close();
return false;
}
m_nID = rsRoot.m_nID ;
m_strText = rsRoot.m_strText ;
m_strDirName = rsRoot.m_strDir ;
rsRoot.Close();
//将非根节点,读进内存
CClassSet rs(CDB::GetDefaultDB());
rs.m_strFilter = "ParentID<>-1" ;
rs.Open();//重新打开一下
CUIntArray pParentID ;
while(!rs.IsEOF())
{
CClassTreeNodeData * pNodeData= new CClassTreeNodeData;
if(NULL == pNodeData)
{
rs.Close();
return false;
}
pNodeData->m_nID = rs.m_nID ;
pNodeData->m_strText = rs.m_strText;
pNodeData->m_strDirName = rs.m_strDir ;
pNodeDatas.Add(pNodeData);
pParentID.Add(rs.m_nParentID) ;
rs.MoveNext();
}
//理顺父子关系
const int nRecordCount = pNodeDatas.GetSize() ;
for(int i = 0 ; i < nRecordCount ; i++ )
{
CClassTreeNodeData * pData = pNodeDatas[i] ;
if(m_nID == pParentID[i])//节点的子节点
{
pData->m_pParentNode = this ;
m_pSubNode.Add(pData);
continue;
}
for(int j = 0 ; j < nRecordCount ; j++ )
{
CClassTreeNodeData * pParentData = pNodeDatas[j] ;
if(pParentData->m_nID == pParentID[i])
{
pData->m_pParentNode = pParentData ;
pParentData->m_pSubNode.Add(pData);
break;
}
}
ASSERT(j != nRecordCount) ;//非根节点必须有次节点
}
//检验非法数据,并释放所占内存
//检验所有节点的祖宗节点的父ID是不是-1.
for(i = nRecordCount-1 ; i >=0 ; i-- )
{
CClassTreeNodeData * pData = pNodeDatas[i] ;
ASSERT(NULL != pData);
CClassTreeNodeData * pParentData = NULL ;
do
{
pParentData = pData->m_pParentNode ;
if(NULL == pParentData)
break;
pData = pParentData ;
} while(true);
if(pData->m_nID != m_nID )
{
ASSERT(false);//此节点的祖宗节点不是合法的根节点
delete pData ;
pNodeDatas.RemoveAt(i) ;
}
}
rs.Close();
return true ;
}
bool CClassTreeNodeData::ReadFromArticleTable(CArray<CArticleData *,CArticleData *>& pContentDatas)
{
pContentDatas.RemoveAll();
CArticleSet rs;
rs.m_strSort = "ArticleID DESC" ;
try
{
rs.Open();
}
catch(CDBException * e )
{
e->m_strError ;
ASSERT(false);
}
//将数据读到内存中
while(!rs.IsEOF())
{
CArticleData * pData = new CArticleData ;
if(NULL == pData)
{
ASSERT(false);
rs.Close();
return false;
}
pData->m_ArticleID = rs.m_ArticleID ;
pData->m_content = rs.m_content ;
pData->m_FileName = rs.m_FileName ;
pData->m_forumid = rs.m_forumid ;
pData->m_topic = rs.m_topic;
pContentDatas.Add(pData);
rs.MoveNext();
}
rs.Close();
return true ;
}
bool CClassTreeNodeData::DeleteTreeNode(int nID)
{
CClassTreeNodeData * pNode = NULL ;
CClassTreeNodeData * pParentNode = NULL ;
pNode = GetTreeNodeByID(nID);
if(NULL == pNode)
{
ASSERT(false);
return false;
}
//为了减少误操作,当此节点有文章或子节点,给出提示
{
CString strMess = "你确认要删除此节点及其子节点和所属的文章吗?";
CWnd * pMainFrm = AfxGetMainWnd();
HWND hWnd = NULL ;
if(NULL != pMainFrm )
hWnd = pMainFrm->GetSafeHwnd() ;
if(IDOK != MessageBox(hWnd,strMess,"确认",MB_OKCANCEL))
return false ;
}
//父节点为空,是根节点无法删除
pParentNode = pNode->m_pParentNode ;
if(NULL == pParentNode)
{
ASSERT(false);
return false;
}
for(int i = pParentNode->m_pSubNode.GetSize()-1 ; i >= 0 ; i-- )
{
CClassTreeNodeData * pSubNode = pParentNode->m_pSubNode[i];
if(NULL == pSubNode)
{
ASSERT(false);
continue;
}
if(pSubNode->m_nID = nID )//要删除的子项
{
delete pSubNode ;//释放内存
pParentNode->m_pSubNode.RemoveAt(i);
CClassSet::DeleteTreeNode(nID);//从数据库中删除
return true;
}
}
return false ;//未找到删除的项
}
bool CClassTreeNodeData::EditTreeNode(int nID, CString strContent, CString strDir, int nParentID)
{
CClassTreeNodeData * pNode = GetTreeNodeByID(nID);
if(NULL == pNode)
{
ASSERT(false);
return false ;
}
pNode->m_strText = strContent ;
pNode->m_strDirName = strDir ;
CClassTreeNodeData * pParentNode = pNode->m_pParentNode ;
if(NULL != pParentNode && pParentNode->m_nID != nParentID)//不能更改根节点的父节点
{//更改了父节点
//原父节点中删除子节点
for(int i = pParentNode->m_pSubNode.GetSize()-1 ; i >= 0 ; i-- )
{
CClassTreeNodeData * pSubNode = pParentNode->m_pSubNode[i] ;
if(NULL == pSubNode)
{
ASSERT(false);
continue;
}
if(pSubNode->m_nID == nID )
{
pParentNode->m_pSubNode.RemoveAt(i);
break;
}
}
ASSERT(i >= 0 );//原父节点中没有找到此节点
//在此节点加到新父节点中
CClassTreeNodeData * pNewParentNode = GetTreeNodeByID(nParentID);
if(NULL == pNewParentNode)
{
ASSERT(false);
return false;
}
pNewParentNode->m_pSubNode.Add(pNode);
pNode->m_pParentNode = pNewParentNode ;//设置父节点
}
CClassSet::EditTreeNode(nID,strContent,nParentID,strDir);//修改数据库
return true ;
}
bool CClassTreeNodeData::AddTreeNode(const CString strText, int nParentID, CString strDir, int &nID)
{
//存数据库时才分配ID
if(!CClassSet::AddTreeNode(strText,nParentID,strDir,nID))
return false ;
CClassTreeNodeData * pParentNode = GetTreeNodeByID(nParentID);
if(NULL == pParentNode)
{
ASSERT(false);
return false;
}
CClassTreeNodeData * pNode = new CClassTreeNodeData ;
pNode->m_nID = nID ;
pNode->m_strText = strText ;
pNode->m_strDirName = strDir ;
pNode->m_pParentNode= pParentNode ;
pParentNode->m_pSubNode.Add(pNode);
return true ;
}
//=======================================================//
// CMainData //
//=======================================================//
CMainData::CMainData()
{
m_pCurTreeNode = NULL ;
}
CMainData::~CMainData()
{
WriteToFile();
}
bool CMainData::CanMovePre()
{
if(NULL == m_pCurTreeNode)
{
ASSERT(false);
return false;
}
ASSERT(m_pCurTreeNode >= 0 );
if(0 == m_nCurContentIndex)
return false;//已经到最前面了
return true;
}
bool CMainData::CanMoveNext()
{
if(NULL == m_pCurTreeNode)
{
ASSERT(false);
return false;
}
if(m_nCurContentIndex >= m_pCurTreeNode->m_arContentData.GetSize())
return false;//已经到最后了.注意有一条空记录,便于用户增加新记录
return true ;
}
bool CMainData::CanMoveLast()
{
if(NULL == m_pCurTreeNode)
{
ASSERT(false);
return false;
}
if(m_nCurContentIndex >= m_pCurTreeNode->m_arContentData.GetSize()-1)
return false;//已经到最后了.
return true ;
}
bool CMainData::MovePre()
{
if(!CanMovePre())
return false ;
m_nCurContentIndex-- ;
AdjustRecentArticleAClass();
return true;
}
bool CMainData::MoveNext()
{
if(!CanMoveNext())
return false;
m_nCurContentIndex++ ;
AdjustRecentArticleAClass();
return true;
}
bool CMainData::MoveFirst()
{
if(!CanMovePre())
return false;
m_nCurContentIndex = 0 ;
AdjustRecentArticleAClass();
return true;
}
bool CMainData::MoveLast()
{
if(!CanMoveNext())
return false;
m_nCurContentIndex = m_pCurTreeNode->m_arContentData.GetSize()-1 ;
AdjustRecentArticleAClass();
return true;
}
CClassTreeNodeData* CMainData::GetCurTreeNode()
{
return m_pCurTreeNode ;
}
CArticleData* CMainData::GetCurArticleData()
{
if(NULL == m_pCurTreeNode)
return NULL;
if(m_nCurContentIndex < 0 || m_nCurContentIndex >= m_pCurTreeNode->m_arContentData.GetSize())
return NULL;
return m_pCurTreeNode->m_arContentData[m_nCurContentIndex];
}
CClassTreeNodeData* CClassTreeNodeData::GetTreeNodeByID(int nID)
{
if(nID == m_nID)
return this ;
for(int i = m_pSubNode.GetSize()-1 ; i >= 0 ; i-- )
{
CClassTreeNodeData * pNode = m_pSubNode[i]->GetTreeNodeByID(nID);
if(NULL != pNode )
return pNode ;
}
return NULL ;
}
bool CMainData::SetCurTreeNode(int nID)
{
if(NULL != m_pCurTreeNode && nID == m_pCurTreeNode->m_nID )
return true ;//节点没有改变,无须修改
CClassTreeNodeData * pNode = m_ClassTreeRoot.GetTreeNodeByID(nID);
if(NULL == pNode)
{
ASSERT(false);
return false ;
}
m_pCurTreeNode = pNode ;
m_nCurContentIndex = m_mRecentArticleID[nID] ;
return true;
}
bool CMainData::DeleteTreeNode(int nID)
{
if(NULL != m_pCurTreeNode && nID == m_pCurTreeNode->m_nID)
m_pCurTreeNode = NULL ;
return m_ClassTreeRoot.DeleteTreeNode(nID);
}
bool CMainData::EditTreeNode(int nID, CString strContent, CString strDir, int nParentID)
{
//不影响当前分类及当前内容
return m_ClassTreeRoot.EditTreeNode(nID,strContent,strDir,nParentID);
}
bool CMainData::AddTreeNode(const CString strText, int nParentID, CString strDir, int &nID)
{
if(!m_ClassTreeRoot.AddTreeNode(strText,nParentID,strDir,nID))
return false;
if(!SetCurTreeNode(nID))
return false;
return true;
}
bool CMainData::Init()
{
if(!m_ClassTreeRoot.ReadFromDB())
return false ;
ReadFromFile();
return true ;
}
CClassTreeNodeData* CMainData::GetTreeNodeByID(int nID)
{
return m_ClassTreeRoot.GetTreeNodeByID(nID);
}
bool CMainData::DeleteCurArticle()
{
if(NULL == m_pCurTreeNode )
{
ASSERT(false);
return false ;
}
if(m_nCurContentIndex < 0 || m_nCurContentIndex >= m_pCurTreeNode->m_arContentData.GetSize())
{
ASSERT(false);
return false ;
}
//先从内存中删除,再从数据库中删除
CArticleData * pData = m_pCurTreeNode->m_arContentData[m_nCurContentIndex];
int nID = pData->m_ArticleID ;
delete pData ;
m_pCurTreeNode->m_arContentData.RemoveAt(m_nCurContentIndex);
CArticleSet::DeleteArticle(nID);
return true ;
}
bool CMainData::CanDeleteArticle()
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?