在單文檔程式中動態切換多個表單
摘要:本文通過一個程式執行個體描述了在VC++6.0下如何在單文檔程式中通過菜單動態控制多個表單的切換。
一、 引言
我們在編製程式中根據需求的不同會在程式風格上選擇多文檔、單文檔或是對話方塊模式,對於單文檔模式可能是我們使用比較多的,但有時我們想採用單文檔的形式顯示多個不同的表單,如作為資料庫前台應用程式就會遇到此類問題,資料庫由大量的表單組成,而同常一個表單內只用來顯示一個表單,所以要顯示其他的表單時就要用到切換表單的技術了,下面就通過一個程式說明該技術的實現方法。
二、 實現技術
建立一個基於CFormView的單文檔應用程式,再添加一個表單和與之對應的基於CFormView的新視類,然後通過在主架構類裡添加控制碼和菜單控制實現這兩個表單的動態切換,下面就是具體的實現過程:
(一) 用 "MFC AppWizard(exe) "建立一個新項目 "SwitchForm ",並在第二步的建立類型上選擇為 "Single documnet "單文檔模式,第三、四、五、六步均取確省狀態,最後一步選擇 "CFormView "作為視類的基類。點按 "完成 "按鈕,產生了初始工程 "SwitchForm "。
(二) 點選菜單 "Insert "、 "Resource… ",在彈出的 "Insert Resource "對話方塊中 "Dialog "樹裡的 "IDD_FORMVIEW ",點擊 "New "按鈕,產生了一個新的表單,將其ID號改為 "IDD_NEXTFORM "。在原有的表單上加一個靜態框 "這是第一個表單 ";在建立的表單上也添加一個靜態框 "這是第二個表單 "。
(三) 在菜單資源的 "IDR_MAINFRAME "上添加一級菜單 "表單切換 ",及其二級菜單 "第一個表單 "、 "第二個表單 ",其標識號分別為 "ID_FIRSTFORM "和 "ID_SECONDFORM "。修該 "第一個表單 "的屬性為 "Checked ",表明程式初始時顯示的是第一個表單。
(四) 在 "ClassView "屬性頁面裡的 "SwitchForm classes "上右鍵,在快顯功能表上選擇 "New Class… ",彈出 "New Class "對話方塊,選擇 "Dialog ID: "為我們剛添加的新表單 "IDD_NEXTFORM ",選擇 "Base class: "為 "CFormView ",類名取為 "CNextFormView ",這樣就把第二個表單對應的視圖類添加到了工程。
(五) 在架構類裡添加函數SwitchToForm():
void CMainFrame::SwitchToForm(int nForm)
{
// 擷取原來的活動表單的視圖控制代碼
CView* pOldActiveView = GetActiveView();
// 擷取由 "nForm "標識的表單所對應的視圖控制代碼
CView* pNewActiveView = (CView*) GetDlgItem(nForm);
// 若視圖控制代碼為空白,則建立一新的。
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();
}
// 選擇pNewActiveView為活動表單
SetActiveView(pNewActiveView);
// 顯示活動表單,隱藏非活動表單
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;
// 設定表單的ID號
pOldActiveView-> SetDlgCtrlID(ID);
pNewActiveView-> SetDlgCtrlID(AFX_IDW_PANE_FIRST);
RecalcLayout();
}
(六)添加兩個菜單相對應的命令響應函數和更新函數如下:
void CMainFrame::OnFirstform()
{
// 通過IsKindOf函數確定當前使用中視窗是否是第一個視窗,如是,則無須切換,
// 否則將通過SwitchToForm函數將當前使用中視窗切換到 "IDD_SWITCHFORM_FORM "
// 標識的第二個表單。
if (GetActiveView()-> IsKindOf(RUNTIME_CLASS(CSwitchFormView)))
return;
SwitchToForm(IDD_SWITCHFORM_FORM);
}
void CMainFrame::OnUpdateFirstform(CCmdUI *pCmdUI)
{
// 通過IsKindOf函數判斷當前使用中視窗是否是第一個表單,如是則將其選中。
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 "
在此須注意:應在兩個視類的引用之前添加對文檔類的引用,否則會引起編譯錯誤。另外,由於視
類的建構函式在聲明時都確省的聲明為保護型的,在架構類中無法引用,所以還要將兩個視類的類
聲明改動如下:
class CNextFormView : public CFormView
{
DECLARE_DYNCREATE(CNextFormView)
// protected: 將 protected 改為 public
public:
CNextFormView();
virtual ~CNextFormView();
……
};
class CSwitchFormView : public CFormView
{
// protected: 將 protected 改成 public
public:
CSwitchFormView();
DECLARE_DYNCREATE(CSwitchFormView)
……
};
三、 編譯運行
編譯運行程式,開始時的表單上有 "這是第一個表單的字樣 ",菜單也只有 "第一個表單 "是被選中的,當前的活動表單是第一個表單;點擊菜單 "第二個表單 ",視圖中的表單上的字樣變成了 "這是第二 個表單 ",同時選中的菜單也由 "第一個表單 "變成了 "第二個表單 ",實現了通過菜單將表單進行動態切換。
總結:此程式中關鍵的是SwitchToView函數,在此函數中,程式搜尋所有當前文檔的顯示視窗來尋找與CruntimeClass變數匹配的視圖類。如果找到,該視窗被啟用。通過與之類似的方法,還可以實現在多文檔模式下的單檔(文檔)多視(視圖),通過不同的視圖以不同的方式顯示來自同一份文檔的資料,以更好的滿足程式的需要。
轉自:http://topic.csdn.net/t/20050216/17/3785968.html