Click here to Skip to main content
15,887,485 members
Articles / Desktop Programming / MFC

Splitter in an MFC dialog based application

Rate me:
Please Sign up or sign in to vote.
4.63/5 (5 votes)
25 Jul 2011CPOL2 min read 60.1K   4.3K   11   20
Using a button as splitter in MFC dialog based applications.

Screen Shot 1

Introduction

This is my first time posting an article in CodeProject. CodeProject has been very helpful to me. I want to give back the help given by the authors by submitting my own article.

In MFC, CSplitterWnd is usually available MDI or SDI. I just think splitter controls are just dragable buttons. So I decided to implement a class named CControlSplitter derived from CButton to work like CSplitterWnd for dialog based MFC applications.

Background

The implementation is very simple. As long as you know how to subclass MFC controls, you can understand how this works and improve it.

Using the code

In your project, include the following files:

  • ControlSplitter.h
  • ControlSplitter.cpp

Include ControlSplitter.h in your dialog header:

C++
#include "ControlSplitter.h"

Add splitter buttons in your dialog using the usual button control which will serve as the splitter and set its control ID such as IDC_SPLITTER1.

Using the MFC Class Wizard, add control member variables in your dialog for the added splitter buttons with type CControlSplitter.

After adding member control variables, the following must be implemented:

  1. Declaration of the control splitter in your dialog header:
    C++
    //{{AFX_DATA(CSplitterDlg)
    ...
    CControlSplitter m_splitter;
    ...
    //}}AFX_DATA
  2. Sub class the control using DDX_Control in the DoDataExchange of your dialog.
    C++
    void CSplitterDlg::DoDataExchange(CDataExchange* pDX)
    {
        CDialog::DoDataExchange(pDX);
        //{{AFX_DATA_MAP(CSplitterDlg)
        ...
        DDX_Control(pDX, IDC_SPLITTER, m_splitter);
        ...
        //}}AFX_DATA_MAP
    }

Setup your splitter in the OnInitDialog() method of your dialog

  1. [Required] Set the type of the control splitter:
    C++
    m_splitter.SetType(CControlSplitter::CS_VERT);

    The available types are CS_NONE (default), CS_VERT, and CS_HORZ.

    C++
    public:
    typedef enum {
        CS_VERT = 1,
        CS_HORZ = 2,
        CS_NONE = 0
    };
  2. Add sibling controls to the splitter's control listing.

    Control splitters have two control listings:

    • Top control listing (for CS_VERT type) or left control listing (for CS_HORZ type)
    • Bottom control listing (for CS_VERT type) or right control listing (for CS_HORZ type)

    To add the control's top control listing or left control listing, use the AddToTopOrLeftCtrls method.

    C++
    m_splitter.AddToTopOrLeftCtrls(IDOK);

    To add the control's bottom control listing or right control listing, use the AddToBottomOrRightCtrls method.

    C++
    m_splitter.AddToBottomOrRightCtrls(IDC_EDIT1);

    Here is the declaration for AddToTopOrLeftCtrls and AddToBottomOrRightCtrls:

    C++
    void AddToBottomOrRightCtrls(UINT nCtrlId, WORD nFlags = 
                                 SPF_TOP|SPF_LEFT|SPF_RIGHT|SPF_BOTTOM);
    void AddToTopOrLeftCtrls(UINT nCtrlId, WORD nFlags = 
                             SPF_TOP|SPF_LEFT|SPF_BOTTOM|SPF_RIGHT);

    [Note:] The two methods have extra flag parameters that can be used to specify the behaviour of the sibling controls when the control splitter is being dragged. Possible values could be the combination of the following:

    C++
    /* distance of the control to the top of the window will be constant */
    #define SPF_TOP     0x0010
    /* distance of the control to the bottom of the window will be constant */
    #define SPF_BOTTOM  0x0020
    /* distance of the control to the left of the window will be constant */
    #define SPF_LEFT    0x0040
    /* distance of the control to the right of the window will be constant */
    #define SPF_RIGHT   0x0080

Class working methods

C++
CControlSplitter();

This is the contstructor.

C++
void SetType(UINT nType);

This sets the type of the control splitter in either CS_VERT or CS_HORZ.

C++
void AddToTopOrLeftCtrls(UINT nCtrlId, WORD nFlags);

This is used to add the control to the top or the left control listing.

C++
void AddToBottomOrRightCtrls(UINT nCtrlId, WORD nFlags);

This is used to add the control to the bottom or the right control listing.

C++
void OnLButtonDown(UINT nFlags, CPoint point);

This is fired when the user presses down the left button of the mouse over the control.

C++
void OnLButtonUp(UINT nFlags, CPoint point);

This is fired when the user releases up the left button of the mouse over the control.

C++
void OnMouseMove(UINT nFlags, CPoint point);

This is fired when the user moves the mouse over the control.

C++
void OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);

This is fired when the system asks for the cursor. The cursor is settled using SetClassLong(m_hWnd,GCL_HCURSOR,(LONG)m_hCursor);.

Class working member variables

C++
//Holds the Type of the control splitter
unsigned int m_nType;
//Holds the Top or Left Control Listing
std::vector<DWORD> m_vtTopLeftControls;
//Holds the Bottom or Right Control Listing
std::vector<DWORD> m_vtBottomRightControls;
//Holds the POINT position used to calculate the movement changes
CPoint m_ptStartDrag,m_ptStartPos;
//Used to determine if user Starts to Drag, Dragging, and Ends Draging
bool m_bDragging;
//Used to hold the loaded HCURSOR 
HCURSOR m_hCursor;
//Holds the bounds the splitter is allowed to be moved.
CRect m_rectMax;
//Holds the old control that is previously holdes cursor capture.
CWnd * m_pOldDragCapture;

History

  • 15 Jul 2011: First release.
  • 25 Jul 2011: Translated Readme.txt in the demo download.

License

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


Written By
Software Developer NCR Cebu Development Center
Philippines Philippines
Focused in Leading Business Development while working as a Software Developer. His specialty is C++ and PHP. Been developing MS Windows application since 2007.

Comments and Discussions

 
QuestionSplitter wiht TAB - opinions please Pin
Vaclav_9-Mar-14 4:51
Vaclav_9-Mar-14 4:51 
QuestionMouse pointer question Pin
Dave Calkins11-Feb-13 4:46
Dave Calkins11-Feb-13 4:46 
AnswerRe: Mouse pointer question Pin
Lucman Abdulrachman14-Feb-13 22:52
Lucman Abdulrachman14-Feb-13 22:52 
AnswerRe: Mouse pointer question Pin
Lucman Abdulrachman14-Feb-13 23:01
Lucman Abdulrachman14-Feb-13 23:01 
GeneralRe: Mouse pointer question Pin
Dave Calkins15-Feb-13 11:20
Dave Calkins15-Feb-13 11:20 
AnswerRe: Mouse pointer question Pin
LupinTaiwan17-Feb-13 20:57
LupinTaiwan17-Feb-13 20:57 
GeneralRe: Mouse pointer question Pin
Dave Calkins18-Feb-13 2:06
Dave Calkins18-Feb-13 2:06 
GeneralMy vote of 5 Pin
Dave Calkins11-Feb-13 3:32
Dave Calkins11-Feb-13 3:32 
GeneralMods for supporting a resizable dialog Pin
Dave Calkins11-Feb-13 3:32
Dave Calkins11-Feb-13 3:32 
GeneralRe: Mods for supporting a resizable dialog Pin
Lucman Abdulrachman14-Feb-13 22:44
Lucman Abdulrachman14-Feb-13 22:44 
GeneralRe: Mods for supporting a resizable dialog Pin
Member 1129440327-Aug-15 21:05
Member 1129440327-Aug-15 21:05 
QuestionPrevent going out of limits Pin
Dialecticus21-Oct-11 2:24
Dialecticus21-Oct-11 2:24 
AnswerRe: Prevent going out of limits Pin
Lucman Abdulrachman2-Nov-11 17:11
Lucman Abdulrachman2-Nov-11 17:11 
GeneralRe: Prevent going out of limits Pin
Dialecticus2-Nov-11 23:52
Dialecticus2-Nov-11 23:52 
QuestionBug : button cursor Pin
Zoylamb27-Jul-11 3:54
Zoylamb27-Jul-11 3:54 
AnswerRe: Bug : button cursor Pin
rdw28-Jul-11 4:09
rdw28-Jul-11 4:09 
QuestionReadMe Pin
RaymondM19-Jul-11 20:20
RaymondM19-Jul-11 20:20 
QuestionReadme Pin
RaymondM18-Jul-11 21:44
RaymondM18-Jul-11 21:44 
AnswerRe: Readme [modified] Pin
Lucman Abdulrachman24-Jul-11 15:20
Lucman Abdulrachman24-Jul-11 15:20 
Hi Raymond,

Apologies for the Japanese text. The reason it was Japanese is ReadMe.txt was actually created by MFC AppWizzard since I'm using Japanese environment.

I translated it by the way.

See text below:

Best Regards,

Lucman

Readme.txt
<br />
========================================================================<br />
       MICROSOFT FOUNDATION CLASS Library : Splitter<br />
========================================================================<br />
<br />
<br />
AppWizard has created this Splitter application for you.  This application<br />
not only demonstrates the basics of using the Microsoft Foundation classes<br />
but is also a starting point for writing your application.<br />
<br />
This file contains a summary of what you will find in each of the files that<br />
make up your Splitter application.<br />
<br />
Splitter.dsp<br />
    This file (the project file) contains information at the project level and<br />
    is used to build a single project or subproject. Other users can share the<br />
    project (.dsp) file, but they should export the makefiles locally.<br />
<br />
Splitter.h<br />
    This is the main header file for the application.  It includes other<br />
    project specific headers (including Resource.h) and declares the<br />
    CSplitterApp application class.<br />
<br />
Splitter.cpp<br />
    This is the main application source file that contains the application<br />
    class CSplitterApp.<br />
<br />
Splitter.rc<br />
    This is a listing of all of the Microsoft Windows resources that the<br />
    program uses.  It includes the icons, bitmaps, and cursors that are stored<br />
    in the RES subdirectory.  This file can be directly edited in Microsoft<br />
	Visual C++.<br />
<br />
Splitter.clw<br />
    This file contains information used by ClassWizard to edit existing<br />
    classes or add new classes.  ClassWizard also uses this file to store<br />
    information needed to create and edit message maps and dialog data<br />
    maps and to create prototype member functions.<br />
<br />
res\Splitter.ico<br />
    This is an icon file, which is used as the application's icon.  This<br />
    icon is included by the main resource file Splitter.rc.<br />
<br />
res\Splitter.rc2<br />
    This file contains resources that are not edited by Microsoft <br />
	Visual C++.  You should place all resources not editable by<br />
	the resource editor in this file.<br />
<br />
<br />
<br />
<br />
/////////////////////////////////////////////////////////////////////////////<br />
<br />
AppWizard creates one dialog class:<br />
<br />
SplitterDlg.h, SplitterDlg.cpp - the dialog<br />
    These files contain your CSplitterDlg class.  This class defines<br />
    the behavior of your application's main dialog.  The dialog's<br />
    template is in Splitter.rc, which can be edited in Microsoft<br />
	Visual C++.<br />
<br />
<br />
/////////////////////////////////////////////////////////////////////////////<br />
Other standard files:<br />
<br />
StdAfx.h, StdAfx.cpp<br />
    These files are used to build a precompiled header (PCH) file<br />
    named Splitter.pch and a precompiled types file named StdAfx.obj.<br />
<br />
Resource.h<br />
    This is the standard header file, which defines new resource IDs.<br />
    Microsoft Visual C++ reads and updates this file.<br />
<br />
/////////////////////////////////////////////////////////////////////////////<br />
Other notes:<br />
<br />
AppWizard uses "TODO:" to indicate parts of the source code you<br />
should add to or customize.<br />
<br />
If your application uses MFC in a shared DLL, and your application is <br />
in a language other than the operating system's current language, you<br />
will need to copy the corresponding localized resources MFC42XXX.DLL<br />
from the Microsoft Visual C++ CD-ROM onto the system or system32 directory,<br />
and rename it to be MFCLOC.DLL.  ("XXX" stands for the language abbreviation.<br />
For example, MFC42DEU.DLL contains resources translated to German.)  If you<br />
don't do this, some of the UI elements of your application will remain in the<br />
language of the operating system.<br />
<br />
/////////////////////////////////////////////////////////////////////////////<br />

In Journey the leader of the people is their servant. -RSAW
modified on Sunday, July 24, 2011 9:28 PM

GeneralRe: Readme Pin
RaymondM25-Jul-11 0:39
RaymondM25-Jul-11 0:39 

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.