轉帖|其它|編輯:郝浩|2010-08-11 11:32:09.000|閱讀 1090 次
概述:本文主要深入分析MFC文檔視圖結構,希望對大家有所幫助。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
1 總攬
1.1 MFC文檔視圖結構程序結構總攬
當我們使用MFC AppWizard生成一個MFC程序,選用所有默認的設置(當然也是Multiple Documents,本文討論主要基于Multiple Documents,對于Single Document情況僅以簡單表述提及,皆因后者和前者很多相似相同之處,但前者更為復雜,并且更加常用。),假設你的程序名稱為A ,則你會得到CMainFrame、CChildFrame、CAboutDlg、CADoc、CAView、CAApp 6個類(Single Document 僅少一個CChildFrame類,其余均同)。這些類的具體含義將在后面給出,這里先要給出一個MFC 支持文檔視圖結構程序(以下簡稱App)的主要組成:
1 一個App(對應類CAApp)可以包含多個文檔模版(CDocTemplate),但是MFC AppWizard(無論是SDI還是MDI)都只是默認生成一個。但是在實際開發中一個文檔模版不夠,需要自己手工添加(在后面實際項目例子提供示例)。這個結構是通過MFC中CWinApp的成員變量CDocManager* m_pDocManager實現的,我們的CAApp正是繼承自MFC提供的CWinApp類。
2 CDocManager類則擁有一個指針鏈表CPtrList m_templateList來維護這些文檔模版。這些文檔模版都是在CAApp::InitInstance()中通過AddDocTemplate(pDocTemplate)。
3 CDocTemplate擁有3個成員變量,分別保存著Document、View、Frame的CRuntimeClass指針,另外持有成員變量m_nIDResource,用來指定這個Document顯示時候采用的菜單資源。這4份數據都在CAApp::InitInstance()中CDocTemplate的構造函數中指定。在Document中擁有一個回指CDocTemplate的指針(m_pDocTemplate)。
4 一個文檔可以有多個視圖,由Document中成員變量CPtrList m_ViewList維護。
5 CFrameWnd擁有一個成員變量CView* m_pActiveView指向當前活動的View。
6 CView中擁有一個成員變量CDocument* m_pDocument指向該視圖相關的Document。
[注解]:①MFC SDI/MDI程序默認都默認生成了一個文檔模版,并將這個文檔模版Add到其文檔模版的鏈表中,由于這是MFC默認提供的,因此這個文檔模版會被插入到文檔模版的第一個位置,而MFC也是通過這個文檔模版的特定位置可以確定的。默認情況下,當我們點擊File(Open)/ File(New)的時候,這個文檔模版會被啟用。
于MFC SDI/MDI的知識:
1 文檔的本質:文檔是用來保存數據以及關于數據的處理的,每當MFC SDI/MDI響應File(Open)/ File(New)的時候都會打開一份文檔。文檔可以擁有多個視圖。文檔和視圖的關系可以這樣理解:文檔是被視圖觀察的對象。
2 視圖本質:視圖在Windows中就是一個窗口,也就是一個可視化的矩形區域。視圖是用來表示文檔的數據的。但是每個視圖必需依附于一個框架(SDI中是MainFrame,MDI是ChildFrame)。當然你可以自己去Create一個視圖,并且去顯示它。
3 框架的本質:框架實際是也是一個Windows窗口。但是在框架上可以放置菜單、工具欄、狀態欄等。而視圖則放在框架的客戶區。因此MFC中我們看到的窗口實際上Frame和View共同作用的結果。
4 在某一時刻,程序中只有一個活動的文檔、框架和視圖,即當前的文檔、框架、視圖。
1.2 MFC SDI/MDI各個類之間的互訪
在實際項目開發中用的最多就是各個類之間的互訪問,這里將網絡上和書籍中提到的做了一個總結,也是筆者在實際開發中都用到過的。
2 文檔、視圖、框架之間的關聯
MFC SDI/MDI中的核心就在于文檔、視圖、框架之間的關聯,形成了一個有機的可運作的整體。MFC提供了默認的關聯關系,但是在實際的項目開發中很多時候需要動態進行他們的之間的關聯。
2.1 文檔和視圖間的關聯
使用MFC AppWizard聲稱MFC SDI/MDI程序,在App類的InitInstance()方法中有如下代碼(假設Project名稱均為Test):
1 SDI中
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CTestDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CTestView));
AddDocTemplate(pDocTemplate);
2 MDI中
關于SDI/MDI:
一、SDI一次只能打開一份document(與mutidoctemplate或者SingleDocTeplate無關)
為了顯示這份document,必須配備以下內容:
A、相應的view(可以是多個,比如所切分視圖)
B、 相應的邊框,其實就是mainframe
C、 相應的IDR(比如說標題等
二、MDI一次可以打開多個documents;
A、 當這多個documents是不同類型時,每一類document必須配備相應的view 和邊框(CMidChildwnd),至于怎么配置?由相應的DocTemplate來決定啦!
B、當這多個documents是同一種類型時,只需配備一次即可。
C、程序中只有一份document,但是執行了window->new window時,可以 打開第二個view,并且這個view也有一個邊框midchlldwnd。
SDI只能有一個框架窗口類和一個框架窗口對象(CMainFrame:CFrameWnd);
MDI應用程序有兩個框架窗口類,并且可以有多個框架對象,即:
CMainFrame:CMDIFrameWnd 只有一個對應對象 有菜單和控制欄 無視圖
CChildFrame:CMDIChildWnd 每個子窗口對應一個對象 無菜單和控制欄 有視圖
對象的創建:CMainFrame對象在應用程序類的InitInstance函數中(即CMainFrame* pMainFrame = new CMainFrame;);CChildFrame對象是當新的子窗口被打開時,由應用程序框架來創建(MDI中InitInstance函數中ProcessShellCommand的調用用以創建子框架)。
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(
IDR_TESTTYPE,
RUNTIME_CLASS(CTestDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CTestView));
AddDocTemplate(pDocTemplate);
這里通過CDocTemplate(無論是SDI中的CSingleDocTemplate還是MDI中的CMultiDocTemplate)的構造
函數,將文當、視圖和框架(SDI中與主框架,MDI中與自框架)關聯在一起了,形成了一個整體。
使用CCreateContext類進行他們之間的關聯,具體實現為:
m_pAnotherView = new CAnotherView(); //new 一個新的視圖,可以改為你新建的視圖
//獲取一個已有的文檔,可以是你新建的文檔
CDocument* m_pDoc = ((CFrameWnd*)m_pMainWnd)->GetActiveDocument();
//文檔和視圖關聯
CCreateContext context;
context.m_pCurrentDoc = m_pDoc;
//創建視圖
UINT m_IDFORANOTHERVIEW = AFX_IDW_PANE_FIRST + 1; //創建視圖的ID號,你可以自己設置
CRect rect;
m_pAnotherView->Create(NULL,NULL,WS_CHILD,rect,m_pMainWnd,m_IDFORANOTHERVIEW,&context);
2.2 框架和視圖的關聯
在第一部分分析我們知道,框架和視圖其實都是windows窗口,不過框架提供了菜單、標題欄、狀態欄等資源,而視圖則只是一個矩形區域。MFC程序中視圖決定大多數時候要依附于一個框架(SDI中的MainFrame和MDI中的子框架窗口),可以這樣理解,框架相當于一個窗口容器(當然它本身也是一個windows窗口),而視圖則正好是放置在框架內客戶區域的內容。
上面已經分析到,我們看到MFC的窗口實際上框架和視圖的一個結合體,我們并不一定要提供文檔、視圖、框架的整個體系,我們只需要框架和視圖的結合即可實現窗口的顯示,這就要經過兩個步驟實現:第一步將視圖和框架關聯,第二步顯示框架(也就是一個windows窗口的顯示)。以下給出框架和視圖關聯的具體實現:
CChildFrame* pFrm = new CChildFrame(); //框架可以是你新建或者定制的框架類
CCreateContext context;
context.m_pNewViewClass = RUNTIME_CLASS(CDemoView); //視圖可以是你想顯示的視圖
pFrm->LoadFrame(IDR_TEST2TYPE,WS_CHILD |
WS_OVERLAPPEDWINDOW,this,&context); //菜單資源你可以修改
pFrm->ShowWindow(SW_SHOW); //顯示窗口
pFrm->InitialUpdateFrame(NULL,true); //調用視圖的OnInitialUpdate()和框架的ActiveFrame(),你可以在這里設置窗口的標題
當然你可以在這里添加視圖和文檔的關聯,具體實現是添加以下代碼:
context.m_pCurrentDoc = m_pDoc; // m_pDoc就是你要關聯到的文檔對象
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:網絡轉載