// DataRoot.cpp: implementation of the CDataRoot class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "DataManager.h" #include "DataNodeBase.h" #include "DataNodeBaseEx.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif Def_CreateObj* g_pfCreateObj = NULL; Def_ReleaseObj* g_pfReleaseObj = NULL; __declspec(dllexport) CDataNodeBase*CreateObj(CString strClassName) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if(strClassName == "CDataNodeBaseEx") return new CDataNodeBaseEx; else //if(strClassName == "CDataNodeBase") return new CDataNodeBaseEx;//CDataNodeBase } __declspec(dllexport) void ReleaseObj(CDataNodeBase *pObj) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); delete pObj; } // 传递主程序的CreateObj和ReleaseObj接口 __declspec(dllexport) void SetMainProgObjInterface(LPVOID pfCreateObj, LPVOID pfReleaseObj) { g_pfCreateObj = (Def_CreateObj*)pfCreateObj; g_pfReleaseObj = (Def_ReleaseObj*)pfReleaseObj; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// IMPLEMENT_SERIAL(CDataNodeBase, CObject, 1) CDataNodeBase::CDataNodeBase() { m_strAppName = "DataManager";//AfxGetAppName(); __classCanUseDirectly = FALSE; m_pParent = NULL; m_uID = 0; m_strName = "NoName"; m_bModified = FALSE; memset(m_uFlags4, 0, sizeof(m_uFlags4)); } CDataNodeBase::~CDataNodeBase() { Reset(); if(!__classCanUseDirectly) { //TRACE("\n\n\n严重编码错误,禁止直接使用CDataNode类或直接派生于此类!这里会制造一些内存泄露来提醒处理.\n\n\n"); //ASSERT(FALSE); //AfxMessageBox("严重编码错误,禁止直接使用CDataNode类或直接派生于此类!"); } } void CDataNodeBase::Reset() { FreeSubs(); m_mutexMapProperties.Lock(); CString strItem; CVariable* pVar = NULL; POSITION pos = m_mapExtProperties.GetStartPosition(); while (pos) { m_mapExtProperties.GetNextAssoc(pos, strItem, (void*&)pVar); delete pVar; } m_mapExtProperties.RemoveAll(); m_mutexMapProperties.Unlock(); // m_mutexTempItems.Lock();中间临时变量不能删除,例如在树中的位置的参数。2006-06-19 // m_mapTempItems.RemoveAll(); // m_mutexTempItems.Unlock(); m_bModified = FALSE; } // 获取节点的父结点 inline CDataNodeBase *CDataNodeBase::GetParent() { // AFX_MANAGE_STATE(AfxGetStaticModuleState()); return m_pParent; } // 设置节点的父结点 inline void CDataNodeBase::SetParent(CDataNodeBase *pParent) { // AFX_MANAGE_STATE(AfxGetStaticModuleState()); m_pParent = pParent; // SetModified(); } // 获取子项列表 CMapPtrToPtr& CDataNodeBase::GetSubs() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); return m_mapSubs; } // 获取指定ID的直接子项 CDataNodeBase* CDataNodeBase::GetSub(UINT uID) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CDataNodeBase* pNode = NULL; m_mapSubs.Lookup((LPVOID)uID, (void*&)pNode); return pNode; } // 获取指定路径的任意深度的子项 CDataNodeBase* CDataNodeBase::GetSub(CString strPath) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CDataNodeBase* pNode = this; if (strPath != "") { int nPos = strPath.Find('.'); while (nPos > -1 && pNode) { CString strID = strPath.Left(nPos); UINT uID = (UINT)atoi(strID); strPath = strPath.Mid(nPos+1); nPos = strPath.Find('.'); pNode = pNode->GetSub(uID); } if(pNode && strPath.GetLength()>0) pNode = pNode->GetSub((UINT)atoi(strPath)); } return pNode; } // 获取名字 CString CDataNodeBase::GetName() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); return m_strName; } // 设置名字 void CDataNodeBase::SetName(CString strName) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); m_strName = strName; SetModified(); } // 获取属性的字符串值 BOOL CDataNodeBase::V_GetPropertyTxtValue(CString strPropertyName, CString &strTxtValue) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); BOOL bRtn = TRUE; m_mutexMapProperties.Lock(); CVariable* pVar = NULL; if((strPropertyName == "V" || strPropertyName == "Value" || strPropertyName == "") && m_mapExtProperties.Lookup("Value", (void*&)pVar)) {//Value的处理频度最大,故最先处理这个属性值 strTxtValue = pVar->GetTextValue(); if(theApp.m_bJtToFj && strTxtValue.GetLength()>1 && strTxtValue.GetAt(0)&(1<<7)) strTxtValue = CLanguage::GetCurLanguage(strTxtValue); } else if((strPropertyName == "S" || strPropertyName == "Status") && m_mapExtProperties.Lookup("Status", (void*&)pVar)) {//Status的处理频度最大,故最先处理这个属性值 strTxtValue = pVar->GetTextValue(); } else if(strPropertyName == "Name") { strTxtValue = GetName(); if(theApp.m_bJtToFj) strTxtValue = CLanguage::GetCurLanguage(strTxtValue); } else if(strPropertyName == "AppName") { strTxtValue = PV_GetAppName(); } else if(strPropertyName == "Type") { strTxtValue = PV_GetType(); } else if(strPropertyName == "ID") { strTxtValue = GetText(m_uID); } else if(strPropertyName == "SubsStatus" && theApp.m_bLoadedByMainProg) { BOOL bAlarm = FALSE; CPtrList listNode, listPos; CDataNodeBase* pNodeA = this; POSITION pos; BEGIN: do { if(pNodeA->PV_IsManagerNode()) {//是设备 CString strStatus; CString strErrorCount; pNodeA->V_GetPropertyTxtValue("S", strStatus); pNodeA->V_GetPropertyTxtValue("SpotErrorCount", strErrorCount); if(atoi(strStatus) > 0 || atoi(strErrorCount) > 0) bAlarm = TRUE; } else if(pNodeA->m_mapSubs.GetCount() > 0) {//是分类节点 pos = pNodeA->m_mapSubs.GetPtrList().GetHeadPosition(); GO_ON: while (pos && !bAlarm) { CDataNodeBase* pNode = (CDataNodeBase*)pNodeA->m_mapSubs.GetPtrList().GetNext(pos); if(pos) { listNode.AddTail(pNodeA); listPos.AddTail(pos); } pNodeA = pNode; goto BEGIN; } } if(listNode.GetCount() > 0 && !bAlarm) { pNodeA = (CDataNodeBase*)listNode.RemoveTail(); pos = (POSITION)listPos.RemoveTail(); goto GO_ON; } else break; } while(!bAlarm); strTxtValue = bAlarm?"2":"0"; } else if(strPropertyName == "XML") { this->SaveObjToString(strTxtValue); } else if(strPropertyName == "UidPath") { strTxtValue = GetIdPath(); } else if(strPropertyName == "NamePath") { strTxtValue = GetNamePath(); } else if(strPropertyName == "NamePath2") { CString strPath = GetName(); CString strNAMN; if(m_pParent != NULL && (!(m_pParent->V_GetPropertyTxtValue("NAMN", strNAMN)) || atoi(strNAMN)==0) ) { strPath = m_pParent->GetName() + "." + strPath; } strTxtValue = strPath; } else if(strPropertyName == "SubsID") { // 添加子项 // CPtrList listSort; // SortSubs(m_mapSubs, listSort); if(m_mapSubs.GetCount() > 0) { POSITION pos = m_mapSubs.GetPtrList().GetHeadPosition(); while (pos) { CDataNodeBase* pNode = (CDataNodeBase*)m_mapSubs.GetPtrList().GetNext(pos); strTxtValue += GetText(pNode->m_uID) + ";"; } } // elser // { // m_mutexMapProperties.Lock(); // CString strKey; // CVariable* pVar = NULL; // int i = 0; // POSITION pos = m_mapExtProperties.GetStartPosition(); // while(pos) // { // m_mapExtProperties.GetNextAssoc(pos, strKey, (void*&)pVar); // if(strKey.GetLength() < 3 || strKey.GetAt(2) != '_') // { // i++; // strTxtValue += GetText(i) + ";"; // } // } // m_mutexMapProperties.Unlock(); // } if(strTxtValue == "") strTxtValue = ""; } else if(strPropertyName == "Properties") { strTxtValue = "Name;"; m_mutexMapProperties.Lock(); POSITION pos = m_mapExtProperties.GetStartPosition(); while (pos) { CString strKey; CVariable* pVar = NULL; m_mapExtProperties.GetNextAssoc(pos, strKey, (void*&)pVar); strTxtValue += strKey + ";"; } m_mutexMapProperties.Unlock(); if(strTxtValue == "") strTxtValue = ""; } else if(m_mapExtProperties.Lookup(strPropertyName, (void*&)pVar)) { strTxtValue = pVar->GetTextValue(); } else { bRtn = FALSE; } m_mutexMapProperties.Unlock(); return bRtn; } // 获取属性的原始值 CVariable* CDataNodeBase::GetProperty(CString strPropertyName) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); ASSERT(FALSE); // AfxMessageBox(strPropertyName + ":获取属性,此函数停止使用!"); CVariable *p = NULL; m_mutexMapProperties.Lock(); m_mapExtProperties.Lookup(strPropertyName, (void*&)p); m_mutexMapProperties.Unlock(); return p; } // 获取属性,支持无限深度子节点的属性获取 BOOL CDataNodeBase::GetProperty(CString strPropertyPath, CString &strTxtValue) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); BOOL bOK = FALSE; CString strPath; CString strPropertyName; SeparatePathAndProperty(strPropertyPath, strPath, strPropertyName); CDataNodeBase* pNode = this; if (strPath != "") { int nPos = strPath.Find('.'); while (nPos > -1 && pNode) { CString strID = strPath.Left(nPos); UINT uID = (UINT)atoi(strID); strPath = strPath.Mid(nPos+1); nPos = strPath.Find('.'); pNode = pNode->GetSub(uID); if(pNode && pNode->PV_IsManagerNode() == NET_LINK_MANAGER_NODE) {//作为站点连接管理节点,需要触发向远程获取数据的请求,需要调用重载的该函数。 return pNode->GetProperty(strPath + strPropertyName, strTxtValue); } } } if(pNode) { bOK = pNode->V_GetPropertyTxtValue(strPropertyName, strTxtValue); } // else if(strPropertyName == "V" || strPropertyName == "Name") // {//增加功能:属性也可以用ID的方式来访问。 // int nDotPos = strPropertyPath.ReverseFind('.'); // if(nDotPos != -1) // { // CString strPropID = strPropertyPath.Left(nDotPos); // strPath = ""; // int nDotPos2 = strPropID.ReverseFind('.'); // if(nDotPos2 != -1) // { // strPath = strPropID.Left(nDotPos2); // strPropID = strPropID.Mid(nDotPos2+1); // } // int nPropID = atoi(strPropID); // pNode = GetSub(strPath); // if(pNode) // { // pNode->m_mutexMapProperties.Lock(); // if(nPropID > 0 && nPropID <= pNode->m_mapExtProperties.GetCount() && // pNode->m_mapSubs.GetCount() == 0) // { // CString strKey; // CVariable* pVar = NULL; // POSITION pos = pNode->m_mapExtProperties.GetStartPosition(); // for(int i = 0; i < nPropID; ) // { // pVar = NULL; // if(pos) // { // pNode->m_mapExtProperties.GetNextAssoc(pos, strKey, (void*&)pVar); // if(strKey.GetLength() < 3 || strKey.GetAt(2) != '_') // i++; // } // else // break; // } // if(i == nPropID) // { // bOK = TRUE; // if(strPropertyName == "V") // { // if(pVar) // strTxtValue = pVar->GetTextValue(); // } // else // strTxtValue = CLanguage::GetCurLanguage(strKey); // } // } // pNode->m_mutexMapProperties.Unlock(); // } // } // } return bOK; } //获取所有属性 void CDataNodeBase::GetPropertyNames(CMapStringToPtr &mapProperties) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); // ASSERT(FALSE); // AfxMessageBox(strPropertyName + ":获取属性,此函数停止使用!"); m_mutexMapProperties.Lock(); POSITION pos = m_mapExtProperties.GetStartPosition(); while (pos) { CString strKey; CVariable* pVar = NULL; m_mapExtProperties.GetNextAssoc(pos, strKey, (void*&)pVar); mapProperties.SetAt(strKey, (LPVOID)pVar); } m_mutexMapProperties.Unlock(); } // 更换属性 void CDataNodeBase::ReplaceProperty(CString strPropertyName, CVariable* pVar) { m_mutexMapProperties.Lock(); CVariable* pVarOld = NULL; if(m_mapExtProperties.Lookup(strPropertyName, (void*&)pVarOld)) { try { delete pVarOld; } catch(...) { } if(pVar == NULL) m_mapExtProperties.RemoveKey(strPropertyName); } if(pVar) m_mapExtProperties.SetAt(strPropertyName, pVar); SetModified(TRUE); m_mutexMapProperties.Unlock(); } // 设置或增加属性的字符串值,名字以V_开头表示每个派生类强烈建议重载该函数. BOOL CDataNodeBase::V_SetPropertyTxtValue(CString strPropertyName, CString strTxtValue, BOOL bAddIfNotExist, UINT uAttrFlag) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); m_mutexMapProperties.Lock(); BOOL bOK = FALSE; if(!IsUnEditableProperty(strPropertyName)) { CVariable* pVar = NULL; if((strPropertyName == "V" || strPropertyName == "Value") && m_mapExtProperties.Lookup("Value", (void*&)pVar)) {//Value的处理频度最大,故最先处理这个属性值 if(uAttrFlag & ATTR_NEET_SET_MODIFY_FLAG) TRACE(""); pVar->SetTextValue(strTxtValue, pVar->GetVarType()); bOK = TRUE; if(uAttrFlag & ATTR_NEET_SET_MODIFY_FLAG) SetModified(); } else if((strPropertyName == "S" || strPropertyName == "Status") && m_mapExtProperties.Lookup("Status", (void*&)pVar)) {//Value的处理频度最大,故最先处理这个属性值 if(uAttrFlag & ATTR_NEET_SET_MODIFY_FLAG) TRACE(""); pVar->SetTextValue(strTxtValue, pVar->GetVarType()); bOK = TRUE; if(uAttrFlag & ATTR_NEET_SET_MODIFY_FLAG) SetModified(); } else if(strPropertyName == "Name") { m_strName = strTxtValue; bOK = TRUE; if(uAttrFlag & ATTR_NEET_SET_MODIFY_FLAG) SetModified(); } else if(strPropertyName == "XML") { this->Reset(); this->LoadObjFromString(strTxtValue); //this->SetModified(); this->SaveObj(); } else if(strPropertyName == "RaiseEvent") { CString strLevel; V_GetPropertyTxtValue("Level", strLevel); ReportNewEvent(this, strTxtValue, atoi(strLevel), 1); } // else if(strPropertyName == "UidPath") // { // } else if(strPropertyName == "NamePath") { } else if(strPropertyName == "SubsID") { } else if(strPropertyName == "Properties") { } else if(strPropertyName == "ID") { if(m_pParent == NULL && atoi(strTxtValue) > 0) m_uID = atoi(strTxtValue); } else if(m_mapExtProperties.Lookup(strPropertyName, (void*&)pVar)) { if(uAttrFlag & ATTR_NEET_SET_MODIFY_FLAG) TRACE(""); ////////////////////////////////////////////////////////////////////////// if(strPropertyName == "PauseTimeRelease" && strTxtValue.GetLength() > 0) {//暂停时间设置时,如果给定的是数字,要自动转换为时间 COleDateTime timeRelease; BOOL bValidTime = TRUE; if(strTxtValue.Find('-') == -1) { bValidTime = FALSE; } else { try { timeRelease.ParseDateTime(strTxtValue); } catch (...) { bValidTime = FALSE; } } if(!bValidTime) { COleDateTimeSpan span; span.SetDateTimeSpan(0, 0, atoi(strTxtValue), 0); timeRelease = COleDateTime::GetCurrentTime() + span; strTxtValue = timeRelease.Format("%Y-%m-%d %H:%M:%S"); } } ////////////////////////////////////////////////////////////////////////// pVar->SetTextValue(strTxtValue, pVar->GetVarType()); bOK = TRUE; if(uAttrFlag & ATTR_NEET_SET_MODIFY_FLAG) SetModified(); } else if(bAddIfNotExist) { pVar = new CVariable; //pVar->SetAttributes(uAttrFlag & ATTR_NEET_SET_MODIFY_FLAG, TRUE, TRUE, VT_BSTR); pVar->SetTextValue(strTxtValue, VT_EMPTY); ReplaceProperty(strPropertyName, pVar); bOK = TRUE; if(uAttrFlag & ATTR_NEET_SET_MODIFY_FLAG) SetModified(); } if(uAttrFlag & ATTR_MANUAL_SET_VALUE) { CStringList strParams, strReturns; strParams.AddTail(strPropertyName); strParams.AddTail(strTxtValue); //???? don't delete thease lines: #ifndef DEMO_VERSION if(!Loadlmage(NULL)) { static int nIncrease = 0; WORD wStop = *(&nIncrease); wStop++; wStop = (WORD)(DWORD)&theApp; wStop = wStop + (BYTE)(DWORD)(LPVOID)(&nIncrease); } else #endif AnyUpCall("", "", "ManualSet", strParams, strReturns);//控制性的操作改变某个属性,此时需要激发上层节点响应设置操作 } } m_mutexMapProperties.Unlock(); return bOK; } // 设置属性,支持无限深度子节点的属性设置 BOOL CDataNodeBase::SetProperty(CString strPropertyPath, CString &strTxtValue, BOOL bAddIfNotExist, UINT uAttrFlag) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); BOOL bOK = FALSE; CString strPath; CString strPropertyName; SeparatePathAndProperty(strPropertyPath, strPath, strPropertyName); CDataNodeBase* pNode = this; if (strPath != "") { int nPos = strPath.Find('.'); while (nPos > -1 && pNode) { CString strID = strPath.Left(nPos); UINT uID = (UINT)atoi(strID); strPath = strPath.Mid(nPos+1); nPos = strPath.Find('.'); pNode = pNode->GetSub(uID); if(pNode && pNode->PV_IsManagerNode() == NET_LINK_MANAGER_NODE) {//作为站点连接管理节点,需要触发向远程获取数据的请求,需要调用重载的该函数。 return pNode->SetProperty(strPath + strPropertyName, strTxtValue, bAddIfNotExist, uAttrFlag); } } } if(pNode) { bOK = pNode->V_SetPropertyTxtValue(strPropertyName, strTxtValue, bAddIfNotExist, uAttrFlag); if(uAttrFlag & ATTR_NEET_SET_MODIFY_FLAG) SetModified(); } return bOK; } // 设置属性的值, 此函数必须重写. BOOL CDataNodeBase::SetProperty(CString strPropertyName, CVariable* pVar, UINT uAttrFlag) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); BOOL bOK = FALSE; m_mutexMapProperties.Lock(); if(strPropertyName != "ID" && strPropertyName != "AppName" && strPropertyName != "Type") { CVariable* pVarOld = NULL; if(m_mapExtProperties.Lookup(strPropertyName, (void*&)pVarOld)) { delete pVarOld; ReplaceProperty(strPropertyName, pVar); bOK = TRUE; if(uAttrFlag & ATTR_NEET_SET_MODIFY_FLAG) SetModified(); } else { ReplaceProperty(strPropertyName, pVar); bOK = TRUE; if(uAttrFlag & ATTR_NEET_SET_MODIFY_FLAG) SetModified(); } } m_mutexMapProperties.Unlock(); return bOK; } // 保存对象到文件 CString CDataNodeBase::V_GetSaveFileName() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); return ""; } // 保存对象到文件, 文件名由虚函数GetSaveFileName给定。 BOOL CDataNodeBase::SaveObj() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); BOOL bOK = FALSE; CString strFileName = V_GetSaveFileName(); if(strFileName != "") bOK = SaveObj(strFileName); return bOK; } // 从文件中装载对象, 文件名由虚函数GetSaveFileName给定。 BOOL CDataNodeBase::LoadObj() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); BOOL bOK = FALSE; CString strFileName = V_GetSaveFileName(); if(strFileName != "") bOK = LoadObj(strFileName); return bOK; } // 保存对象到文件 BOOL CDataNodeBase::SaveObj(CString strFileName) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); BOOL bOK = FALSE; CStdioFile file; CString strEncryptSeed = GetSaveEncryptSeed(); CString strFileNameTemp = strFileName; try { if(strEncryptSeed != "") { strFileNameTemp += "T"; } if(file.Open(strFileNameTemp, CFile::modeCreate|CFile::modeWrite)) { //file.WriteString("" + LineEnd); SaveObj(&file, "", this, FALSE); file.Close(); bOK = TRUE; m_bModified = FALSE; } if(strEncryptSeed != "") { Encrypt(strFileNameTemp, strFileName, strEncryptSeed); } } catch (...) { TRACE("\n保存对象%s到文件%s时出现异常。", m_strName, strFileName); bOK = FALSE; } if(strEncryptSeed != "") { DeleteFile(strFileNameTemp); } return bOK; } // 保存对象到多行字符串 BOOL CDataNodeBase::SaveObjToString(CString &strXmlTxt) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); BOOL bOK = FALSE; CMemFile memFile; SaveObj(&memFile, "", this, TRUE); int nLen = memFile.GetLength(); memFile.SeekToBegin(); char* pBuf = new char[nLen+1]; pBuf[nLen] = 0; memFile.Read(pBuf, nLen); strXmlTxt = pBuf; delete []pBuf; bOK = TRUE; // m_bModified = FALSE; return bOK; } //从一行字符串中提取属性信息 void CDataNodeBase::PickItemsFromStrLine( CString strLine, CDataNodeBase* &pCurrentNode, CDataNodeBase* &pParent ) { while(strLine.GetLength() > 0) { strLine.TrimLeft(); if(strLine.Find("'); ASSERT(nPosEnd > -1); if(nPosEnd > -1) strLine = strLine.Mid(nPosEnd+1); else strLine = ""; pCurrentNode = pParent; if(pParent) pParent = pParent->m_pParent; continue; } int nPos = strLine.Find('<'); if(nPos == 0) { pParent = pCurrentNode; if(pCurrentNode == NULL) { pCurrentNode = this; pParent = this->m_pParent; } else { pCurrentNode = new CDataNodeBase;//CDataNodeBaseEx; //pCurrentNode->__classCanUseDirectly = TRUE;//需要临时指定为可用. } pCurrentNode->m_pParent = pParent; strLine = strLine.Mid(1); CString strItemType; if(PickItemType(strLine, strItemType)) { pCurrentNode->m_strType = strItemType; } } else if(pCurrentNode != NULL) { // 获取属性 CString strItem, strValue; while (PickOneItem(strLine, strItem, strValue)) { if(strItem == "ID") { if(pCurrentNode != this) {//当前装载操作对象的ID不能被修改! pCurrentNode->m_uID = atoi(strValue); if(pParent != NULL) pParent->AddSub(pCurrentNode, TRUE); } pCurrentNode->V_SetPropertyTxtValue("UidPath", GetIdPath(), TRUE, NULL); } else if(strItem == "UidPath") { ;}//do nothing else if(strItem == "AppName") pCurrentNode->m_strAppName = strValue; else if(strItem == "Name") pCurrentNode->SetName(strValue); // else if(strItem == "DeviceType") // { // if(pCurrentNode != this) // {//当前装载操作对象的ID不能被修改! // pCurrentNode->V_SetPropertyTxtValue(strItem, strValue, TRUE, ATTR_NEET_SET_MODIFY_FLAG); // } // } else pCurrentNode->V_SetPropertyTxtValue(strItem, strValue, TRUE, ATTR_NEET_SET_MODIFY_FLAG); } } else { //文件头信息,不做处理. strLine = ""; break; } } } //将子项替换为制定App内的对象 void CDataNodeBase::ReplaceSubs() { POSITION pos = m_mapSubs.GetStartPosition(); while(pos) { UINT uID = 0; CDataNodeBase *pNode = NULL; m_mapSubs.GetNextAssoc(pos, (void*&)uID, (void*&)pNode); CDataNodeBase* pNodeNew = ReplaceObj(pNode, TRUE); if(pNodeNew) { m_mapSubs.SetAt((LPVOID)uID, (LPVOID)pNodeNew); } } } // 从文件中装载对象 BOOL CDataNodeBase::LoadObj(CString strFileName) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); BOOL bOK = FALSE; CStdioFile file; CString strEncryptSeed = GetSaveEncryptSeed(); try { if(strEncryptSeed != "") { Encrypt(strFileName, strFileName+"T", strEncryptSeed); strFileName += "T"; } if(file.Open(strFileName, CFile::modeRead)) { if(CheckXMLFile(file)) { CDataNodeBase *pCurrentNode = NULL; CDataNodeBase *pParent = NULL; CString strLine; while (file.ReadString(strLine)) { PickItemsFromStrLine(strLine, pCurrentNode, pParent); strLine = ""; } } file.Close(); m_bModified = FALSE; CString strFileTemp; strFileTemp.Format("%s\\DataCenterTemp", GetUserTempPath()); if(strFileName.Find(strFileTemp) != 0)//如果是从临时文件中读取的,则不替换子项 ReplaceSubs(); bOK = TRUE; } } catch (...) { TRACE("\n从文件%s装载对象%s时出现异常。", m_strName, strFileName); } if(strEncryptSeed != "") { DeleteFile(strFileName);//删除解密时生成的临时文件 } return bOK; } //从多行字符串中读取一行字符串 BOOL CDataNodeBase::ReadStringLine(CString &strXmlTxt, CString &strLine) { BOOL bOK = FALSE; strLine = ""; if(strXmlTxt.GetLength() > 0) { int nPos = strXmlTxt.Find(LineEnd); if(nPos > -1) { strLine = strXmlTxt.Left(nPos); strXmlTxt = strXmlTxt.Mid(nPos + LineEnd.GetLength()); } else { strLine = strXmlTxt; strXmlTxt = ""; } bOK = TRUE; } return bOK; } // 从字符串中装载对象 BOOL CDataNodeBase::LoadObjFromString(CString strXmlTxt) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); BOOL bOK = FALSE; for(int n = 0; n < 2; n++) {//若字符串过长将尝试采用先存到文件的方式处理,所有这里要进行两次处理。 if(strXmlTxt.GetLength() < 500 || n == 1) { if(CheckXMLString(strXmlTxt)) { CDataNodeBase *pCurrentNode = NULL; CDataNodeBase *pParent = NULL; CString strLine; while (ReadStringLine(strXmlTxt, strLine)) { PickItemsFromStrLine(strLine, pCurrentNode, pParent); strLine = ""; } } break; } else { CString strFileTemp; strFileTemp.Format("%s\\DataCenterTemp%d.xml", GetUserTempPath(), rand()); CStdioFile fileTemp; CFileException e; try { if(fileTemp.Open(strFileTemp, CFile::modeCreate|CFile::modeWrite|CFile::typeBinary, &e)) { fileTemp.WriteString(strXmlTxt); fileTemp.Close(); if(LoadObj(strFileTemp)) bOK = TRUE; } } catch (...) { } DeleteFile(strFileTemp); if(bOK) break; } } // m_bModified = FALSE; // ReplaceSubs();从字符串装载时不替换内容,因为这种情况发生在网络浏览端, bOK = TRUE; return bOK; } // 更换子项 void CDataNodeBase::ReplaceSub(UINT uID, CDataNodeBase* pNodeNew) { //删除原来的ID相同的数据 this->m_mutexMapSubs.Lock(); CDataNodeBase* pNodeOld = NULL; if(m_mapSubs.Lookup((LPVOID)uID, (void*&)pNodeOld)) { delete pNodeOld; } m_mapSubs.SetAt((LPVOID)uID, (LPVOID)pNodeNew); this->m_mutexMapSubs.Unlock(); } // 添加对象为子项 void CDataNodeBase::AddSub(CDataNodeBase *pSub, BOOL bNotChangeID) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); m_mutexMapSubs.Lock(); if(!bNotChangeID) { if(pSub->m_uID == 0) pSub->m_uID = m_mapSubs.GetCount() + 1; int nCount = m_mapSubs.GetCount(); if(nCount > 0) { BOOL *pUint = new BOOL[nCount]; memset(pUint, FALSE, sizeof(BOOL)*nCount); POSITION pos = m_mapSubs.GetStartPosition(); while(pos) { UINT uID = 0; CDataNodeBase *pNode = NULL; m_mapSubs.GetNextAssoc(pos, (void*&)uID, (void*&)pNode); if(uID <= (UINT)nCount && uID > 0) pUint[uID-1] = TRUE; } for(int i = 0; i < nCount; i++) { if(pUint[i] == FALSE) { pSub->m_uID = i+1; break; } } delete []pUint; } } ReplaceSub(pSub->m_uID, pSub); pSub->SetParent(this); m_mutexMapSubs.Unlock(); SetModified(); } // 移除子项 void CDataNodeBase::RemoveSub(CDataNodeBase* pSub) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CDataNodeBase* pSubFind = NULL; if(m_mapSubs.Lookup((LPVOID)pSub->m_uID, (void*&)pSubFind) && pSub == pSubFind) { m_mapSubs.RemoveKey((LPVOID)pSub->m_uID); SetModified(); } // 删除工作不在此处进行! TRACE("\n进行移除子项操作RemoveSub时,子项不会被删除,请在此过程外进行手动删除!"); } // 动态库的名字 //注意基类不能用AfxGetAppName(); 而其派生类,相反,必须用AfxGetAppName(); CString CDataNodeBase::PV_GetAppName() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); return m_strAppName; } // 获取类型名字, 名字以PV_开头表示每个派生类都必须重载该函数. //注意基类不能直接用类类型的名字,而用变量,而其派生类, 相反, 必须返回其类名的字符串 CString CDataNodeBase::PV_GetType() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if(m_strType == "") return "CDataNodeBase"; return m_strType; } // 任意函数调用,万能接口,调用通常是顶层调用底层的节点 void CDataNodeBase::AnyDownCall( int nCallStackDepth, CString strFuncName, CStringList &strParams, CStringList &strReturns ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if(nCallStackDepth < MAX_DEPTH) {//最多往下递归256层,防止连环连接出现死递归 if(strFuncName == "SetModified") SetModified(strParams.GetCount()?atoi(strParams.GetHead()):TRUE); POSITION pos = m_mapSubs.GetStartPosition(); while (pos) { UINT uID; CDataNodeBase* pNode = NULL; m_mapSubs.GetNextAssoc(pos, (void*&)uID, (void*&)pNode); pNode->AnyDownCall(nCallStackDepth+1, strFuncName, strParams, strReturns); } } } // 任意汇报接口,万能接口,与AnyDownCall的区别是,该接口是由底层节点往顶层调用 void CDataNodeBase::AnyUpCall( CString strPathInternal, //调用发出位置路径内部管理路径,用ID作为节点名的路径 CString strPathShow, //调用发出位置路径显示路径,用名字作为节点的路径 CString strFuncName, //函数名 CStringList &strParams, //函数的输入参数表 CStringList &strReturns //函数的输出参数表 ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if(m_pParent && strPathInternal.GetLength()<=255)//防止连环连接而出现死递归,限制最深路径不超过255个字符 { CString strPathShow2; CString strNotAppendMyName; if(strPathShow != "" && V_GetPropertyTxtValue("NAMN", strNotAppendMyName) && atoi(strNotAppendMyName) != 0) strPathShow2 = strPathShow; else strPathShow2 = GetName()+"."+strPathShow; m_pParent->AnyUpCall(GetText(m_uID)+"."+strPathInternal, strPathShow2, strFuncName, strParams, strReturns); } } void CDataNodeBase::FreeSubs() { POSITION pos = m_mapSubs.GetStartPosition(); while (pos) { CDataNodeBase *pSub = NULL; UINT uID = -1; m_mapSubs.GetNextAssoc(pos, (void*&)uID, (void*&)pSub); delete pSub; } m_mapSubs.RemoveAll(); } // 检查文件是否为正确的xml文件 BOOL CDataNodeBase::CheckXMLFile(CStdioFile &file) { BOOL bXMLOK = TRUE; int nBracket = 0; int nFlash = 0;//反斜杠统计 CString strLine; while(file.ReadString(strLine)) { int nPos = MyStrFind(strLine, "= 0) nFlash--; else if(MyStrFind(strLine, '<') >= 0)//strLine.Find('<') >= 0) nFlash++; if(nFlash < 0) { bXMLOK = FALSE; goto EXIT; } char cPrev = '?'; for(int i=0; i' && cPrev != '\\') nBracket--; if(nBracket < 0) { bXMLOK = FALSE; goto EXIT; } if((c == '=' && cPrev != '\\') && ( strLine.GetLength()<=i+2 || strLine.GetAt(i+1) != '"' || strLine.Find('"', i+2) == -1)) { bXMLOK = FALSE; goto EXIT; } cPrev = c; } } if(nBracket != 0 || nFlash != 0) bXMLOK = FALSE; EXIT: file.SeekToBegin(); return bXMLOK; } //检查多行字符串是否为合法的xml字符串 BOOL CDataNodeBase::CheckXMLString(CString strXmlTxt) { BOOL bXMLOK = TRUE; int nBracket = 0; int nFlash = 0;//反斜杠统计 CString strLine; while(ReadStringLine(strXmlTxt, strLine)) { int nPos = MyStrFind(strLine, "= 0) nFlash--; else if(MyStrFind(strLine, '<') >= 0)//strLine.Find('<') >= 0) nFlash++; if(nFlash < 0) { bXMLOK = FALSE; goto EXIT; } char cPrev = '?'; for(int i=0; i' && cPrev != '\\') nBracket--; if(nBracket < 0) { bXMLOK = FALSE; goto EXIT; } if((c == '=' && cPrev != '\\') && ( strLine.GetLength()<=i+2 || strLine.GetAt(i+1) != '"' || strLine.Find('"', i+2) == -1)) { bXMLOK = FALSE; goto EXIT; } cPrev = c; } strLine = ""; } if(nBracket != 0 || nFlash != 0) bXMLOK = FALSE; EXIT: return bXMLOK; } // 保存对象到文件 void CDataNodeBase::SaveObj(CFile* pFile, CString strHeadSpace, CDataNodeBase* pNodeRoot, BOOL bIncludeMgrSub) { if(pFile == NULL) return; CString strLine; // 节点:类名为节点名 strLine = strHeadSpace + "<" + PV_GetType() + " "; pFile->Write(strLine, strLine.GetLength()); //AppName:动态库名字 strLine = "AppName=\"" + PV_GetAppName() + "\" "; pFile->Write(strLine, strLine.GetLength()); //Name:动态库名字 strLine = "Name=\"" + GetSavedStr(GetName()) + "\" "; pFile->Write(strLine, strLine.GetLength()); //ID: CString strTemp; strTemp.Format("ID=\"%d\" ", m_uID); strLine = strTemp; pFile->Write(strLine, strLine.GetLength()); // 其他动态属性 CMapStringToPtr mapProperties; GetPropertyNames(mapProperties); POSITION pos = mapProperties.GetStartPosition(); while (pos) { CString strKey; CVariable* pVar = NULL; mapProperties.GetNextAssoc(pos, strKey, (void*&)pVar); //if(pVar->m_bIsDesignTimeVar) { CString strSaveFmtTxt = pVar->GetSaveFmtTxt(); if(strSaveFmtTxt.Find("DTV:-1,") == -1) { strSaveFmtTxt = GetSavedStr(strSaveFmtTxt); strLine = LineEnd + strHeadSpace + "\t" + strKey + "\t=\"" + strSaveFmtTxt + "\""; pFile->Write(strLine, strLine.GetLength()); } } } strLine = " >" + LineEnd; pFile->Write(strLine, strLine.GetLength()); if(PV_IsManagerNode() && this != pNodeRoot && !bIncludeMgrSub) {// 是管理类节点,并且该节点不是当前保存操作的根,并且当前不是保存到字符串中,则子项不在这里保存,而是在该节点自己的保存函数中保存 // Do nothing else. } else {// // 子项: // CPtrList listSort; // SortSubs(m_mapSubs, listSort); POSITION pos = m_mapSubs.GetPtrList().GetHeadPosition(); while (pos) { UINT uID = 0; CDataNodeBase* pNode = (CDataNodeBase*)m_mapSubs.GetPtrList().GetNext(pos); pNode->SaveObj(pFile, strHeadSpace + "\t", pNodeRoot, bIncludeMgrSub); } } strLine = strHeadSpace + "" + LineEnd; pFile->Write(strLine, strLine.GetLength()); } // 字符串中提炼1个属性,并将提炼的属性从字符串中移出 BOOL CDataNodeBase::PickItemType(CString &strLine, CString &strItemType) { strLine.TrimLeft(); strLine.TrimLeft('>'); strLine.TrimLeft('\r'); // 优先找类名字(类名字是出现等号之前出现空格时之前的字符串) for(int i = 0; i < strLine.GetLength(); i++) { char c = strLine.GetAt(i); if(c == ' ') { strItemType = strLine.Left(i); strLine = strLine.Mid(i + 1); break; } } // if(strItemType == "") { strItemType = strLine; strLine = ""; } return strItemType.GetLength()>0; } // 字符串中提炼1个属性,并将提炼的属性从字符串中移出 BOOL CDataNodeBase::PickOneItem(CString &strLine, CString &strItem, CString &strValue) { strItem = ""; strValue = ""; strLine.TrimLeft(); strLine.TrimLeft('>'); strLine.TrimLeft('\r'); //找属性 int nPos = strLine.Find('='); if(nPos > -1) { strItem = strLine.Left(nPos); strItem.TrimRight(); strLine = strLine.Mid(nPos + 1); strLine.TrimLeft(); // if(strLine.GetLength() > 0 && // strLine.GetAt(0) == '"' && // strLine.Find('"', 1) > 0 ) if(strLine.GetLength() > 0 && strLine.GetAt(0) == '"' && MyStrFind(strLine, '"', 1) > 0 ) { nPos = MyStrFind(strLine, '"', 1);//strLine.Find('"', 1); ASSERT(nPos > 0); strValue = strLine.Left(nPos); strValue = strValue.Mid(1); strValue = GetOrigStr(strValue); strLine = strLine.Mid(nPos + 1); } else ASSERT(FALSE); } if(strItem == "") { strItem = strLine; strLine = ""; } return strItem.GetLength()>0; } CDataNodeBase* CDataNodeBase::ReplaceObj(CDataNodeBase* pNodeOld, BOOL bAlsoSubs) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CDataNodeBase* pNodeNew = NULL; Def_CreateObj* fpCreateObj = NULL; Def_ReleaseObj* fpReleaseObj = NULL; if(theApp.GetObjFuncs(pNodeOld->PV_GetAppName(), fpCreateObj, fpReleaseObj)) { try { pNodeNew = fpCreateObj(pNodeOld->PV_GetType()); pNodeNew->m_uID = pNodeOld->m_uID; pNodeNew->SetName(pNodeOld->GetName()); // 拷贝属性 pNodeOld->m_mutexMapProperties.Lock(); //CMapStringToPtr mapProperties; //pNodeOld->V_GetPropertyNames(mapProperties); POSITION pos = pNodeOld->m_mapExtProperties.GetStartPosition(); while (pos) { CString strItem; CVariable* pVar = NULL; pNodeOld->m_mapExtProperties.GetNextAssoc(pos, strItem, (void*&)pVar); pNodeNew->ReplaceProperty(strItem, pVar); } pNodeOld->m_mapExtProperties.RemoveAll();// 清除但不能删除关联的对象! pNodeOld->m_mutexMapProperties.Unlock(); // 拷贝子项: pNodeOld->m_mutexMapSubs.Lock(); pos = pNodeOld->m_mapSubs.GetStartPosition(); while(pos) { UINT uID = 0; CDataNodeBase *pNode = NULL; pNodeOld->m_mapSubs.GetNextAssoc(pos, (void*&)uID, (void*&)pNode); pNode->m_pParent = pNodeNew; pNodeNew->ReplaceSub(pNode->m_uID, pNode); } pNodeOld->m_mapSubs.RemoveAll();// 清除但不能删除关联的对象! pNodeOld->m_mutexMapSubs.Unlock(); pNodeNew->m_bModified = FALSE; // 父项的更新 if(pNodeOld->m_pParent != NULL) { pNodeNew->m_pParent = pNodeOld->m_pParent; pNodeOld->m_pParent->m_mapSubs.SetAt((LPVOID)pNodeOld->m_uID, pNodeNew); } delete pNodeOld;// 析构函数为虚函数,删除可不需要通过接口ReleaseObj. //pNodeOld = pNodeNew; if(bAlsoSubs) { pos = pNodeNew->m_mapSubs.GetStartPosition(); while(pos) { UINT uID = 0; CDataNodeBase *pNode = NULL; pNodeNew->m_mapSubs.GetNextAssoc(pos, (void*&)uID, (void*&)pNode); CDataNodeBase* pNodeNewSub = ReplaceObj(pNode, TRUE); if(pNodeNewSub) { pNodeNew->m_mapSubs.SetAt((LPVOID)uID, (LPVOID)pNodeNewSub); } } } } catch (...) { } } return pNodeNew; } // 由全路径分离出路径和属性名称 void CDataNodeBase::SeparatePathAndProperty(CString strFullName, CString &strPath, CString &strPropertyName) { int nPos = strFullName.ReverseFind('.'); if(nPos > -1) { strPath = strFullName.Left(nPos+1); strPropertyName = strFullName.Mid(nPos+1); } else strPropertyName = strFullName; } // 获取名字方式表达的路径 CString CDataNodeBase::GetNamePath() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CString strPath; CDataNodeBase* pNode = this; while (pNode->m_pParent != NULL) { strPath = pNode->GetName() + "." + strPath; pNode = pNode->m_pParent; } return strPath; } // 获取ID方式表达的路径 CString CDataNodeBase::GetIdPath() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CString strPath; CDataNodeBase* pNode = this; while (pNode->m_pParent != NULL) { CString strID; strID.Format("%u", pNode->m_uID); strPath = strID + "." + strPath; pNode = pNode->m_pParent; } return strPath; } // 将对象展现在树结构中 HTREEITEM CDataNodeBase::BuildTree(CDataNodeTree &treeCtrl, HTREEITEM hItemNow, int nBuildDepth, BOOL bBuildSubOnly, HTREEITEM hParent, HTREEITEM hInsertAfter) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); ASSERT(FALSE);//已经停止使用此函数! ASSERT(treeCtrl.m_hWnd); return BuildTree(treeCtrl.GetTreeCtrl(), hItemNow, nBuildDepth, bBuildSubOnly, hParent, hInsertAfter); // // 删除原有子项 // if(hItemNow != TVI_ROOT && hItemNow != NULL) // { // HTREEITEM hSub = treeCtrl.GetTreeCtrl().GetChildItem(hItemNow); // while (hSub) // { // HTREEITEM hNext = treeCtrl.GetTreeCtrl().GetNextSiblingItem(hSub); // treeCtrl.GetTreeCtrl().DeleteItem(hSub); // hSub = hNext; // } // } // // 创建自己的节点 // HTREEITEM hItemNew = hItemNow; // if(!bBuildSubOnly) // {// 创建自己在树中的节点 // int nImage, nSelectedImage; // GetImage(treeCtrl.m_imageList, nImage, nSelectedImage); // hItemNew = treeCtrl.GetTreeCtrl().InsertItem(GetName(), nImage, nSelectedImage, hParent, hInsertAfter); // treeCtrl.GetTreeCtrl().SetItemData(hItemNew, (DWORD)this); // } // // if(nBuildDepth > 0) // { // // 添加子项 //// CPtrList listSort; //// SortSubs(m_mapSubs, listSort); // POSITION pos = m_mapSubs.GetPtrList().GetHeadPosition(); // while (pos) // { // UINT uID = 0; // CDataNodeBase* pNode = (CDataNodeBase*)m_mapSubs.GetPtrList().GetNext(pos); // pNode->BuildTree(treeCtrl, TVI_ROOT, nBuildDepth-1, FALSE, hItemNew); // } // } // return hItemNew; } // 将对象展现在树结构中 HTREEITEM CDataNodeBase::BuildTree(CDataNodeTreeCtrl &treeCtrl, HTREEITEM hItemNow, int nBuildDepth, BOOL bBuildSubOnly, HTREEITEM hParent, HTREEITEM hInsertAfter) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); ASSERT(treeCtrl.m_hWnd); // 删除原有子项 if(hItemNow != TVI_ROOT && hItemNow != NULL) { HTREEITEM hSub = treeCtrl.GetTreeCtrl().GetChildItem(hItemNow); while (hSub) { HTREEITEM hNext = treeCtrl.GetTreeCtrl().GetNextSiblingItem(hSub); treeCtrl.GetTreeCtrl().DeleteItem(hSub); hSub = hNext; } } // 创建自己的节点 HTREEITEM hItemNew = hItemNow; if(!bBuildSubOnly) {// 创建自己在树中的节点 if(hItemNow != TVI_ROOT && hItemNow != NULL) { treeCtrl.GetTreeCtrl().DeleteItem(hItemNow); } int nImage, nSelectedImage; GetImage(treeCtrl.m_imageList, nImage, nSelectedImage); hItemNew = treeCtrl.GetTreeCtrl().InsertItem(GetName(), nImage, nSelectedImage, hParent, hInsertAfter); treeCtrl.GetTreeCtrl().SetItemData(hItemNew, (DWORD)this); treeCtrl.GetTreeCtrl().m_mapNodeTohItem.SetAt(this, hItemNew); CString strPause; BOOL bPause = FALSE; if(V_GetPropertyTxtValue("Pause", strPause) && (strPause == "1" || strPause.Find('T') == 0)) bPause = TRUE; treeCtrl.ChangePauseDeviceIco(hItemNew, bPause); } if(nBuildDepth > 0) { // 添加子项 // CPtrList listSort; // SortSubs(m_mapSubs, listSort); POSITION pos = m_mapSubs.GetPtrList().GetHeadPosition(); while (pos) { UINT uID = 0; CDataNodeBase* pNode = (CDataNodeBase*)m_mapSubs.GetPtrList().GetNext(pos); pNode->BuildTree(treeCtrl, TVI_ROOT, nBuildDepth-1, FALSE, hItemNew); } } return hItemNew; } // 获取图标 void CDataNodeBase::GetImage(CImageListDyn &imageList, int &nImage, int &nSelectedImage) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CString strProptery; this->V_GetPropertyTxtValue("Image", strProptery); nImage = imageList.GetImage(strProptery); this->V_GetPropertyTxtValue("SelectedImage", strProptery); nSelectedImage = imageList.GetImage(strProptery); if(nImage == -1) nImage = 0; if(nSelectedImage == -1) nSelectedImage = 1; } UINT CDataNodeBase::GetID() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); return m_uID; } // 是否为管理类的节点 BOOL CDataNodeBase::PV_IsManagerNode() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); return FALSE; } // 对象配置接口 BOOL CDataNodeBase::DoConfig(CDataNodeBase* pPrjRoot, CString strPathCur) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CDataNodeBase* pMgr = this; CString strPathCurNew; while(pMgr->m_pParent) { CString strID; strID.Format("%u", pMgr->m_uID); strPathCurNew = strID + "." + strPathCurNew; pMgr = pMgr->m_pParent; if(pMgr->PV_IsManagerNode()) { return pMgr->DoConfigSub(pPrjRoot, this, strPathCurNew); } } return FALSE; } // 子对象配置接口 BOOL CDataNodeBase::DoConfigSub(CDataNodeBase* pPrjRoot, CDataNodeBase* pNodeSub, CString strPathCur) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); return FALSE; } // 对象属性编辑接口,此接口只负责编辑内容,不负责将修改后的值应用到相应点。(因为要支持多点同时设置。) BOOL CDataNodeBase::EditProperty(CString strProp, CString& strValue, UINT& uOption, UINT& uResult) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); BOOL bRtn = FALSE; if(m_pParent && m_pParent->EditProperty(strProp, strValue, uOption, uResult)) bRtn = TRUE; return bRtn; } // 获取修改标志 BOOL CDataNodeBase::GetModified() { return m_bModified; } // 设置修改标志 void CDataNodeBase::SetModified(BOOL bModified) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); m_bModified = bModified; if(bModified) {// 如果是将修改标志置位TRUE,则同时修改所在的管理类的对象的修改标志也修改为修改标志,以便保存。 CDataNodeBase *pNode = m_pParent; while (pNode) { if(pNode->PV_IsManagerNode()) { pNode->m_bModified = bModified; break; } pNode = pNode->m_pParent; } } } // 获取指定属性的特性 CString CDataNodeBase::GetAttributes(CString strPropertyName) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); m_mutexMapProperties.Lock(); CString strAttr; CVariable var; if(strPropertyName == "Name") { var.SetAttributes(TRUE, TRUE, TRUE, VT_BSTR); } else if(strPropertyName == "ID") { var.SetAttributes(TRUE, TRUE, FALSE, VT_UINT); } else if(strPropertyName == "AppName") { var.SetAttributes(TRUE, TRUE, FALSE, VT_BSTR); } else if(strPropertyName == "Type") { var.SetAttributes(TRUE, TRUE, FALSE, VT_BSTR); } else { CVariable* pVar = GetProperty(strPropertyName); if(pVar) strAttr = pVar->GetAttributesMsg(); } m_mutexMapProperties.Unlock(); if(strAttr == "") strAttr = var.GetAttributesMsg(); return strAttr; } // 工程装载后调用 void CDataNodeBase::DoAfterProjectLoaded(CString strProjectPath) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); POSITION pos = m_mapSubs.GetStartPosition(); while (pos) { UINT uID; CDataNodeBase* pNode = NULL; m_mapSubs.GetNextAssoc(pos, (void*&)uID, (void*&)pNode); pNode->DoAfterProjectLoaded(strProjectPath); } } // 工程关闭前调用 void CDataNodeBase::DoBeforeProjectClose() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); POSITION pos = m_mapSubs.GetStartPosition(); while (pos) { UINT uID; CDataNodeBase* pNode = NULL; m_mapSubs.GetNextAssoc(pos, (void*&)uID, (void*&)pNode); pNode->DoBeforeProjectClose(); } } //代理的方式异步调用获取属性 void CDataNodeBase::AsyncDelegateGetProperty(CString strPropertyName) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if(m_pParent && strPropertyName.GetLength()<=255)//防止连环连接而出现死递归,限制最深路径不超过255个字符 { m_pParent->AsyncDelegateGetProperty(GetText(m_uID)+"."+strPropertyName); } } //代理的方式异步接收属性,该事件在调用AsyncDelegateGetProperty获取请求后对方回应后被调用, //调用发起者通常是重载了AsyncDelegateGetProperty函数的类的对象. void CDataNodeBase::OnAsyncDelegateReceiveProperty(CString strPropertyName, CString strTxtValue, BOOL bDataFromNet) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if(bDataFromNet) this->V_SetPropertyTxtValue(strPropertyName, strTxtValue, FALSE, 0); } //登记定制回调定制者 void CDataNodeBase::RegisterCustomCall(CDataNodeBase* pCustomer, BOOL bLowPriority) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); m_mutexCustomCall.Lock(); POSITION pos = m_customersCutomCall.Find(pCustomer); if(pos == NULL) { if(bLowPriority) m_customersCutomCall.AddTail(pCustomer); else m_customersCutomCall.AddHead(pCustomer); } m_mutexCustomCall.Unlock(); } //取消登记定制回调定制者 void CDataNodeBase::UnRegisterCustomCall(CDataNodeBase* pCustomer) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); m_mutexCustomCall.Lock(); POSITION pos = m_customersCutomCall.Find(pCustomer); if(pos != NULL) { m_customersCutomCall.RemoveAt(pos); } m_mutexCustomCall.Unlock(); } //定制回调 BOOL CDataNodeBase::DoCustomCall( CString strPathInternalFromRoot, //调用发出位置路径内部管理路径,用ID作为节点名的路径 CString strPathShowFromRoot, //调用发出位置路径显示路径,用名字作为节点的路径 CString strFuncName, //函数名 CStringList &strParams, //函数的输入参数表 CStringList &strReturns //函数的输出参数表 ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); BOOL bDealed = FALSE; if(m_customersCutomCall.GetCount() > 0) { m_mutexCustomCall.Lock(); POSITION pos = m_customersCutomCall.GetHeadPosition(); while (pos != NULL) { POSITION posLast = pos; CDataNodeBase* pCustomer = m_customersCutomCall.GetNext(pos); try { if(pCustomer->OnCustomCall( strPathInternalFromRoot, strPathShowFromRoot, strFuncName, strParams, strReturns ))//处理后返回TRUE,表示不需要再作处理 { bDealed = TRUE; break; } } catch(...) { m_customersCutomCall.RemoveAt(posLast);//出现异常时立即清除此定制者 } } m_mutexCustomCall.Unlock(); } return bDealed; } //执行定制回调,处理完毕,无需后续处理时返回TRUE,否则返回FALSE BOOL CDataNodeBase::OnCustomCall( CString strPathInternalFromRoot, //调用发出位置路径内部管理路径,用ID作为节点名的路径 CString strPathShowFromRoot, //调用发出位置路径显示路径,用名字作为节点的路径 CString strFuncName, //函数名 CStringList &strParams, //函数的输入参数表 CStringList &strReturns //函数的输出参数表 ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); try { //.... do some thing. } catch (...) { } return FALSE; } //删除属性 void CDataNodeBase::DeleteProperty(CString strPropertyName) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if(!IsUnEditableProperty(strPropertyName)) ReplaceProperty(strPropertyName, NULL); } //判断一个属性是否为不可编辑 BOOL CDataNodeBase::IsUnEditableProperty(CString strPropertyName) { return (strPropertyName == "ID" && m_pParent != NULL) || strPropertyName == "AppName" || strPropertyName == "Type"; } //设置临时变量 BOOL CDataNodeBase::SetTempItem(CString strItemName, CString strValue) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if(m_mutexTempItems.Lock(10000)) { if(strValue == "") m_mapTempItems.RemoveKey(strItemName); else m_mapTempItems.SetAt(strItemName, strValue); m_mutexTempItems.Unlock(); return TRUE; } return FALSE; } //获取临时变量 BOOL CDataNodeBase::GetTempItem(CString strItemName, CString &strValue) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); BOOL bOK = FALSE; if(m_mutexTempItems.Lock(10000)) { bOK = m_mapTempItems.Lookup(strItemName, strValue); m_mutexTempItems.Unlock(); } return bOK; } //一步获得属性的字符串值 CString CDataNodeBase::GetProperty1(CString strPropertyName) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CString strTxtValue; GetProperty(strPropertyName, strTxtValue); return strTxtValue; } //文件保持加密种子, 为空表示文件不加密 CString CDataNodeBase::GetSaveEncryptSeed() { return ""; } //找出所有指定字母开头的项目 void CDataNodeBase::GetItemsName(CStringList& strlistNames, char cHead) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); POSITION pos = m_mapExtProperties.GetStartPosition(); while (pos) { CString strItem; LPVOID p; m_mapExtProperties.GetNextAssoc(pos, strItem, (void*&)p); if(strItem.GetLength() >= 1 && strItem.GetAt(0) == cHead) strlistNames.AddTail(strItem); } } //保存修改 void CDataNodeBase::SaveChange() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if(this->GetModified()) { this->SaveObj(); } } //获取与之关联的管理节点 CDataNodeBase* CDataNodeBase::GetRelateManagerNode() { CDataNodeBase* pRtn = this; while(pRtn) { CString strDeviceType;//有设备类型属性即认为是设备 if(pRtn->PV_IsManagerNode() || pRtn->V_GetPropertyTxtValue("DeviceType", strDeviceType)) break; pRtn = pRtn->m_pParent; } return pRtn; }