八宝书库 > 文学其他电子书 > 深入浅出MFC第2版(PDF格式) >

第92部分

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

小说: 深入浅出MFC第2版(PDF格式) 字数: 每页4000字

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



                          // TODO: add loading code here 

                  } 

          } 



        由于CDocument 衍生自CObject,所以它就有了CObject 所支持的一切性质,包括执行 



        时期型别信息(RTTI )、动态生成(Dynamic Creation )、文件读写(Serialization)。又 



        由于它也衍生自CCmdTarget,所以它可以接收来自菜单或工具栏的WM_MAND 讯 



       息。 



                                                                                          457 


…………………………………………………………Page 520……………………………………………………………

                  第篇    深入  MFC  程式設計 



            View 



                 View 负责描述(呈现)Document  中的资料。 



                 View 在MFC  的CView 里头被具体化。CView 本身亦无实务贡献,它只是提供一个空 



                  壳。当你开发自己的程序,应该从CView 衍生出一个属于自己的View 类别,并且在 



                  类别中(至少)改写专门负责显示资料的OnDraw 函数(针对屏幕)或OnPrint 函数 



                  (针对打印机)。事实上,AppWizard 为我们把空壳都准备好了,以下是Scribble step0 的 



                  部份内容: 

                     class CScribbleView : public CView 

                     { 

                             DECLARE_DYNCREATE(CScribbleView) 

                             。。。 

                             virtual void OnDraw(CDC* pDC); 

                             DECLARE_MESSAGE_MAP() 

                     }; 



                     void CScribbleView::OnDraw(CDC* pDC) 

                     { 

                             CScribbleDoc* pDoc = GetDocument(); 

                             ASSERT_VALID(pDoc); 



                             // TODO: add draw code for native data here 

                     } 



                   由于CView 衍生自CWnd,所以它可以接收一般Windows 消息(如WM_SIZE、 



                   WM_PAINT 等等),又由于它也衍生自CCmdTarget,所以它可以接收来自菜单或工具 



                   列的WM_MAND 消息。 



                   在传统的C/SDK 程序中,当窗口函数收到WM_PAINT ,我们(程序员)就调用 



                   BeginPaint ,获得一个Device Context (DC ),然后在这个DC 上作画。这个DC 代表萤 



                   幕装置。在MFC 里头,一旦WM_PAINT 发生,Framework 会自动调用OnDraw 函数。 



                   View 事实上是个没有边框的窗口。真正出现时,其外围还有一个有边框的窗口,我们称 



                   为Frame 窗口。 



458 


…………………………………………………………Page 521……………………………………………………………

                                          第8章    Document…View  深入探討 



Document Frame (View Frame) 



    如果你的程序管理两种不同类型的资料,譬如说一个是TEXT ,一个是BITMAP ,作为 



    一位体贴的程序设计者,我想你很愿意为你的使用者考虑多一些:你可能愿意在使用者 



    操作TEXT 资料时,换一套TEXT 专属的使用者接口,在使用者操作BITMAP 资料时, 



    换一套BITMAP 专属的使用者接口。这份工作正是由Frame 窗口负责。 



    乍见这个观念,我想你会惊讶为什么UI  的管理不由View 直接负责,却要交给Frame 



    窗口?你知道,有时候机能与机能之间要有点黏又不太黏才好,把UI 管理机能隔离出来, 



    可以降低彼此之间的依存性,也可以使机能重复使用于各种场合如SDI、MDI 、OLE in…place 



    editing  (即地编辑)之中。如此一来View  的弹性也会大一些。 



Document Template 



    MFC 把Document/View/Frame 视为三位一体。可不是吗!每当使用者欲打开(或新增) 



    一份文件,程序应该做出Document 、View 、Frame 各一份。这个「三口组」成为一个 



    运作单元,由所谓的Document Template 掌管。MFC 有一个CDocTemplate 负责此事。 



    它又有两个衍生类别,分别是CMultiDocTemplate 和CSingleDocTemplate。 



   所以我在上一章说了,如果你的程序能够处理两种数据类型,你必须制造两个Document 



   Template  出来,并使用AddDocTemplate  函数将它们一一加入系统之中。这和程序是不 



   是MDI 并没有关系。如果你的程序支持多种数据类型,但却是个SDI,那只不过表示 



   你每次只能开启一份文件罢了。 



   但是,逐渐地,MDI 这个字眼与它原来的意义有了一些出入(要知道,这个字眼早在SDK 



    时代即有了)。因此,你可能会看到有些书籍这么说:『MDI 程序使用CMultiDocTemplate, 



    SDI 程序使用CSingleDocTemplate』,那并不是很精准。 



    CDocTemplate 是个抽象类别,定义了一些用来处理「Document/View/Frame 三口组」的 



   基础函数。 



                                                                   459 


…………………………………………………………Page 522……………………………………………………………

                    第篇    深入  MFC  程式設計 



             CDocTemplate 管理CDocument / CView / CFrameWnd 



                        好,我们说Document Template 管理「三口组」,谁又来管理Document Template 呢? 



                        答案是CWinApp。下面就是InitInstance  中应有的相关作为: 



                        BOOL CScribbleApp::InitInstance() 

                        { 

                                。。。 

                                CMultiDocTemplate* pDocTemplate; 

                                pDocTemplate = new CMultiDocTemplate( 

                                        IDR_SCRIBTYPE; 

                                        RUNTIME_CLASS(CScribbleDoc); 

                                        RUNTIME_CLASS(CChildFrame); 

                                        RUNTIME_CLASS(CScribbleView)); 

                                AddDocTemplate(pDocTemplate); 

                                。。。 

                        } 



                        想一想文件是怎么开启的:使用者选按【File/New 】或【File/Open 】(前者开启一份空文 



                        件,后者读档放到文件中),然后在View 窗口内展现出来。我们很容易误以为是CWinApp 



                        直接产生Document : 



                        BEGIN_MESSAGE_MAP(CScribbleApp; CWinApp) 

                                ON_MAND(ID_APP_ABOUT; OnAppAbout) 

                                ON_MAND(ID_FILE_NEW; CWinApp::OnFileNew) 

                                ON_MAND(ID_FILE_OPEN; CWinApp::OnFileOpen) 

                                ON_MAND(ID_FILE_PRINT_SETUP; CWinApp::OnFilePrintSetup) 

                        END_MESSAGE_MAP() 



                        其实才不,是Document Template  的杰作: 



460 


…………………………………………………………Page 523……………………………………………………………

                                          第8章    Document…View  深入探討 



            【      】       【       】 

             File/New       File/Open 



          CWinApp 选择适当 的Document Template 



                        CMyDoc 



               构造Document 对象 

                                        CMyView 

                       CChildFrame   构造View 对象      Dynamic Creation 



               构造Frame  

                       窗口对象 



               产生Frame 窗口            产生View 窗口 



    如果是【File/Open】                          注意:或许你搞不清楚“构造View 对象”和 



                    读档                      “产生View 窗口”的关系。是这样的,View 



                                            窗口就是道道地地的Windows 窗口,而为了 

               将View 窗口初始化 

                                            对象管理,MFC 把View 窗口外包一个专属的 



                                            C++ 类别,那就是CView。所以当然是先构造 

               在View 中显示资料 

                                             (construct)一个View 对象,再由其构造式 



            图8…1 Document/View/Frame 的产生    产生(create)对应的View 窗口。Frame 物 



                                            件与Frame 窗口的关系亦复如此。 



图8…1 的灰色部份,正是Document Template 动态产生「三位一体之 



Document/View/Frame 」的行动。下面的流程以及MFC 源代码足以澄清一切疑虑。在 



CMultiDocTemplate::OpenDocumentFile (注)出现之前的所有流程,我只做文字叙述,不 



显示其源代码。本章稍后有一节「台面下的Serialize 读档奥秘」,则会将每一环节的原 



始码呈现在你眼前,让你无所挂虑。 



注:如果是SDI 程序,那么就是CSingleDocTemplate::OpenDocumentFile 被调用。但「多」 



比「单」有趣,而且本书范例Scribble 程序也使用CMultiDocTemplate,所以我就以此 



为说明对象。 



CSingleDocTemplate 只支持一种文件类型,所以它的成员变量是: 



                                                                      461 


…………………………………………………………Page 524……………………………………………………………

                     第篇    深入  MFC  程式設計 



                     class CSingleDocTemplate : public CDocTemplate 

                     { 

                     。。。 

                     protected:  // standard implementation 

                             CDocument* m_pOnlyDoc; 

                     }; 



                     CMultiDocTemplate 支持多种文件类型,所以它的成员变量是: 



                     class CMultiDocTemplate : public CDocTemplate 

                     { 

                     。。。 

                     protected:  // standard implementation 

                             CPtrList m_docList; 

                     }; 



                     当使用者选按【File/New 】命令项,根据AppWizard 为我们所做的Message Map ,此一 



                     命令由CWinApp::OnFileNew 接手处理。后者调用CDocManager ::OnFileNew,后者再呼 



                     叫CWinApp::OpenDocumentFile,后者再调用CDocManager ::OpenDocumentFile,后者 



                     再调用CMultiDocTemplate::OpenDocumentFile     (这是观察MFC 源代码所得结果): 



                     // in AFXWIN。H 

                     class CDocTemplate : public CCmdTarget 

                     { 

                       。。。 

                             UINT m_nIDResource;            // IDR_ for frame/menu/accel as well 

                             CRuntimeClass* m_pDocClass;    // class for creating new documents 

                             CRuntimeClass* m_pFrameClass;  // class for creating new frames 

                             CRuntimeClass* m_pViewClass;   // class for creating new views 

                             CString m_strDocStrings;       // 'n' separated names 

                     

返回目录 上一页 下一页 回到顶部 0 0

你可能喜欢的