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

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

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



BEGIN 

    。。。 

    POPUP 〃&Edit〃 

    BEGIN 

        。。。 

        MENUITEM 〃Clear &All〃;       ID_EDIT_CLEAR_ALL 

    END 

    POPUP 〃&Pen〃 

    BEGIN 

        MENUITEM 〃Thick &Line〃;      ID_PEN_THICK_OR_THIN 

        MENUITEM 〃Pen &Widths。。。〃;   ID_PEN_WIDTHS 

    END 

    。。。 

END 



                                                                                      587 


…………………………………………………………Page 650……………………………………………………………

                      第篇    深入  MFC  程式設計 



                      STRINGTABLE DISCARDABLE 

                      BEGIN 

                        ID_PEN_THICK_OR_THIN  〃Toggles the line thickness between thin and thicknToggle pen〃 

                        ID_PEN_WIDTHS         〃Sets the size of the thin and thick pennPen thickness〃 

                      END 



                      STRINGTABLE DISCARDABLE 

                      BEGIN 

                          ID_EDIT_CLEAR_ALL       〃Clears the drawingnErase All〃 

                          。。。 

                      END 



               改变工具栏 



                    过去,也就是Visual C++ 4。0 之前,改变工具栏有点麻烦。你必须先以图形编辑器修改工 



                     具列对应之bitmap  图形,然后更改程序代码中对应的工具栏按钮识别码。现在可就轻松 



                     多了,工具栏编辑器让我们一气呵成。主要原因是,工具栏现今也成为了资源的一种。 



                     下面是Scribble Step1 的工具栏: 



                                               File/New       Edit/Cut     File/Print 



                                                    File/Open    Edit/Copy    Help/About 



                                                        File/Save    Edit/Paste 



                    现在我希望为【Pen/Thick Line 】命令项设计一个工具栏按钮,并且把Scribble 用不到的 



                    三个预设按钮去除(分别是Cut 、Copy 、Paste): 



                                                    File/ New           File/ Print 



                                                        File/Open          Help/About 



                                                            File/Save 



                                                                 Pen/Thick Line 



                     编辑动作如下: 



588 


…………………………………………………………Page 651……………………………………………………………

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



 激活工具栏编辑器,选择IDR_MAINFRAME 。有一个绘图工具箱出现在最右侧。 



 将三个用不着的按钮除去:以鼠标拖拉这些按钮,拉到工具栏以外即可。 



 在工具栏最右侧的空白按钮上作画,并将它拖拉到适当位置。 



为了让这个新的按钮起作用,必须指定一个ID 给它。我们希望这个按钮相当 

 于【Pen/Thick Line 】命令项,所以它的ID 当然应该与该命令项的ID 相同, 



 也就是ID_PEN_THICK_OR_THIN 。双击这个新按钮,出现【Toolbar Button 



 Properties 】对话框,请选择正确的ID 。注意,由于此一ID 先前已定义好,所 



 以其提示字符串以及小黄卷标也就与此一工具栏按钮产生了关联。 



 存盘。 



  工具栏编辑器为我们修改了工具栏的bitmap  图形文件内容: 



   IDR_MAINFRAME BITMAP MOVEABLE PURE 〃resToolbar。bmp〃 



  同时,工具栏项目也由原来的: 



                                                             589 


…………………………………………………………Page 652……………………………………………………………

                    第篇    深入  MFC  程式設計 



                            IDR_MAINFRAME TOOLBAR DISCARDABLE  16; 15 

                            BEGIN 

                                BUTTON      ID_FILE_NEW 

                                BUTTON      ID_FILE_OPEN 

                                BUTTON      ID_FILE_SAVE 

                                SEPARATOR 

                                BUTTON      ID_EDIT_CUT 

                                BUTTON      ID_EDIT_COPY 

                                BUTTON      ID_EDIT_PASTE 

                                SEPARATOR 

                                BUTTON      ID_FILE_PRINT 

                                BUTTON      ID_APP_ABOUT 

                            END 



                         改变为: 



                            IDR_MAINFRAME TOOLBAR DISCARDABLE  16; 15 

                            BEGIN 

                                BUTTON      ID_FILE_NEW 

                               BUTTON      ID_FILE_OPEN 

                               BUTTON      ID_FILE_SAVE 

                                SEPARATOR 

                               BUTTON      ID_PEN_THICK_OR_THIN 

                                SEPARATOR 

                               BUTTON      ID_FILE_PRINT 

                               BUTTON      ID_APP_ABOUT 

                            END 



            利用ClassWizard 连接命令项识别码与命令处理函数 



                    新增的三个命令项和一个工具栏按钮,都会产生命令消息。接下来的任务就是为它们指 



                    定一个对应的命令消息处理例程。下面是一份整理: 



                     UI 对象(命令项) 项目识别码处理例程 



                     【              】  

                      Pen/Thick Line         ID_PEN_THI CK_O  R_THIN      OnPenThi  ckOrThin 



                     【              】                                     OnPen Widths             理) 

                      Pen/Pen Widths         ID_PEN_  W  IDTHS                        (第10 章再处 



590 


…………………………………………………………Page 653……………………………………………………………

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



 【         】 

  Edit/Clear All    ID_EDIT_CLEAR_ALL     OnEditClearAll 



消息与其处理例程的连接关系是在程序的Message Map 中确立,而Message Map 可藉 



由ClassWizard 或WizardBar 完成。第8章已经利用这两个工具成功地为三个标准的 



Windows 消息(WM_LBUTTONDOWN、WM_LBUTTONUP、WM_MOUSEMOVE )设 



立其消息处理函数,现在我们要为Step2 新增的命令消息设立消息处理例程。过程如下: 



  首先你必须决定,在哪里拦截【Edit/Clear All 】才好?本章前面对于消息映射 



   与命令绕行的深度讨论这会儿派上了用场。【Edit/Clear All 】这个命令的目的 



   是要清除文件,文件的根本是在资料的「体」,而不在资料的「面」,所以把 



   文件的命令处理例程放在Document 类别中比放在View 类别来得高明。命令讯 



   息会不会流经Document 类别?经过前数节的深度之旅,你应该自有定论了。 

 所以, 让我们在CScribbleDoc 的WizardBar 选择【Object IDs  】为 



  ID_EDIT_CLEAR_ALL ,并选择【Messages 】为MAND 。 



 猜猜看,如果你在【Object IDs 】中选择CScribbleDoc,右侧的【Messages 】清 



  单会出现什么? 什么都没有! 因为Document 类别只可能接受 



  WM_MAND,这一点你应该已经从前面所说的消息递送过程中知道了。如 



  果你在CScribbleApp 的WizardBar 上选择【Object IDs 】为CScribbleApp, 



  右侧的【Messages 】清单中也是什么都没有,道理相同。 



 你会获得一个对话框,询问你是否接受一个新的处理例程。选择Yes ,于是文 



   字编辑器中出现该函数之骨干,等待你的幸临。。。。 



这样就完成了命令消息与其处理函数的连接工作。这个工作称为〃mand binding〃 。我 



们的源代码获得以下修改: 



 Document 类别之中多了一个函数声明: 



   class CScribbleDoc : public CDocument 

   { 

   protected: 

           afx_msg void OnEditClearAll(); 

           。。。 

    } 



                                                                      591 


…………………………………………………………Page 654……………………………………………………………

                   第篇    深入  MFC  程式設計 



                   Document 类别的Message Map 中多了一笔记录: 



                       BEGIN_MESSAGE_MAP(CScribbleDoc; CDocument) 

                               ON_MAND(ID_EDIT_CLEAR_ALL; OnEditClearAll) 

                               。。。 

                       END_MESSAGE_MAP() 



                   Document 类别中多了一个函数空壳: 



                       void CScribbleDoc::OnEditClearAll() 

                       { 



                       } 



                   现在请写下OnEditClearAll 函数码: 



                  依此要领,我们再设计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 ),命令项没
返回目录 上一页 下一页 回到顶部 9 10
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!