Click here to Skip to main content
15,883,922 members
Articles / Programming Languages / XML

Read and Write application parameters in XML

Rate me:
Please Sign up or sign in to vote.
4.38/5 (33 votes)
30 Jun 20034 min read 1.6M   6.8K   141  
This article provides an easy way to load and save the parameters of an application in XML format.
// XML_Dialog.cpp : implementation file
//

#include "Afxcmn.h"
#include "XML_Dialog.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CXML_Dialog dialog


CXML_Dialog::CXML_Dialog(ParamIO &paramIO, CWnd* pParent)
	: CDialog(CXML_Dialog::IDD, pParent),
     _paramIO(paramIO),
	  _tree(paramIO.getTree())
{
	//{{AFX_DATA_INIT(CXML_Dialog)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}


void CXML_Dialog::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CXML_Dialog)
	DDX_Control(pDX, IDC_TREE, m_tree);
	DDX_Control(pDX, IDC_LIST, m_list);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CXML_Dialog, CDialog)
	//{{AFX_MSG_MAP(CXML_Dialog)
	ON_NOTIFY(TVN_SELCHANGED, IDC_TREE, OnSelchangedTree)
   ON_MESSAGE(WM_MODIFIED_ELEMENT, OnModifiedElement)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CXML_Dialog message handlers

BOOL CXML_Dialog::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	// List init
	CRect rect;
	m_list.GetClientRect(&rect);
	int nColInterval = rect.Width()/3;

	m_list.InsertColumn(0, _T("Parameter Name"), LVCFMT_LEFT, nColInterval);
	m_list.InsertColumn(1, _T("Value"), LVCFMT_LEFT, rect.Width()-nColInterval);
   m_list.SetExtendedStyle (LVS_EX_GRIDLINES);
	m_list.setTreeWnd(&m_tree);
	
	// Init to the top of the tree by default
	initTree();
	initList(_tree.top());

	// In case we require to open to a special node, do it
	if(_access.size() > 1)
	{
	   // First parse the acess in a vector of strings
	   std::vector<std::string> strs;
	   ParamIO::parseAccess(_access.c_str(), strs);
		setSelectedItem(strs);
	}

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CXML_Dialog::initTree()
{
	addToTree(_tree.top(), TVI_ROOT);
}

void CXML_Dialog::addToTree(XML_Node::nodes_const_iterator it, HTREEITEM hParent)
{
	HTREEITEM item = m_tree.InsertItem(it->getName().c_str(), hParent);

	XML_Node::nodes_const_iterator begin = it->beginNodes();
	XML_Node::nodes_const_iterator end   = it->endNodes();
	XML_Node::nodes_const_iterator nodeIt;

	for(nodeIt = begin; nodeIt != end; nodeIt++)
	{
		addToTree(nodeIt, item);
	}

	m_tree.Expand(item, TVE_EXPAND);
	m_tree.EnsureVisible(item);
}


void CXML_Dialog::OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

	std::vector<std::string> access;
	getTreeAccess(access);
	initList(_tree.getNode(access));
	
	*pResult = 0;
}

void CXML_Dialog::initList(XML_Node::nodes_const_iterator node)
{
	XML_Node::elements_const_iterator begin = node->beginElements();
	XML_Node::elements_const_iterator end   = node->endElements();
	XML_Node::elements_const_iterator it;

	m_list.DeleteAllItems();

	LVITEM lvi;
	int i = 0;
	for(it = begin; it != end; it++, i++)
	{
		lvi.mask =  LVIF_TEXT;
		lvi.iItem = i;
		lvi.iSubItem = 0;
		lvi.pszText = (char*)(it->first).c_str();
		m_list.InsertItem(&lvi);

		// Set subitem 1
		lvi.iSubItem =1;
		lvi.pszText = (char*)(it->second.value).c_str();
		m_list.SetItem(&lvi);
	}

	// Gives the current node to the list Ctrl
	std::vector<std::string> access;
	getTreeAccess(access);
	m_list.setCurrentNode(_tree.getNode(access));
}

void CXML_Dialog::getTreeAccess(std::vector<std::string> &access)
{
	access.clear();

	HTREEITEM hitem = m_tree.GetSelectedItem();

	while(hitem != NULL)
	{
		access.insert(access.begin(), std::string(m_tree.GetItemText(hitem)));
		hitem = m_tree.GetParentItem(hitem);
	}
}

void CXML_Dialog::setSelectedAccess(const char *access)
{
	_access = std::string(access);
}


void CXML_Dialog::setSelectedItem(std::vector<std::string> &strs)
{
   // Check bad access
   if(strs.size() == 0)
   {
      return;
   }


	// Go through the tree using the access
	HTREEITEM hitem = m_tree.GetRootItem();

	// First check if the first access is equal to the root text
	if(m_tree.GetItemText(hitem).Compare(strs[0].c_str()) != 0)
	{
		return;
	}

	for(int i=1; i<strs.size(); i++)
	{
		// Go away if the item has no child
		if(m_tree.ItemHasChildren(hitem) == false)
		{
			break;
		}

		// Find the item with the first access string
		HTREEITEM hNextItem;
		HTREEITEM hChildItem = m_tree.GetChildItem(hitem);
		while (hChildItem != NULL)
		{
			if(m_tree.GetItemText(hChildItem).Compare(strs[i].c_str()) == 0)
			{
				break;
			}

			hNextItem = m_tree.GetNextItem(hChildItem, TVGN_NEXT);
			hChildItem = hNextItem;
		}

		// Go to found child and go on loop with new string
		hitem = hChildItem;

		if(hitem == NULL)
		{
			return;
		}
	}

	m_tree.SelectItem(hitem);
	initList(_tree.getNode(strs));
}

LONG CXML_Dialog::OnModifiedElement(UINT wParam, LONG lParam)
{
   // Enable the cancel button
   GetDlgItem(IDCANCEL)->EnableWindow(TRUE);
   return 0;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
China China
I've been living & working in Tokyo since 2000 . I'm currently working in Gentech Corp. (www.gen.co.jp), developing computer vision applications, especially in the field of face detection.

I've been interested in C++ for quite a while and recently discovered Ruby.

My hobbies are trekking, japanese food, yoga & onsens.

Comments and Discussions