Minimum size splitter

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

For my latest project we needed splitter panes that had proper
minimum sizes, in that the user couldn’t physically resize the
splitter pane smaller than a specified amount. The standard MFC
splitter class allows you to set minimum sizes, but these only
affect what is displayed, not how small the panes can be.
CMinSplitterWnd is a drop-in replacement for (and is derived
from) CSplitterWnd.

Instructions:

  1. Add MinSplitterWnd.cpp and MinSplitterWnd.h
    to your current project (e.g. Menu Project->Add to
    project->Add files).
  2. Where you currently use CSplitterWnd, replace
    with CMinSplitterWnd (Note: remember to include MinSplitterWnd.h):
  3. #include "MinSplitterWnd.h" // Minimum size splitter.
    ....
    class CMyWnd : public CMDIChildWnd
    {
        ....
        CMinSplitterWnd m_wndSplitter;
        ....
    };
    
  4. Call SetRowInfo and SetColumnInfo as
    necessary, specifying the required minimum row and column
    sizes: (this is normally done in the parent window’s OnCreateClient function)
  5. ....
    m_wndSplitter.CreateStatic( this, 2, 2 );      // Create with 2 rows and 2 columns.
    m_wndSplitter.SetRowInfo( 0, 100, 100 );       // Set ideal and minimum size to 100.
    m_wndSplitter.SetRowInfo( 1, 100, 100 );       // Set ideal and minimum size to 100.
    m_wndSplitter.SetColumnInfo( 0, 100, 100 );    // Set ideal and minimum size to 100.
    m_wndSplitter.SetColumnInfo( 1, 100, 100 );    // Set ideal and minimum size to 100.
    ....
    
  6. In the splitter’s parent window, add a message handler
    for OnWindowPosChanging (this prevents the user
    from sizing the window too small) and add the following
    code to it:
  7. void CMyWnd::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
    {
    	//	Don't do anything if minimized.
    	if ( IsIconic() )
    	{
    		CMDIChildWnd::OnWindowPosChanging( lpwndpos );
    		return;
    	} // if
    
    	//	Calculate the window rect if we have no client area.
    	CRect rc( 0, 0, 0, 0 );
    	CalcWindowRect( rc );
    
    	//	Add on the minimum client width and height from the splitter.
    	int nMinWidth	= rc.Width() + m_wndSplitter.GetMinClientWidth();
    	int nMinHeight	= rc.Height() + m_wndSplitter.GetMinClientHeight();
    
    	//	Get the current window size.
    	CRect rcWindow;
    	GetWindowRect( rcWindow );
    	GetParent()->ScreenToClient( rcWindow );
    
    	//	If trying to size too small...
    	if ( lpwndpos->cx < nMinWidth )
    	{
    		//	If dragging left border right...
    		if ( rcWindow.left < lpwndpos->x )
    		{
    			//	How much over are we?
    			int nOver = nMinWidth - lpwndpos->cx;
    
    			//	Adjust left coord.
    			lpwndpos->x -= nOver;
    
    		} // if
    
    		//	Fix width.
    		lpwndpos->cx = nMinWidth;
    	} // if
    
    	//	If trying to size too small...
    	if ( lpwndpos->cy < nMinHeight )
    	{
    		//	If dragging top border down...
    		if ( rcWindow.top < lpwndpos->y )
    		{
    			//	How much over are we?
    			int nOver = nMinHeight - lpwndpos->cy;
    
    			//	Adjust left coord.
    			lpwndpos->y -= nOver;
    		} // if
    
    		//	Fix height.
    		lpwndpos->cy = nMinHeight;
    	} // if
    }
    
  8. That’s it!

Limitation:

If the minimum sizes exceed the initial frame window size, the window will
snap when the window is first resized.

Download demo project and executable – 36 KB

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read