【文章內(nèi)容簡(jiǎn)介】
員變量 doc 的值保存到 file 指定的文件中。 const stringamp。 getdoc() 返回 doc 的值。 bool setdoc(const stringamp。 _doc) 以 _doc 設(shè)置 doc 的值。 表 2 Xmlparser設(shè)計(jì)表 類名: XmlParser 設(shè)計(jì)用途:用于實(shí)現(xiàn) XmlTree 和字符串化的 XML 文檔的相互轉(zhuǎn)換。 方法 /屬性 作用 static XmlTree* doc2tree(const stringamp。 doc) 將 doc 轉(zhuǎn)換成一個(gè) XmlTree。 static string tree2doc(XmlTree* pXmlTree) 將一個(gè) XmlTree 轉(zhuǎn)換為字符串。 static int gettoken(string strDoc, stringamp。 token) 從 strDoc 中獲取第一個(gè)標(biāo)記(或者值) 說明:正是通過這兩個(gè)類的協(xié)作,實(shí)現(xiàn)了 XML 文檔的讀寫和轉(zhuǎn)換。例如: XmlFile file。 if(!(Settings\\)) { AfxMessageBox(打開數(shù)據(jù)文件 )。 return。 } XmlTree* pTree = XmlParser::doc2tree(())。 if(!pTree) { AfxMessageBox(轉(zhuǎn)換數(shù)據(jù)文件 )。 return。 } 上面的代碼段首先使用 XmlFile 的實(shí)例 load 了一個(gè) XML 文檔,然后使用XmlParser::doc2tree 創(chuàng)建了一個(gè) XmlTree,從而為內(nèi)存中使用 XML 提供了基礎(chǔ)。 下面說明一下對(duì) XML 的處理方案。使用樹型結(jié)構(gòu)表達(dá) XML 文檔,可以比較方便的進(jìn)行相應(yīng)的讀寫刪改操作。因?yàn)?XML 本身就是一個(gè)數(shù)型的結(jié)構(gòu)。例如: DATA item nametttttt/name catalogs13/catalogs pathd/path /item item namexx/name catalogs7/catalogs pathxx/path /item /DATA 以上是一段程序中用到的 XML 文檔結(jié)構(gòu)。注意到整個(gè)文檔以 DATA開始,以/DATA結(jié)尾,表示之間的都是存儲(chǔ)的數(shù)據(jù)(實(shí)際上就是資源的屬性數(shù)據(jù))。中間共有兩個(gè) item,而每個(gè) item 又各有幾個(gè)屬性(如 name, catalogs等)。所以可以用一顆樹來表示: N a m e = ” D A T A ”N a m e = ” i t e m ”N a m e = ” i t e m ”N a m e = ” n a m e ”v a l u e = ” t t t t t t ”N a m e = ” c a t a l o g ” v a l u e = ” 1 3 ”N a m e = ” p a t h ” v a l u e = ” d ”N a m e = ” n a m e ” v a l u e = ” x x ”N a m e = ” c a t a l o g ” v a l u e = ” 7 ”N a m e = ” p a t h ” v a l u e = ” x x ”圖 2 Xml樹型結(jié)構(gòu)圖 注意到上面的樹中有些節(jié)點(diǎn)只有 Name 沒有 Value,而有些卻都有。雖然它們都是節(jié)點(diǎn),但類型上還是有區(qū)別的。故,采用三個(gè)類表達(dá)這種信息: XmlNode,XmlLeaf, XmlContainer。 首先定義一個(gè)接口類 XmlNode,該類表達(dá)抽象的 XML節(jié)點(diǎn)。然后使用 XmlLeaf類和 XmlContainer類來實(shí)現(xiàn) XmlNode, XmlLeaf表示葉節(jié)點(diǎn)(有 Name和 Value雙重屬性的節(jié)點(diǎn),但自己沒有子節(jié)點(diǎn) ), XmlContainer表示容器節(jié)點(diǎn)(只有 Name屬性的節(jié)點(diǎn),而且自己可以有子節(jié)點(diǎn))。下面是它們的定義 : class XmlNode { public: XmlNode(){name = node。parent = NULL。} virtual ~XmlNode(){}。 virtual bool isleaf()=0。 //是否葉節(jié)點(diǎn) virtual bool iscontainer()=0。//是否容器節(jié)點(diǎn) virtual XmlNode* getparent(){return parent。}。 //返回父節(jié)點(diǎn) virtual bool setparent(XmlNode* _parent){ parent=_parent。 return true。}。 //設(shè)置父節(jié)點(diǎn) virtual const stringamp。 getname(){return name。}。 //返回節(jié)點(diǎn)名稱 virtual bool setname(const stringamp。 _name){name=_name。 return true。}。 //設(shè)置節(jié)點(diǎn)名稱 protected: XmlNode* parent。 string name。 }。 class XmlContainer : public XmlNode { public: XmlContainer(){pos = 1。 name=container。}。 XmlContainer(const stringamp。 _name){name=_name。 pos = 1。}。 ~XmlContainer(){release()。}。 bool isleaf(){ return false。}。 bool iscontainer(){return true。}。 bool addchild(XmlNode* _node)。 //新增一個(gè)子節(jié)點(diǎn) bool remove(XmlNode* pNode)。 //刪除一個(gè)子節(jié)點(diǎn) XmlNode* firstchild()。 //返回第一個(gè)子節(jié)點(diǎn) XmlNode* nextchild()。 //返回下一個(gè)字節(jié)點(diǎn) XmlNode* getchild(int nIndex)。 //返回第 nIndex個(gè)子節(jié)點(diǎn) XmlNode* search(const stringamp。 name)。 //找到第一個(gè)以 name為名的子孫節(jié) 點(diǎn) XmlNode* search(const stringamp。 name, const stringamp。 value)。 //找到第一個(gè)以 name為名,以 value為值的葉節(jié)點(diǎn) void trav(ostreamamp。 out)。 //遍歷并輸出到 out中 void print(int lev)。 protected: void release()。 int pos。 vectorXmlNode* children。 }。 typedef XmlContainer XmlTree。 class XmlLeaf : public XmlNode {public: XmlLeaf(){name=leaf。}。 XmlLeaf(const stringamp。 _name) {name=_name。}。 XmlLeaf(const stringamp。 _name, const stringamp。 _value) {name=_name。 value=_value。}。 ~XmlLeaf(){}。 bool isleaf(){ return true。}。 //是葉節(jié)點(diǎn),返回 true bool iscontainer(){return false。}。 //不是容器節(jié)點(diǎn),返回 false const stringamp。 getvalue(){return value。}。 //獲取值 bool setvalue(const stringamp。 _value){value=_value。 return true。}。//設(shè)置值 protected: string value。 }。 下圖為數(shù)據(jù)流的轉(zhuǎn)化圖 : 圖 3 Xml 數(shù)據(jù)流轉(zhuǎn)換圖 在讀取文件數(shù)據(jù)的時(shí)候使用 XmlFile 從磁盤 讀取文件數(shù)據(jù),并轉(zhuǎn)化為一個(gè)String 對(duì)象,然后使用 XmlParser 轉(zhuǎn)化為一個(gè) XmlTree 對(duì)象,這樣就可以很方便的操作數(shù)據(jù)。當(dāng)存儲(chǔ)數(shù)據(jù)的時(shí)候,使用 XmlParser 把一個(gè) XmlTree 對(duì)象轉(zhuǎn)化為一個(gè) String 對(duì)象,然后通過 XmlFile 類將這個(gè) String 對(duì)象保存到磁盤文件中。上述過程就實(shí)現(xiàn)了系統(tǒng)數(shù)據(jù)流的轉(zhuǎn)化,也在次基礎(chǔ)上變于整個(gè)系統(tǒng)調(diào)用 XML 來實(shí)現(xiàn)具體的功能。 用戶界面和事物處理 用戶界面 本系統(tǒng)的用戶界面是一個(gè), 類似 VC的界面,左邊、底下有兩個(gè)可浮動(dòng)、可變大小的控制窗口。 具體 實(shí)現(xiàn)的為:首先 創(chuàng)建窗口的定義如下:磁盤文件I te m s . x m lX m lF il e儲(chǔ)存到文件載入到內(nèi)存內(nèi)存 X m l S tr in gX m lP a r s e r轉(zhuǎn)化為 X m lT r e e內(nèi)存 X m l T r e e轉(zhuǎn)化為 S tr in g先 為 CMainFrame增加成員變量 : class CMainFrame : public CFrameWnd { protected: CMainFrame()。 DECLARE_DYNCREATE(CMainFrame) public: CDlgInfo m_dlgInfo。 //用于顯示信息,位于程序最下方 CCoolTabCtrl m_TabCtrl。 CCoolBar m_wndMyBar1。 //我們將它作為左邊的窗口 CCoolBar m_wndMyBar2。 //我們將它作為右邊的窗口 創(chuàng)建 ControlBar 即控制條和 “ 刪除 ” , “ 修改 ” , “ 修改 ” 按鈕: if (!(_T(我的控制條 ), this, CSize(230,260) ,TRUE,123)){?? }。if (!(_T(我的控制條 2), this,CSize(200,100),TRUE,124)){??} (0, 增加 )。 (1, 刪除 )。 (2, 修改 )。 創(chuàng)建 TAB Control,并把它加入到 ControlBar 中。需要注意的是 :同一個(gè) ControlBar 只能加入一個(gè) 一級(jí)子窗口 (TCS_DOWN|WS_CHILD|WS_VISIBLE,CRect(0,0,0,0),amp。m_wndMyBar1,125)。 (RUNTIME_CLASS(CCatalogDlg),IDD_DLG_CATALOG, 目 錄 , IDI_ICON_CATALOG)。 (RUNTIME_CLASS(CSearchDlg),IDD_DLG_SEARCH, 搜 索 , IDI_ICON_SEARCH)。 (RUNTIME_CLASS(CFavDlg), IDD_DLG_FAV, 收藏夾 , IDI_ICON_FAC)。 ??靠刂?: (() |CBRS_TOOLTIPS | CBRS_FLYBY| CBRS_SIZE_DYNAMIC)。 (() |CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC)。 (CBRS_ALIGN_ANY)。 (CBRS_ALIGN_ANY)。 (CBRS_ALIGN_ANY)。 EnableDocking(CBRS_ALIGN_ANY)。 DockControlBar(amp。m_wndToolBar)。 DockControlBar(amp。m_wndMyBar1, AFX_IDW_DOCKBAR_LEFT)。//??孔筮? DockControlBar(amp。m_wndMyBar2, AFX_IDW_DOCKBAR_BOTTOM)。//??坑疫? (CBRS_ALIGN_ANY)。 EnableDocking(CBRS_ALIGN_ANY)。 DockControlBar(amp。m_wndToolBar)。 此時(shí)我們已經(jīng)生成了兩個(gè)控制條窗口,但窗口中還沒有任何東西 。 在創(chuàng)建這些控件時(shí)將控制條窗口指針作為父窗口指針賦值給這些控件 。在上面敘訴中,創(chuàng)建了“添加”“刪除”,“ 修改”按鈕。其他按鈕,控件在 class CCoolTabCtrl : public CWnd類中聲明和定義,在使用中調(diào)用。由于它們涉及到對(duì)具體事件的處理,在下面部分分類說明。其中對(duì)于風(fēng)格的使用,論文中沒有特別說明,在使用中可以看出來。 事務(wù)處理 事務(wù)處理這個(gè)模塊就是對(duì)具體的按鈕,控件的設(shè)置和響應(yīng),通過對(duì)它們函數(shù)的定義和調(diào)用實(shí)現(xiàn)具體的功能,主要實(shí)現(xiàn)的就是添加,刪除,搜索,和一些具體功能的實(shí)現(xiàn)。下面就是對(duì)具體事務(wù)的介紹。 添加資源:通過點(diǎn)擊工具條的增加按鈕彈出添加資源對(duì)話框,用戶對(duì)資源屬性進(jìn)行逐一設(shè)置 ,并在點(diǎn)擊確定后保存。 該功能的流程圖如下圖所示: 1 . 彈 出 添 加 資 源對(duì) 話 框2 . 用