單文檔、多文檔淺析 [一]


廢話不多說,直切主題。(以下的示例說明均以MDI作為敘述)

整個程序就相當於一個 文檔模板[CSingleDocTemplate/CMultiDocTemplate]列表,單文檔就是只有一個模板,多文檔就是有多個模板。

一個模板就包括:菜單[Menu]、文檔[Doc]、框架[Frame]、視圖[View]

注意,他們是一個整體。

看一下代碼:

CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_MDI_TETYPE, // 菜單資源ID RUNTIME_CLASS(CMDI_testDoc), RUNTIME_CLASS(CChildFrame), // custom MDI child frame
 RUNTIME_CLASS(CMDI_testView)); AddDocTemplate(pDocTemplate); // 放到模板列表中

當使用VC自動生成的代碼時,編譯運行,使用菜單“開始”->“新建”,會從模板列表中選擇一個模板進行創建一個“整體”,最初的話,會自動生成一個新的窗口,因為最初只有一個文檔模板(“整體”),所以,它自動就生成了一個。注意菜單ID,它是子框架的菜單,它與ChildFrame綁定在一起了。我們可以通過關閉所有的View窗口,就可以觀察到菜單改變了,MainFrame主框架和ChildFrame在默認的情況下,它們的菜單是不同的。

請做試驗:添加一個菜單,響應該菜單函數,代碼就是創建一個新的模板,並加入到列表:

CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_MDI_TETYPE, RUNTIME_CLASS(CMDI_testDoc), RUNTIME_CLASS(CChildFrame), // custom MDI child frame
 RUNTIME_CLASS(CMDI_testView)); AddDocTemplate(pDocTemplate);

再通過“開始”->“新建”,這個時候,你會不會發現,這個時候,就會有兩個模板供你選擇了,因為你已經又創建了一個模板。如下圖:

 

說完了他們一個整體性,接下來,我們就來說說一個整體中,各個部件的關系。

1)框架 (Frame)是視圖和文檔的載體,視圖是一個窗口,文檔則不是窗口,視圖是要顯示在框架中的。我們看一下窗口父子關系:

從上面這兩幅圖對比,可以看出,視圖“sfdjk”的父窗口是“MDIClient”即是類CChildFrame[它從CMDIClientWnd派生出來]的對象。

2)視圖是顯示文檔數據的窗口。這里可以看出,文檔負責管理數據,視圖負責將文檔中的數據顯示出來。我們可以看下視圖OnDraw的代碼:

void CMDI_testView::OnDraw(CDC* pDC) { CMDI_testDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here
}

通過GetDocument就獲取了文檔的指針,然后就能去文檔中取數據,並在OnDraw中顯示出來。我們要知道的是,視圖View是有一個文檔Document的指針的,這便是對應關系了。[文檔並不需要一個視圖指針,因為數據便是數據,它不需要去關心誰去顯示它,但是事實上,它保存有與它關聯的視圖指針]

很多時候,我們一個文檔可以會包含有多份不同類別的數據,而又想用不同的窗口顯示不同類別的數據,這個時候,可以創建多個視圖,一個文檔是可以包含多個視圖的。然后在程序中處理好視圖的切換即可。我們創建一個新的視圖時,如何與文檔關聯起來呢?見代碼[主框架中,而非子框架中]:

// 文檔和視圖關聯
 CDocument* m_pDoc = ((CFrameWnd*)m_pMainWnd)->GetActiveDocument(); // 這里為什么要獲取活動的文檔呢?
// 因為主框架有可能含有多個模板,就有可能有多個文檔[因為一個模板有一個文檔就足夠了,多出的文檔有可能是其它模板的]
// 所以要獲取活動的文檔 CCreateContext context; context.m_pCurrentDoc
= m_pDoc; // 創建視圖 UINT nIDFORANOTHERVIEW = AFX_IDW_PANE_FIRST + 1; CRect rect; m_pAnotherView->Create(
  NULL,
  NULL,
  WS_CHILD,
  rect,
  ((CFrameWnd*)m_pMainWnd)->GetActiveFrame (),
  nIDFORANOTHERVIEW,
  &context);

通過 CCreateCContext對象進行關聯。注意:因為框架是視圖和文檔的載體,所以框架有必要提供接口:獲取活動文檔、獲取活動視圖 [這里要注意,文檔和視圖雖然是對應關系,或者說有一定的包含關系,但它們並不能互相管理對方,它們只能由框架(Frame)進行統一管理]。

視圖既然是顯示在框架上的,那二者又如何關聯起來呢?見代碼:

CChildFrame * pFrm = new CChildFrame();// 框架可以是你新建或者定制的框架類
 CCreateContext context; context.m_pNewViewClass = RUNTIME_CLASS(CDemoView);// 視圖可以是你想顯示的視圖 // context.m_pCurrentDoc = m_pDoc;// m_pDoc 就是你要關聯到的文檔對象 // 也可以進行文檔的關聯
 pFrm->LoadFrame(IDR_TEST2TYPE,WS_CHILD|WS_OVERLAPPEDWINDOW, this, &context);// 菜單資源你可以修改
 pFrm->ShowWindow(SW_SHOW);// 顯示窗口
 pFrm->InitialUpdateFrame(NULL,true);// 調用視圖的 OnInitialUpdate ()和框架的 ActiveFrame (),你可以在這里設置窗口的標題 

 最后來說一下他們之間的關系。

Frame框架可以:

1)獲取活動的Frame框架[如果沒有子框架,就返回它自己]

2)獲取活動的文檔

2)獲取/設置活動的視圖

 

Document文檔可以:

1)獲取Frame框架

2)增加/刪除視圖

3)更新視圖

4)設備所有從該文檔生成的Frame框架的標題

 

View視圖可以:[就它最可憐]

1)獲取它所關心的文檔

 

 參考資料:http://blog.163.com/hzxjtx@126/blog/static/356533742009121105752954/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM