您的位置:首页 > 其它

【交互】MFC单文档多视图实例分析

2013-10-30 18:01 218 查看
一、基本原理

        对于多文档App而言,首先是创建CMainFrame窗口和它的子窗口MDIClient。当新建一个文档,则会new CDocument,顺便创建CChildFrame和它的子窗口CView,再次新建时,会建立另一个文档,创建另外一个CChildFrame和它的子窗口CView。对于不同视图,CView的ID标识是AFX_IDW_PANE_FIRST。在本次CChildFrame新建另外的CView时,ID标识要改变,以免重复。

        向MDIClient发送WM_MDICREATE创建CChildFrame时,内部会分配子窗口的ID值,另外MDIClient在CManiFrame::OnCreate中调用到CMDIFrameWnd中的一个函数,里面创建时,Menu ID标识也是AFX_IDW_PANE_FIRST,但是MDIClient的创建 CLIENTCREATESTRUCT ccs的里面,可以指定子窗口id标识ccs.id,即子窗口CChildFrame的id标识从这个数字开始编号AFX_IDM_FIRST_MDICHILD。

        若要获取激活窗口,则向MDIClient发送WM_GETACTIVATE消息,每个激活的CChildFrame父类CFrameWnd保存一个 CView* m_pViewActive,也就是CChildFrame会有一个主视图。

二、SDI单文档多视图的实现及自由切换【1、2】

        主要是获取当前活动文档ActiveDocument,放到context.m_pCurrentDoc,然后再创建的时候,传上下文context信息。

classCMultiViewApp : publicCWinApp{
public:      
CView* m_pFirstView;      
CView* m_pOtherView;      
int m_currentView;      
CView* m_pView2;      
CView* m_pView1;
}
CMultiViewApp::InitInstance()
{
  CDocument* pDoc = ((CFrameWnd*)m_pMainWnd)->GetActiveDocument();     
 //通过CCreateContext实现第二视图和文档的关联      
CCreateContext   context;       context.m_pCurrentDoc = pDoc;//把视图放在当前文档      
UINT  m_ID = AFX_IDW_PANE_FIRST + 1;//设置标识作为CMainFrame的子窗口      
CRect  rect;        //为了演示第一种多视图是实现方法,把Vew的实例创建放在了这里      
m_pOtherView->Create(NULL, NULL, WS_CHILD, rect, m_pMainWnd, m_ID, &context);}
//切换时,设置活动视图,另外就是重新计算,这里要具体看RecalcLayout
 ……//里面会交换View窗口ID,是因为 CFrameWnd::RecalcLayout will allocate
 // this "first pane" to that portion of the frame window's client area
//not allocated to control bars.
m_pOtherView->ShowWindow(SW_HIDE);
m_pFirstView->ShowWindow(SW_SHOW);
 m_pMainWnd->SetActiveView(m_pFirstView);
 m_pMainWnd->RecalcLayout();
m_pFirstView->Invalidate();

三、CMainFrame中添加不同的CChildFrame【3、4】

1、这个子窗口,只是创建了一个视图,没有指定context.m_pCurrentDoc,在CView::OnCreate()里面会报错。

CMainFrame::OnFuncTwo()
{
//仿照上面的思想,new Frame,点击一个菜单时,切换到这个CChildFrame
m_pFuncOneFrame = new CDemoFrame();
CCreateContext context;
context.m_pNewViewClass = RUNTIME_CLASS(CFuncOneView); //关联的视图类,又它新建一个视图对象
m_pFuncOneFrame->LoadFrame(IDR_MAINFRAME, WS_MAXIMIZEWS_OVERLAPPEDWINDOW, this, &context);
m_pFuncOneFrame->SetWindowText(" 业务逻辑一 ");
m_pFuncOneFrame->ShowWindow(SW_SHOWMAXIMIZED);
m_pFuncOneFrame->InitialUpdateFrame(NULL,true);
}

2、加入文档后

void CMainFrame::OnFuncOne()
{
// TODO: Add your command handler code here
if (m_pFuncOneFrame != NULL) //已创建,则激活它
{
m_pFuncOneFrame->MDIActivate();
return ;
}
m_pFuncOneFrame = new CDemoFrame();
CDemoDoc* m_pDoc = new CDemoDoc(); //new了一个文档
CCreateContext context;
context.m_pNewViewClass = RUNTIME_CLASS(CFuncOneView); //传CView class
context.m_pCurrentDoc = m_pDoc;
m_pFuncOneFrame->LoadFrame(IDR_MAINFRAME, WS_MAXIMIZEWS_OVERLAPPEDWINDOW, this, &context);
m_pFuncOneFrame->SetWindowText(" 业务逻辑一 ");
m_pFuncOneFrame->ShowWindow(SW_SHOWMAXIMIZED);
m_pFuncOneFrame->InitialUpdateFrame(NULL,true);
}


四、总结

       CMainFrame建立了MDIClient之后,会new CDocument,然后pFrame

CCreateContext context;
 context.m_pCurrentFrame = pOther;//NULL,
 context.m_pCurrentDoc = pDoc;//当前文档
 context.m_pNewViewClass = m_pViewClass;//CDocTemplate中已经保存有它
 context.m_pNewDocTemplate = this;
pFrame->LoadFrame(m_nIDResource, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,NULL, &context))
//pParenWnd会在后面设置为MDIClient
//其函数原型
virtual BOOL LoadFrame(UINT nIDResource,DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,
CWnd* pParentWnd = NULL,CCreateContext* pContext = NULL);

       对于文档管理,三、2中,可将模板放在保存一个位置,或者直接获取pDocTemplate,然后将pDoc加入到文档模板当中。

           

参考:1、MFC SDI单文档多视图的实现及自由切换(2种实现方式简析)

2、为啥交换窗口ID标识

3、MFC文档视图深入详解

4、深入分析MFC文档视图结构(项目实践)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: