Minimum size splitter
Posted
by Graham Lyus
on August 25th, 1998
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.

Comments
vPqkc dFn vELg
Posted by zzZMKBwvMM on 04/06/2013 02:16pmtramadol online buy tramadol online overnight mastercard - tramadol for dogs vs tramadol for humans
Replya simple way ...
Posted by FDogY on 06/08/2004 09:25amFirst of all: Putting the variable nIdealSize by SetColumnInfo() or SetRowInfo() serves only as an initial setting! nIdealSize is always updated with the current value of the partial window after the first drawing. Use only this value. In this context the additional variable nCurSize leads to confusion. Forget about this. Here is the really short solution for the "minimum size splitter"-problem: 1. you create a class which is derived from CSplitterWnd 2. overwrite the function RecalcLayout() as follows: void CMySplitterWnd::RecalcLayout(){ for (int i = 0; i < m_nCols; i++) { // Check all columns if ( m_pColInfo[i].nIdealSize < m_pColInfo[i].nMinSize ) { m_pColInfo[i].nIdealSize=m_pColInfo[i].nMinSize; } } for (int i = 0; i < m_nRows; i++) { // Check all rows if ( m_pRowInfo[i].nIdealSize < m_pRowInfo[i].nMinSize ) { m_pRowInfo[i].nIdealSize=m_pRowInfo[i].nMinSize; } } CSplitterWnd::RecalcLayout(); } 3. create an object of your class (CMySpliterWnd m_SplitterWnd) 4. after creating the SplitterWindow set the (initial) IdealSize value (e.g. 150) and the MinimalSize (e.g. 20) m_SplitterWnd.SetColumnInfo(0, 150, 20); m_SplitterWnd.SetRowInfo(0, 150, 20); readyReplyGreate work... How can I do the same in VB
Posted by Legacy on 06/03/2002 12:00amOriginally posted by: Navneet Gupta
Hey Dude !
Great wrok ..
I want to implement the same thing in Visual Basic can you guide me how can I do this.
ReplyU do a pretty work.There is a Bug in Dynamic Split
Posted by Legacy on 12/14/2001 12:00amOriginally posted by: zsj
U do a good job,But When I create a dynamic split with CScrollView ,the Splitbar stop in wrong position ,I Think You may make a wrong that U have not considered the size of ScrollBox .
Replysimpler solution continued...
Posted by Legacy on 08/20/2001 12:00amOriginally posted by: Alan Kang
ReplyAn even simple solution .....
Posted by Legacy on 10/08/1999 12:00amOriginally posted by: Vinayak Tadas
ReplyThank U mail
Posted by Legacy on 09/20/1999 12:00amOriginally posted by: wowow
This is the article what I was looking for.
The 'minimum size splitter' may not be very useful for most people, but there's always somebody really, really needs it.( eg., me! )
I thank U again and I expect many other useful articles from U and the CodeGuru.
Reply