動(dòng)態(tài)切分窗口:
動(dòng)態(tài)切分窗口不能包含多于4個(gè)的窗格,要想得到4個(gè)以上的窗格,可以使用靜態(tài)切分窗口。動(dòng)態(tài)切分窗口中的幾個(gè)窗格通常使用的是同一個(gè)視圖類(lèi)。
創(chuàng )建動(dòng)態(tài)切分窗口的方式共有3種:
1、在創(chuàng )建應用程序時(shí),利用應用程序向導AppWizard的選項設置切分窗口
2、在創(chuàng )建了應用程序之后,通過(guò)添加組件對窗口進(jìn)行切分
3、通過(guò)手動(dòng)添加代碼編程的方式
使用AppWizard創(chuàng )建動(dòng)態(tài)切分:
在MFC AppWizard Step 4 of 6對話(huà)框中,單擊Advanced按鈕,彈出Advanced Options對話(huà)框,選擇Window Styles選項卡,選中該頁(yè)的Use split window檢查框。
使用Splitter Bar組件:
選擇Project|Add To Project|Components and Controls...菜單,彈出Components and Controls Gallery對話(huà)框。雙擊Visual C++ Components目錄,選擇Splitter Bar項,插入Splitter Bar組件。
運行程序,打開(kāi)【查看】菜單或者是【窗口】菜單,找不到前面使用AppWizard添加動(dòng)態(tài)切分時(shí)的【分隔】菜單項。說(shuō)明Splitter Bar組件的方式并沒(méi)有添加相應的菜單項,程序員可以自己添加上去。
注意:菜單的Caption(標題)可以隨便設定,但注意菜單項的ID必須是ID_WINDOW_SPLIT。ID_WINDOW_SPLIT是系統預先指定的,程序員一般不需要對此命令I(lǐng)D添加命令消息處理函數,就可以實(shí)現分隔,因為MFC應用程序框架中已經(jīng)對該命令I(lǐng)D的消息進(jìn)行了處理。
手動(dòng)添加代碼:
1、在框架窗口類(lèi)(對單文檔為主框架窗口,對多文檔為子框架窗口)中聲明一個(gè)CSplitterWnd類(lèi)的成員變量m_wndSplitter
2、使用ClassWizard為框架窗口類(lèi)添加OnCreateClient函數
注意:這里使用ClassWizard是重寫(xiě)父類(lèi)的虛函數,而不是添加消息處理
3、在OnCreateClient函數中調用CSplitterWnd類(lèi)的成員函數Create產(chǎn)生動(dòng)態(tài)切分
4、為應用程序添加一個(gè)ID為ID_WINDOW_SPLIT的菜單項
CSplitterWnd切分窗口類(lèi):
CSplitterWnd的成員函數中,有3個(gè)使用非常頻繁
1、Create函數
創(chuàng )建一個(gè)動(dòng)態(tài)的切分窗口
2、CreateStatic函數
創(chuàng )建一個(gè)靜態(tài)的切分窗口
3、CreateView函數
為靜態(tài)切分窗口創(chuàng )建視圖窗口。在框架顯示一個(gè)靜態(tài)切分窗口之前,該窗口的所有視圖窗格都必須已被創(chuàng )建好。當動(dòng)態(tài)切分窗口時(shí),此函數被框架窗口自動(dòng)調用。
靜態(tài)切分窗口:
靜態(tài)切分窗口是指在窗口創(chuàng )建時(shí),切分窗口的窗格就已經(jīng)創(chuàng )建好了,且窗格的數量和順序不會(huì )改變。最多可以支持16行×16列的窗口(即256個(gè)窗格),但是必須在應用程序中創(chuàng )建窗格,而且不同的窗口往往使用不同的視圖類(lèi)。
創(chuàng )建靜態(tài)切分的步驟:
1、在框架窗口類(lèi)中聲明一個(gè)CSplitterWnd類(lèi)的成員變量m_wndSplitter
2、使用ClassWizard為框架窗口類(lèi)添加OnCreateClient函數
3、在OnCreateClient函數中調用CSplitterWnd::CreateStatic產(chǎn)生靜態(tài)切分
4、在OnCreateClient函數中調用CSplitterWnd::CreateView產(chǎn)生每個(gè)切分的視圖窗口
為2DCAD應用程序添加靜態(tài)切分功能:
1、聲明切分窗口類(lèi)對象m_wndSplitter
為主框架窗口類(lèi)CMainFrame添加保護成員變量m_wndSplitter,代碼如下:
2、在框架窗口類(lèi)中添加OnCreateClient函數
打開(kāi)ClassWizard,選中MessageMaps選項卡,在Class name中選擇CMainFrame類(lèi),在ObjectIDs列表中選擇CMainFrame,在Message列表框中雙擊OnCreateClient項,為框架窗口添加OnCreateClient函數。
3、使用CreateStatic產(chǎn)生靜態(tài)切分
在OnCreateClient函數中添加如下代碼,就可以產(chǎn)生1×2的靜態(tài)切分窗口:
4、使用CreateView產(chǎn)生每個(gè)視圖窗口
當用戶(hù)建立一靜態(tài)切分窗口時(shí),應當同時(shí)建立窗口內的所以區域??梢栽贠nCreateClient函數中添加如下代碼來(lái)為第一行第一列的窗格產(chǎn)生視圖:
其中,第3個(gè)參數,視圖類(lèi)的執行期類(lèi)CRuntimeClass指針,可以用宏RUNTIME_CLASS來(lái)獲得。
注意:(1)必須為每一個(gè)靜態(tài)切分窗口創(chuàng )建視圖窗口,不能漏掉一個(gè)
#include "2DCADDoc.h"
#include "2DCADView.h"
//
最后,完整的CMainFrame::OnCreateClient函數代碼如下:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
//
}
這時(shí),用戶(hù)在一個(gè)視圖中所作的修改還不能立刻反映到其他視圖窗口中,還應添加相應的通知視圖重畫(huà)的代碼。
5、通知視圖重畫(huà)
文檔類(lèi)有一個(gè)名為UpdateAllViews的函數,可以在文檔數據發(fā)生改變時(shí)通知所有的視圖窗口重畫(huà)。
在視圖類(lèi)的OnLButtonDown函數中每個(gè)調用SetModifiedFlag函數的后面立即調用UpdateAllViews的函數,代碼如下:
...
...
向當前工程中插入新類(lèi)的兩種方式:
1、使用New Class對話(huà)框添加新類(lèi)
(1)MFC ClassWizard中的New Class對話(huà)框
使用ClassWizard對話(huà)框中的Add Class...按鈕下的New...菜單項可以打開(kāi)MFC ClassWizard對話(huà)框下的New Class對話(huà)框。這個(gè)對話(huà)框用來(lái)向當前工程中添加派生自MFC類(lèi)庫的新類(lèi)。
(2)通用的New Class對話(huà)框
單擊菜單命令I(lǐng)nsert|New Class...可以打開(kāi)一個(gè)通用的New Class對話(huà)框。實(shí)際上通用的New Class對話(huà)框相當于包含了3個(gè)對話(huà)框,用于產(chǎn)生幾乎所有不同的類(lèi)。
2、使用插入包含類(lèi)定義的文件到當前工程中
(1)將所需類(lèi)的.h、.cpp文件復制到目標工程目錄下
(2)打開(kāi)目標工程,單擊Project|Add To Project|Files...菜單項插入所需類(lèi)的.h、cpp文件到目標工程中
(3)在所需類(lèi)的.cpp文件中,去掉包含原來(lái)的工程的頭文件語(yǔ)句(比如2DCAD.h),添加包含目標工程的頭文件語(yǔ)句(比如Mut.h)
添加新的視圖類(lèi):
為2DCAD工程添加一個(gè)新的視圖類(lèi)CTextView,單擊Insert|New Class...菜單項,在New Class對話(huà)框中確保Class type中選擇的是MFC Class,在Name編輯框中輸入CTextView,在Base class下拉列表中指定基類(lèi)為CEditView。
添加了新的視圖類(lèi)之后,就可以在框架窗口的OnCreateClient函數中調用CreateView函數時(shí)使用這個(gè)新視圖類(lèi)了。接下來(lái)使用CTextView作為靜態(tài)切分窗口中第二個(gè)窗格的視圖類(lèi),在OnCreateClient函數中修改創(chuàng )建第二個(gè)窗口視圖的代碼如下:
由于使用到了新的視圖類(lèi),因此,應該在MainFrm.cpp文件的開(kāi)始部分添加包含CTextView類(lèi)頭文件的代碼:
#include "TextView.h"
注意:CEditView封裝了編輯框的功能,因此,如果要編寫(xiě)文字處理軟件,可以使用CEditView作為視圖基類(lèi)。CEditView最多支持64K的文本,如果需要支持更豐富的文本,可以使用CRichEditView作為視圖基類(lèi),但要包含頭文件afxrich.h。
表單視圖類(lèi)CFormView:
CFormView就是可以在其中包含許多控件的視圖基類(lèi)。這個(gè)類(lèi)也像CDialog對話(huà)框類(lèi)一樣,封裝了數據交換功能。甚至可以將CFormView理解為作為視圖的對話(huà)框。
1、創(chuàng )建對話(huà)框模板資源
(1)添加對話(huà)框模板,ID為IDD_FORMVIEW
(2)修改屬性
在Style選項卡中,設置Style選項為Child,Border選項為None,并去掉對Title Bar復選框的勾選。
注意:由于視圖類(lèi)是一個(gè)子窗口,因此,必須設置Child選擇,否則程序不能正常運行。
(3)添加控件
刪掉默認的OK和Cancel按鈕,依次添加一個(gè)靜態(tài)文本、一個(gè)分組框和4個(gè)單選按鈕,同時(shí)為第一個(gè)單選按鈕添加上Group屬性。
注意:對一組單選按鈕來(lái)說(shuō),只需要對該組的第一個(gè)單選按鈕設置Group屬性就可以了。如果不設置Group屬性,就無(wú)法添加對應的成員變量。
2、產(chǎn)生CFormView的派生類(lèi)
(1)使用ClassWizard為IDD_FORMVIEW對話(huà)框模板資源添加一個(gè)名為CColorForm的視圖類(lèi),注意選擇基類(lèi)為CFormView
(2)在Member Variables選項卡中為IDC_RADIO1添加一個(gè)名為m_nColor的整型成員變量
注意:對一組單選按鈕只能對帶有Group屬性的按鈕增加一個(gè)成員變量,并且這個(gè)成員變量必須是int型。0表示選擇第一個(gè),依次類(lèi)推,-1表示未選擇。
在CColorForm構造函數中令成員變量m_nColor的初始值為0,表示選擇第一項。
3、修改切分窗口的視圖類(lèi)
打開(kāi)OnCreateClient函數,修改創(chuàng )建第二個(gè)窗口視圖的代碼如下:
由于使用到了新的視圖類(lèi),因此,應該在MainFrm.cpp文件的開(kāi)始部分添加包含CColorForm類(lèi)頭文件的代碼:
#include "ColorForm.h"
可以像處理無(wú)模式對話(huà)框那樣,在表單視圖類(lèi)中添加相應的消息處理函數。
一個(gè)多文檔多視圖的綜合示例:
下面綜合前面的知識,創(chuàng )建一個(gè)包含多文檔、多視圖、動(dòng)態(tài)切分、三叉靜態(tài)切分以及可以支持多種文檔類(lèi)型的綜合示例。
支持多種文檔類(lèi)型:
在MFC應用程序中,要增加附加的文檔類(lèi)型,大致可分為以下幾步:
1、使用ClassWizard添加新的文檔類(lèi)、子框架窗口類(lèi)以及視圖類(lèi)(如果需要的話(huà))
2、利用資源編輯器為新的文檔類(lèi)型添加字符串資源
3、利用資源編輯器添加附加的圖標和菜單資源
4、創(chuàng )建新的文檔模板對象并加入到應用程序中
5、完成文檔的序列化以及視圖的顯示交互工作
下面為Mut添加支持多文檔類(lèi)型的功能(此時(shí)Mut本身是一個(gè)空的具有動(dòng)態(tài)切分窗口的多文檔程序):
1、添加新的文檔類(lèi)、子框架窗口類(lèi)和視圖類(lèi)
一般來(lái)說(shuō),一個(gè)新的文檔類(lèi)型所需要的文檔類(lèi)、外邊框窗口類(lèi)和視圖類(lèi)有可能都不同于已經(jīng)存在的類(lèi)的,但也可能和現存的類(lèi)相同(比如使用相同的子框架窗口)。因此,根據不同的需要會(huì )添加不同的類(lèi)。這里,首先只添加一個(gè)新的視圖類(lèi)和子框架窗口類(lèi),而文檔類(lèi)則使用原來(lái)的類(lèi)。
注意:多種文檔類(lèi)型的各個(gè)文檔類(lèi)一般是不同的
(1)添加新的視圖類(lèi)的方法可以參加《向當先工程中插入新類(lèi)的兩種方式》中的第二種方式,插入2DCAD程序中所用到的可以輸入簡(jiǎn)單的文本的CTextView類(lèi)。
(2)添加新的子框架窗口類(lèi)CTextFrame,基類(lèi)選擇為CMDIChildWnd。具體方法參加向當先工程中插入新類(lèi)的兩種方式》中的第一種方式。
2、利用資源編輯器為新的文檔類(lèi)型添加字符串資源
參照Mut應用程序已經(jīng)存在的文檔模板字符串資源IDR_MUTTYPE,在字符串編輯器中增加一個(gè)新的字符串資源,指定ID為IDR_TEXTTYPE,內容為:
\nText\n文本視圖窗口\nText Files(*.txt)\n.txt\nTextDocument\nText Document
可見(jiàn)文檔模板字符串包含7個(gè)由“\n”結尾并分隔的子串,最后一個(gè)字符串后面不需要“\n”。這些子串描述了文檔的類(lèi)型,它們的含義按照順序分別如下:
(1)窗口標題(2)文檔名(3)新建文檔類(lèi)型名(4)過(guò)濾器名(5)文件擴展名(6)文檔類(lèi)型ID(7)注冊文檔類(lèi)型名
3、利用資源編輯器添加附加的圖標和菜單資源
(1)添加一個(gè)ID為IDR_TEXTTYPE的圖標,可以利用畫(huà)圖工具編輯之
(2)添加一個(gè)ID為IDR_TEXTTYPE的菜單,將IDR_MUTTYPE菜單資源下的【文件】、【編輯】、【查看】、【幫助】菜單復制到IDR_TEXTTYPE中。注意:可以使用右鍵菜單中的Insert Copy...,然后再修改。
注意:這些資源的ID必須同第二步中創(chuàng )建文檔模板字符串中所用的ID相同。
4、創(chuàng )建新的文檔模板對象并加入到應用程序中
在應用程序類(lèi)CMutApp的InitInstance函數中,參照應用程序框架生成的代碼,創(chuàng )建另一個(gè)CMultiDocTemplate對象,并用CWinApp::AddDocTemplate成員函數注冊該模板對象。
由于使用到了新的視圖類(lèi)CTextView和新的子框架窗口類(lèi)CTextFrame,因此應該在Mut.cpp文件的開(kāi)始部分包含它們的頭文件:
#include "TextView.h"
#include "TextFrame.h"
注意:此時(shí)Mut程序就包含有兩個(gè)文檔模板對象,可以支持兩種不同的文檔了,但是,它們使用了相同的文檔類(lèi),而實(shí)際應用中應該使用不同的文檔類(lèi)。
5、完成文檔的序列化以及視圖的顯示交互工作
最后,根據用戶(hù)的需要,可以為文檔類(lèi)添加上數據保存以及序列化功能,為視圖類(lèi)添加相應的顯示數據和交換功能。
多文檔的三叉靜態(tài)切分:
這三個(gè)窗口的排列方式類(lèi)似“|—”形狀,所使用的視圖類(lèi)分別類(lèi)似前面2DCAD工程中創(chuàng )建的CColorForm類(lèi)以及Mut工程中創(chuàng )建的CTextView類(lèi)和CMutView類(lèi)。
1、添加新的文檔模板對象
(1)添加新的視圖類(lèi)和子框架窗口類(lèi)
在Mut工程中創(chuàng )建一個(gè)和2DCAD工程中相同的CFormView類(lèi)的派生類(lèi)CColorForm。
注意:可以使用文件復制再插入的方法,還需要將所需的對話(huà)框資源模板以及控件的ID值定義都復制過(guò)來(lái)。
再添加一個(gè)派生自CMDIChildWnd類(lèi)的CThreeFrame類(lèi),作為文檔的外邊框窗口。
(2)編輯資源
添加ID都為IDR_THREETYPE的三個(gè)資源,字符串資源,圖標資源和菜單資源。其中,字符串資源如下:
\nThree\n三叉切分窗口\nThree Files(*.thr)\n.txt\nThreeDocument\nThree Document
(3)創(chuàng )建新的文檔模板對象
在應用程序類(lèi)CMutApp的InitInstance函數中,參照應用程序框架生成的代碼,創(chuàng )建另一個(gè)CMultiDocTemplate對象,并用CWinApp::AddDocTemplate成員函數注冊該模板對象。
由于使用到了新的視圖類(lèi)CColorForm和新的子框架窗口類(lèi)CThreeFrame,因此應該在Mut.cpp文件的開(kāi)始部分包含它們的頭文件:
#include "ColorForm.h"
#include "ThreeFrame.h"
2、添加三叉靜態(tài)切分
(1)在子框架窗口類(lèi)CThreeFrame中添加兩個(gè)CSplitterWnd類(lèi)的保護成員變量m_wndSplitter1和m_wndSplitter2,分別用于產(chǎn)生第一次靜態(tài)切分和第二次靜態(tài)切分。
(2)使用ClassWizard為CThreeFrame添加OnCreateClient成員函數。
(3)改寫(xiě)OnCreateClient成員函數代碼如下:
BOOL CThreeFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
//
}
可見(jiàn)產(chǎn)生第一次切分的方法是,先使用CreateStatic函數產(chǎn)生第一次切分,然后再使用CreateStatic函數對第一次切分所產(chǎn)生的窗口再次切分。
注意:第二次調用CreateStatic函數切分時(shí),函數的參數有些變化:一是父窗口是第一次的切分窗口,二是ID必須是上次切分窗格的ID。
(4)在ThreeFrame.cpp文件的開(kāi)始部分包含下列頭文件:
#include "MutDoc.h"
#include "MutView.h"
#include "TextView.h"
#include "ColorForm.h"

