BiSplitter 1.1

Overview

CBiSplitterWnd is an MFC-compatible class for creating a binary splitter window that looks like a Microsoft Outlook window. This class splits the window into two parts, called panes. Each pane can be split into two parts also and so on. In that way, you divide a window into as many panes as you need. The binary splitting gives you the opportunity to arrange the panes in any order except for the most exotic. A special bar, called a splitter or gap, separates one pane from another. The gap can be oriented vertically or horizontally. Gap orientation is specified in the BiSplitter window styles and can be changed at any time. There are numerous properties that are responsible for panels look as well.

What Is New in BiSplitter 1.1

  1. The Unicode Character Set support was added.
  2. The compatibility with VC 6.0 was added.
  3. The BiSplitter incorporation into the C++ project was simpler.

A pane is the container for the view; it displays application-dependent information. The view has to be derived from the CView or CWnd classes. The view is developed by the programmer in accordance with standard MFC conventions. A pane also can contain a view derived from the CBiSplitterWnd class. In that case, the pane is split into two subpanes. On the internal level of the application, this process looks like the building of a binary tree. The root and nodes of the tree are objects derived from the CBiSplitterWnd class. Leaves are objects derived from the CView or CWnd classes. For example, the splitter window, shown in Figure 1, defines the tree in Figure 2.

Figure 1

Figure 2

A pane can contain no view or subpanes. In that case, a background color fills it. Multiple views are allowed for every pane. Besides the view, a pane consists of a border and a caption bar with a Close button and caption text that is drawn on it. All these items are optional. The BiSplitter window supports pane gripping as well. The grip buttons for both panes are positioned on the gap. Pane gripping is not the same as pane closing. When a pane is closed, for example by clicking the Close button, there is no simple way to open it, for example by clicking some control in BiSplitter window. To open a closed pane, the application should call a special function of the CBiSplitter class. Unlike the Close button, the grip button acts in both directions.to grip the pane and to expand the gripped pane. But, the disadvantage of gripping is that the gripped pane takes some space in the BiSplitter window; this space is needed to draw the grip button. Unlike this, the Close pane is entirely invisible. The BiSplitter window panes and buttons can be drawn in various styles, both 3D and flat.

You create a BiSplittter window by using the Create function specified in the CBiSplitterWnd class.

Set the BiSplitter initial styles when you create one. You can retrieve and change the styles after creating the BiSplitter window by using the AcquireStyles and ChangeStyles functions. Styles are combined with the bitwise OR operator. After creating a BiSplitter window, you have to create views. You can create any quantity of views, but only two views can be displayed at the same time. There are three kinds of views. The first kind is the view derived from the CView class. For applications that support doc/view architecture, most views will be derived from this class. The second kind is the view derived from the CWnd class. Such views are most appropriate for non-doc/view applications. The third kind is the views derived from the CBiSplitterWnd class. These special-purpose views are destined to split a pane into two subpanes. To create a view of any kind, you have to call the CreateView function.

There are three CreateView functions that have differents set of parameters. These functions are responsible for creating the different kinds of views. After the views have been created, you have to create two panes by using the CreatePane function. Strictly speaking, the CreatePane function does not create a pane; it only initializes the specified pane, assigning a style, view, and caption title. These two panes always exist and you can't delete any of them or create a new pane. To receive or modify the set of styles, you have to call the AcquirePaneStyles and ChangePaneStyles functions accordingly. The GetPaneView function returns a pointer to the view of the specified pane. Call the GetPaneViewID function if only a view identifier is needed. To receive or change pane caption text, use the GetCaptionText and SetCaptionText functions accordingly. After pane initialization, you can change the pane view by calling the AssignViewToPane function. The following example creates a BiSplitter window with many views.

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/,
{
   // create splitter window
   if (!m_wndBiSplitter.Create(this, VSPLITTER | FIXED0 | VIEW3D ))
   return FALSE;

   m_wndBiSplitter.CreateView(RUNTIME_CLASS(CPaneTreeView), 0,
                              pContext);
   m_wndBiSplitter.CreateView(RUNTIME_CLASS(CPaneListView), 1,
                              pContext);
   m_wndBiSplitter.CreateView(RUNTIME_CLASS(CPaneEditView), 2,
                              pContext);
   m_wndBiSplitter.CreateView(RUNTIME_CLASS(CPaneFormView), 3,
                              pContext);
   m_wndBiSplitter.CreateView(RUNTIME_CLASS(CPaneTreeView), 10,
                              pContext);
   m_wndBiSplitter.CreateView(RUNTIME_CLASS(CPaneListView), 11,
                              pContext);
   m_wndBiSplitter.CreateView(RUNTIME_CLASS(CPaneEditView), 12,
                              pContext);
   m_wndBiSplitter.CreateView(RUNTIME_CLASS(CPaneFormView), 13,
                              pContext);

  if (
   !m_wndBiSplitter.CreatePane(0, THICK_BORDER | SMCAPTION |
                               THICK_CAPTIONBORDER | CLOSEBTN |
                               FLAT_BUTTON | GRIPBTN
   , "First pane", m_wndBiSplitter.GetView(0) )

   ||

   !m_wndBiSplitter.CreatePane(1, THICK_BORDER | SMCAPTION |
                               THICK_CAPTIONBORDER | FLAT_BUTTON
   , "Second pane", m_wndBiSplitter.GetView(11))
   )

   {
      m_wndBiSplitter.DestroyWindow();
      return FALSE;
   }

   return TRUE;
}

After the panes have been created, you can set the gap position and width by using the SetSplitterPos and SetSplitterGap functions. The HidePane and ShowPane functions allow you to hide or show either of the panes.

Creating a BiSplitter Project

You can use the current version of BiSplitter in the VC++.NET 2003 or VC++ 6.0 environment. To create a BiSplitter application, you should create an MFC project, write code for the BiSplitter initialization, and attach the BiSplitter.h and BiSplitter.cpp files.

It's easiest to create the BiSplitter project by using the MFC Application Wizard. You start to create a BiSplitter application by creating an MFC application in the Windows Explorer style. After this, go to the MainFrm.h file and replace the following line:

CSplitterWnd m_wndSplitter;

with this line:

CBiSplitterWnd m_wndSplitter;

Then, go to the CMainFrame::OnCreateClient function and rewrite its body to create a BiSplitter window. After this, go to the CMainFrame::GetRightPane function and replace this line:

CWnd* pWnd = m_wndSplitter.GetPane(0, 1);

with the new line:

CWnd* pWnd = m_wndSplitter.GetPaneView(1);

Then, include the BiSplitter.h file in the MainFrm.cpp and <application name>.cpp files. You have to include this file before the #include "MainFrm.h" line.



About the Author

Sergey Polyakov

I am a software developer. My major skills include programming in C++, .Net/C#, Delphi, HTML/JavaScript. I am originally from Kiev, Ukraine. I have an applied mathematics degree in computer science from the Kiev National Taras Shevchenko University (1985) in Ukraine. After graduating from university, I was a software engineer at the Glushkov Institute of Cybernetics NAS Ukraine. I joined to the department of cybernetics of National Taras Shevchenko University at 1990 as a researcher in the database group. Since 1995 I work as telecommuter and freelancer. I like swimming, hiking and travelling. My personal internet page is http://polyakov.50webs.com

Downloads

Comments

  • compiling under Visual Studio 2008

    Posted by richbl on 03/23/2009 11:24am

    For anyone interested in VS2008 compiles, the solution is to replace the defines in BiSplitterWnd.cpp after the line /***************************************************************************************************************/
    /** follow definitions were copied from file \Microsoft Visual Studio .NET 2003\Vc7\atlmfc\src\mfc\afximpl.h  **/
    
    with the equivalent defines found in the updated afximpl.h found in C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src\mfc\afximpl.h
    
    Thanks to Sergey for this code.
    
    rich

    • VS 2008

      Posted by maxbld on 12/01/2009 10:57am

      I've put the following:
      
      /**/ #if (_MSC_VER == 1200) /* VS 6 */
      /**/ #define AFX_WNDCLASS(s) _T("Afx") _T(s) _T("42") _STATIC_SUFFIX _UNICODE_SUFFIX 
      
      _DEBUG_SUFFIX
      /**/ #elif (_MSC_VER == 1310) /* VS .NET 2003 */
      /**/ #define AFX_WNDCLASS(s) _T("Afx") _T(s) _T("70") _STATIC_SUFFIX _UNICODE_SUFFIX 
      
      _DEBUG_SUFFIX
      /**/ #elif (_MSC_VER == 1400) /* VS 2005 */ 
      /**/ #define AFX_WNDCLASS(s) _T("Afx") _T(s) _T("80") _STATIC_SUFFIX _UNICODE_SUFFIX 
      
      _DEBUG_SUFFIX 
      /**/ #elif (_MSC_VER == 1500) /* VS 2008 */ 
      /**/ #define AFX_WNDCLASS(s) _T("Afx") _T(s) _T(_MFC_FILENAME_VER) _STATIC_SUFFIX 
      
      _UNICODE_SUFFIX _DEBUG_SUFFIX
      /**/ #else
      /**/ #error Unsupported version of MFC
      /**/ #endif
      /**/ 
      #define AFX_WND             AFX_WNDCLASS("Wnd")
      #define AFX_WNDCONTROLBAR   AFX_WNDCLASS("ControlBar")
      #define AFX_WNDMDIFRAME     AFX_WNDCLASS("MDIFrame")
      #define AFX_WNDFRAMEORVIEW  AFX_WNDCLASS("FrameOrView")
      #define AFX_WNDOLECONTROL   AFX_WNDCLASS("OleControl")
      
      /**/ #define AFX_WNDMDIFRAME_REG                             0x00004
      // #define AFX_WNDMDIFRAME     AFX_WNDCLASS("MDIFrame")
      /**/ #define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)
      /**/ BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister);
      /**/ #define _AfxGetDlgCtrlID(hWnd)          ((UINT)(WORD)::GetDlgCtrlID(hWnd))
      
      Also, using XP, i had to do also this change:
      
      FROM:
      
          NONCLIENTMETRICS metrics;
      	metrics.cbSize=sizeof(NONCLIENTMETRICS);
      	SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &metrics, 
      
      0);
      
      TO:
      
      	// System metrics
      	// Get os version 
      	OSVERSIONINFO osvi;
      	ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
      	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 
      	GetVersionEx(&osvi); 
      	BOOL bIsWindowsBeforeVista = osvi.dwMajorVersion < 6; 
      	// Get the system window message font for use in the cancel button and text area
      	NONCLIENTMETRICS metrics;
      	metrics.cbSize = sizeof(NONCLIENTMETRICS);
      	if (bIsWindowsBeforeVista) metrics.cbSize -= sizeof(int);
      	VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0));

      Reply
    Reply
  • Sergey Polyakov ,urgent!please help me!

    Posted by flyingco on 02/13/2008 08:40am

    when does your CBiSplitterWnd support vs2005? when i use CBiSplitterWnd on vs2005 ,it failed . can you upload a version which support vs2005? I am a college student who urgently needs your help. thanks a lot!

    Reply
  • Cannot restore splitter position for FIXED1 style BiSplitterWnd

    Posted by shallyee on 02/11/2005 08:28pm

    Excellent class. This is what I'm searching for a long time. A little problem. I guess I can make the right pane fixed by assigning a FIXED1 style. I did that, it works. But if the width of the whole window grows, right pane always disappeared.

    BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) 
    {
        if (!m_wndBiSplitter.Create(this, VSPLITTER | FIXED1 | VIEW3D ))
            return FALSE;
        ......
    
        int nWidth = pApp->GetProfileInt(_T("Settings"), _T("SplitterWidth"), 100);
        m_wndBiSplitter.SetSplitterPos(nWidth);
            // SetSplitterPos(1045) does not work as expect
    }
    
    
    void CMainFrame::OnDestroy() 
    {
        CFrameWnd::OnDestroy();
        ......
    
        pApp->WriteProfileInt(_T("Settings"), _T("SplitterWidth"), m_wndBiSplitter.GetSplitterPos());
            //if I zoomed the whole window then exist, GetSplitterPos() returns 1045
            // (I have a 1280x1024 display)
    }

    Reply
  • Memory Leak!?

    Posted by noldman on 07/13/2004 12:51am

    although we can override PostNcDestroy in our CWnd-Derived class,and the code like this: void CYourWnd::PostNcDestroy { delete this; } but i think the style is ugly(althought in MFC the implementation of CView::PostNcDestroy also like this)

    Reply
  • Memory Leak!?

    Posted by noldman on 07/12/2004 10:27pm

    when the view type of some pane is CWnd(or CWnd-Derived),the memory of the view is not deleted! please forgive my broken english.

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

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

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