CSplitterWnd in a Dialog based Application

Download Example Project

Had this problem before. I guess there are some more interested in a solution.

It seems CSplitterWnd is designed to be used in document/view-based applications only.
But by overriding some virtual methods in a derived class, you can make splitter windows based on CSplitterWnd be used in dialog based application, ActiveX-Controls using MFC:

All virtual methods that call GetParentFrame() in its implementation have to be overridden.
I have done this by using existing code except
- that I replaced the call to GetParentFrame() by a call to GetParent().
- all references or pointers to CFrameWnd were changed to references or pointers to CWnd.

I derived a class CxSplitterWnd from the class CSplitterWnd and proceeded as stated above.
Then I used this class in a dialog based application in the same way as any other CWnd derived class.
For example:

class CSampleDialog : public CDialog
	CxSplitterWnd m_wndSplitter; 

BOOL CSampleDlg::OnInitDialog()
	// TODO: Add extra initialization here
	m_wndSplitter.CreateStatic(this, 1, 2);
	m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CSampleView), CSize(50,0), NULL);
	m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CSampleView), CSize(0,0), NULL); 

	CRect rect = ...;

The sample attached is a dialog based application and demonstrates the use of CxSplitterWnd. It does
nothing useful.

This is the new class declaration:

// SplitWnd.h : implementation file
class CxSplitterWnd : public CSplitterWnd
	// Construction
	CxSplitterWnd() {};
	virtual ~CxSplitterWnd() {}; 

	// Operations
	// Overrides
	// ClassWizard generated virtual function overrides

	// Implementation
	// These are the methods to be overridden
	virtual void StartTracking(int ht); 
	virtual CWnd* GetActivePane(int* pRow = NULL, int* pCol = NULL);
	virtual void SetActivePane( int row, int col, CWnd* pWnd = NULL ); 
	virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
	virtual BOOL OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult );
	virtual BOOL OnWndMsg( UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult ); 

	// Generated message map functions
	// NOTE - the ClassWizard will add and remove member functions here.

And here the implementation file:
// SplitWnd.cpp : implementation file
#include "stdafx.h"
#include "SplitWnd.h" 

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;

// HitTest return values (values and spacing between values is important)
// Had to adopt this because it has module scope 
enum HitTestValue
	noHit = 0,
	vSplitterBox = 1,
	hSplitterBox = 2,
	bothSplitterBox = 3, // just for keyboard
	vSplitterBar1 = 101,
	vSplitterBar15 = 115,
	hSplitterBar1 = 201,
	hSplitterBar15 = 215,
	splitterIntersection1 = 301,
	splitterIntersection225 = 525

// CxSplitterWnd 

BEGIN_MESSAGE_MAP(CxSplitterWnd, CSplitterWnd)
// NOTE - the ClassWizard will add and remove mapping macros here.

CWnd* CxSplitterWnd::GetActivePane(int* pRow, int* pCol)
	CWnd* pView = GetFocus();
	// make sure the pane is a child pane of the splitter
	if (pView != NULL && !IsChildPane(pView, pRow, pCol))
	pView = NULL; 
	return pView;

void CxSplitterWnd::SetActivePane( int row, int col, CWnd* pWnd)
	// set the focus to the pane
	CWnd* pPane = pWnd == NULL ? GetPane(row, col) : pWnd;

void CxSplitterWnd::StartTracking(int ht)
	if (ht == noHit)
	// GetHitRect will restrict 'm_rectLimit' as appropriate
	if (ht >= splitterIntersection1 && ht <= splitterIntersection225)
		// split two directions (two tracking rectangles)
		int row = (ht - splitterIntersection1) / 15;
		int col = (ht - splitterIntersection1) % 15; 
		GetHitRect(row + vSplitterBar1, m_rectTracker);
		int yTrackOffset = m_ptTrackOffset.y;
		m_bTracking2 = TRUE;
		GetHitRect(col + hSplitterBar1, m_rectTracker2);
		m_ptTrackOffset.y = yTrackOffset;
	else if (ht == bothSplitterBox)
		// hit on splitter boxes (for keyboard)
		GetHitRect(vSplitterBox, m_rectTracker);
		int yTrackOffset = m_ptTrackOffset.y;
		m_bTracking2 = TRUE;
		GetHitRect(hSplitterBox, m_rectTracker2);
		m_ptTrackOffset.y = yTrackOffset; 
		// center it
		m_rectTracker.OffsetRect(0, m_rectLimit.Height()/2);
		m_rectTracker2.OffsetRect(m_rectLimit.Width()/2, 0);
		// only hit one bar
		GetHitRect(ht, m_rectTracker);

	// steal focus and capture
	// make sure no updates are pending
	// set tracking state and appropriate cursor
	m_bTracking = TRUE;
	if (m_bTracking2)
	m_htTrack = ht;

// CSplitterWnd command routing 
BOOL CxSplitterWnd::OnCommand(WPARAM wParam, LPARAM lParam)
	if (CWnd::OnCommand(wParam, lParam))
	return TRUE; 
	// route commands to the splitter to the parent frame window
	return GetParent()->SendMessage(WM_COMMAND, wParam, lParam);

BOOL CxSplitterWnd::OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult )
	if (CWnd::OnNotify(wParam, lParam, pResult))
	return TRUE; 
	// route commands to the splitter to the parent frame window
	*pResult = GetParent()->SendMessage(WM_NOTIFY, wParam, lParam);
	return TRUE;

BOOL CxSplitterWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
	// The code line below is necessary if using CxSplitterWnd in a regular dll
	// AFX_MANAGE_STATE(AfxGetStaticModuleState()); 
	return CWnd::OnWndMsg(message, wParam, lParam, pResult);

Posted: 11 May 1998


  • Thanks for this article.

    Posted by Nedy Kim on 03/31/2016 09:42pm

    Thank you very much.

  • Nike Display Max 1 FB publicity, have a strong color character, the chic shoes

    Posted by Geozyoceada on 04/24/2013 07:49am

    In the summer in a pane backing bowels the imperturbable sprite seems to be a wholesome choice, but if the sprite "feet"? Resolution also give you a lapse, bring a sustenance! This summer, Nike and Sprite [url=http://fossilsdirect.co.uk/glossarey.cfm]nike huarache[/url] and his sneakers to a fuse of enduring snow spread of callow, off-white and downcast color scheme in the definitive Nike Air Max 1 shoes let slip a refreshing cool scent.[url=http://fossilsdirect.co.uk/glossarey.cfm]nike huarache free[/url] Summer is the yet to select a clean shoe, shoes should be a obedient choice. Qualifying series Nike Air Max HomeTurf borough recently finally comes up, this series in the immortal Breath Max shoes to London, Paris and Milan the three paid tribute to the iconic megalopolis of Europe, combined with the characteristics of the three cities, Feeling Max 1 HYP,Make public Max 90 HYP,Connected Max 1 and shoes such as Style Max 95, combined [url=http://markwarren.org.uk/property-waet.cfm]nike air max 90[/url] with the Hyperfuse, as marvellously as a collection of materials, such as suede, Whether you hankering functional or retro-everything.

  • How to solve crack in release mode?

    Posted by Legacy on 10/24/2002 12:00am

    Originally posted by: mihee

    in debug mode, i solve ASSERT problem with Christian's comment.
    but crack fired in release mode...
    how to solve?

  • Works nicely

    Posted by Legacy on 05/30/2001 12:00am

    Originally posted by: Richard Cullen

    Thanks for this article - with the fix from Christian it seems to work nicely.

    - Richard

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

Top White Papers and Webcasts

Most Popular Programming Stories

More for Developers

RSS Feeds

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