盾怪网教程:是一个免费提供流行杀毒软件教程、在线学习分享的学习平台!

文档/视图结构中的各个局部是怎么联系到一起的

时间:2024/12/25作者:未知来源:盾怪网教程人气:

[摘要]OFN_FILEMUSTEXIST, TRUE, NULL)) return; // open cancelled AfxGetApp()->OpenD...
OFN_FILEMUSTEXIST, TRUE, NULL))

              return; // open cancelled



       AfxGetApp()->OpenDocumentFile(newName);          //实际也是调用文档模板的同名函数

}

(二)文档模板与文档之间的联系:

        从上面看出应用程序对象对文件的新建和打开是依靠文档模板的OpenDocumentFile函数实现的。MFC的模板类是用来联系文档类、视类和框架类的,在它的构造函数就需要这三者的信息:

CDocTemplate ( UINT nIDResource, CRuntimeClass* pDocClass, CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass );

构造函数利用后三个参数为它的三个CruntimeClass*类型的保护成员赋值:

       m_pDocClass = pDocClass;

       m_pFrameClass = pFrameClass;

       m_pViewClass = pViewClass;

    文档模板分为单文档模板和多文档模板两种,这两个模板的实现是不同的,除了上面的三个成员,内部有彼此不相同的但是很重要的成员变量。对于多文档模板:CPtrList m_docList;,单文档模板:CDocument* m_pOnlyDoc;。它们都有一个成员函数AddDocument,分别各自的成员进行赋值操作,而在它们的父类的CDocTemplate中则是为它所添加的文档的m_pDocTemplate变量赋值为模板自己的地址:

void CDocTemplate::AddDocument(CDocument* pDoc)

{

       ASSERT_VALID(pDoc);

       ASSERT(pDoc->m_pDocTemplate == NULL);   

       pDoc->m_pDocTemplate = this;

}

由于单文档模板只能拥有一个文档,所以它只是维护一个指向自己所拥有的模板的指针:m_pOnlyDoc,AddDocument函数就是要为这个成员赋值:

void CSingleDocTemplate::AddDocument(CDocument* pDoc)

{

                ......

       CDocTemplate::AddDocument(pDoc);

       m_pOnlyDoc = pDoc;

}
由于多文档模板可以拥有多个文档,所以它要维护的是包含它所打开的所有文档的指针的链表,所以它的AddDocument的实现为:

void CMultiDocTemplate::AddDocument(CDocument* pDoc)

{

                ......

       CDocTemplate::AddDocument(pDoc);

       m_docList..AddTail(pDoc);

}
    模板通过m_pOnlyDoc(单文档)或记住了自己所拥有的所有的模板的指针,并通过GetFirstDocPosition和GetNextDoc函数可以实现对它所拥有的文档的访问,同时使文档记住了自己所属文档模板的指针,同时文档提供了GetDocTemplate()函数可以取得它所属的模板。

对AddDocument函数的调用主要是发生在另一个成员函数CreateNewDocument里,它的作用是创建一个新的文档:

CDocument* CDocTemplate::CreateNewDocument()

{

       if (m_pDocClass == NULL)

       {

         ……

       }

       CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject();

    ……

       AddDocument(pDocument);

       return pDocument;

}

CreateNewDocument函数主要利用文档类的运行时指针的函数CreateObject创建一个新文档对象,并利用AddDocument将其指针赋給相关的成员,留做以后使用。

    在应用程序的OnFileNew和OnFileOpen函数都使用了模板的OpenDocumentFile函数,而且在实际编程的时候也大都使用这个函数。在MSDN的文档说这个函数当参数不为NULL的时候打开文件,否则就用上面所说的CreateNewDocument函数创建一个新文档,那么它是如何实现的呢?

CDocument* CSingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,

       BOOL bMakeVisible)

{

       CDocument* pDocument = NULL;

       CFrameWnd* pFrame = NULL;

       BOOL bCreated = FALSE;      // => doc and frame created

       BOOL bWasModified = FALSE;

    //如果已经有打开的文档,就会询问否保存文件

       if (m_pOnlyDoc != NULL)

       {

              pDocument = m_pOnlyDoc;

              if (!pDocument->SaveModified())

                     return NULL;      



              pFrame = (CFrameWnd*)AfxGetMainWnd();

                                ......

       }

    //创建新文件

       else

       {

              pDocument = CreateNewDocument();

              ASSERT(pFrame == NULL);     

              bCreated = TRUE;

       }

                ......

    //如果第一次创建文档则也要创建框架窗口。

       if (pFrame == NULL)

       {

              ASSERT(bCreated);



              // create frame - set as main document frame

              BOOL bAutoDelete = pDocument->m_bAutoDelete;

              pDocument->m_bAutoDelete = FALSE;

              pFrame = CreateNewFrame(pDocument, NULL);

              pDocument->m_bAutoDelete = bAutoDelete;

                                ......

       }



       if (lpszPathName == NULL)

       {

              // 为新文档设置默认标题

              SetDefaultTitle(pDocument);

        ……

      //一般的时候重载OnNewDocument初始化一些数据,如果返回FALSE,表示初始化失//败,销毁窗口。

              if (!pDocument->OnNewDocument())

              {

                                                ......

                     if (bCreated)

                            pFrame->DestroyWindow();    // will destroy document

                     return NULL;

              }

       }

       else

       {

              CWaitCursor wait;



              // open an existing document

              bWasModified = pDocument->IsModified();

              pDocument->SetModifiedFlag(FALSE);

              //OnOpenDocument函数重新初始化文档对象

              if (!pDocument->OnOpenDocument(lpszPathName))

              {

                     if (bCreated)

                     {

                //新建文档的情况

                            pFrame->DestroyWindow();    

                     }

                     else if (!pDocument->IsModified())

                     {

                            // 文档没有被修改,恢复原来文档的修改标志

                            pDocument->SetModifiedFlag(bWasModified);

                     }

                     else

                     {

                            // 修改了原始的文档

                            SetDefaultTitle(pDocument);



                            if (!pDocument->OnNewDocument())

                            {

                                   TRACE0("Error: OnNewDocument failed after trying to open a document - trying to continue.\n");

                            }

                     }

                     return NULL;        // open failed

              }

              pDocument->SetPathName(lpszPathName);

       }



       CWinThread* pThread = AfxGetThread();

       if (bCreated && pThread->m_pMainWnd == NULL)

       {

              pThread->m_pMainWnd = pFrame;

       }

       InitialUpdateFrame(pFrame, pDocument, bMakeVisible);



       return pDocument;

}

以下是多文档模板的OpenDocumentFile的实现

CDocument* CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,

       BOOL bMakeVisible)

{

       //新建一个文档对象

       CDocument* pDocument = CreateNewDocument();

……



       BOOL bAutoDelete = pDocument->m_bAutoDelete;

       pDocument->m_bAutoDelete = FALSE;   

       CFrameWnd* pFrame = CreateNewFrame(pDocument, NULL);

       pDocument->m_bAutoDelete = bAutoDelete;

……



       if (lpszPathName == NULL)

    //当是新建的时候

       {

              SetDefaultTitle(pDocument);



              // avoid creating temporary compound file when starting up invisible

              if (!bMakeVisible)

                     pDocument->m_bEmbedded = TRUE;



              if (!pDocument->OnNewDocument())

              {

                     pFrame->DestroyWindow();

                     return NULL;

              }



              m_nUntitledCount++;

       }

       else

       {

              // 打开一个已经存在的文件

              CWaitCursor wait;

              if (!pDocument->OnOpenDocument(lpszPathName))

              {

                     // user has be alerted to what failed in OnOpenDocument

                     TRACE0("CDocument::OnOpenDocument returned FALSE.\n");

                     pFrame->DestroyWindow();

                     return NULL;

              }

              pDocument->SetPathName(lpszPathName);

       }



       InitialUpdateFrame(pFrame, pDocument, bMakeVisible);

       return pDocument;

}

    从上面看出模板类的OpenDocumentFile函数里,利用CreateNewDocument对象使文档对象与模板对象建立了联系,利用了CreateNewFrame函数使框架窗口与文档、视图、模板发生了联系:



CFrameWnd* CDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther)

{

       if (pDoc != NULL)

              ASSERT_VALID(pDoc);



       ASSERT(m_nIDResource != 0); // 必须有资源ID

       CCreateContext context;

       context.m_pCurrentFrame = pOther;

       context.m_pCurrentDoc = pDoc;

       context.m_pNewViewClass = m_pViewClass;

       context.m_pNewDocTemplate = this;



       if (m_pFrameClass == NULL)

       {

           ……

       }

       CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();

       if (pFrame == NULL)

       {

        ……

              return NULL;

       }

       ASSERT_KINDOF(CFrameWnd, pFrame);



       if (context.m_pNewViewClass == NULL)

              TRACE0("Warning: creating frame with no default view.\n");



       if (!pFrame->LoadFrame(m_nIDResource,

                     WS_OVERLAPPEDWINDOW

关键词:文档/视图结构中的各个局部是如何联系到一起的




Copyright © 2012-2018 盾怪网教程(http://www.dunguai.com) .All Rights Reserved 网站地图 友情链接

免责声明:本站资源均来自互联网收集 如有侵犯到您利益的地方请及时联系管理删除,敬请见谅!

QQ:1006262270   邮箱:kfyvi376850063@126.com   手机版