2013年8月8日 星期四

單文檔(SDI)顯示不同的控制頁面(CFormView):

 

新建一個基於CFormView的單文檔應用程式,再添加一個控制頁面和與之對應的基於CFormView的類,然後通過在主框架類裡添加控制代碼和功能表控制實現這兩個控制頁面的動態切換,下面就是具體的實現過程:

(一) 用 "MFC AppWizard(exe) "建立一個新專案 "SwitchForm ",並在第二步的創建類型上選擇為 "Single documnet "單文檔模式,第三、四、五、六步均取預設狀態,最後一步選擇 "CFormView "作為view類的基類。

點按 "完成 "按鈕,生成了初始工程 "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函數將當前使用中視窗切換到”DD_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變數匹配的視圖類。如果找到,該視窗被啟動。通過與之類似的方法,還可以實現在多文檔模式下的單檔(文檔)多視(視圖),通過不同的視圖以不同的方式顯示來自同一份文檔的資料,以更好的滿足程式的需要。

沒有留言:

張貼留言