Multiple Views Using SDI | CodeGuru

Multiple Views Using SDI

There are many advantages to using a CView derived class over a dialog based application. Many times however there is more information than screen space or the program just needs logical seperation of elements. MDI ( Multiple Document Interface) is the standard method of achiving this but many designers do not care for it. It […]

Written By
CodeGuru Staff
CodeGuru Staff
Dec 2, 1998
2 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

There are many advantages to using a CView derived class over a dialog based
application. Many times however there is more information than screen space or the program just needs logical seperation of elements. MDI ( Multiple Document Interface) is the standard method of achiving this but many designers do not care for it. It tends to get messy
quickly. Most of the time what is needed is a generalized easy way to have a
SDI ( Single Document Interface) framework and the ability to switch the active
view when needed. This article describes such a method.

In order for this method to work correctly you need to make one simple change
in the header of your CView derived classes. The default constructor for the
view needs to be have the protected storage class changed to public ( See code
sample below). This is due to the fact that we will be constructing the view on
the fly when it is switched to the active view. We could create all the views
at one time and have them available but that is wasteful of memory and
resources and is not really needed. If you wish to do so, however the code can
easily be changed to achive this.

class CMainView : public CFormView
{
protected: 	// create from serialization only   Change this to
public: 	// create from serialization only     this in all CView derived classes
 CMainView();
 DECLARE_DYNCREATE(CMainView)


The actual function that will swap the views is located in your CFrame derived
class. This is the logical place to put it because in the SDI architecture the
frame class controls the view class. It also allows us to centralize message
handling for switching views in/out. As far as MFC member functions go it is
pretty simple. It simply disconnects the old view and destroys it , creates a
new CView derived class and attaches the document to it, sets a few flags,
shows the view and we are in business. here it is.

void CMainFrame::SwitchToForm(int nForm)
{
 CView* pOldActiveView = GetActiveView();	// save old view
 CView* pNewActiveView = (CView*)GetDlgItem(nForm);  // get new view
 if (pNewActiveView == NULL)
 {
  switch(nForm) // these IDs are the dialog IDs of the view but can use anything
  {
   case IDD_MULTISCREEN_FORM:
    pNewActiveView = (CView*)new CMainView;
    break;
   case IDD_MULTISCREEN_FORM2:
    pNewActiveView = (CView*)new CView2;
    break;
   case IDD_MULTISCREEN_FORM3:
    pNewActiveView = (CView*)new CView3;
    break;
   case IDD_MULTISCREEN_FORM4:
    pNewActiveView = (CView*)new CView4;
    break;
  }
  CCreateContext context;       // attach the document to the new view
  context.m_pCurrentDoc = pOldActiveView->GetDocument();
  pNewActiveView->Create(NULL, NULL, 0L, CFrameWnd::rectDefault, // and the frame
   this, nForm, &context);
  pNewActiveView->OnInitialUpdate();
 }
 SetActiveView(pNewActiveView);		// change the active view
 pNewActiveView->ShowWindow(SW_SHOW);	// show the new window
 pOldActiveView->ShowWindow(SW_HIDE);	// hide the old
 ::SetWindowWord(pNewActiveView->m_hWnd, GWL_ID, AFX_IDW_PANE_FIRST);  // gotta have it
 RecalcLayout();		//	adjust frame
 delete	pOldActiveView;	//	kill old view
}


Now all we need to do is attach some menu options and handle the users requests
to switch views. This is easily done using Class wizard to create the blank
functions and message handlers. Below is the code demonstrating a call to
switch screens.

void CMainFrame::OnForm1()
{
 SwitchToForm(IDD_MULTISCREEN_FORM);
}


Also as a UI issue it would be nice if the menu option gave a clue as to what
screen we were on and to prevent the user from attempting to switch to the
current screen. This is easily accomplished by the code below.

void CMainFrame::OnUpdateForm1(CCmdUI* pCmdUI)
{
 pCmdUI->Enable(GetActiveView()->GetRuntimeClass()!=RUNTIME_CLASS(CMainView));
}


I have a small demo project that shows illustrates the principals talked about in this article. It shows a SDI with 4 screens and allows one to switch views via a popup menu or a frame menu.

Download demo project – 26 KB

CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.