boost
庫實在是乙個博大精深的庫。經過實驗,我發現巧用boost::bind和boost::function可以實現一些巧妙的設計。
編寫過mfc程式的朋友都知道,通過資源編輯器編輯選單項,設定選單項id,然後mfc內部通過該id來對映選單命令處理函式和選單介面更新函式。我設想撇開mfc的資源編輯,在mfc程式中通過xml檔案來進行介面配置,然後利用字串來對映訊息處理函式。借助boost庫,我實現了這一設想。具體就是在xml檔案指定乙個字串,然後通過這個字串就能找到它的命令訊息處理函式和介面更新命令訊息處理函式。
下面具體談談怎麼實現這一設想。我需要解決的是兩大問題:一是通過xml檔案來動態建立介面;二是根據xml檔案裡指定的選單項字串找到它的命令訊息處理函式。
第乙個問題相對簡單。首先我談談我的系統介面配置xml檔案的設計。我的系統介面配置xml檔案比較簡單,具體如下:
xml version="1.0" encoding="gb2312" standalone="no"
?>
<
boostbind
>
<
framework
="boost庫測試程式 v1.0"
="檔案(f)"
>
<
menuitem
valid
="1"
identity
="file_new"
caption
="新建"
/>
<
menuitem
valid
="1"
identity
="file_open"
caption
="開啟"
/>
>
<
valid
="1"
caption
="編輯(e)"
>
<
menuitem
valid
="1"
identity
="edit_copy"
caption
="拷貝"
/>
<
menuitem
valid
="1"
identity
="edit_paste"
caption
="貼上"
/>
>
uidescription
>
boostbind
>
簡單解釋就是:framework節點儲存的是程式的基本資訊,包括
包含了程式名、公司名和公司**;接著就是
uidescription
——介面描述,主要包括全部選單欄資訊和選單項資訊。
對應這個系統配置xml檔案,我們需要在程式中定義相應的結構體,具體如下:
#include
<
string
>
using
std::
string
;#include
<
vector
>
using
std::vector;
/**/
struct
=_t(
"");
m_strcompanyname
=_t(
"") ;
m_strurl
=_t(
"") ;}/*
** \brief 應用程式名。
*/string/**
* \brief 公司名。
*/string
m_strcompanyname;/**
* \brief 公司**。
*/string
m_strurl;
};/*
! \struct menuitem basestruct.h
* \brief 選單項資訊結構體.
** 包含了選單是否有效,選單識別符號和選單名
*/struct
menuitem /**
* \brief 選單項是否有效,1為有效,0為無效。
*/string
m_strvalid;/**
* \brief 選單標識,用於對映訊息處理函式。
*/string
m_strid;/**
* \brief 選單項名。
*/string
m_strcaption;
};/*
*/struct
=_t(
"");
m_strcaption
=_t(
"");}/*
** \brief 選單欄是否有效,1為有效,0為無效。
*/string
m_valid;/**
* \brief 選單欄名。
*/string
m_strcaption;/**
* \brief 對應的選單項陣列。
*/vector
<
menuitem
>
m_menuitemvec;
};程式定義了乙個基於tinyxml庫的xml檔案解析類cxmlparse,關於如何解析xml檔案本部落格已經有過詳細介紹,具體參考如下文章:
tinyxml快速入門(三)
就tinyxml
使用答覆一位網友
將tinyxml
快速入門的介面物件導向化
具體做法是在應用程式類裡定義兩個變數:
/*** \brief 用於儲存程式資訊的變數。**/
/*** \brief 用於儲存程式資訊的變數。**/
cxmlparse
*m_psyssetting;
在程式初始化例項函式initinstance()裡呼叫cxmlparse下面我具體談談如何通過xml檔案中指定的選單id字串來對映它的訊息處理函式,概括來說是通過乙個函式來實現的。類的介面來解析系統配置檔案。根據解析系統xml檔案來動態建立選單欄的**也比較簡單,集中在getallmenubar和mainmenubarcreate兩個函式,具體見上傳的**,這裡不作
贅述。
/*** \brief 選單命令訊息處理函式指標。**/
typedef boost::function
<
void
( )>
cmdfunction;/**
* \brief 選單介面更新命令訊息處理函式指標。**/
typedef boost::function
<
void
(ccmdui*)
>
updatecmduifunction;
在框架類裡定義乙個map,選單id作為鍵,訊息處理函式指標作為鍵值:
typedef std::map
<
int, std::pair
<
cmdfunction, updatecmduifunction
>>
cuicommandmap;/**
* \brief 儲存所有命令訊息處理函式指標的map。
*/然後在建立選單的時候將訊息處理函式指標新增進這個map:
void
cmainframe::addtomessagemap(uint umenuid,cmdfunction cmd, updatecmduifunction updateuicmd)
void
cmainframe::mainmenubarcreate()
m_menu.createmenu();
//給cmdid賦值為系統起始選單id值
intcmdid
=sys_command_begin;
intmenubarsize
=m_menubarvec.size();
for(
inti=0
;i<
menubarsize;i++)
if(string
(_t(
"file_open"))
==m_menubarvec[i].m_menuitemvec[j].m_strid)if(
string
(_t(
"edit_copy"))
==m_menubarvec[i].m_menuitemvec[j].m_strid)if(
string
(_t(
"edit_paste"))
==m_menubarvec[i].m_menuitemvec[j].m_strid)
cmdid++;
}//將彈出選單欄插入到主選單
//設定為系統主選單
setmenu(
&m_menu);
}最後過載框架類的
oncmdmsg
函式,根據選單id值呼叫map裡的函式:
bool cmainframe::oncmdmsg(uint nid,
intncode,
void
*pextra, afx_cmdhandlerinfo
*phandlerinfo)
。程式介面如下:
巧用boost庫實現字串對映訊息處理函式
boost庫實在是乙個博大精深的庫。經過實驗,我發現巧用boost bind和boost function可以實現一些巧妙的設計。編寫過mfc程式的朋友都知道,通過資源編輯器編輯選單項,設定選單項id,然後mfc內部通過該id來對映選單命令處理函式和選單介面更新函式。我設想撇開mfc的資源編輯,在m...
巧用boost庫實現字串對映訊息處理函式
boost庫實在是乙個博大精深的庫。經過實驗,我發現巧用boost bind和boost function可以實現一些巧妙的設計。編寫過mfc程式的朋友都知道,通過資源編輯器編輯選單項,設定選單項id,然後mfc內部通過該id來對映選單命令處理函式和選單介面更新函式。我設想撇開mfc的資源編輯,在m...
巧用boost庫實現字串對映訊息處理函式
boost庫實在是乙個博大精深的庫。經過實驗,我發現巧用boost bind和boost function可以實現一些巧妙的設計。編寫過mfc程式的朋友都知道,通過資源編輯器編輯選單項,設定選單項id,然後mfc內部通過該id來對映選單命令處理函式和選單介面更新函式。我設想撇開mfc的資源編輯,在m...