友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
一世书城 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

深入浅出MFC第2版(PDF格式)-第152章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!






                  依此要领,我们再设计OnPenThickOrThin 函数。此一函数用来更改现行的笔宽,与 



                  Document 有密切关系,所以在Document 类别中放置其消息处理例程是适当的: 



                   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(); 

                   } 



592 


…………………………………………………………Page 655……………………………………………………………

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



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 

} 



注意,ReplacePen 并非由WizardBar      (或ClassWizard )加上去,所以我们必须自行在 



CScribbleDoc 类别中加上这个函数的声明: 



class CScribbleDoc : public CDocument 

{ 

protected: 

        void ReplacePen(); 

        。。。 

} 



OnPenThickOrThin 函数用来更换笔的宽度,所以CScribbleDoc 势必需要加些新的成 



员变量。变量m_bThickPen 用来记录目前笔的状态(粗笔或细笔),变量m_nThinWidth 



和m_nThickWidth 分别记录粗笔和细笔的笔宽…在Step2 中此二者固定为2 和5, 



原本并不需要变量的设置,但下一章的Step3 中粗笔和细笔的笔宽可以更改,所以这里 



未雨绸缪: 



class CScribbleDoc : public CDocument 

{ 

// Attributes 

protected: 

        UINT            m_nPenWidth;        // current user…selected pen width 

        BOOL            m_bThickPen;        // TRUE if current pen is thick 

        UINT            m_nThinWidth; 

        UINT            m_nThickWidth; 

        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; OnEditCle
返回目录 上一页 下一页 回到顶部 0 1
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!