Toolbar within splitter windows
Introduction
Has anyone ever wondered how to dock a toolbar inside a splitter pane? Normally you cannot do that, but you can alter your splitter pane so that it will look just like you placed a toolbar on one of it's sides. The trick is to create a two-pane splitter where your initial pane was; but not just any splitter, we will use our own, which does not allow resizing, and has different border settings. There is one additional view to create, and we will derive a class from CFormView since features provided by this class are closer to our goal.
The code
First goes the custom splitter window:
// class definition
classCSmartSplitterWnd :public CSplitterWnd
{
public:
CSmartSplitterWnd();
virtual ~CSmartSplitterWnd();
intHitTest(CPoint pt)const;
protected:
DECLARE_MESSAGE_MAP()
};
// class implementation
CSmartSplitterWnd::CSmartSplitterWnd()
{
m_cxSplitter=3; // put your own values here, to make the splitter fit your needs
m_cySplitter=3;
m_cxBorderShare=0;
m_cyBorderShare=0;
m_cxSplitterGap=3;
m_cySplitterGap=3;
}
CSmartSplitterWnd::~CSmartSplitterWnd()
{
}
BEGIN_MESSAGE_MAP(CSmartSplitterWnd, CSplitterWnd)
//{{AFX_MSG_MAP(CSmartSplitterWnd)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
intCSmartSplitterWnd::HitTest(CPoint pt)const
{
ASSERT_VALID(this);
// do not allow caller to see mouse hits
return 0;
}
Next, we must create a simple CFormView using the resource editor and ClassWizard. You can add any controls to your form view, but you must keep in mind that handling the WM_SIZE message may help you improve the look of your view. There are several ways to update your buttons and other controls inside the view; you may need to implement one of them to update, enable or disable the controls.
The last step is to create the splitter itself and the views. The code below matches a SDI application that accomodates the code above inside a splitter pane, but you can easily adjust it to fit your needs.
First add a member to the CMainFrame class of type CSmartSplitterWnd:
classCMainFrame :public CFrameWnd
{
[...]
public:
CSmartSplitterWnd m_barSplitter;
In the OnCreateClient member of the CMainFrame class, add code to create the splitter inside the right pane:
// create the splitter window if (!m_barSplitter.CreateStatic(&m_parentSplitter, 2, 1, WS_CHILD|WS_VISIBLE|WS_BORDER, m_parentSplitter.IdFromRowCol(1, 0))) returnfalse; // create the views m_barSplitter.CreateView(0, 0, RUNTIME_CLASS(CBarView), CSize(0, 0), pContext); m_barSplitter.CreateView(1, 0, RUNTIME_CLASS(CTheView), CSize(0, 0), pContext); // then set heights
The code is quite easy to follow and change to meet your needs, but if you need assistance, contact me. Also please send me bugs or updates, to keep this solution up-to-date. For more details on the sample application, contact me.
Date Last Updated: February 3, 1999

Comments
here is a 'm_parentSplitter' and some hint for source...
Posted by Legacy on 03/09/2003 12:00amOriginally posted by: Jin, Yong-Chul
hi all.
don't worry, code beginners...
class CMainFrame : public CFrameWnd
{
:
:
CSplitterWnd m_parentSplitter;
:
:
};
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
:
:
if ( !m_wndParentSplitter.CreateStatic(this, 1, 2) )
return FALSE;
// create the splitter window
if (!m_barSplitter.CreateStatic(&m_parentSplitter, 2, 1, WS_CHILD|WS_VISIBLE|WS_BORDER,
m_parentSplitter.IdFromRowCol(1, 0))) returnfalse;
// create the views
m_wndParentSplitter.CreateView(0, 0, RUNTIME_CLASS(CTheView), CSize(0, 0), pContext);
m_barSplitter.CreateView(0, 0, RUNTIME_CLASS(CBarView), CSize(0, 0), pContext);
m_barSplitter.CreateView(1, 0, RUNTIME_CLASS(CTheView), CSize(0, 0), pContext);
:
:
}
CTheView is a MFC's CView class.
class CTheView : public CView
{
:
:
};
Good Luck!
Allways Be Happy. anecia.
ReplyI LIKE IT VERY MUCH
Posted by Legacy on 02/03/2003 12:00amOriginally posted by: Dillohn
THIS IS A GOOD SITE AND HELPING VERY CH ME BUT I WANT IT SOURCE ALL
ReplyUse CFrameWnd derived class as view
Posted by Legacy on 11/02/2002 12:00amOriginally posted by: Kin Hoon
The simplest way is just to create a CFrameWnd derived class, and add this CWnd to CSplitterWnd. CSpliiterWnd actually takes generic CWnd object instead of just CView object.
And in your CFrameWnd derived class, you can have all your toolbars and status bars and MFC message routing, and a cleaner look.
Reply
Same goal with different approach
Posted by Legacy on 10/02/2002 12:00amOriginally posted by: Asif
Instead of creating two panes,one for toolbar and other for client window, we can achieve the same goad by creating a single pane,creating a view in it, then creating a new view eg CScrollView as child of the first view and moving it to a position like CPoint(0,50).
ReplyIf you request, I can send you the source
awaiting feedback
easiest way
Posted by Legacy on 07/02/2002 12:00amOriginally posted by: Ayach
ReplyUsing a real CToolbar (and not a CFormView derived class)
Posted by Legacy on 05/15/2002 12:00amOriginally posted by: gatorette
In fact, using the same technique described here, you can add a toolbar to a split window (and you don't need to design a new dialog and create a new class).
Everyone knows how to add a CFrameWnd-derived window in a pane. What is less known is that you can add any kind of windows (CWnd and all its derived classes) in a pane. This behavior is used in this article to add a CSplitterWnd in a pane. And I used it again to add a CToolbar in place of the CFormView.
I had difficulties making what is explained in the article work. That's why I will start by a small explanation.
The first part of the article about the custom splitter window is not important! For the code you can use a standard splitter. This CSmartSplitterWnd changes the appearance of the splitter and makes it non-sizeable.
You can then create a new dialog resource (use IDD_FORMVIEW) representing your toolbar and create a class derived from CFormView based on this template.
Then you need to have 2 splitters in your CMainFrame (edit MainFrm.h):
* the main one which is usually a standard splitter that is declared as "CSplitterWnd m_parentSplitter;"
* the one we will use to create our "toolbar" which is declared as "CSmartSplitterWnd m_barSplitter;"
You can then add the function "OnCreateClient" in CMainFrame, to create the splitters and the associated views. Here is an example of such a function:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
m_parentSplitter.CreateStatic( this, 2, 1 );
m_parentSplitter.CreateView( 1, 0, RUNTIME_CLASS( CBottomView ), CSize( 0, 0 ), pContext );
m_barSplitter.CreateStatic( &m_parentSplitter, 1, 2, WS_CHILD | WS_VISIBLE, m_parentSplitter.IdFromRowCol( 0, 0 ) );
m_barSplitter.CreateView( 0, 0, RUNTIME_CLASS( CMyToolBarView ), CSize( 0, 0), pContext);
m_barSplitter.CreateView( 0, 1, RUNTIME_CLASS( CMyAppView ), CSize( 0, 0), pContext);
return TRUE;
}
Ok, I hope that it is now clearer for everyone !
Now let's add a toolbar instead of this CFormView derived window.
Just add a CToolBar in your CMainFrame (for example: "CToolBar m_wndToolBar;").
And replace the OnCreateClient function like this:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
m_parentSplitter.CreateStatic( this, 2, 1 );
m_parentSplitter.CreateView( 1, 0, RUNTIME_CLASS( CBottomView ), CSize( 0, 0 ), pContext );
m_barSplitter.CreateStatic( &m_parentSplitter, 1, 2, WS_CHILD | WS_VISIBLE, m_parentSplitter.IdFromRowCol( 0, 0 ) );
m_barSplitter.CreateView( 0, 1, RUNTIME_CLASS( CMyAppView ), CSize( 0, 0 ), pContext);
m_wndToolBar.CreateEx( &m_barSplitter, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_LEFT | CBRS_TOOLTIPS | CBRS_FLYBY, CRect( 0, 0, 0, 0 ), m_barSplitter.IdFromRowCol( 0, 0 ) );
m_wndToolBar.LoadToolBar(IDR_MYTOOLBAR);
return TRUE;
}
Hope it will help some!
Reply
Good idea!!!
Posted by Legacy on 05/13/2002 12:00amOriginally posted by: MikeFunny
A great inspiration!
Reply
Good idea!!!
Posted by Legacy on 05/13/2002 12:00amOriginally posted by: MikeFunny
A great inspiration!
Reply
Great Trick!!
Posted by Legacy on 04/28/2002 12:00amOriginally posted by: Brick Luo
thx
But
I want to know the particular about the follow member
Replym_cxSplitter=30; // put your own values here, to make the splitter fit your needs
m_cySplitter=30;
m_cxBorderShare=0;
m_cyBorderShare=0;
m_cxSplitterGap=30;
m_cySplitterGap=30;
Source Code... Please!
Posted by Legacy on 03/08/2002 12:00amOriginally posted by: JinWook
How can I get your source code?
ReplyLoading, Please Wait ...