青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

(轉)文檔/視圖結構中的各個部分是如何聯系到一起的

文檔/視圖結構是MFC中最有特色而又有難度的部分,在這當中涉及了應用、文檔模板、文檔、視圖、MDI框架窗口、MDI子窗口等不同的對象,如果不了解 這些部分之間如何關聯的話,就可能犯錯誤,也就很難編出有水平的文檔/視圖程序。比如我在初學VC編程的時候,為應用程序添加了兩個文檔模板,兩個模板公 用一個文檔類,只是視圖不一樣,期望當一個模板的文檔的視圖改變了文檔后,調用UpdateAllViews后也能更新另一個文檔模板的視圖,結果當然是 不行的,原因就是對MFC的文檔/視圖結構沒有深入的了解,了解的最好方法就是閱讀一下MFC的源代碼。下面就是我的筆記:

(一)應用程序對象與文檔模板之間的聯系:

        首先,在應用程序對象中有一個CDocManager指針類型的共有數據成員m_pDocManager,在CDocManager中維護一個 CPtrList類型的鏈表:m_tempateList,它是一個保護成員。InitInstance函數中調用CWinApp:: AddDocTemplate函數,實際上是調用m_pDocManager的AddDocTemplate函數向鏈表m_templateList添加 模板指針。CWinApp提供了GetFirstDocTemplatePosition和GetNextDocTemplate函數實現對 m_templateList鏈表的訪問(實際上是調用了CDocManager的相關函數)。

         在文件操作方面CWinApp提供的最常用的功能是文件的新建(OnFileNew)和打開(OnFileOpen),它也是調用CDocManager 類的同名函數。對于新建,一般的時候在只有一個文檔模板的時候,它新建一個空白的文件;如果有多個文檔模板的時候,它會出現一個對話框提示選擇文檔類型。 它的源代碼如下:

void CDocManager::OnFileNew()

{

       if (m_templateList.IsEmpty())

       {

                                .......

              return;

       }

                //取第一個文檔模板的指針

       CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();

       if (m_templateList.GetCount() > 1)

       {

              // 如果多于一個文檔模板,出現對話框提示用戶去選擇

              CNewTypeDlg dlg(&m_templateList);

              int nID = dlg.DoModal();

              if (nID == IDOK)

                     pTemplate = dlg.m_pSelectedTemplate;

              else

                     return;     // none - cancel operation

       }

                ......

                //參數為NULL的時候OpenDocument File會新建一個文件

       pTemplate->OpenDocumentFile(NULL);

}

打開文件:

void CDocManager::OnFileOpen()

{

       // 出現打開文件對話框

       CString newName;

       if (!DoPromptFileName(newName, AFX_IDS_OPENFILE,

         OFN_HIDEREADONLY | 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函數使框架窗口與文檔、視圖、模板發生了聯系:

posted on 2011-04-17 20:43 蝸牛也Coding 閱讀(501) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


<2010年8月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
2930311234

導航

統計

常用鏈接

留言簿(8)

隨筆檔案(78)

搜索

積分與排名

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            免费欧美在线| 麻豆精品在线播放| 国产精品亚洲美女av网站| 欧美理论在线| 欧美亚韩一区| 国产女主播视频一区二区| 国产伦精品一区二区三区照片91| 国产精品99一区二区| 国产精品欧美日韩一区二区| 国产一区二区精品| 最新高清无码专区| 午夜精品久久久久| 久久久久一区二区| 亚洲国产美女久久久久| 日韩一级成人av| 欧美在线日韩精品| 欧美v亚洲v综合ⅴ国产v| 欧美午夜剧场| 在线观看精品| 亚洲综合大片69999| 六月婷婷一区| 亚洲男人的天堂在线| 久久综合久久综合久久综合| 国产精品久久久99| 亚洲精品综合在线| 久久国产黑丝| 亚洲免费成人av| 久久久久久999| 国产精品女主播在线观看 | 一区二区亚洲精品国产| 99精品国产在热久久婷婷| 久久国产婷婷国产香蕉| 亚洲精品影院在线观看| 久久精视频免费在线久久完整在线看| 欧美日韩三级| 亚洲精品视频在线| 国产一区二区av| 亚洲伦伦在线| 欧美1区2区视频| 亚洲欧美日韩久久精品| 欧美欧美在线| 亚洲人成网站影音先锋播放| 久久久噜噜噜久久久| 亚洲午夜国产成人av电影男同| 另类成人小视频在线| 国产午夜精品福利| 午夜精品视频一区| 在线亚洲美日韩| 欧美日韩精品一区二区三区| 亚洲精品国精品久久99热一| 蜜臀a∨国产成人精品| 亚洲欧美日韩精品综合在线观看| 欧美亚洲成人免费| 亚洲网站视频福利| 亚洲精品你懂的| 久久久噜噜噜久久人人看| 国产亚洲一区二区三区在线观看 | 久久九九免费| 黑人巨大精品欧美一区二区| 久久久一区二区| 久久精品免费播放| 精品动漫一区二区| 老司机久久99久久精品播放免费| 欧美伊人久久久久久午夜久久久久| 国产精品免费看片| 午夜一区不卡| 欧美一区二区免费| 精品va天堂亚洲国产| 欧美成人中文字幕| 欧美日韩国语| 欧美在线观看你懂的| 久久国产精品久久精品国产| 影音国产精品| 亚洲电影下载| 国产精品久久久久久久久免费| 午夜久久电影网| 久久成人精品一区二区三区| 一区二区在线观看视频| 欧美激情精品久久久| 欧美日韩亚洲成人| 久久久久久精| 欧美另类videos死尸| 先锋影音国产精品| 久久综合九色综合欧美就去吻 | 国产精品成人播放| 久久国产成人| 欧美α欧美αv大片| 亚洲在线观看免费| 久久久精品网| 亚洲自拍16p| 免费中文字幕日韩欧美| 欧美激情中文字幕乱码免费| 亚洲欧美日韩综合国产aⅴ| 久久国产精品网站| 日韩亚洲欧美一区二区三区| 亚洲影视综合| 亚洲人成亚洲人成在线观看图片 | 美女国产一区| 亚洲综合三区| 欧美高清在线视频| 久久久久高清| 欧美日韩免费| 免费视频一区二区三区在线观看| 国产精品av久久久久久麻豆网| 久久综合电影一区| 国产精品日韩| 99国产一区二区三精品乱码| 伊人影院久久| 午夜亚洲福利在线老司机| 亚洲精品社区| 久久色在线观看| 欧美在线免费看| 欧美色图麻豆| 亚洲国产一二三| 在线成人h网| 久久高清福利视频| 欧美在线免费观看视频| 欧美调教视频| 99成人免费视频| 亚洲精品一品区二品区三品区| 久久成人国产| 久久精品一区蜜桃臀影院| 国产精品拍天天在线| 一区二区三区高清在线观看| 亚洲精品国产精品乱码不99| 久久久久久久久久久成人| 久久精品亚洲精品国产欧美kt∨| 国产精品久久久久久久久婷婷| 亚洲精品一区在线| 亚洲美女啪啪| 欧美日韩精品免费看| 亚洲精品视频二区| 一区二区三区高清| 欧美日韩直播| 中文成人激情娱乐网| 亚洲欧美日韩综合| 国产精品美女www爽爽爽| 99re在线精品| 亚洲综合国产精品| 国产免费一区二区三区香蕉精| 亚洲在线观看免费| 久久高清国产| 亚洲国产电影| 欧美精品成人一区二区在线观看 | 久久精品综合一区| 激情欧美一区二区三区| 久久久999精品| 欧美成人亚洲成人日韩成人| 亚洲激情欧美| 欧美视频你懂的| 亚洲午夜精品17c| 久久精品视频播放| 怡红院精品视频| 欧美极品一区二区三区| 9i看片成人免费高清| 性欧美暴力猛交另类hd| 久久婷婷影院| 亚洲国产精品毛片| 亚洲图片在区色| 国内伊人久久久久久网站视频| 久久久久久久91| 亚洲精品日产精品乱码不卡| 亚洲综合色视频| 在线精品在线| 国产精品国内视频| 久久人人爽人人爽爽久久| 欧美激情欧美狂野欧美精品| 一区二区三区**美女毛片| 国产欧美综合一区二区三区| 麻豆国产精品一区二区三区| 一区二区电影免费观看| 毛片精品免费在线观看| 亚洲私拍自拍| 在线观看福利一区| 欧美午夜精品伦理| 久久在线免费| 亚洲综合电影| 亚洲人线精品午夜| 久久久一区二区三区| 亚洲视频你懂的| 亚洲电影免费在线观看| 国产精品日韩电影| 欧美精品一区二区三区蜜臀| 久久9热精品视频| 日韩视频一区二区三区| 另类天堂av| 久久精彩视频| 亚洲欧美一区二区三区久久| 亚洲国产天堂久久国产91| 国产婷婷色一区二区三区| 欧美日韩情趣电影| 欧美sm视频| 久久在线91| 久久精品免费播放| 亚洲欧美在线看| 一区二区日韩| 99精品视频一区二区三区| 亚洲日本成人| 亚洲青涩在线| 亚洲三级视频在线观看|