SDI Interface with Multi-Views and Multi-Splitters

WEBINAR: On-demand webcast

How to Boost Database Development Productivity on Linux, Docker, and Kubernetes with Microsoft SQL Server 2017 REGISTER >

Environment: The demo was compiled with Visual C++ 5.0

Overview

For a true SDI application, it is oft necessary to have more than one view. In most cases, it is also necessary to have splitter windows containing other views. This sample can be used to implement multi-views in SDI application with or without splitter. Menu and accelerator table can be changed between views, help ID too.

About this sample

This sample implement 7 views. A standalone CEditView as first view, a splitter window containing a CTreeView and a CListView, an other splitter window containing a CView and a CScrollView, a standalone CRichEditView and a standalone CFormView. The CRichEditView has a new menu with find, next and replace as sample for view context menu.

Problem creating multi-views and multi-splitters

The framework implement functions to create new views CFrameWnd::CreateView() and CSplitterWnd::CreateView(). CFrameWnd, uses the AFX_IDW_PANE_FIRST as default dialog ID for the new view. This ID is used in the RecalcLayout() and if the view is a standalone view, there is not problem because there is only one view active with this ID at a time. CSplitterWnd implement a function IdFromRowCol() to calculate a dialog ID started with AFX_IDW_PANE_FIRST until AFX_IDW_PANE_LAST. Because there is only 256 possible values for this ID, the splitter limits the view on a 16x16 matrix. If we want to create a second splitter with other views, CSplitterWnd::CreateView() fail because the dialog ID exists in the first splitter.

Solution to create multi-splitters

The simple solution for the splitter dialog ID problem is to change the dialog id of the new created views to zero after creation of all panes so we preserve the ASSERT message if the programmer try to create an other view at the same row/column position. To make consistency, we do the same for standalone Views.

Solution to display multi-views and multi-splitters

The framework implements a function to activate views CFrameWnd::SetActiveView() but not to show or hide other views or splitters. If we want to activate a new view, we must first hide the actual splitter and views. To preserve the dialog ID architecture, we must set the dialog ID of hidden splitters and views to zero and the dialog ID of the active splitter and views to the correct ID i.e. IdFromRowCol() for views in splitter and AFX_IDW_PANE_FIRST for standalone view.

Implementation

To create new views, it is only necessary to add doc template to the application, but the resource string must be cleared i.e. containing only the window title "ViewTitle\n\n\n\n\n\n". To implement this architecture automatically, I use a new CSDIDocTemplate class derived from CSingleDocTemplate containing splitter information (splitter #, row, column). The default constructor set the splitter # to -1 so to implement a standalone view, we do exactly the same as for a CSingleDocTemplate. For splitter views, we must give a splitter # different of -1, the row and column. The new CSDIFrameWnd class derived from CFrameWnd creates the splitters and views in his CSDIFrameWnd::OnCreateClient() member automatically and store a view pointer in the doc template for later use. To do this, it uses a new CSDIWinApp class derived from CWinApp that implement three new little functions to access these doc templates with view runtime class or view pointer. The CSDIFrameWnd class has only two user functions. ActivateView(CRuntimeClass* pViewClass) switch between views and IsViewActive(CRuntimeClass* pViewClass) to update the user interface.

Menu, Accelerator and Help ID

If you give new menu and accelerator table for the resource IDs in SDIDocTemplate menu and accelerator table will be changed. The help ID for the view will be changed according to the resource ID.

Limitation

The number of views or splitters is only limited by memory. Because the two user functions in CSDIFrameWnd use runtime class, it is not possible to have more than one view of the same class but normally, it is not a problem. With little change, you can implement a view ID in the CSDIDocTemplate and use it to switch between views.

Step by Step

To create an SDI application with multiple views and splitters, do this.

- Create the SDI application with ClassWizard.

- Add SDIApp.* and SDIFrame.* to your project.

- Change the base class CWinApp to CSDIWinApp.

- Change the base class CFrameWin to CSDIFrameWnd.

- Use CSDIDocTemplate instead of CSingleDocTemplate.

- Create new views with ClassWizard.

- Create new resource ID string with new window title, but you can use the same for all new views.

- Create new menu with this resource ID if necessary.

- Add new CSDIDocTemplate in InitInstance() with resource ID, view and splitter number and position.

- In the CMainFrame, add message command to switch between views.

Download demo application - 17 KB

Download demo project - 71 KB

Date Last Updated: February 14, 1999



Comments

  • Hi......Nice Work!

    Posted by bhushan1980 on 08/09/2006 11:33pm

    I have learned a new approach to alter Doc/View architecture from your application. I just realized that how the so called template classes can customize our application to the very best. But when I tried to add GetDocument() support to the view classes, other than the main view class, I am getting errors like base class undeclared, GetDocument() base class unidentified, insert ; before * in the line C3View* GetDocument(). I don't know why is it so. Also when I try to save some text it gives me an assertion failure message. Please can anyone shed light on this...... Thank you once again Mr. Invincible.

    Reply
  • Problem when screen saver starts

    Posted by fornin on 04/13/2006 08:27am

    Every time a system value change tha application crashes. If you try to change the screen saver (with tha application running) the program crashes. Someone knows the solution for this problem? Thanks in advance, Nik

    Reply
  • Problem on resizing the task bar

    Posted by basteo on 02/02/2006 05:44am

    This job is great but there is a critical error when resizing the taskbar...
    To avoid this problem, go in the section code :
    >>BOOL CSDIFrameWnd::OnCreateClient(LPCREATESTRUCT /*lpcs*/,
    >>	CCreateContext* pContext)
    >>...
    >>// create the splitter and the views in the 
    >>...
    >>// disable view ID to use for next splitter
    And add this lines :
    >>m_SplitInfo[nID].m_wndSplitter.SetDlgCtrlID(0);	>>m_SplitInfo[nID].m_wndSplitter.ShowWindow(SW_HIDE); // this one
    
    It works better.

    Reply
  • Swapping between views

    Posted by Legacy on 09/16/2003 12:00am

    Originally posted by: Murli

    The application what i have developed is MDI having 2 views in single document. my intention is to swap between these 2 views. For example if there are 2 views A and B. and these options must be placed on menubar. While running i must open both the views. if i select optioon A from menubar, then A view must highlighted, and similarly with the case of option B. There should not be any hiding in the views, both the views must be either cascaded or tiled.

    Reply
  • how to add a new view

    Posted by Legacy on 06/09/2003 12:00am

    Originally posted by: mathew

    i want to add a new form view to this project.
    but it is not working properly..

    while trying to load the new forview, entire menu
    become inactive..

    pl.. send ur suggestions..

    thanks in advance

    Reply
  • How can I can do this with one document?

    Posted by Legacy on 04/10/2003 12:00am

    Originally posted by: Dafna Zamir

    I would like to implement this switch of views but only with one document, so when data is changed all other doument will be updated also.

    I don't like to use the splitter window.

    Reply
  • How to update a specific view?

    Posted by Legacy on 03/03/2003 12:00am

    Originally posted by: swad

    hi, ive got a splitter window with 2 views which are created dynamically.
    my question is : how do i update a specific view?(ive tried using Invalidate()but doesn't work)

    Reply
  • Problem ... Problem...Problem

    Posted by Legacy on 01/29/2003 12:00am

    Originally posted by: Rock

    Problem?

    exception error!!

    windows bottom bar resize

    Switched view does not repaint properly when the main frame window is resized

    Reply
  • Ugly dialog did not disappear :(

    Posted by Legacy on 08/07/2002 12:00am

    Originally posted by: AndreiIsakov

    Hello! How did you eliminate the ugly dialog to choose a template from the list? What is the dialog ID and where to set it to zero?

    Thanks in advance,
    Andrei

    Reply
  • CRichEditView&CSplitter&DragDropFiles

    Posted by Legacy on 07/02/2002 12:00am

    Originally posted by: romberg

    In my app(a SDI app),I splitted a view into two,the view derived from CRichEditView.And when I try to Drag and drop a file into one of the two views,I can't catch the EN_DROPFILES message, so I can't execute my operation.who can help me.thanks.

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date