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

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

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





                                              份菜单是否一开始就有功效,必须视你选 



                                              用哪一种View 而定,例如CEditView 



                                              就内建有剪贴簿功能。 



416 


…………………………………………………………Page 479……………………………………………………………

                                第7章    簡單而完整:MFC 骨幹程式 



                              标准MDI 程序应该具备的 



                               【Window】菜单 



                              【Help】菜单和About 对话框 



                              亦已备妥。 



此外,标准的工具栏和状态列也已备妥,并与菜单内容建立起映射关系。所谓工具栏, 



是将某几个常用的菜单项目以按钮型式呈现出来,有一点热键的味道。这个工具栏可以 



随处停驻(dockable )。所谓状态列,是主窗口最下方的文字显示区;只要菜单拉下,状 



态列就会显示鼠标座落的菜单项目的说明文字。状态列右侧有三个小窗口(可扩充个 



数),用来显示一些特殊按键的状态。 



                                                        417 


…………………………………………………………Page 480……………………………………………………………

               第篇    湷觥 FC  程式設計 



               打印与预视功能也已是半成品。【File 】菜单拉下来可以看到【Print。。。 】和【Print Preview 】 



               两项目: 



               骨干程序的Document 和View  目前都还是白纸一张,需要我们加工,所以一开始看不 



               出打印与预视的真正功能。但如果我们在AppWizard  中选用的View 类别是CEditView 



                (如同第4章292 页),使用者就可以打印其编辑成果,并可以在打印之前预视。也就 



               是说,一进程序代码都不必写,我们就获得了一个可以同时编辑多份文件的文字编辑软件。 



418 


…………………………………………………………Page 481……………………………………………………………

                                                 第7章    簡單而完整:MFC 骨幹程式 



Document/View 支撑你的应用程序 



      我已经多次强调,Document/View 是MFC 进化为Application Framework  的灵魂。这个特 



      征表现于程序设计技术上远多于表现在使用者接口上,因此使用者可能感觉不到什么是 



      Document/View 。程序员呢?程序员将因陌生而有一段阵痛期,然后开始享受它带来的便 



      利。 



      我们在OLE  中看到各对象(注)的集合称为一份Document ;在MDI  中看到子窗口所 



      掌握的资料称为一个Document ;现在在MFC 又看到Document 。〃Document〃 如今处处 



      可见,再过不多久八成也要和〃Object〃 一样地泛滥了。 



      OLE 对象指的是PaintBrush 完成的一张bitmap 、SoundRecorder 完成的一段Wave 声 



      音、Excel 完成的一份电子表格、Word 完成的一份文字等等等。为了恐怕与C++  的「对象」 



      混淆,有些书籍将OLE object 称为OLE item 。 



      在MFC 之中,你可以把Document 简单想作是「资料」。是的,只是资料,那么MFC 



      的CDocument 简单地说就是负责处理资料的类别。 



      问题是,一个预先写好的类别怎么可能管理未知的资料呢?MFC 设计之际那些伟大的天 



      才们并不知道我们的数据结构,不是吗?! 他怎么知道我的程序要处理的资料是简单 



      如: 



         char  name'20'; 

         char  address'30'; 

         int   age; 

         bool  sex; 



      或是复杂如: 



         struct dbllistnode 

                { 

                  struct dbllistnode *next; *prev; 

                  struct info_t 

                         { 

                          int left; 

                          int top; 



                                                                                  419 


…………………………………………………………Page 482……………………………………………………………

                           第篇    湷觥 FC  程式設計 



                                               int width; 

                                               int height; 

                                               void (*cursor)(); 

                                              } *item; 

                                     }; 



                         的确,预先处理未知的资料根本是不可能的。CDocument 只是把空壳做好,等君入瓮。 



                         它可以内嵌其它对象(用来处理基层数据类型如串行、数组等等),所以程序员可以在 



                         Document  中拼拼凑凑出实际想要表达的文件完整格式。下一章进入Scribble 程序的实际 



                         设计时,你就能够感受这一点。 



                         CDocument 的另一价值在于它搭配了另一个重要的类别:CView。 



                         不论什么型式,数据总是有体有面。实际的资料数值就是体,显示在屏幕上(甚而打印 



                         机上)的画面就是面(图7…3a )。「数值的处理」应该使用字节、整数、浮点数、串 



                         列、数组等数据结构,而「数值的表现」应该使用绘图工具如坐标系统、笔刷颜色、点 



                         线圆弧、字形。。。。CView 就是为了资料的表现而设计的。 



                            CMyDoc::Serialize(。。。) 

                                                         CMyView::OnDraw(。。。) 

                            { 

                                                         { 

                             // 把资料读出文件                   // 取得Document, 

                             // 放入Document 中              // 调用GDI 函数, 

                            }                             // 将资料表现出来。 



                                                         } 

                                          磁盘中的文件 



                                The C++ piler gen 

                                ings; all of which a 

                                are caused by the ol 

                                。。。 



                                Hello; I am J。J。Hou;  

                                a goodman。 

                                。。。 



                                The difference; omit 

                                lpCmdLine parameter 

                                。。。 



                             图7…3a Document 是资料的体, View 是资料的面。 



         420 



} 


…………………………………………………………Page 483……………………………………………………………

                                                第7章    簡單而完整:MFC 骨幹程式 



 除了负责显示,View 还负责程序与使用者之间的交谈接口。使用者对资料的编辑、修改 



 都需仰赖窗口上的鼠标与键盘动作才得完成,这些消息都将由View 接受后再通知 



 Document ( 图7…3b) 。 



   CMyDoc::Serialize(。。。)       CMyView::OnLButtonDown(。。。) 

   {                            { 

   //把资料从Document 写入文件           //记录鼠标位置为DWORD, 

                                 //并将DWORD 加入Document 

   }                            } 



                                                        当使用者在窗口中按下鼠标左键,LButtonDown 

                  磁盘中的文件文件 

                                                        消息会被窗口攫取,只要程序员曾对此消息设定 

          04 00 FF FF 01 00 07 

          43 53 74 72 6F 6B 65                          消息映射,CMyView::OnLButtonDown 就会被 

          00 02 00 26 00 08 00 

          。。。                                           调用. 



          00 08 00 01 80 05 00 

          00 26 00 1C 00 27 00 

          。。。 



          00 27 00 1C 00 01 80 

          。。。 



            图7…3b View 是Document 的第一线, 负责与使用者接触。 



Document/View  的价值在于,这些MFC 类别已经把一个应用程序所需的「数据处理与 



显示」的函数空壳都设计好了,这些函数都是虚拟函数,所以你可以(也应该)在衍生 



类别中改写它们。有关文件读写的动作在CDocument 的Serialize  函数进行,有关画面显 



示的动作在CView 的OnDraw 或OnPaint 函数进行。当我为自己衍生两个类别CMyDoc 



和CMyView,我只要把全付心思花在CMyDoc::Serialize 和CMyView::OnDraw 身上,其它 



琐事一概不必管,整个程序自动会运作得好好的。 



                                                                                  421 


…………………………………………………………Page 484……………………………………………………………

              第篇    湷觥 FC  程式設計 



              什么叫做「整个程序会自动运作良好」?以下是三个例子: 



                ■  如果按下【File/Open 】,Application Framework 会激活对话框让你指定文件名, 



                  然后自动调用CMyDoc::Serialize 读档。Application Framework 还会调用 



                  CMyView::OnDraw,把资料显示出来。 



                ■   如果屏幕状态改变, 产生了WM_PAINT  , Framework 会自动调用你的 



                  CMyView::OnDraw,传一个Display DC 让你重新绘制窗口内容。 



                ■   如果按下【File/Print。。。】,Framework 会自动调用你的CMyView::OnDraw,这 



                  次传进去的是个Printer DC ,因此绘图动作的输出对象就成了打印机。 



              MFC  已经把程序大架构完成了,模块与模块间的消息流动路径以及各函数的功能职司都 



               已确定好(这是MFC 之所以够格称为一个Framework  的原因),所以我们写程序的焦 



              点就放在那些必须改写的虚拟函数身上即可。软件界当初发展GUI 系统时,目的也是 



              希望把程序员的心力导引到应用软件的真正目标去,而不必花在使用者接口上。MFC  的 



              Document/View 架构希望更把程序员的心力导引到真正的数据结构设计以及真正的数据 



              显示动作上,而不要花在模块的沟通或消息的流动传递上。今天,程序员都对GUI 称 



               便,Document/View 也即将广泛地证明它的贡献。 



              Application Framework 使我们的程序写作犹如做填充题;Visual C++  的软件开发工具则 



              使我们的程序写作犹如做选择题。我们先做选择题,再在骨干程序中做填充题。的确, 



              程序员的生活愈来愈像侯捷所言「只是软件IC 装配厂里的男工女工」了。 



              现在让我们展开MFC 深度之旅,彻底把MFC 骨干程序的每一行都搞清楚。你应该已 



              经从上一章具体了解了MFC 程序从激活到结束的生命过程,这一章的例子虽然比较复 



              杂,程序的生命过程是一样的。我们看看新添了什么内容,以及它们如何运作。我将以 



              AppWizard 完成的Scribble Step0  (第4章)为解说对象,一行不改。然后我会做一点点 



              修改,使它成为一个多窗口文字编辑器。 



422 


…………………………………………………………Page 485……………………………………………………………

                                                第7章    簡單而完整:MFC 骨幹程式 



利用Visual C++ 工具完成Scribble step0 



       我已经在第4章示范过AppWizard  的使用方法,并实际制作出Scribble Step0 程序,这 



       里就不再重复说明了。完整的骨干程序源代码亦已列于第4章。 



       这些由「生产线」做出来的程序代码其实对初学者并不十分合适,原因之一是容易眼花撩 



       乱,有许多#if。。。#endif、批注、奇奇怪怪的符号(例如//{ 和//});原因之二 



       是每一个类别有自己的。H 档和。CPP 文件,整个程序因而幅员辽阔(六个。CPP 档和六 



       个。H 档)。 



        图7…4 是Scribble step0 程序中各类别的相关资料。 



        类别名称           基础类别          类别声明于        类别定义于 



       CScribbleApp     CWinApp         Scribble。h     Scribble。cpp 



       CMainFrame       CMDIFrameWnd    Mainfrm。h      Mainfrm。cpp 



       CChildFrame      CMDIChildWnd    Childfrm。h     Childfrm。cpp 



       CScribbleDoc     CDocument       ScribbleDoc。h  ScribbleDoc。cpp 



       CScribbleView    CView           ScribbleView。h ScribbleView。cpp 



       CAboutDlg        CDialog         Scribble。cpp   Scribble。cpp 



          图7…4 Scribble 骨干程序中的重要组成份子 



  骨干程序使用哪些MFC 类别? 



       对,你看到的Scribble step0 就是一个完整的MFC 应用程序,而我保证你一定昏头转向 



       茫无头线程。没有关系,我们才刚启航。 



       如果把标准图形接口(工具栏和状态列)以及Document/View 考虑在内,一个标准的 



       MFC MDI 程序使用这些类别: 



                                                                               423 


…………………………………………………………Page 486……………………………………………………………

                  第篇    湷觥 FC  程式設計 



                   MFC 类别名称       我的类别名称           功能 



                  CWinApp              CScribbleApp     application object 



                  CMDIFrame Wnd        CMainFrame       MDI 主窗口 



                                                                 Document/View 

                  CMultiDocTemplate      直接使用       管理 



                  CDocument            CScribbleDoc     Document ,负责数据结构与文件动作 



                  CView                CScribble View   View  ,负责资料的显示与打印 



                  CMDIChild Wnd        CChildFrame      MDI   子窗口 



                  CToolBar              直接使用       工具栏 



                  CStatusBar             直接使用       状态列 



                  CDialog              CAboutDlg        About  对话框 



                  应用程序各显身手的地方只是各个可被改写的虚拟函数。这九个类别在MFC  的地位请看 



                  图7…1 。下一节开始我会逐项解释每一个对象的产生时机及其重要性质。 



                  Document/View 不只应用在MDI 程序,也应用在SDI 程序上。你可以在AppWizard  的 



                   「Options 对话框」(图4…2b )选择SDI 风格。本书以MDI 程序为讨论对象。 



                  为了对标准的MFC 程序有一个大局观,图7…4 显示Scribble step0 中各重要组成份子(类 



                  别),这些组成份子在执行时期的意义与主从关系显示于图7…5 。 



424 


…………………………………………………………Page 487……………………………………………………………

                                                    第7章    簡單而完整:MFC 骨幹程式 



                                    Document 

                                    (CDocument 对象) 



           Application 对象 



            (CWinApp 对象) 



      Document Template 对象                                   工具栏(CToolBar 对象) 



     (CMultiDocTemplate 对象) {                                  MDI Frame 窗口 



                                                               (CMDIFrameWnd 对象) 



                                                             状态列(CStatusBar 对象) 



                                                 MDI Child 窗口 

        对话框(CDialog 对象)          View 

                                                 (Document Frame 窗口) 

                                 (CView 对象)      (CMDIChildWnd 对象) 



       虚线框者表示,应用程序通常不必改写该基础类别,可直接拿来使用. 



                                                  

   图7…5 Scribble step0 程序中的九个对象 (几乎每个MFC MDI 程序都如此)  

                                                                               。 



   图7…6 是Scribble step0 程序缩影,我把执行时序标上去,对于整体概念的形成将有帮助。 



#0001 class CScribbleApp : public CWinApp 

#0002 { 

                                                注意:第6章的HelloMFC 程序是在 

#0003     virtual BOOL InitInstance();   //  

#0004     afx_msg void OnAppAbout();          //  

                                                 类别中处理〃About〃 命令,这里的 

#0005     DECLARE_MESSAGE_MAP()               //程序却在CWinApp 衍生类别中处理之。到底, 

#0006 };                                      //一个消息可以(或应该)在哪里被处理才是合理? 

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