Thursday 18 August 2011

Simple application with two panes and a splitter

Applications of this type are very common: we have some objects, or items, listed in a left pane and when we click on some item its attributes are displayed in the right pane. Items can be listed within a tree control, and right click context menu possibly provides actions we can perform on them. But let us focus now only on basic: a splitter window with two panes.

The quickest way to make application with such layout in MFC is by creating SDI (Single Document Interface) project. Document/View support is not required. Wizard creates CMainFrame class which is the main window of SDI application. Wizard also adds to it a View class - a child window that occupies the client area of the main frame:

Application looks like this:

SplitterTest1_5

We want to embed Splitter window into the main frame instead of this default View so we need to replace CChildView with instance of CSplitterWnd:

The right place to put code that creates controls in the main client area of the frame window is overloaded CFrameWnd::OnCreateClient.

Now how to overload parent's implementation of this method? The easiest way to insert various message handlers and overloads into MFC class is via class properties window:

  • go to class declaration in its header file
  • click on the class name
  • in the main menu in Visual Studio go to View->Other Windows->Properties Window
  • click Properties, Events, Messages or Overrides button in order to change properties or add event/messages handlers or to override base class methods

SplitterTest1_8

In this case, we click on Overrides, find and select OnCreateClient in the left side of the properties window, click in the value field and select Add OnCreateClient. This will automatically insert all necessary code in our class. This is default implementation of this overload:

We want to have static layout - left and right pane and a splitter bar all the time so will use CSplitterWnd::CreateStatic. Creating static splitter requires creating its panes within OnCreateClient.

A pane within a splitter window is usually a window derived from CView class. As we want to embed various controls (e.g. CTreeCtrl) in it, we will use CFormView, a class very similar to CDilaog. We could embed controls in a CView-derived class but using CFormView makes life simpler as allows using Visual Studio resource editor to design a form (properties, children controls) which is associated to CFormView object.

So how to add CFormView windows to our project? Just add a new Dialog in the resource editor and make sure its Style in Properties is set to Child. Optionally, remove Border and System menu. By default, this dialog has OK and Cancel button controls and we can leave them.

SplitterTest1_7

Right click on the dialog and pick "Add Class..." in order to associate a class with this resource. Select CFormView for the base class. I picked CLeftPaneFormView and CRightPaneFormView as names for my panes' classes.

SplitterTest1_6

Now when having panes ready, we can instruct our splitter to create them as its views:

If we run this application, we will see our dialogs with their children controls (OK and cancel buttons) embedded as the left and right pane in the splitter window - just what we wanted!

SplitterTest1_9

Throughout the code in main frame, panes can be accessed with this code:



Links and references:

TN029: Splitter Windows
MFC Tutorial
Visual C++ tutorial

No comments: