MFC下实现单文档多视图(非切割模式),虽然现在有了CTabView,主视图从CTabView继承,然后主视图初始化时把自己子视图添加进去,各个视图以Tab页的方式显示。这种方式在某些场景下 可以,多数情况下不符号用户要求。下面介绍两种非Tab页方式的实现:
第一种,利用CCreateContext,动态创建和切换视图。在CMainFrame中,枚举视图ID,并创建视图切换函数。
// Attributes
public:
/***********窗口切换*****/
enum eView { VIEW = 1, VIEW1 = 2 ,VIEW2 = 3,VIEW3 = 4,VIEW4 = 5,VIEW5 = 6};
void SwitchToView(eView nView);
在CPP中的实现:
BOOL bFirst = TRUE;
void CMainFrame::SwitchToView(eView nView)
{
CView* pOldActiveView = GetActiveView();
if (bFirst)
{
m_pView[0] = pOldActiveView;
bFirst =FALSE;
}
CView* pNewActiveView = (CView*) GetDlgItem(nView);
//如果视图不存在,动态创建
if(m_pView[nView-1]==NULL)
{
switch (nView)
{
case VIEW:
m_pView[0] = (CView*) new CMonitoringSysView;
break;
case VIEW1:
m_pView[1] = (CView*) new EnvironmentParaShow;
break;
}
pNewActiveView = m_pView[nView-1];
CCreateContext context;
context.m_pCurrentDoc = pOldActiveView->GetDocument();
pNewActiveView->Create(NULL, NULL, WS_BORDER|WS_CHILD ,
rectDefault, this, nView, &context);
pNewActiveView->OnInitialUpdate();
}
//隐藏旧视图,显示新视图
pNewActiveView = m_pView[nView-1];
SetActiveView(pNewActiveView);
pNewActiveView->ShowWindow(SW_SHOW);
pOldActiveView->ShowWindow(SW_HIDE);
if (GetRuntimeClass() == RUNTIME_CLASS(CMonitoringSysView))
{
pOldActiveView->SetDlgCtrlID(nView);
}
else if (GetRuntimeClass() == RUNTIME_CLASS(EnvironmentParaShow))
{
pOldActiveView->SetDlgCtrlID(nView);
}
pNewActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
RecalcLayout();
}
//切换视图
void CMainFrame::OnMonitsys()
{
SwitchToView(VIEW);
}
OnMonitsys是菜单关联函数。
第二种,使用多视图模板类CMDIMVDocTemplate,这是一个老外写的模板类,在APP类中屏蔽掉原来的doc、frame和view的常见,使用这个模板类创建。这个模板类每创建一个视图类View,必须同时创建一个ChildFrame.
CMvDocTemplate *pDocTemplate = new CMDIMVDocTemplate(IDR_WATERINFO, RUNTIME_CLASS(CWaterInfoSysDoc));
pDocTemplate->AddFrameTemplate(
new CFrameTemplate(
IDR_WATERINFO,
RUNTIME_CLASS( CChildFrame ),
RUNTIME_CLASS( CWaterInfoSysView ),
ID_REALTIMEMONITOR,//该视图对应的菜单ID,
SW_SHOWMAXIMIZED,
TRUE ) ); //为TRUE时,激活态,系统开始运行时创建
pDocTemplate->AddFrameTemplate(
new CFrameTemplate(
IDR_WATERINFO,
RUNTIME_CLASS( CChileFrmRpt),
RUNTIME_CLASS( CDialyWaterLevelRptView),
ID_DAILY_WATERLEVCAPATY,
SW_SHOWMAXIMIZED,
FALSE ) );
pDocTemplate->AddFrameTemplate(
new CFrameTemplate(
IDR_WATERINFO,
RUNTIME_CLASS(CChildFrmRainfall),
RUNTIME_CLASS(CRainfallHistogramView),
ID_RAINFALLHISTOGRAM,
SW_SHOWMAXIMIZED,
FALSE));
AddDocTemplate(pDocTemplate);
m_server.ConnectTemplate(clsid, pDocTemplate, FALSE);
COleTemplateServer::RegisterAll();
// 创建主 MDI 框架窗口
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame || !pMainFrame->LoadFrame(IDR_WATERINFO))//IDR_MAINFRAME))
{
delete pMainFrame;
return FALSE;
}
m_pMainWnd = pMainFrame;
ChildFrame需继承自CMDIChildWndEx,头文件:
#pragma once
// CChildFrmRainfall
class CChildFrmRainfall : public CMDIChildWndEx
{
DECLARE_DYNCREATE(CChildFrmRainfall)
public:
CChildFrmRainfall();
virtual ~CChildFrmRainfall();
protected:
DECLARE_MESSAGE_MAP()
virtual void OnUpdateFrameTitle(BOOL bAddToTitle);
};
CPP文件
#include "stdafx.h"
#include "WaterInfoSys.h"
#include "ChildFrmRainfall.h"
// CChildFrmRainfall
IMPLEMENT_DYNCREATE(CChildFrmRainfall, CMDIChildWndEx)
CChildFrmRainfall::CChildFrmRainfall()
{
}
CChildFrmRainfall::~CChildFrmRainfall()
{
}
BEGIN_MESSAGE_MAP(CChildFrmRainfall, CMDIChildWndEx)
END_MESSAGE_MAP()
// CChildFrmRainfall message handlers
void CChildFrmRainfall::OnUpdateFrameTitle(BOOL bAddToTitle)
{
CMDIChildWndEx::OnUpdateFrameTitle(bAddToTitle);
SetWindowText(_T("降雨量柱状图"));
}
每个视图类继承自CFormView即可。
第三种方式是同MFC自身带的TabView类似,也是Tab页的方式实现,即使用BCGCtrolBar控件,这个控件很早就实现了,比MFC还早。
安装好BCGContrilBar以后,修改主主视图类继承自CBCGPTabView,在OnCreate内添加你自己的子视图即可。
int CDahangAcqgateStudioView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CBCGPTabView::OnCreate(lpCreateStruct) == -1)
return -1;
AddView(RUNTIME_CLASS(CAcqNetgatewayView),_T("采集网关"),0);
AddView(RUNTIME_CLASS(CSerialPortDevView), _T("串口设备"), 1);
AddView(RUNTIME_CLASS(CSerialPortIoPtView), _T("串口设备IO点"), 2);
AddView(RUNTIME_CLASS(CLocalIOPtView),_T("本地IO点"), 3);
AddView(RUNTIME_CLASS(CUserCustomPtView), _T("用户点"), 4);
AddView(RUNTIME_CLASS(CModbusTcpProtoPtsView), _T("Modbus协议"), 5);
AddView(RUNTIME_CLASS(COPCUAProtoPtsView), _T("OPC UA协议"), 6);
AddView(RUNTIME_CLASS(CMQTTProtoPtsView), _T("MQTT协议"),7);
OnShowAllChildView(FALSE);
return 0;
}
//视图切换
void CDahangAcqgateStudioView::OnAcqNetgatewayView()
{
GetTabControl().SetActiveTab(0);
}
点击 MFC多视图模板类和BCGCtolBarForMFC25 下载资源。