
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:
- Add MinSplitterWnd.cpp and MinSplitterWnd.h
to your current project (e.g. Menu Project->Add to
project->Add files). - Where you currently use CSplitterWnd, replace
with CMinSplitterWnd (Note: remember to include MinSplitterWnd.h): - 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) - 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: - That’s it!
#include "MinSplitterWnd.h" // Minimum size splitter.
....
class CMyWnd : public CMDIChildWnd
{
....
CMinSplitterWnd m_wndSplitter;
....
};
....
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.
....
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
}
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