Click here to Skip to main content
15,868,016 members
Articles / Desktop Programming / MFC

SDI with split window

Rate me:
Please Sign up or sign in to vote.
4.85/5 (67 votes)
1 Jan 2007CPOL7 min read 329.1K   4.4K   106   44
Create an SDI with split window without all the extra garbage of the Doc/View architecture.

Sample Image - SplitWindow.jpg

Introduction

Have you ever wanted to use a split window in you program but didn’t want all the extra garbage of the Doc/View architecture?

In the new project wizard, in order to make the “Split Window” check box available, you have to choose “Document/View architecture support”. This puts a lot of extra unneeded code in your project if all you wanted was a split main window.

In this article, I am going to walk you through creating a simple SDI with a split main window, a tool bar, and status bar. The window will be split into a left and right pane that are resource based and can be modified easily in the resource editor just like making a simple dialog based application.

These instructions and project files are for Visual Studio 2005; while they may work in older versions of Visual Studio, you’ll be on your own to adapt them.

Start Visual Studio and create a new project. Select MFC application, give your project a name, and click “OK”.

Image 2

Image 3

Click Next.

Image 4

In order to keep this as simple as possible, we will use minimal options for our project.

Choose “Single document”, uncheck “Document/View architecture”, uncheck “Use Unicode libraries”, and select “Use MFC in static library”. Click Next.

Image 5

We don’t want any database support, so just click Next.

Image 6

On this page, we will keep the defaults. This will give us a status bar and a tool bar. Nice things to have in an SDI project. Hit Next.

Image 7

Uncheck “ActiveX controls” and “Common Control Manifest”; unless you know you are going to be using ActiveX controls and the new XP specific controls in your project, there is no reason for the extra overhead. Hit Next.

Image 8

Here is where it would be nice if they let us choose what kind of child view we want, but they don’t, so just hit Finish.

Compile and run the project.

Image 9

Notice that the icon on the title bar is set to a default icon instead of the one defined in the project's resource file. This is a bug in Visual studio that’s been around for years. Here’s how to fix it.

Image 10

In the IDE, select the class view and double click on “InitInstance”.

Image 11

You should see:

Image 12

To change the icon on the title bar, first we need to create one, then we need to tell the main application window to use it. Place the following code after the “UpdateWindow” but before the “return”.

C++
//Create and load the titlebar icon
HICON hIcon;
hIcon = LoadIcon(IDR_MAINFRAME);    
AfxGetMainWnd()->SendMessage(WM_SETICON,TRUE,(LPARAM)hIcon);

Contrary to what you might think, LoadIcon doesn’t actually load the icon, it just creates it. We have to tell the application to use the new icon with a SendMessage.

Your “InitInstance” should now look like this:

Image 13

Now when you compile and run, you should see the resource defined icon on the title bar.

Image 14

You can now use the resource editor to change the icon to whatever you want.

Now it is time to add the split window I promised. In order to have a split window, we will use a class called CSplitterWnd. In the class view, right click on CMainFrame and select “Add Variable”. Change the access to “Protected”, the variable type to “CSplitterWnd”, and the variable name to “m_wndSplitter”, and click Finish.

Image 15

Since the split will be in the client area, the code for it will need to be in an override function called OnCreateClient in CMainFrame.

In the class view, select CMainFrame. In the properties area, press the “Overrides” button and scroll down to “OnCreateClient” and add the function with the combo box to the right.

Image 16

Add the following code to the OnCreateClient function:

C++
// create splitter window
if (!m_wndSplitter.CreateStatic(this, 1, 2))
    return FALSE;

This will create a static split window for us that will have one row and two columns.

But wait, don’t compile yet. We still need to tell the splitter what to display in each pane and we need to get rid of the old view Visual Studio created for us.

For this tutorial, let us use resource based forms. That will make it easy to add controls and use this project as a template for building other applications.

Switch to Resource view, expand the dialog leaf, right click and choose “Insert Dialog”. This will insert a new dialog resource and open it in the resource editor.

Image 17

Delete the “OK” and “Cancel” buttons. Right click on the dialog and choose Properties.

In Properties, change:

  • Border to “None”.
  • Control to “True”.
  • ID to “IDD_FORM_LEFT”.
  • Style to “Child”.

Image 18

Now add a new dialog in the same manner but make the ID: IDD_FORM_RIGHT.

In the resource view, double click IDD_FORM_LEFT. This will open up the left form in the resource editor. Right click on the dialog in the editor and choose “Add Class”.

Change the base class to “CFormView”, the name to “CFormLeft”, and hit Finish.

Image 19

Repeat this process on the IDD_FORM_RIGHT resource but make the class name CFormRight.

Image 20

Now we have views for the splitter to display.

In MainFrm.cpp, add the header lines:

C++
#include "FormLeft.h"
#include "FormRight.h"

Scroll down to the “OnCreateClient” function and add the create view calls to the splitter. Add the following code after the splitter creation, but before the return.

C++
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CFormLeft), CSize(125, 100), pContext) ||
    !m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CFormRight), CSize(100, 100), pContext))
{
    m_wndSplitter.DestroyWindow();
    return FALSE;
}

Your OnCreateClient should look like this.

Image 21

We’re almost there. Now we need to get rid of the View Visual Studio made for us and any uses of the old view.

Scroll up to the OnCmdMsg function and remove:

C++
if (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
    return TRUE;

Scroll up to the OnSetFocus function and remove:

C++
m_wndView.SetFocus();

Scroll up to the OnCreate function and remove:

C++
// create a view to occupy the client area of the frame
if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
    CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
{
    TRACE0("Failed to create view window\n");
    return -1;
}

At the top of MainFrm.h, remove:

C++
#include "ChildView.h"

Scroll down and remove:

C++
CChildView    m_wndView;

Switch to Solution Explorer, right click on “ChildView.h”, and choose Remove. On the pop up box, press the Delete button.

Image 22

Delete “ChildView.cpp” in the same manner.

Image 23

You can compile and run now, and you will have an SDI with a split window. Try it out, drag the split bar around:

Image 24

It doesn’t do anything at this point, but you can add controls with the resource editor.

However, the controls in each pane can only affect controls in the same pane. In order to have controls in the left pane affect controls in the right pane, we will need to reroute some messages.

In the class view, right click on “CformLeft” and choose “Add variable”. Make the access protected, the type “CWnd*”, and the name “m_target”. Hit Finish.

Image 25

In the class view, right click on “CFormLeft” and choose “Add function”. Make the return type void, the name “SetTarget”, and add a parameter of type “CWnd*” named “m_cwnd”. Hit Finish.

Image 26

In the SetTarget function, add the code:

C++
m_target = m_cwnd;

You should see:

Image 27

Next we will need to override the OnCommand function. Select “CFormLeft” in the class view. Click the Overrides button and scroll down to OnCommand and use the dropdown box to add the function.

Image 28

In the OnCommand function, add the following code:

C++
if(m_target)
{           
    m_target->SendMessage(WM_COMMAND, wParam, lParam);
}
else
{
    CFormView::OnCommand(wParam, lParam);
}
return true;

You should see:

Image 29

This will send the messages from this form to the target window we set. Now we want to set the target to the form in the right pane.

Add the following code to the OnCreateClient function in CMainFrame after the splitter creates views and before the return:

C++
//set the target for mapped messages
((CFormLeft*)m_wndSplitter.GetPane(0,0))->SetTarget(m_wndSplitter.GetPane(0,1));

Your function should now look like:

Image 30

Now let's add some controls and use it. Open IDD_FORM_RIGHT in the resource editor and add a static text control.

Image 31

Change the ID to IDC_STATIC_HELLO, the caption to “Click the button”, and the text align to Center.

Image 32

Right click on the static control and choose Add Variable. Click the control type check box, the type “CStatic”, and the name “m_hello”. Click Finish.

Image 33

Open IDD_FORM_LEFT in the resource editor and add a button.

Image 34

Change the ID to IDC_BUTTON_HELLO and the caption to “Say Hello”.

Image 35

Right click on the button and choose “Add Event Handler”. Select message type BN_CLICKED and “CFormRight” from the class list, then hit Add and Edit.

Image 36

In the OnBnClickedButtonHello function, add the following code:

C++
m_hello.SetWindowText("Hello Window Splitter!");

Your function should look like:

Image 37

Compile and run your program. Click the Say Hello button and you should see the test change in the right pane. Now try dragging the split bar and you should see the text in the right pane move with the splitter bar.

Image 38

I hope you found this article useful.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
I am a contract developer of windows based software written in C++.

Comments and Discussions

 
QuestionMFC FormView -I can't find CFormView or CView Pin
Member 1392785916-Aug-18 1:24
Member 1392785916-Aug-18 1:24 
QuestionTree view control in SplitterCtrl Pin
Member 959902624-Oct-16 0:24
Member 959902624-Oct-16 0:24 
QuestionWill this allow your own drawing in the right side via OnPaint()? Pin
ReturnVoid9-Nov-15 11:58
ReturnVoid9-Nov-15 11:58 
QuestionSplitter pane resizing problem Pin
Chetan Kammar9-Jun-15 20:11
Chetan Kammar9-Jun-15 20:11 
QuestionSplitter windows Pin
Member 1141763714-Feb-15 3:35
Member 1141763714-Feb-15 3:35 
GeneralMy vote of 5 Pin
Harkin.Dong26-Apr-13 17:06
Harkin.Dong26-Apr-13 17:06 
GeneralMy vote of 5 Pin
shetkarabhijeet14-Nov-12 20:04
shetkarabhijeet14-Nov-12 20:04 
Generalthanks Pin
vinaypeepl27-Aug-12 22:47
vinaypeepl27-Aug-12 22:47 
QuestionProblem with panes Pin
Ganesh Jeevaa21-Aug-12 22:57
Ganesh Jeevaa21-Aug-12 22:57 
QuestionHelp me pls... Pin
Ganesh Jeevaa21-Aug-12 22:35
Ganesh Jeevaa21-Aug-12 22:35 
QuestionSend message Pin
sc9311-Jun-12 3:44
sc9311-Jun-12 3:44 
GeneralMy vote of 5 Pin
xmbfd14-Feb-12 23:24
xmbfd14-Feb-12 23:24 
GeneralMy vote of 5 Pin
neuodpo3-Aug-11 22:56
neuodpo3-Aug-11 22:56 
QuestionHow to implement this sample with VC6.0 ? Pin
neuodpo2-Aug-11 21:29
neuodpo2-Aug-11 21:29 
AnswerRe: How to implement this sample with VC6.0 ? Pin
neuodpo2-Aug-11 23:14
neuodpo2-Aug-11 23:14 
GeneralMy vote of 5 Pin
Dai Yan26-Apr-11 16:47
Dai Yan26-Apr-11 16:47 
GeneralMy vote of 5 Pin
Member 778626531-Mar-11 18:43
Member 778626531-Mar-11 18:43 
GeneralThanks a lot Pin
Member 77406709-Mar-11 15:48
Member 77406709-Mar-11 15:48 
GeneralMy vote of 5 Pin
Antonio Pedone19-Feb-11 10:02
Antonio Pedone19-Feb-11 10:02 
Generalhelp reqd on my split wnd [modified] Pin
ashwani_gupt28-Dec-10 21:53
ashwani_gupt28-Dec-10 21:53 
GeneralRe: help reqd on my split wnd Pin
ashwani_gupt29-Dec-10 0:04
ashwani_gupt29-Dec-10 0:04 
GeneralMy vote of 5 Pin
hiddensoul26-Dec-10 8:58
hiddensoul26-Dec-10 8:58 
GeneralMy vote of 5 Pin
StoreThick_StartThin15-Dec-10 21:35
StoreThick_StartThin15-Dec-10 21:35 
Generalthanks Pin
fanliu9-Nov-09 21:36
fanliu9-Nov-09 21:36 
GeneralVery Useful Pin
KinjalMansi1-Nov-09 19:06
KinjalMansi1-Nov-09 19:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.