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

MFC SDI单文档多视图的实现及自由切换

结合网上学习总结别人的例子,以及参考MSDN给出的例子,对SDI多视图的实现进行了一个简单的总结,以记录学习点滴.

首先在H文件有如下声明:

class CMultiViewApp : public CWinApp

{

public:

       CView* m_pFirstView;

       CView* m_pOtherView;

       int m_currentView;

       CView* m_pView2;

       CView* m_pView1;

       CMultiViewApp();

 

// Overrides

       // ClassWizard generated virtual function overrides

       //{{AFX_VIRTUAL(CMultiViewApp)

       public:

       virtual BOOL InitInstance();

       //}}AFX_VIRTUAL

 

// Implementation

       //{{AFX_MSG(CMultiViewApp)

       afx_msg void OnAppAbout();

       afx_msg void OnViewOtherview();

       afx_msg void OnViewFirstview();

       //}}AFX_MSG

       afx_msg void OnViewChange(UINT nCmdID);

       DECLARE_MESSAGE_MAP()

};

 

其次,在CPP文件有如下消息MAP

/

// CMultiViewApp

 

BEGIN_MESSAGE_MAP(CMultiViewApp, CWinApp)

       //{{AFX_MSG_MAP(CMultiViewApp)

       ON_COMMAND(ID_APP_ABOUT, OnAppAbout)

       ON_COMMAND(ID_VIEW_OTHERVIEW, OnViewOtherview)

       ON_COMMAND(ID_VIEW_FIRSTVIEW, OnViewFirstview)

       //}}AFX_MSG_MAP

       // Standard file based document commands

       ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)

       ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)

       // Standard print setup command

       ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)

       ON_COMMAND_RANGE( ID_VIEW_VIEW1, ID_VIEW_VIEW2, OnViewChange)   

END_MESSAGE_MAP()

 

说明:SDI程序在CMyApp::InitInstance()已经通过DocTemplate创建一个关联的视图/文档实例,切显示出来.具体实现如下:

BOOL CMultiViewApp::InitInstance()

{

       AfxEnableControlContainer();

 

       // Standard initialization

       // If you are not using these features and wish to reduce the size

       //  of your final executable, you should remove from the following

       //  the specific initialization routines you do not need.

 

#ifdef _AFXDLL

       Enable3dControls();                 // Call this when using MFC in a shared DLL

#else

       Enable3dControlsStatic();       // Call this when linking to MFC statically

#endif

 

       // Change the registry key under which our settings are stored.

       // TODO: You should modify this string to be something appropriate

       // such as the name of your company or organization.

       SetRegistryKey(_T("Local AppWizard-Generated Applications"));

 

       LoadStdProfileSettings();  // Load standard INI file options (including MRU)

 

       // Register the application's document templates.  Document templates

       //  serve as the connection between documents, frame windows and views.

 

       CSingleDocTemplate* pDocTemplate;

       pDocTemplate = new CSingleDocTemplate(

              IDR_MAINFRAME,

              RUNTIME_CLASS(CMultiViewDoc),

              RUNTIME_CLASS(CMainFrame),       // main SDI frame window

              RUNTIME_CLASS(CMultiViewView));

       AddDocTemplate(pDocTemplate);

 

       // Parse command line for standard shell commands, DDE, file open

       CCommandLineInfo cmdInfo;

       ParseCommandLine(cmdInfo);

 

       // Dispatch commands specified on the command line

       if (!ProcessShellCommand(cmdInfo))

              return FALSE;

 

       CView* pActiveView = ((CFrameWnd*) m_pMainWnd)->GetActiveView();

       m_pFirstView = pActiveView;

       m_pOtherView = (CView*) new COtherView;

 

       CDocument* pDoc = ((CFrameWnd*)m_pMainWnd)->GetActiveDocument();

       //通过CCreateContext实现第二视图和文档的关联

       CCreateContext context;

       context.m_pCurrentDoc = pDoc;

 

       UINT m_ID = AFX_IDW_PANE_FIRST + 1;

       CRect rect;

       //为了演示第一种多视图是实现方法,Vew的实例创建放在了这里

       m_pOtherView->Create(NULL, NULL, WS_CHILD, rect, m_pMainWnd, m_ID, &context);

 

       // The one and only window has been initialized, so show and update it.

       m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);

       m_pMainWnd->UpdateWindow();

       m_currentView=1;

       return TRUE;

}

1.     SDI单文档多视图实现方法1

void CMultiViewApp::OnViewOtherview()

{

       // TODO: Add your command handler code here

       UINT temp = ::GetWindowLong(m_pOtherView->m_hWnd, GWL_ID);

    ::SetWindowLong(m_pOtherView->m_hWnd, GWL_ID, ::GetWindowLong(m_pFirstView->m_hWnd, GWL_ID));

    ::SetWindowLong(m_pFirstView->m_hWnd, GWL_ID, temp);

 

       m_pFirstView->ShowWindow(SW_HIDE);

       m_pOtherView->ShowWindow(SW_SHOW);      

 

       ((CFrameWnd*)m_pMainWnd)->SetActiveView(m_pOtherView); 

       ((CFrameWnd*) m_pMainWnd)->RecalcLayout();

    m_pOtherView->Invalidate();

      

}

 

void CMultiViewApp::OnViewFirstview()

{

      // TODO: Add your command handler code here

   

    UINT temp = ::GetWindowLong(m_pOtherView->m_hWnd, GWL_ID); //GetWindowWord()

    ::SetWindowLong(m_pOtherView->m_hWnd, GWL_ID, ::GetWindowLong(m_pFirstView->m_hWnd, GWL_ID));//SetWindowWord()

    ::SetWindowLong(m_pFirstView->m_hWnd, GWL_ID, temp);//SetWindowWord()

 

      m_pOtherView->ShowWindow(SW_HIDE);

      m_pFirstView->ShowWindow(SW_SHOW);        

     

      ((CFrameWnd*)m_pMainWnd)->SetActiveView(m_pFirstView); 

      ((CFrameWnd*)m_pMainWnd)->RecalcLayout();

    m_pFirstView->Invalidate();

}

2.     SDI单文档多视图实现方法2

void CMultiViewApp::OnViewChange(UINT nCmdID)

{

       //另外一种方法实现SDI的多视图切换

       CView* pViewAdd;

       CView* pViewRemove;

       CMainFrame* pMainFrame=(CMainFrame*)AfxGetMainWnd();

       CDocument* pDoc = pMainFrame->GetActiveDocument();

      

       if((nCmdID == ID_VIEW_VIEW1) && (m_currentView == 1))

              return;

       if((nCmdID == ID_VIEW_VIEW2) && (m_currentView == 2))

              return;

      

       if (nCmdID == ID_VIEW_VIEW2)

       {

              if (m_pView2 == NULL)

              {

                     m_pView1 = pMainFrame->GetActiveView();

                     m_pView2 = new COtherView();

                    

                     //Note that if OnSize has been overridden in CMyView2

                     //and GetDocument() is used in this override it can

                     //cause assertions and, if the assertions are ignored,

                     //cause access violation.

                     //使用CCreateContext structure实现viewdocument的关联

                     CCreateContext context;

                     context.m_pCurrentDoc=pDoc;//m_pView1->GetDocument();

                    

                     m_pView2->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,

                            CFrameWnd::rectDefault, AfxGetMainWnd(), AFX_IDW_PANE_FIRST + 1, &context/*NULL*/);

              }

              pViewAdd = m_pView2;

              pViewRemove = m_pView1;

              m_currentView= 2;

       }

       else

       {

              pViewAdd = m_pView1;

              pViewRemove = m_pView2;

              m_currentView= 1;

       }

      

       // Set the child i.d. of the active view to AFX_IDW_PANE_FIRST,

       // so that CFrameWnd::RecalcLayout will allocate to this

       // "first pane" that portion of   the frame window's client area

       // not allocated to control   bars.  Set the child i.d. of the

       // other view to anything other than AFX_IDW_PANE_FIRST; this

       // examples switches the child id's of the two views.

      

       int nSwitchChildID = pViewAdd->GetDlgCtrlID();

       pViewAdd->SetDlgCtrlID(AFX_IDW_PANE_FIRST);

       pViewRemove->SetDlgCtrlID(nSwitchChildID);

      

       // Show the newly active view and hide the inactive view.

      

       pViewAdd->ShowWindow(SW_SHOW);

       pViewRemove->ShowWindow(SW_HIDE);

      

       // Connect the newly active view to the document, and

       // disconnect the inactive view.

       //通过CCreateContext实现视图View和文档Document的关联

       //就没有必要手动AddView(),如果需要可以进行手动RemoveView()

       //AddView()会在CView::OnCreate()MFC调用,RemoveView()会在CView::~CView()被调用

       //当然可以根据需要手动调用它们,在本例当中,View都是被创建一次,没有被销毁,所以不会自动

       //调用RemoveView()

       //pDoc->AddView(pViewAdd);

       //pDoc->RemoveView(pViewRemove);

      

       pMainFrame->SetActiveView(pViewAdd);

       pMainFrame->RecalcLayout();

      

       return ;

}

 
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值