最近在做实验室项目的时候需要在MFC下生成单文档多视图的结构,经过网上几个小时的寻找以及查书终于找到了一种可行的同时又较好理解的解法,记录下来:
首先,由于是静态创建,所以肯定是先初始化好想创建的视图啦。注意,我所有的操作都在**App类中做。
1
private
:
2 CView * m_pView[ 4 ];
2 CView * m_pView[ 4 ];
我在App类中声明了一个视图数组,并在InitInstance中初始化它,还包括视图的创建等。
视图类初始化
1
CView
*
m_pActiveView
=
((CFrameWnd
*
)m_pMainWnd)
->
GetActiveView();
2 m_pView[ 0 ] = m_pActiveView; //由于一开始显示的就是m_pView[0]所以直接赋给它
3 m_pView[ 1 ] = new CProductionFormView;
4 m_pView[ 2 ] = new CEventsListView;
5 m_pView[ 3 ] = new CRunningFormView;
6 //初始化上下文,主要是文档指针,并创建其余视图
7 CCreateContext context;
8 context.m_pCurrentDoc = ((CFrameWnd * )m_pMainWnd) -> GetActiveDocument();
9 m_pView[ 1 ] -> Create(NULL,NULL,(AFX_WS_DEFAULT_VIEW & ~ WS_VISIBLE),CFrameWnd::rectDefault,m_pMainWnd,AFX_IDW_PANE_FIRST + 1 , & context);
10 m_pView[ 2 ] -> Create(NULL,NULL,(AFX_WS_DEFAULT_VIEW & ~ WS_VISIBLE),CFrameWnd::rectDefault,m_pMainWnd,AFX_IDW_PANE_FIRST + 2 , & context);
11 m_pView[ 3 ] -> Create(NULL,NULL,(AFX_WS_DEFAULT_VIEW & ~ WS_VISIBLE),CFrameWnd::rectDefault,m_pMainWnd,AFX_IDW_PANE_FIRST + 3 , & context);
12 //需要我们人工调用更新函数
13 for ( int i = 0 ; i < 4 ; i ++ )
14 m_pView[i] -> OnInitialUpdate();
2 m_pView[ 0 ] = m_pActiveView; //由于一开始显示的就是m_pView[0]所以直接赋给它
3 m_pView[ 1 ] = new CProductionFormView;
4 m_pView[ 2 ] = new CEventsListView;
5 m_pView[ 3 ] = new CRunningFormView;
6 //初始化上下文,主要是文档指针,并创建其余视图
7 CCreateContext context;
8 context.m_pCurrentDoc = ((CFrameWnd * )m_pMainWnd) -> GetActiveDocument();
9 m_pView[ 1 ] -> Create(NULL,NULL,(AFX_WS_DEFAULT_VIEW & ~ WS_VISIBLE),CFrameWnd::rectDefault,m_pMainWnd,AFX_IDW_PANE_FIRST + 1 , & context);
10 m_pView[ 2 ] -> Create(NULL,NULL,(AFX_WS_DEFAULT_VIEW & ~ WS_VISIBLE),CFrameWnd::rectDefault,m_pMainWnd,AFX_IDW_PANE_FIRST + 2 , & context);
11 m_pView[ 3 ] -> Create(NULL,NULL,(AFX_WS_DEFAULT_VIEW & ~ WS_VISIBLE),CFrameWnd::rectDefault,m_pMainWnd,AFX_IDW_PANE_FIRST + 3 , & context);
12 //需要我们人工调用更新函数
13 for ( int i = 0 ; i < 4 ; i ++ )
14 m_pView[i] -> OnInitialUpdate();
我在菜单中加入Command消息响应视图的切换,整个切换在SwitchView函数中完成,其定义如下:
SwitchView
1
void
CCardSystemApp::SwithToView(
int
nView)
2 {
3 ASSERT(nView >= 0 && nView <= 4 );
4 CView * pOldActiveView = ((CFrameWnd * ) m_pMainWnd) -> GetActiveView();
5 CView * pNewActiveView = m_pView[nView];
6 ASSERT(pNewActiveView);
7 if (pNewActiveView == pOldActiveView)
8 return ;
9
10 // 交换视图的窗口ID,使RecalcLayout()可以工作
11 UINT temp = ::GetWindowLong(pOldActiveView -> m_hWnd,GWL_ID);
12 ::SetWindowLong(pOldActiveView -> m_hWnd,GWL_ID,::GetWindowLong(pNewActiveView -> m_hWnd,GWL_ID));
13 ::SetWindowLong(pNewActiveView -> m_hWnd,GWL_ID,temp);
14
15 pOldActiveView -> ShowWindow(SW_HIDE);
16 pNewActiveView -> ShowWindow(SW_SHOW);
17
18 ((CFrameWnd * ) m_pMainWnd) -> SetActiveView(pNewActiveView);
19 ((CFrameWnd * ) m_pMainWnd) -> RecalcLayout();
20 pNewActiveView -> Invalidate();
21
22 }
2 {
3 ASSERT(nView >= 0 && nView <= 4 );
4 CView * pOldActiveView = ((CFrameWnd * ) m_pMainWnd) -> GetActiveView();
5 CView * pNewActiveView = m_pView[nView];
6 ASSERT(pNewActiveView);
7 if (pNewActiveView == pOldActiveView)
8 return ;
9
10 // 交换视图的窗口ID,使RecalcLayout()可以工作
11 UINT temp = ::GetWindowLong(pOldActiveView -> m_hWnd,GWL_ID);
12 ::SetWindowLong(pOldActiveView -> m_hWnd,GWL_ID,::GetWindowLong(pNewActiveView -> m_hWnd,GWL_ID));
13 ::SetWindowLong(pNewActiveView -> m_hWnd,GWL_ID,temp);
14
15 pOldActiveView -> ShowWindow(SW_HIDE);
16 pNewActiveView -> ShowWindow(SW_SHOW);
17
18 ((CFrameWnd * ) m_pMainWnd) -> SetActiveView(pNewActiveView);
19 ((CFrameWnd * ) m_pMainWnd) -> RecalcLayout();
20 pNewActiveView -> Invalidate();
21
22 }
按照以上方法就可以创建切换视图了,我在项目中已实验成功。