友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
第三电子书 返回本书目录 加入书签 我的书架 我的书签 TXT全本下载 『收藏到我的浏览器』

深入浅出MFC第2版(PDF格式)-第111部分

快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!


        CPen            m_penCur;           // pen created according to 

。。。 

} 



                                                                                     593 


…………………………………………………………Page 656……………………………………………………………

                 第篇    深入  MFC  程式設計 



                 现在重新考虑文件初始化的动作,将Step1 的: 



                 void CScribbleDoc::InitDocument() 

                 { 

                         m_nPenWidth = 2; // default 2 pixel pen width 

                         // solid; black pen 

                         m_penCur。CreatePen(PS_SOLID; m_nPenWidth; RGB(0;0;0)); 

                 } 



                 改变为Step2 的: 



                 void CScribbleDoc::InitDocument() 

                 { 

                         m_bThickPen = FALSE; 

                         m_nThinWidth = 2;   // default thin pen is 2 pixels wide 

                         m_nThickWidth = 5;  // default thick pen is 5 pixels wide 

                         ReplacePen();       // initialize pen according to current width 

                 } 



           维护UI 对象状态(UPDATE_MAND_UI) 



                 上一节我曾提过WizardBar 右侧的【Messages 】清单中,针对各个命令项,会出现 



                 MAND 和UPDATE_MAND_UI 两种选择。后者做什么用? 



                 一个菜单拉下来,使用者可以从命令项的状态(打勾或没打勾、灰色或正常)得到一些 



                 状态提示。如果Document  中没有任何资料的话,【Edit/Clear All 】照道理就不应该起作 



                 用,因为根本没资料又如何〃Clear All〃 呢?! 这时候我们应该把这个命令项除能 



                  (disable )。又例如在粗笔状态下,程序的【Pen/Thick Line 】命令项应该打一个勾(所 



                 谓的check mark ),在细笔状态下不应该打勾。此外,菜单命令项的状态应该同步影响 



                 到对应之工具栏按钮状态。 



                 所有UI 对象状态的维护可以依赖所谓的UPDATE_MAND_UI 消息。 



                 传统SDK 程序中要改变菜单命令项状态, 可以调用EnableMenuItem 或是 



                 CheckMenuItem ,但这使得程序杂乱无章,因为你没有一个固定的位置和固定的原则处 



                 理命令项状态。MFC 提供一种直觉并且仍旧依赖消息观念的方式,解决这个问题,这就 



594 


…………………………………………………………Page 657……………………………………………………………

                                                第9章   訊息映射與命令繞行   



 是UPDATE_MAND_ UI 消息。其设计理念是,每当菜单被拉下并尚未显示之前, 



 其命令项(以及对应之工具栏按钮)都会收到UPDATE_MAND_ UI 消息,这个消 



 息和WM_MAND 有一样的绕行路线,我们(程序员)只要在适当的类别中放置其 



 处理函数,并在函数中做某些判断,便可决定如何显示命令项。 



 这种方法的最大好处是,不但把问题的解决方式统一化,更因为Framework 传给 



 UPDATE_MAND_ UI 处理例程的参数是一个「指向CCmdUI 对象的指针」,而 



 CCmdUI 对象就代表着对应的菜单命令项,因此你只需调用CCmdUI 所准备的,专门 



 用来处理命令项外观的函数(如Enable 或SetCheck )即可。我们的工作量大为减轻。 



选按【Edit/Clear All】                             CScribbleDoc::OnEditClearAll 

                                          对象 

                                CScribbleDoc        (清除文件内容) 



             ID_EDIT_CLEAR_ALL 

  UI 对象被选择                      ON_MAND 



  有机会修改UI 对象状态                  ON_UPDATE_MAND_UI 



                                mand Target Message Map  



   拉下【Edit】菜单                             CScribbleDoc::OnUpdateEditClearAll 

  (菜单命令项即将显示)                             (将菜单项致能或除能、打勾或取消) 



           图9…7 ON_MAND 和ON_UPDATE_MAND_UI 的运作 



图9…7 以【Edit/Clear All 】实例说明ON_MAND 和ON_ UPDATE_MAND_ UI 



的运作。为了拦截UPDATE_MAND_ UI 消息,你的mand Target 对象(也许是 



Application ,也许是windows ,也许是Views ,也许是Documents )要做两件事情: 



  1。 利用WizardBar (或ClassWizard )加上一笔Message Map 项目如下: 



      ON_UPDATE_MAND_UI(ID_xxx; OnUpdatexxx) 



                                                                           595 


…………………………………………………………Page 658……………………………………………………………

                  第篇    深入  MFC  程式設計 



                  2。 提供一个OnUpdatexxx 函数。这个函数的写法十分简单,因为Framework 传 



                    来一个代表UI 对象(也就是菜单命令项或工具栏按钮)的CCmdUI 对象指 



                    标,而对UI 对象的各种操作又都已设计在CCmdUI 成员函数中。举个例子: 



                     void CScribbleDoc::OnUpdateEditClearAll(CCmdUI* pCmdUI) 

                     { 

                             pCmdUI…》Enable(!m_strokeList。IsEmpty()); 

                     } 



                     void CScribbleDoc::OnUpdatePenThickOrThin(CCmdUI* pCmdUI) 

                     { 

                             pCmdUI…》SetCheck(m_bThickPen); 

                     } 



                  如果命令项与某个工具栏按钮共享同一个命令ID ,上述的Enable 动作将不只影响命令 



                  项,也影响按钮。命令项的打勾(checked )即是按钮的按下(depressed ),命令项没有 



                  打勾(unchecked )即是按钮的正常化(松开)。 



                  现在,Scribble 第二版全部修改完毕,制作并测试之: 



                    在整合环境中按下【Build/Build Scribble 】编译并联结。 



                    按下【Build/Execute】执行Scribble。测试细笔粗笔的运作情况,以及【Edit /Clear 



                    All 】是否生效。 



596 


…………………………………………………………Page 659……………………………………………………………

                                                     第9章   訊息映射與命令繞行   



 从写程序(而不是挖背后意义)的角度去看Message Map ,我把Step2 所进行的菜单改 



 变对Message Map 造成的影响做个总整理。一共有四个相关成份会被ClassWizard                        (或 



 WizardBar )产生出来,下面就是相关源代码,其中只有第4 项的函数内容是我们撰写的, 



 其它都由工具自动完成。 



1。  CSRIBBLEDOC。CPP 



    BEGIN_MESSAGE_MAP(CScribbleDoc; CDocument) 

            //{{AFX_MSG_MAP(CScribbleDoc) 

            ON_MAND(ID_EDIT_CLEAR_ALL; OnEditClearAll) 

            ON_MAND(ID_PEN_THICK_OR_THIN; OnPenThickOrThin) 

            ON_UPDATE_MAND_UI(ID_EDIT_CLEAR_ALL; OnUpdateEditClearAll) 

            ON_UPDATE_MAND_UI(ID_PEN_THICK_OR_THIN; OnUpdatePenThickOrThin) 

            //}}AFX_MSG_MAP 

    END_MESSAGE_MAP() 



    不要去掉//{{ 和//}},否则下次ClassWizard 或WizardBar 不能正常工作。 



2。  CSRIBBLEDOC。H 



    class CScribbleDoc : public CDocument 

    { 

    。。。 

    // Generated message map functions 

    protected: 

            //{{AFX_MSG(CScribbleDoc) 

            afx_msg void OnEditClearAll(); 

            afx_msg void OnPenThickOrThin(); 

            afx_msg void OnUpdateEditClearAll(CCmdUI* pCmdUI); 

            afx_msg void OnUpdatePenThickOrThin(CCmdUI* pCmdUI); 

            //}}AFX_MSG 

    。。。 

    }; 



3。  RESOURCE。H 



    #define ID_PEN_THICK_OR_THIN            32772 

    #define ID_PEN_WIDTHS                   32773 



     (另一个项目ID_EDIT_CLEAR_ALL 已经在AFXRES。H 中定义了) 



                                                                                   597 


…………………………………………………………Page 660……………………………………………………………

                   第篇    深入  MFC  程式設計 



                   4。   SCRIBBLEDOC。CPP 



                       void CScribbleDoc::OnEditClearAll() 

                       { 

                              DeleteContents(); 

                              SetModifiedFlag();  // Mark the document as having been modified; for 

                                                     // purposes of confirming File Close。 

                              UpdateAllViews(NULL); 

                       } 



                       void CScribbleDoc::OnPenThickOrThin() 

                       { 

                              // Toggle the state of the pen between thin or thick。 

                              m_bThickPen = !m_bThickPen; 



                              // Change the current pen to reflect the new user…specified width。 

                              ReplacePen(); 

                       } 



                       void CScribbleDoc::ReplacePen() 

                       { 

                              m_nPenWidth = m_bThickPen? m_nThickWidth : m_nThinWidth; 



                              // Change the current pen to reflect the new user…specified width。 

                              m_penCur。DeleteObject(); 

                              m_penCur。CreatePen(PS_SOLID; m_nPenWidth; RGB(0;0;0)); // solid black 

                       } 



                       void CScribbleDoc::OnUpdateEditClearAll(CCmdUI* pCmdUI) 

                       { 

                              // Enable the mand user interface object (menu item or tool bar 

                              // button) if the document is non…empty; i。e。; has at least one stroke。 

                              pCmdUI…》Enable(!m_strokeList。IsEmpty()); 

                       } 



                       void CScribbleDoc::OnUpdatePenThickOrThin(CCmdUI* pCmdUI) 

                       { 

                              // Add check mark to Draw Thick Line menu item; if the current 

                              // pen width is 〃thick〃。 

                              pCmdUI…》SetCheck(m_bThickPen); 

                       } 



598 


…………………………………………………………Page 661……………………………………………………………

                                       第9章   訊息映射與命令繞行   



本章回顾 



   这一章主要为Scribble Step2 增加新的菜单命令项。在这个过程中我们使用了工具栏编 



   辑器和ClassWizard (或Wizardbar )等工具。工具的使用很简单,但是把消息的处理常 



   式加在什么地方却是关键。因此本章一开始先带你深入探索MFC 源代码,了解消息的 



   递送以及所谓Message Map 背后的意义,并且也解释了命令消息(WM_MAND) 特 



   异的绕行路线及其原因。 



   我在本章中挖出了许多MFC 源代码,希望藉由源代码的自我说明能力,加深你对消息 



   映射与消息绕行路径的了解。这是对MFC      「知其所以然」的重要关键。这个知识基础不 



   会因为MFC  的源代码更动而更动,我要强调的,是其原理。 



                                                            599 


…………………………………………………………Page 662……………………………………………………………

                第篇    深入  MFC  程式設計 



600 


…………………………………………………………Page 663……………………………………………………………

                                          10     MFC 

                                        第 章      與對話盒 



  10 

第  章 



               MFC 与对话框 



 上一章我们为Scribble 新增了一个【Pen 】菜单,其中第二个命令项【Pen Width。。。 】准 



 备用来提供一个对话框,让使用者设定笔的宽度。每一线条都可以拥有自己的笔宽。原 



 预设粗笔是5个图素宽,细笔是2个图素宽。 



 为了这样的目的,在对话框中放个Spin 控制组件是极佳的选择。Spin 就是那种有着上下 



 小三角形箭头、可搭配一个文字显示器的控制组件,有点像转轮,用来选择数字最合适: 



                                  
返回目录 上一页 下一页 回到顶部 0 0
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!