tag:C++、接口編程、設(shè)計(jì)方法 、工具條
/* Create by? zyzx
* Created 2008-05-18
* Modified 2008-05-25
*/
???????
???????? 呵呵,原本想取題為T(mén)ools模式的,但想想只是一個(gè)慣用法還談不上一種設(shè)計(jì)模式。。
???????? 好了,言歸正傳,做用戶(hù)界面的時(shí)候通常會(huì)碰到這個(gè)問(wèn)題:比如,我們?yōu)榻缑孀隽艘幌盗械墓ぞ邫诎粹o,當(dāng)用戶(hù)點(diǎn)選按鈕后會(huì)設(shè)置程序進(jìn)入某個(gè)狀態(tài),在這種狀態(tài)下,軟件做出相應(yīng)反饋。 如果只做一個(gè)或幾個(gè)工具,按過(guò)程式的方法,還勉強(qiáng)可以接受,但不利于擴(kuò)展。如果做成軟件,一般可不只幾個(gè)工具供用戶(hù)選擇了哦。。。
???????? Tools模式,有前人發(fā)表過(guò)的思想,但偶楞是沒(méi)找著,還是楞楞看開(kāi)源代碼才明白啥回事的。。。
???????? 舉個(gè)簡(jiǎn)單的例子:就拿我們常用的Windows自帶的畫(huà)圖工具來(lái)說(shuō),選中左邊的工具欄框選項(xiàng),在繪圖區(qū)域按下左鍵拖動(dòng)鼠標(biāo),是在屏幕上繪制虛線(xiàn)框,執(zhí)行選框操作;選中直線(xiàn),在繪圖區(qū)域按下左鍵拖動(dòng)鼠標(biāo),是繪制直線(xiàn),執(zhí)行繪直線(xiàn)操作;選中橡皮,在繪圖區(qū)域按下左鍵拖動(dòng)鼠標(biāo),執(zhí)行擦除操作………
??????? 這里由于跟窗口(GDI對(duì)象)有關(guān),從簡(jiǎn)來(lái)說(shuō):無(wú)非是左鍵按下啊,拖動(dòng)啊,再到釋放左鍵執(zhí)行操作,或是右鍵的啥啊啥的。。他們的共通之處:(由于與DC相關(guān),參數(shù)可酌情考慮)
?????? Class CUIToolsBase : public XXX(?)
?????? {
?????? public:
????????????? virtual void OnMouseDown( UINT nFlags, CPoint point ) = 0; ????? //鼠標(biāo)點(diǎn)下,參數(shù)按MFC格式
?????? ?????? virtual void OnMouseUp( UINT nFlags, CPoint point ) = 0;??????????? //鼠標(biāo)彈起
?????? ?????? virtual void OnMouseMove( UINT nFlags, CPoint point ) = 0;?????? //鼠標(biāo)移動(dòng)
????????????? virtual void OnMouseDraging( UINT nFlags, CPoint point ) = 0;?????? //鼠標(biāo)拖動(dòng)
????? ????? …………
??????? public:
????????????? CUIToolsBase ();
????????????? virtual ~CUIToolsBase();
?????? protected:
????????????? virtual void Execute() = 0;??????????????????????????????????????????????????????????? //執(zhí)行本Tool的操作
?????? };
而其他的Tool都從本類(lèi)繼承而來(lái)。
???
比如選擇框的Tool
???? CUIToolsSelect : public CUIToolsBase
???? {
???? public:
????????? virtual void OnMouseDown( UINT nFlags, CPoint point )????????????????????? //實(shí)現(xiàn)代碼最好寫(xiě)在cpp文件中,懶下
????????? {
???????????????? if( 左鍵 == nFlags /*&& 要判斷鍵盤(pán)(Ctrl,Shift,Alt )狀態(tài)嗎 */){
??????????????????????? m_StartPt = point ;
??????????????????????? m_EndPt = point;
???????????????? }
????????? }?????
????????? virtual void OnMouseDraging( UINT nFlags, CPoint point )
????????? {
??????????????? if( 左鍵 == nFlags /*&& 要判斷鍵盤(pán)(Ctrl,Shift,Alt )狀態(tài)嗎 */){
??????????????????????? if( !m_DrawRect ){
????????????????????????????? XXX( m_StartPt, point );???????????????? //異或方式在CDC上繪制矩形框,第一次繪制
??????????????????????? }else{
????????????????????????????? XXX( m_StartPt, m_EndPt );????????? //異或方式在CDC上清除上一次繪制的矩形框
????????????????????????????? XXX( m_StartPt, point );??????????????? //異或方式在CDC上繪制當(dāng)前矩形框
??????????????????????? }
??????????????????????? m_EndPt = point;
???????????????? }
??????????? }
?????????? virtual void OnMouseUp( UINT nFlags, CPoint point )
?????????? {
??????????????? if( 左鍵 == nFlags /*&& 要判斷鍵盤(pán)(Ctrl,Shift,Alt )狀態(tài)嗎 */){
??????????????????????? if ( m_DrawRect ){
???????????????????????????????? XXX( m_StartPt, m_EndPt );????? //異或方式在CDC上清除上一次繪制的矩形框
???????????????????????????????? m_EndPt = point
???????????????????????????????? m_DrawRect = false;
???????????????????????????????? Execute();
???????????????????????? }
????????????????? }
??????????? }
??????????????
????? public:
??????????? CUIToolsSelect () { Init(); }
???????? ?? virtual ~CUIToolsSelect (){ }
????? protected:
??????????? void Init() { m_StarPt = ??; m_EndPt = ??; m_DrawRect = false; }
??????????? virtual void Execute()
??????????? {
?????????????????? XXXX( m_StartPt, m_EndPt );???????????? //執(zhí)行選擇操作
?????????????????? //這里也可以按Command模式只發(fā)出命令
??????????? }
?????
????? private:
??????????????? CPoint m_StartPt;??????????? //啟始點(diǎn)
??????????????? CPoint m_EndPt;???????????? //結(jié)束點(diǎn)
??????????? bool???? m_DrawRect;?????? //是否已經(jīng)繪制矩形框標(biāo)志,初始化為false!
????? };
?????
如下圖:
在要設(shè)置Tools的窗口內(nèi)作如下處理:
??????? CWorkWnd : public XXXX
??????? {
??????? public:
????????????? 構(gòu)造,析構(gòu)......
????????????? enum{
?????????????????? UITOOLS_UNKNOW = 0,
?????????????????? UITOOLS_SELECT,
?????????????????? UITOOLS_ERASE,
?????????????????? UITOOLS_LINE,
?????????????????? ......
?????????????????? UITOOLS_COUNT = ?
????????????? }
??????? public:
????????????? void SetCurrentTool( int tool ){?????????????????????????????????????? ?? // 外部調(diào)用此方法設(shè)置Tool
???????????????????? XXXXX???????????????????????????????????????????????????????????????????????? // 相關(guān)前處理
???????????????????? switch( tool ) {
???????????????????? case UITOOLS_SELECT:
?????????????????????????? DoSetCurrentTool( new CUIToolsSelect() );
?????????????????????????? break;
???????????????????? case UITOOLS_ERASE:
?????????????????????????? DoSetCurrentTool( new CUIToolsErase() );
?????????????????????????? break;
???????????????????? case UITOOLS_LINE:
?????????????????????????? DoSetCurrentTool( new CUIToolsLine() );
?????????????????????????? break;
???????????????????? default:
?????????????????????????? break;
???????????????????? }
??? ??? ??? }
?????? protected:
????????????? void OnMouseDown( UINT nFlags, CPoint point ){
???????????????????? if ( m_CurrentTool ) {
???????????????????????????? m_CurrentTool->OnMouseDown( nFlags, point );
???????????????????? }
????????????? }
????????????? void OnMouseUp( UINT nFlags, CPoint point ) {
???????????????????? if ( m_CurrentTool ) {
????????????????????????????? m_CurrentTool->OnMouseUp( nFlags, point );
???????????????????? }
????????????? }
????????????? void OnMouseMove( UINT nFlags, CPoint point ) {
????????????????????? if ( m_CurrentTool ) {
????????????????????????????? m_CurrentTool->OnMouseMove( nFlags, point );
????????????????????? }
????????????? }
????????????? void OnMouseDraging( UINT nFlags, CPoint point ){
????????????????????? if( m_CurrentTool ) {
????????????????????????????? m_CurrentTool->OnMouseDraging( nFlags, point );
????????????????????? }
????????????? }
?????? protected:
????????????? void DoSetCurrentTool( CUIToolsBase* tool ){
????????????????????? if ( m_CurrentTool ) delete m_CurrentTool;
????????????????????? m_CurrentTool = tool;
?????????????? }
?????? ......
?????? private:
?????????????? CUIToolsBase*?????????????? m_CurrentTool;????????????????????? // 只關(guān)聯(lián)到接口,運(yùn)行時(shí)指定對(duì)象
?????? }
總結(jié):
??????? 此方法思路比較簡(jiǎn)單:無(wú)非是先定義一系列接口,在某個(gè)模塊( 小到類(lèi),函數(shù))中使用接口,執(zhí)行動(dòng)作由運(yùn)行時(shí)的實(shí)際對(duì)象決定。關(guān)于這種方式在實(shí)際中會(huì)碰到很多類(lèi)似的問(wèn)題。
擴(kuò)展:
??????? 為軟件建立統(tǒng)一的Tools管理類(lèi),支持多個(gè)工具條。。。