Summary of MFC view switching

Source: Internet
Author: User

Switching between views

Multi-view switching of a single document is an old and difficult problem I encountered in learning MFC. Today, I finally cracked it one by one. In my opinion, view switching is divided into three levels. The first is to switch the View class without splitting the pane, and the second is to implement view switching within one pane of the split pane; the third is switching between the split pane and the unsplit view.

At the beginning of MFC's SDI creation, the default view class of MFC is CView. If the CView meets your needs, click finish. If you do not want CView to become your default view class, you can modify it here.

If you forget to modify the default view class, you can change it in the Code:

In the App class, there is a function called InitInstance (), where there is a piece of code

CSingleDocTemplate * pDocTemplate;
PDocTemplate = new CSingleDocTemplate (
IDR_MAINFRAME,
RUNTIME_CLASS (Cprogram8Doc ),
RUNTIME_CLASS (CMainFrame ),
RUNTIME_CLASS (CView1); // change your default view class here. Do not forget to include the header file.
If (! PDocTemplate)
Return FALSE;
AddDocTemplate (pDocTemplate );

After changing the default view class, we will enter the topic.

1. First create the View class you need to switch to. AddClass enters or creates a control and AddClass creates the Control Association class. The latter applies to controls such as Form.

2. For control items, such as clicking a menu item or clicking a mouse, I use a menu item to switch the window.

Void CMainFrame: OnView1 ()
{
// TODO: Add your command handler code here

SwitchToForm (IDD_FORMVIEW1 );

}

Void CMainFrame: OnView2 ()
{
// TODO: Add your command handler code here

SwitchToForm (IDD_FORMVIEW2 );

}

3. The SwitchToForm function is mainly used for view switching.

In this function, perform the following actions:

1. Obtain the current view class pointer and the View class pointer to be converted. If this is the first time a New view class is used, it is associated with the document class;

2. Change the activity view;

3. display the new view and hide the old view;

4. Set the Control ID;

5. Adjust the framework view.

Void CMainFrame: SwitchToForm (int nForm)
{
CView * pOldActiveView = GetActiveView (); // 1
CView * pNewActiveView = (CView *) GetDlgItem (nForm );
If (NULL = pNewActiveView)
{
Switch (nForm)
{
Case IDD_FORMVIEW1:
PNewActiveView = (CView *) new CView1;
Break;
Case IDD_FORMVIEW2:
PNewActiveView = (CView *) new CView2;
Break;
Case IDD_FORMVIEW3:
PNewActiveView = (CView *) new CView3;
Break;
Case IDD_FORMVIEW4:
PNewActiveView = (CView *) new CView4;
Break;
Default:
Break;
}
CCreateContext context;
Context. m_pCurrentDoc = pOldActiveView-> GetDocument ();
PNewActiveView-> Create (NULL, NULL, WS_CHILD | WS_BORDER, CFrameWnd: rectDefault, this, nForm, & context );
PNewActiveView-> UpdateData ();
}
SetActiveView (pNewActiveView); // 2
PNewActiveView-> ShowWindow (SW_SHOW); // 3
POldActiveView-> ShowWindow (SW_HIDE );
If (pOldActiveView-> GetRuntimeClass () = RUNTIME_CLASS (CView1) // 4
POldActiveView-> SetDlgCtrlID (IDD_FORMVIEW1 );
Else if (pOldActiveView-> GetRuntimeClass () = RUNTIME_CLASS (CView2 ))
POldActiveView-> SetDlgCtrlID (IDD_FORMVIEW2 );
Else if (pOldActiveView-> GetRuntimeClass () = RUNTIME_CLASS (CView3 ))
POldActiveView-> SetDlgCtrlID (IDD_FORMVIEW3 );
Else if (pOldActiveView-> GetRuntimeClass () = RUNTIME_CLASS (CView4 ))
POldActiveView-> SetDlgCtrlID (IDD_FORMVIEW4 );
PNewActiveView-> SetDlgCtrlID (AFX_IDW_PANE_FIRST );
RecalcLayout (); // 5
}
When reading posts from other people on the Internet, I found that in RecalcLayout (); I had to add a delete pOldActiveView before; I felt that this was a waste of resources, and the View class was hidden after it was created, re-display. This method should be better than creating it every time you use it. If you have any questions, contact me.

View switching with split pane

The second layer of switching a view is a view switch with a split pane.

In my opinion, it is difficult to switch between views in a limited area.

1. Split the pane first. I will not explain it here. For details, refer to the link below;

2. assign a unique ID number to each view;

M_splitter.CreateStatic (this, 1, 2 );
M_splitter.CreateView (100,100, RUNTIME_CLASS (CTree1), CSize (), pContext );
M_splitter.CreateView (100,100, RUNTIME_CLASS (CForm1), CSize (), pContext );
CWnd * pWnd = m_splitter.GetPane (0, 1 );
M_pViews [0] = (CView *) m_splitter.GetPane (0, 1 );
PWnd-> SetDlgCtrlID (IDD_FORM1 );
PWnd-> ShowWindow (SW_HIDE );
M_splitter.CreateView (100,100, RUNTIME_CLASS (CForm2), CSize (), pContext );
PWnd = m_splitter.GetPane (0, 1 );
M_pViews [1] = (CView *) m_splitter.GetPane (0, 1 );
PWnd-> SetDlgCtrlID (m_splitter.IdFromRowCol (0, 1 ));
PWnd-> ShowWindow (SW_SHOW );
RedrawWindow ();
Return true;

Note: Here, I create a new view to overwrite the previous view. The last view is displayed. The previous view is hidden and displayed only when used. Return Value overwrites the statement returned to the base class return CFrameWndEx: OnCreateClient (lpcs, pContext); annotate this sentence, and return true;

3. Where to activate the switch function? I use menus;

4. The response mainly includes the following steps:

1. First, obtain the current view in the pane;

2. Use IsKindOf to determine whether the class is to be switched;

3. Obtain the frame width and pane width;

CView * pView = (CView *) m_splitter.GetPane (0, 1); // 1
M_bTest = pView-> IsKindOf (RUNTIME_CLASS (CForm2); // 2
CRect rcFrame, rcClient; // 3
M_splitter.GetClientRect (& rcClient );
GetClientRect (& rcFrame );

All of the above are preparations, and the following is the real switchover;

4. Delete the original view

5. Create the current view

6. Adjust the framework

If (m_bTest)
{
M_splitter.DeleteView (0, 1 );
M_splitter.CreateView (0, 1, RUNTIME_CLASS (CForm1), CSize (rcClient. Width (), rcFrame. Height (), NULL );
M_splitter.RecalcLayout ();
}
Else
{
M_splitter.DeleteView (0, 1 );
M_splitter.CreateView (0, 1, RUNTIME_CLASS (CForm2), CSize (rcClient. Width (), rcFrame. Height (), NULL );
M_splitter.RecalcLayout ();
}

Taking a closer look, it seems that this is much simpler than simply switching a view. CSplitterWnd provides such a convenient method.

Switching between a split view and An unsplit View

This is what I think is the most difficult in the trilogy. It doesn't mean how difficult the program is, but it is really not easy to think of this splitting method. Today I will share the last song of this trilogy with you, it also contributes a little to the Internet.

First, let's talk about the idea of the program. Specifically, we create a CFrameWnd-based class for the split window layer, write the code for splitting the view, and then switch with other unsplit view classes.

The following describes the implementation process:

1. Create a CSplitterFrame derived class based on CFrameWnd;

2. Add the View class to fill in the split window and the View class to switch from the split view;

3. overload the OnCreateClient function for this derived class to construct the split view.

M_Splitter.CreateStatic (this, 1, 2 );
M_Splitter.CreateView (, RUNTIME_CLASS (CLeftTree), CSize (), pContext );
M_Splitter.CreateView (, RUNTIME_CLASS (CRightList), CSize (), pContext );
Return true;

I will not explain it here. I am sure everyone is familiar with it. Here I will talk about some mistakes I have made. I originally wanted to get the window size here by GetClientRect, but failed. I couldn't understand it. Later I found that this is not a CMainFrame, so I couldn't get it at all. I should use an API function.

4. Add the framework and View class pointer variables in the CMainFrame class.

CSplitterFrame * m_pSplitterFrame; // splits the View frame pointer.
CView * m_pView; // a separate View class, based on the CView class
CView * m_pForm; // a separate View class, based on the CFormView class
Int m_nCurrentID; // record the current view

5. Reload the OnCreateClient function in the CMainFrame class to create a view and split the framework.

CRect rcClient;
GetClientRect (& rcClient );
M_pView = new CViewShow;
M_pView-> Create (NULL, NULL, AFX_WS_DEFAULT_VIEW &~ WS_BORDER, rcClient, this, NULL, pContext );
M_pView-> ShowWindow (SW_SHOW );
M_pView-> SetDlgCtrlID (AFX_IDW_PANE_FIRST );
PContext-> m_pNewViewClass = (CRuntimeClass *) m_pView; // you can specify the default view class.
M_pForm = new CFormShow;
M_pForm-> Create (NULL, NULL, AFX_WS_DEFAULT_VIEW &~ WS_BORDER, rcClient, this, IDD_FORMSHOW, pContext );
M_pForm-> ShowWindow (SW_HIDE );
M_pSplitterFrame = new CSplitterFrame;
M_pSplitterFrame-> Create (NULL, NULL, AFX_WS_DEFAULT_VIEW &~ WS_BORDER, rcClient, this, NULL, 0, pContext );
M_pSplitterFrame-> ShowWindow (SW_HIDE );
Return true;

6. Create a view switching function

Bool CMainFrame: Switch (int nID)
{
If (nID = m_nCurrentID)
Return false;
Switch (nID)
{
Case IDD_FORMSHOW:
M_pForm-> ShowWindow (SW_SHOW );
M_pForm-> SetDlgCtrlID (AFX_IDW_PANE_FIRST );
M_pView-> ShowWindow (SW_HIDE );
M_pView-> SetDlgCtrlID (AFX_IDW_PANE_FIRST + 2 );
M_pSplitterFrame-> ShowWindow (SW_HIDE );
M_pSplitterFrame-> SetDlgCtrlID (AFX_IDW_PANE_FIRST + 1 );
M_nCurrentID = IDD_FORMSHOW;
Break;
Case AFX_IDW_PANE_FIRST + 1:
M_pSplitterFrame-> ShowWindow (SW_SHOW );
M_pSplitterFrame-> SetDlgCtrlID (AFX_IDW_PANE_FIRST );
M_pForm-> ShowWindow (SW_HIDE );
M_pForm-> SetDlgCtrlID (IDD_FORMSHOW );
M_pView-> ShowWindow (SW_HIDE );
M_pView-> SetDlgCtrlID (AFX_IDW_PANE_FIRST + 2 );
M_nCurrentID = AFX_IDW_PANE_FIRST + 1;
Break;
Case AFX_IDW_PANE_FIRST + 2:
M_pView-> ShowWindow (SW_SHOW );
M_pView-> SetDlgCtrlID (AFX_IDW_PANE_FIRST );
M_pForm-> ShowWindow (SW_HIDE );
M_pForm-> SetDlgCtrlID (IDD_FORMSHOW );
M_pSplitterFrame-> ShowWindow (SW_HIDE );
M_pSplitterFrame-> SetDlgCtrlID (AFX_IDW_PANE_FIRST + 1 );
M_nCurrentID = AFX_IDW_PANE_FIRST + 2;
Break;
Default:
Break;
}
RecalcLayout ();
Return true;
}

7. Create a call Method

Void CMainFrame: OnForm ()
{
// TODO: Add your command handler code here
Switch (IDD_FORMSHOW );
}
Void CMainFrame: OnView ()
{
// TODO: Add your command handler code here
Switch (AFX_IDW_PANE_FIRST + 2 );
}
Void CMainFrame: OnSplitter ()
{
// TODO: Add your command handler code here
Switch (AFX_IDW_PANE_FIRST + 1 );
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.