CSplitterWnd

CFrameWnd can have only one window frame. CSplitterWnd class can be used in CFrameWnd to create splitter views in main frame window.

CSplitterWnd::Create

To create a dynamic splitter window, call the Create member function.

virtual BOOL Create(
    CWnd* pParentWnd,  
    int nMaxRows,  
    int nMaxCols,  
    SIZE sizeMin,  
    CCreateContext* pContext,  
    DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | SPLS_DYNAMIC_SPLIT,  
    UINT nID = AFX_IDW_PANE_FIRST);

CSplitterWnd::CreateStatic

To create a static splitter window, call the CreateStatic member function.

virtual BOOL CreateStatic(
    CWnd* pParentWnd,  
    int nRows,  
    int nCols,  
    DWORD dwStyle = WS_CHILD | WS_VISIBLE,  
    UINT nID = AFX_IDW_PANE_FIRST);

CSplitterWnd::CreateView

Creates the panes for a static splitter window.
virtual BOOL CreateView(
    int row,  
    int col,  
    CRuntimeClass* pViewClass,  
    SIZE sizeInit,  
    CCreateContext* pContext);

CSplitterWnd::SetRowInfo

Call to set the specified row information.
void SetRowInfo(
    int row,  
    int cyIdeal,  
    int cyMin);

CSplitterWnd::SetColumnInfo

Call to set the specified column information.
void SetColumnInfo(
    int col,  
    int cxIdeal,  
    int cxMin);

CSplitterWnd::RecalcLayout

Call to redisplay the splitter window after adjusting row or column size.
virtual void RecalcLayout();

CSplitterWnd demo

This source code only shows CSplitterWnd part of CMainFrame source file. Rest of the code can be taken from our SDI doc/view demo code.

class CMainFrame : public CFrameWnd
{
protected:
  CMainFrame();
  DECLARE_DYNCREATE(CMainFrame)

public:
  virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
  virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);
  void OnSize(UINT nType, int cx, int cy) ;
  virtual ~CMainFrame();

protected:  /* control bar embedded members */
  CStatusBar  m_wndStatusBar;
  CToolBar    m_wndToolBar;
  CSplitterWnd m_mainSplitter;

protected:
  BOOL m_bInitSplitter;
  afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

  DECLARE_MESSAGE_MAP()
};

/* CMainFrame message handlers */
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
  ON_WM_CREATE()
  ON_WM_SIZE()
END_MESSAGE_MAP()

CMainFrame::CMainFrame()
{
  m_bInitSplitter = false;
}
CMainFrame::~CMainFrame()
{
}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
  if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
    return -1;
  
  if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
    | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
    !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
  {
    TRACE0("Failed to create toolbar ");
    return -1;
  }
  if (!m_wndStatusBar.Create(this) ||
    !m_wndStatusBar.SetIndicators(indicators,
      sizeof(indicators)/sizeof(UINT)))
  {
    TRACE0("Failed to create status bar ");
    return -1;
  }
  m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
  EnableDocking(CBRS_ALIGN_ANY);
  DockControlBar(&m_wndToolBar);
  return 0;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
  if( !CFrameWnd::PreCreateWindow(cs) )
    return FALSE;
  return TRUE;
}
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) 
{
  /* calculate client size */
  CRect cr;
  GetWindowRect( &cr );
  
  /* Create the main splitter with 1 row and 2 columns */
  if ( !m_mainSplitter.CreateStatic( this, 1, 2 ) )
  {
    MessageBox( "Error setting up m_mainSplitter", "ERROR", MB_OK | MB_ICONERROR );
    return FALSE;
  }

  /* The views for each pane must be created */
  if ( !m_mainSplitter.CreateView( 0, 0, RUNTIME_CLASS(CSplitterDemoView),
    CSize(cr.Width()/2, cr.Height()), pContext ) )
  {
    MessageBox( "Error setting up splitter view", "ERROR", MB_OK | MB_ICONERROR );
    return FALSE;
  }

  if ( !m_mainSplitter.CreateView( 0, 1, RUNTIME_CLASS(CSplitterDemoView),
    CSize(cr.Width()/2, cr.Height()), pContext ) )
  {
    MessageBox( "Error setting up splitter view", "ERROR", MB_OK | MB_ICONERROR );
    return FALSE;
  }

  /* change flag to show splitter created */
  m_bInitSplitter = true;

  /*return TRUE instead of the parent method since that would not show our window */
  return TRUE;
}
void CMainFrame::OnSize(UINT nType, int cx, int cy) 
{
  CFrameWnd::OnSize(nType, cx, cy);
  
  CRect cr;
  GetWindowRect(&cr);

  if (m_bInitSplitter && nType != SIZE_MINIMIZED )
  {
    m_mainSplitter.SetRowInfo( 0, cy, 0 );
    m_mainSplitter.SetColumnInfo( 0, cr.Width() / 2, 50);
    m_mainSplitter.SetColumnInfo( 1, cr.Width() / 2, 50);
    
    m_mainSplitter.RecalcLayout();
  }  
}

CSplitterWnd output

CSplitterWnd demo

About our authors: Team EQA

Further readings

Where is WinMain() function in MFC application ?

MFC hides WinMain in its framework and includes source file on WinMain(). This explains how framework calls global CWinApp::Initinstance() from entry WinMain.

What is the utility of CWinApp class?

This is constructed during global C++ objects are constructed and is already available when Windows calls the WinMain function, which is supplied by the ...

Basic steps in Win32 GUI Application with source code.

Define a custom Window class structure, Register the class name, CreateWindow, Show windows and write message get and dispatch loop statements. Define the Window CallBack procedure and write the handlers.

What is a Window CallBack procedure and what is its utility?

DispatchMessage() is a API which indirectly triggers the Window CallBack procedure. Message structure members from this function are passed to the CallBack procedure. CallBack procedure should implement event handlers depending on the need of the application.

What are LPARAM and WPARAM in window proc function?

LPARAM and WPARAM are the two parameters in Window CallBack procedure. They signifies parameters of various events. They are used in handing individual events.

What are the basic steps of a typical MFC based application?

We need to write WinMain and need to follow all these in a Win32 application. However we need not to write much if we are writing an application with MFC ...

#