摘要:本文通過一個程序?qū)嵗枋隽嗽赩C 6.0(vc2008可行)下如何在單文檔程序中通過菜單動態(tài)控制多
個窗體的切換。
一、 引言
我們在編制程序中根據(jù)需求的不同會在程序風格上選擇多文檔、單文檔或是對話框模式
,對于單文檔模式可能是我們使用比較多的,但有時我們想采用單文檔的形式顯示多個不同
的窗體,如作為數(shù)據(jù)庫前臺應(yīng)用程序就會遇到此類問題,數(shù)據(jù)庫由大量的表單組成,而同常
一個窗體內(nèi)只用來顯示一個表單,所以要顯示其他的表單時就要用到切換窗體的技術(shù)了,下
面就通過一個程序說明該技術(shù)的實現(xiàn)方法。
二、 實現(xiàn)技術(shù)
新建一個基于CFormView的單文檔應(yīng)用程序,再添加一個窗體和與之對應(yīng)的基于
CFormView的新視類,然后通過在主框架類里添加控制代碼和菜單控制實現(xiàn)這兩個窗體的動態(tài)
切換,下面就是具體的實現(xiàn)過程:
(一) 用"MFC AppWizard(exe)"建立一個新項目"SwitchForm",并在第二步的創(chuàng)建類型上選
擇為"Single documnet"單文檔模式,第三、四、五、六步均取確省狀態(tài),最后一步選擇
"CFormView"作為視類的基類。點按"完成"按鈕,生成了初始工程"SwitchForm"。
(二) 點選菜單"Insert"、"Resource…",在彈出的"Insert Resource"對話框中"Dialog"樹
里的"IDD_FORMVIEW",點擊"New"按鈕,生成了一個新的窗體,將其ID號改為"IDD_NEXTFORM"。
在原有的窗體上加一個靜態(tài)框"這是第一個窗體";在新建的窗體上也添加一個靜態(tài)框"這是第二
個窗體"。
(三) 在菜單資源的"IDR_MAINFRAME"上添加一級菜單"窗體切換",及其二級菜單"第一個窗
體"、"第二個窗體",其標識號分別為"ID_FIRSTFORM"和"ID_SECONDFORM"。修該"第一個窗體"
的屬性為"Checked",表明程序初始時顯示的是第一個窗體。
(四) 在"ClassView"屬性頁里的"SwitchForm classes"上右鍵,在彈出菜單上選擇
"New Class…",彈出"New Class"對話框,選擇"Dialog ID:"為我們剛添加的新窗體
"IDD_NEXTFORM",選擇"Base class:"為"CFormView",類名取為"CNextFormView",這樣就把第
二個窗體對應(yīng)的視圖類添加到了工程。
(五) 在框架類里添加函數(shù)SwitchToForm():
void CMainFrame::SwitchToForm(int nForm)
{
file://獲取原來的活動窗體的視圖句柄
CView* pOldActiveView = GetActiveView();
file://獲取由"nForm"標識的窗體所對應(yīng)的視圖句柄
CView* pNewActiveView = (CView*) GetDlgItem(nForm);
file://若視圖句柄為空,則創(chuàng)建一新的。
if (pNewActiveView == NULL)
{
if (nForm == IDD_SWITCHFORM_FORM)
pNewActiveView = (CView*)new CSwitchFormView;
if (nForm == IDD_NEXTFORM)
pNewActiveView = (CView*)new CNextFormView;
CCreateContext context;
context.m_pCurrentDoc = pOldActiveView->GetDocument();
pNewActiveView->Create(NULL,NULL,0L,
CFrameWnd::rectDefault,
this,nForm,&context);
pNewActiveView->OnInitialUpdate();
}
file://選擇pNewActiveView為活動窗體
SetActiveView(pNewActiveView);
file://顯示活動窗體,隱藏非活動窗體
pNewActiveView->ShowWindow(SW_SHOW);
pOldActiveView->ShowWindow(SW_HIDE);
int ID;
if(pOldActiveView->GetRuntimeClass() == RUNTIME_CLASS(CSwitchFormView))
ID=IDD_SWITCHFORM_FORM;
if(pOldActiveView->GetRuntimeClass() == RUNTIME_CLASS(CNextFormView))
ID=IDD_NEXTFORM;
file://設(shè)置窗體的ID號
pOldActiveView->SetDlgCtrlID(ID);
pNewActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
RecalcLayout();
}
(六)添加兩個菜單相對應(yīng)的命令響應(yīng)函數(shù)和更新函數(shù)如下:
void CMainFrame::OnFirstform()
{
file://通過IsKindOf函數(shù)確定當前活動窗口是否是第一個窗口,如是,則無須切換,
file://否則將通過SwitchToForm函數(shù)將當前活動窗口切換到"IDD_SWITCHFORM_FORM"
file://標識的第二個窗體。
if (GetActiveView()->IsKindOf(RUNTIME_CLASS(CSwitchFormView)))
return;
SwitchToForm(IDD_SWITCHFORM_FORM);
}
void CMainFrame::OnUpdateFirstform(CCmdUI* pCmdUI)
{
file://通過IsKindOf函數(shù)判斷當前活動窗口是否是第一個窗體,如是則將其選中。
pCmdUI->SetCheck(GetActiveView()->IsKindOf(RUNTIME_CLASS(CSwitchFormView)));
}
void CMainFrame::OnSecondform()
{
if (GetActiveView()->IsKindOf(RUNTIME_CLASS(CNextFormView)))
return;
SwitchToForm(IDD_NEXTFORM);
}
void CMainFrame::OnUpdateSecondform(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(GetActiveView()->IsKindOf(RUNTIME_CLASS(CNextFormView)));
}
然后再在該文件開始處添加對兩個視圖類的引用:
#include "SwitchFormDoc.h"
#include "SwitchFormView.h"
#include "NextFormView.h"
在此須注意:應(yīng)在兩個視類的引用之前添加對文檔類的引用,否則會引起編譯錯誤。另外,由于視
類的構(gòu)造函數(shù)在聲明時都確省的聲明為保護型的,在框架類中無法引用,所以還要將兩個視類的類
聲明改動如下:
class CNextFormView : public CFormView
{
public: file://將protected 改為public.
CNextFormView();
……
};
class CSwitchFormView : public CFormView
{
public: file://將protected 改為public.
CSwitchFormView();
……
};
三、 編譯運行
編譯運行程序,開始時的窗體上有"這是第一個窗體的字樣",菜單也只有"第一個窗體"是被選中的,
當前的活動窗體是第一個窗體;點擊菜單"第二個窗體",視圖中的窗體上的字樣變成了"這是第二 個
窗體",同時選中的菜單也由"第一個窗體"變成了"第二個窗體",實現(xiàn)了通過菜單將窗體進行動態(tài)切換。
總結(jié):此程序中關(guān)鍵的是SwitchToView函數(shù),在此函數(shù)中,程序搜索所有當前文檔的顯示窗口來查找與CruntimeClass變量匹配的視圖類。如果找到,該窗口被激活。通過與之類似的方法,還可以實現(xiàn)在多文檔模式下的單檔(文檔)多視(視圖),通過不同的視圖以不同的方式顯示來自同一份文檔的數(shù)據(jù),以更好的滿足程序的需要。