// MinSplitterWnd.cpp : implementation file
//
#include "stdafx.h"
#include <afxpriv.h> // For AFX_SIZEPARENTPARAMS and AfxRepositionWindow
#include "MinSplitterWnd.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//==============================================================================
//
// Kludges because we don't have access to mfc\src.
//
//==============================================================================
// From afximpl.h and auxdata.cpp
// Note: afxData.cxBorder and afxData.cyBorder aren't used anymore
#define CX_BORDER 1
#define CY_BORDER 1
struct _AFXDATA
{
int cxBorder2, cyBorder2;
BOOL bWin4; // TRUE if Windows 4.0
BOOL bNotWin4; // TRUE if not Windows 4.0
_AFXDATA() // From auxdata.cpp
{
// Cache various target platform version information
DWORD dwVersion = ::GetVersion();
bWin4 = (BYTE)dwVersion >= 4;
bNotWin4 = 1 - bWin4; // for convenience
// cxBorder2 and cyBorder are 2x borders for Win4
cxBorder2 = bWin4 ? CX_BORDER*2 : CX_BORDER;
cyBorder2 = bWin4 ? CY_BORDER*2 : CY_BORDER;
}
} afxData;
// From winsplit.cpp...
// HitTest return values (values and spacing between values is important)
enum HitTestValue
{
noHit = 0,
vSplitterBox = 1,
hSplitterBox = 2,
bothSplitterBox = 3, // just for keyboard
vSplitterBar1 = 101,
vSplitterBar15 = 115,
hSplitterBar1 = 201,
hSplitterBar15 = 215,
splitterIntersection1 = 301,
splitterIntersection225 = 525
};
//==============================================================================
//
// End of Kludges.
//
//==============================================================================
/////////////////////////////////////////////////////////////////////////////
// CMinSplitterWnd
CMinSplitterWnd::CMinSplitterWnd()
{
}
CMinSplitterWnd::~CMinSplitterWnd()
{
}
BEGIN_MESSAGE_MAP(CMinSplitterWnd, CSplitterWnd)
//{{AFX_MSG_MAP(CMinSplitterWnd)
ON_WM_MOUSEMOVE()
ON_WM_WINDOWPOSCHANGING()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMinSplitterWnd message handlers
void CMinSplitterWnd::OnMouseMove(UINT nFlags, CPoint point)
{
if ( m_bTracking && GetCapture() == this )
{
// Work out which panes are left or above the splitter (horiz and vert).
bool bSizingCol = false;
bool bSizingRow = false;
int nCol;
int nRow;
if ( m_htTrack >= hSplitterBar1 && m_htTrack <= hSplitterBar15 )
{
nCol = m_htTrack - hSplitterBar1;
bSizingCol = true;
}
else if ( m_htTrack >= vSplitterBar1 && m_htTrack <= vSplitterBar15 )
{
nRow = m_htTrack - vSplitterBar1;
bSizingRow = true;
}
else if ( m_htTrack >= splitterIntersection1 && m_htTrack <= splitterIntersection225 )
{
nCol = ( m_htTrack - splitterIntersection1 ) % 15;
nRow = ( m_htTrack - splitterIntersection1 ) / 15;
bSizingCol = true;
bSizingRow = true;
} // if
// Get client rect for limit calculations.
CRect rectClient;
GetClientRect( rectClient );
point.Offset( m_ptTrackOffset ); // point is the upper right of hit detect
// Limit row.
if ( bSizingRow )
{
int nLimit1 = m_cyBorder; // Start with top border.
// If top splitter...
if ( nRow == 0 )
{
nLimit1 += m_pRowInfo[ 0 ].nMinSize; // ...just add first row minimum size.
}
// If pane above splitter at minimum size...
else if ( m_pRowInfo[ nRow ].nCurSize == m_pRowInfo[ nRow ].nMinSize )
{
for ( int i = 0; i < nRow; i++ )
{
nLimit1 += m_pRowInfo[ i ].nCurSize; // ...add previous rows' sizes and splitters.
nLimit1 += m_cySplitter;
} // for
nLimit1 += m_pRowInfo[ i ].nCurSize;
}
// Otherwise...
else
{
for ( int i = 0; i < nRow; i++ )
{
nLimit1 += m_pRowInfo[ i ].nMinSize; // ...add previous rows' minimum sizes and splitters.
nLimit1 += m_cySplitter;
} // for
nLimit1 += m_pRowInfo[ i ].nMinSize;
} // if
int nLimit2 = rectClient.bottom; // Start with bottom.
nLimit2 -= m_cyBorder; // Take off bottom border.
// If bottom splitter...
if ( nRow + 1 == m_nRows - 1 )
{
nLimit2 -= m_pRowInfo[ nRow + 1 ].nMinSize; // ...just take off last row minimum size.
}
// Otherwise...
else
{
for ( int i = m_nRows - 1; i > nRow + 1; i-- )
{
nLimit2 -= m_pRowInfo[ i ].nMinSize; // ...take off following rows' minimum sizes and splitters.
nLimit2 -= m_cySplitter;
} // for
nLimit2 -= m_pRowInfo[ i ].nMinSize;
} // if
nLimit2 -= m_cySplitter / 2; // Take off half a splitter.
if ( point.y < nLimit1 + m_cySplitter / 2 - 2 )
{
point.y = nLimit1 + m_cySplitter / 2 - 2;
} // if
if ( point.y > nLimit2 - m_cySplitter / 2 )
{
point.y = nLimit2 - m_cySplitter / 2;
} // if
} // if
// Limit column.
if ( bSizingCol )
{
int nLimit1 = 0;// = m_cxBorder; // Start with left border.
// If left splitter...
if ( nCol == 0 )
{
nLimit1 += m_pColInfo[ 0 ].nMinSize; // ...just add first column minimum size.
}
// If pane left of splitter at minimum size...
else if ( m_pColInfo[ nCol ].nCurSize == m_pColInfo[ nCol ].nMinSize )
{
for ( int i = 0; i < nCol; i++ )
{
nLimit1 += m_pColInfo[ i ].nCurSize; // ...add previous columns' sizes and splitters.
nLimit1 += m_cxSplitter;
} // for
nLimit1 += m_pColInfo[ i ].nCurSize;
}
// Otherwise...
else
{
for ( int i = 0; i < nCol; i++ )
{
nLimit1 += m_pColInfo[ i ].nMinSize; // ...add previous columns' minimum sizes and splitters.
nLimit1 += m_cxSplitter;
} // for
nLimit1 += m_pColInfo[ i ].nMinSize; // Minimum height of each column,
} // if
int nLimit2 = rectClient.right; // Start with right.
nLimit2 -= m_cxBorder; // Take off right border,
// If right splitter...
if ( nCol + 1 == m_nCols - 1 )
{
nLimit2 -= m_pColInfo[ nCol + 1 ].nMinSize; // ...just take off last column minimum size.
}
// Otherwise...
else
{
for ( int i = m_nCols - 1; i > nCol + 1; i-- )
{
nLimit2 -= m_pColInfo[ i ].nMinSize; // ...take off following columns' minimum sizes and splitters.
nLimit2 -= m_cxSplitter;
} // for
nLimit2 -= m_pColInfo[ i ].nMinSize;
} // if
nLimit2 -= m_cxSplitter / 2; // Take off half a splitter,
if ( point.x < nLimit1/* + m_cxSplitter / 2 - 2*/ )
{
point.x = nLimit1 /*+ m_cxSplitter / 2 - 2*/;
} // if
if ( point.x > nLimit2 - m_cxSplitter / 2 )
{
point.x = nLimit2 - m_cxSplitter / 2;
} // if
} // if
// Restore offset 'cos CSplitterWnd::OnMouseMove will do it again.
point.Offset( -m_ptTrackOffset ); // point is the upper right of hit detect
} // if
// Call base class.
CSplitterWnd::OnMouseMove(nFlags, point);
}
int CMinSplitterWnd::GetMinClientWidth()
{
// If no columns, no width.
if ( m_pColInfo == NULL )
{
return 0;
} // if
// Min width is...
int nMinWidth = m_cxBorder; // Left border,
for ( int nCol = 0; nCol < m_nCols; nCol++ )
{
nMinWidth += m_pColInfo[ nCol ].nMinSize; // Minimum width of each column,
if ( nCol < m_nCols - 1 )
{
nMinWidth += m_cxSplitter; // Width of splitter for each column except the last,
} // if
} // for
nMinWidth += m_cxBorder; // Right border.
return nMinWidth;
}
int CMinSplitterWnd::GetMinClientHeight()
{
// If no rows, no height.
if ( m_pRowInfo == NULL )
{
return 0;
} // if
// Min height is...
int nMinHeight = m_cyBorder; // Top border,
for ( int nRow =