MFC开发xml编辑器小结

MFC开发xml编辑器整理

xml格式如下所示:

<CalibrationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<CalConfig name="TEST">
		<CalPath number="1" name="ANT0" data="2022-10-11 20:05:51" dayLimit="999">
			<CalPoint key="822.500" value="1100"/>
			<CalPoint key="1745.00" value="0.72"/>
			<CalPoint key="1747.50" value="0.71"/>			
		</CalPath>
		<CalPath number="2" name="ANT1" data="2022-10-11 20:05:51" dayLimit="999">
			<CalPoint key="195000" value="1500"/>
			<CalPoint key="1784.90" value="0.78"/>
			<CalPoint key="1785.00" value="0.78"/>
			<CalPoint key="1805.00" value="0.80"/>
			<CalPoint key="1840.00" value="0.68"/>
		</CalPath>
		<CalPath number="3" name="ANT2" data="2022-10-11 20:05:51" dayLimit="999">
			<CalPoint key="192500" value="4100"/>
		</CalPath>
		<CalPath number="4" name="ANT3" data="2022-10-11 20:05:51" dayLimit="999">
			<CalPoint key="192500" value="2900"/>
		</CalPath>
		<CalPath number="5" name="ANT4" data="2022-10-11 20:05:51" dayLimit="999">
			<CalPoint key="35000" value="3200"/>
		</CalPath>
	</CalConfig>
</CalibrationData>

设计步骤:
1.拖入treeControl控件,创建变量m_tree,用于显示TEST节点下的子节点CalPath
在这里插入图片描述
向tree插入节点

CString strName(_T(""));
HTREEITEM hCalConfig = m_tree.InsertItem(strName);
m_tree.InsertItem(strName, hCalConfig);

2.拖入listControl控件,创建变量m_list,用于显示子节点CalPoint 的属性值
在这里插入图片描述
表格中插入表头信息,并设置格式

	m_list.ModifyStyle( 0, LVS_REPORT );               // 报表模式  
	m_list.SetExtendedStyle(m_list.GetExtendedStyle() | LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT /*| LVS_EX_CHECKBOXES*/);

	CRect rect;
	m_list.GetClientRect(rect);
	m_list.InsertColumn(0, L"", LVCFMT_CENTER);
	m_list.InsertColumn(1, L"freq", LVCFMT_CENTER, rect.Width() / 2);
	m_list.InsertColumn(2, L"loss", LVCFMT_CENTER, rect.Width() / 2);

	CImageList   image;
	image.Create(1, 25, TRUE | ILC_COLOR16, 1, 0);   //设置表格的高度 
	m_list.SetImageList(&image, LVSIL_SMALL);

	m_list.DeleteColumn(0);//第一列无法居中显示,删除第一列

双击表格实现内容可编辑,需要往界面上拖入Edit Control控件

OnDblclkList(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	m_hitRow = pNMListView->iItem;//获得选中的行
	m_hitCol = pNMListView->iSubItem;//获得选中列
	if (m_hitRow != -1 && m_hitCol != -1 )
	{
		/*if (pNMListView->iSubItem == 0)
		{
		return;//设置第一列不可编辑
		}*/
		CRect rect;
		m_list.GetSubItemRect(m_hitRow, m_hitCol, LVIR_LABEL, rect);
		m_editListCtrl.SetWindowText(m_list.GetItemText(m_hitRow, m_hitCol));
		m_editListCtrl.SetParent(&m_list);
		m_editListCtrl.MoveWindow(&rect, TRUE);
		m_editListCtrl.ShowWindow(TRUE);
		m_editListCtrl.SetFocus();
		m_editListCtrl.ShowCaret();//显示光标
		m_editListCtrl.SetSel(-1);
	}

	*pResult = 0;
}

编辑框中的光标消失后,将数据保存到表格中

OnKillfocusEdit()
{
	// TODO: 在此添加控件通知处理程序代码
	CString str;
	m_editListCtrl.GetWindowText(str);    //得到用户输入的新的内容
	m_list.SetItemText(m_hitRow, m_hitCol, str);   //设置编辑框的新内容
	m_editListCtrl.ShowWindow(SW_HIDE);                //应用编辑框

	//同步节点中保存的信息
	if (!m_hEditItem)
	{
		return;
	}
	CString text = m_tree.GetItemText(m_hEditItem);	

	//CalPoint节点,将界面上修改的参数保存到m_mapDataMT
	map<CString, CalPath>::iterator ite = m_mapDataMT.find(text);
	if (ite == m_mapDataMT.end())
	{
		return;
	}
	vector<map<CString, CString>>& vecCalPoint = ite->second.CalPathList;
	//修改数据的行数要小于vecCalPoint容器大小
	if (m_hitRow < (int)vecCalPoint.size())
	{
		map<CString, CString>& mapCalPoint = vecCalPoint[m_hitRow];
		if (0 == m_hitCol)
		{
			mapCalPoint[L"freq"] = str;
		} 
		else if (1 == m_hitCol)
		{
			mapCalPoint[L"loss"] = str;
		}
	}
}

3.本文借用MSXML读取和修改xml属性值,需要在头文件 #import <msxml4.dll> 这是微软库

ReadXml(CString strXmlPath, bool bModify)
{
	if (strXmlPath.IsEmpty())
	{
		MessageBox(_T("xml文件名为空"), _T("错误"), MB_ICONERROR);
	}
	MSXML2::IXMLDOMDocumentPtr pDoc;
	::CoInitialize(NULL);
	HRESULT hr = pDoc.CreateInstance(__uuidof(MSXML2::DOMDocument40)); 

	if (!SUCCEEDED(hr)) 
	{  
		MessageBox(_T("创建DOMDocument对象失败。\n请检查运行环境"), _T("错误"), MB_ICONERROR); 
		return;
	}
	// 读取xml
	pDoc->put_async(VARIANT_FALSE);
	VARIANT_BOOL bhr = pDoc->load((_variant_t)strXmlPath);

	if (bhr != VARIANT_TRUE) {
		MessageBox(_T("无法正确读取xml文件"), _T("错误"), MB_ICONERROR);
		return;
	}

	// 根节点取得
	MSXML2::IXMLDOMElementPtr root = pDoc->documentElement;
	// 取得根节点的名字
	_variant_t strRootName = root->nodeName;
	_bstr_t wstrRootName(strRootName.bstrVal);
	MSXML2::IXMLDOMNodeListPtr nodeList = root->GetchildNodes();

	// 解析CalibrationData的子节点
	ReadCalConfig(nodeList, bModify);

	if (bModify)
	{
		pDoc->save((_variant_t)strXmlPath);
	}
}
ReadCalConfig(MSXML2::IXMLDOMNodeListPtr nodeList, bool bModify )
{
	int ilength = nodeList->Getlength();
	for (int nodeCount = 0; nodeCount < ilength; nodeCount++) {
		MSXML2::IXMLDOMNodePtr nodePtr = nodeList->nextNode();
		_variant_t strNodeName = nodePtr->GetnodeName();
		_variant_t strNodeValue = nodePtr->GetnodeValue();

		// 取得节点的属性值
		MSXML2::IXMLDOMNamedNodeMapPtr pDOMAttrList= nodePtr->Getattributes();
		MSXML2::IXMLDOMNodePtr pDOMAttr= pDOMAttrList->Getitem(0); 
		CString cstrValue = (CString)(char*)pDOMAttr->GetnodeName();
		if (0 == CString(L"name").CompareNoCase(cstrValue))
		{
			CString strName =pDOMAttr->GetnodeTypedValue();
			//向combox插入CalConfig节点列表
			m_comNodeList.AddString(strName);
			int nSel = m_comNodeList.GetCurSel();
			CString cstrEditNode = _T("");
			if (nSel > -1)
			{
				m_comNodeList.GetLBText(nSel, cstrEditNode);
			}
			//判断combox控件中,当前名字是否跟xml的节点名字一样
			if (cstrEditNode == strName && bModify)
			{
				ReadCalPath(nodePtr->GetchildNodes(), true);
			}
			else if (cstrEditNode == strName && !bModify)
			{
				
				m_hCalConfig = m_tree.InsertItem(strName);
				// 读取指定节点的 CalConfig节点下的子节点
				ReadCalPath(nodePtr->GetchildNodes());
			}
			
			
		}
		
	}
}
ReadCalPath(MSXML2::IXMLDOMNodeListPtr nodeList, bool bModify)
{
	CString strNo;              
	CString strNumber;         // number
	CString strName;        // name
	for (int nodeCount = 0; nodeCount < nodeList->Getlength(); nodeCount++)
	{
		MSXML2::IXMLDOMNodePtr nodePtr = nodeList->nextNode();
		_variant_t strCaseNodeName = nodePtr->GetnodeName();//获取节点的名字
		_variant_t strCaseNodeValue = nodePtr->Gettext();//获取节点内的值
		BSTR bStrTemp = strCaseNodeName.bstrVal;
		CString strTemp = CString(bStrTemp);
		SysFreeString(bStrTemp);
		CString strNodeName = strTemp;
		
		// 节点有属性值
		if (0 == strNodeName.CompareNoCase(_T("CalPath")))
		{
			strNumber.Empty();
			strName.Empty();
			// 取得节点的属性值
			MSXML2::IXMLDOMNamedNodeMapPtr pDOMAttrList= nodePtr->Getattributes();
			for (int j = 0; j < pDOMAttrList->Getlength(); j++)
			{
				MSXML2::IXMLDOMNodePtr pDOMAttr= pDOMAttrList->Getitem(j); 
				CString cstrValue = (CString)(char*)pDOMAttr->GetnodeName();
				if (0 == CString(L"number").CompareNoCase(cstrValue))
				{
					strNumber = pDOMAttr->GetnodeTypedValue();
				
				} 
				else if (0 == CString(L"name").CompareNoCase(cstrValue))
				{
					strName =pDOMAttr->GetnodeTypedValue();
					//向树控件插入节点
					if (!bModify)
					{
						m_tree.InsertItem(strName, m_hCalConfig);
					}
				}
			}
		}

		if (bModify)
		{
			//修改xml节点的值
			ModifyCalPoint(nodePtr->GetchildNodes(), strName);
		}
		else
		{
			//只读xml节点的值
			ReadCalPoint(nodePtr->GetchildNodes(), strName);
		}
	}
}
ReadCalPoint(MSXML2::IXMLDOMNodeListPtr nodeList, CString cstr)
{
	CString strNo;           
	CString strKey;         // key
	CString strValue;        // value
	vector<map<CString, CString>> vecCalPath;
	for (int nodeCount = 0; nodeCount < nodeList->Getlength(); nodeCount++)
	{
		MSXML2::IXMLDOMNodePtr nodePtr = nodeList->nextNode();
		_variant_t strCaseNodeName = nodePtr->GetnodeName();
		_variant_t strCaseNodeValue = nodePtr->Gettext();
		BSTR bStrTemp = strCaseNodeName.bstrVal;
		CString strTemp = CString(bStrTemp);
		SysFreeString(bStrTemp);
		CString strNodeName = strTemp;

		// 节点没有属性值
		if (0 != strNodeName.CompareNoCase(_T("CalPoint")))
		{
			continue;
		}
		strKey.Empty();
		strValue.Empty();
		map<CString, CString> mapCalPoint;
		// 取得节点的属性值
		MSXML2::IXMLDOMNamedNodeMapPtr pDOMAttrList= nodePtr->Getattributes();
		for (int j = 0; j < pDOMAttrList->Getlength(); j++)
		{
			MSXML2::IXMLDOMNodePtr pDOMAttr= pDOMAttrList->Getitem(j); 
			CString cstrValue = (CString)(char*)pDOMAttr->GetnodeName();
			
			if (0 == CString(L"key").CompareNoCase(cstrValue))
			{
				strKey= pDOMAttr->GetnodeTypedValue();
				mapCalPoint.insert(make_pair(L"key", strFreq));
			} 
			else if (0 == CString(L"value").CompareNoCase(cstrValue))
			{
				strValue=pDOMAttr->GetnodeTypedValue();
				mapCalPoint.insert(make_pair(L"value", strLoss));
			}
		}
		vecCalPath.push_back(mapCalPoint);
	}
	CalPath calPoint;
	calPoint.CalPathList = vecCalPath;
	m_mapDataMT.insert(make_pair(cstr, calPoint));
}
ModifyCalPoint(MSXML2::IXMLDOMNodeListPtr nodeList, CString cstr)
{
	CString strNo;           
	       
	vector<map<CString, CString>> vecCalPath = m_mapDataMT[cstr].CalPathList;

	for (int nodeCount = 0; nodeCount < nodeList->Getlength(); nodeCount++)
	{
		MSXML2::IXMLDOMNodePtr nodePtr = nodeList->nextNode();
		_variant_t strCaseNodeName = nodePtr->GetnodeName();
		_variant_t strCaseNodeValue = nodePtr->Gettext();
		BSTR bStrTemp = strCaseNodeName.bstrVal;
		CString strTemp = CString(bStrTemp);
		SysFreeString(bStrTemp);
		CString strNodeName = strTemp;

		// 节点没有属性值
		if (0 != strNodeName.CompareNoCase(_T("CalPoint")) || MSXML2::DOMNodeType::NODE_COMMENT == nodePtr->GetnodeType())
		{
			continue;
		}

		map<CString, CString> mapCalPoint = vecCalPath[nodeCount];
		// 取得节点的属性值
		MSXML2::IXMLDOMNamedNodeMapPtr pDOMAttrList= nodePtr->Getattributes();
		for (int j = 0; j < pDOMAttrList->Getlength(); j++)
		{
			MSXML2::IXMLDOMNodePtr pDOMAttr= pDOMAttrList->Getitem(j); 
			CString cstrValue = (CString)(char*)pDOMAttr->GetnodeName();

			if (0 == CString(L"key").CompareNoCase(cstrValue))
			{
				variant_t var = (LPCTSTR)(mapCalPoint[L"key"]);
				pDOMAttr->PutnodeTypedValue(var);
			} 
			else if (0 == CString(L"value").CompareNoCase(cstrValue))
			{
				
				variant_t var = (LPCTSTR)(mapCalPoint[L"value"]);
				pDOMAttr->PutnodeTypedValue(var);
			}
		}
	}
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值