Toolbar within splitter windows

Environment: -->

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:00am

    Originally 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.

    Reply
  • I LIKE IT VERY MUCH

    Posted by Legacy on 02/03/2003 12:00am

    Originally posted by: Dillohn

    THIS IS A GOOD SITE AND HELPING VERY CH ME BUT I WANT IT SOURCE ALL

    Reply
  • Use CFrameWnd derived class as view

    Posted by Legacy on 11/02/2002 12:00am

    Originally 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:00am

    Originally 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).
    If you request, I can send you the source
    awaiting feedback

    Reply
  • easiest way

    Posted by Legacy on 07/02/2002 12:00am

    Originally posted by: Ayach

    why not create the toolbar directly in the view;
    
    overwrite the WM_CREATE message of your view, then creates the toolbar

    int CMyView::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    if (CView ::OnCreate(lpCreateStruct) == -1)
    return -1;

    m_wndToolBar.CreateEx(this);
    m_wndToolBar.LoadToolBar(IDR_MAINFRAME);

    return 0;
    }
    ;o)

    Reply
  • Using a real CToolbar (and not a CFormView derived class)

    Posted by Legacy on 05/15/2002 12:00am

    Originally 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:00am

    Originally posted by: MikeFunny

    A great inspiration!

    Reply
  • Good idea!!!

    Posted by Legacy on 05/13/2002 12:00am

    Originally posted by: MikeFunny

    A great inspiration!

    Reply
  • Great Trick!!

    Posted by Legacy on 04/28/2002 12:00am

    Originally posted by: Brick Luo

    thx
    But

    I want to know the particular about the follow member
    m_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;

    Reply
  • Source Code... Please!

    Posted by Legacy on 03/08/2002 12:00am

    Originally posted by: JinWook

    How can I get your source code?

    Reply
  • Loading, Please Wait ...

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

Top White Papers and Webcasts

  • On-demand Event Event Date: October 29, 2014 It's well understood how critical version control is for code. However, its importance to DevOps isn't always recognized. The 2014 DevOps Survey of Practice shows that one of the key predictors of DevOps success is putting all production environment artifacts into version control. In this webcast, Gene Kim discusses these survey findings and shares woeful tales of artifact management gone wrong! Gene also shares examples of how high-performing DevOps …

  • On-demand Event Event Date: December 18, 2014 The Internet of Things (IoT) incorporates physical devices into business processes using predictive analytics. While it relies heavily on existing Internet technologies, it differs by including physical devices, specialized protocols, physical analytics, and a unique partner network. To capture the real business value of IoT, the industry must move beyond customized projects to general patterns and platforms. Check out this webcast and join industry experts as …

Most Popular Programming Stories

More for Developers

RSS Feeds