2021-01-02 02:46:39 +00:00
// Windows Template Library - WTL version 10.0
// Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
2008-09-18 03:15:49 +00:00
//
// This file is a part of the Windows Template Library.
// The use and distribution terms for this software are covered by the
2021-01-02 02:46:39 +00:00
// Microsoft Public License (http://opensource.org/licenses/MS-PL)
// which can be found in the file MS-PL.txt at the root folder.
2008-09-18 03:15:49 +00:00
# ifndef __ATLSPLIT_H__
# define __ATLSPLIT_H__
# pragma once
# ifndef __ATLAPP_H__
# error atlsplit.h requires atlapp.h to be included first
# endif
# ifndef __ATLWIN_H__
# error atlsplit.h requires atlwin.h to be included first
# endif
///////////////////////////////////////////////////////////////////////////////
// Classes in this file:
//
2021-01-02 02:46:39 +00:00
// CSplitterImpl<T>
// CSplitterWindowImpl<T, TBase, TWinTraits>
// CSplitterWindowT<t_bVertical> - CSplitterWindow, CHorSplitterWindow
2008-09-18 03:15:49 +00:00
namespace WTL
{
///////////////////////////////////////////////////////////////////////////////
// CSplitterImpl - Provides splitter support to any window
// Splitter panes constants
# define SPLIT_PANE_LEFT 0
# define SPLIT_PANE_RIGHT 1
# define SPLIT_PANE_TOP SPLIT_PANE_LEFT
# define SPLIT_PANE_BOTTOM SPLIT_PANE_RIGHT
# define SPLIT_PANE_NONE -1
// Splitter extended styles
# define SPLIT_PROPORTIONAL 0x00000001
# define SPLIT_NONINTERACTIVE 0x00000002
# define SPLIT_RIGHTALIGNED 0x00000004
# define SPLIT_BOTTOMALIGNED SPLIT_RIGHTALIGNED
2015-01-23 00:32:27 +00:00
# define SPLIT_GRADIENTBAR 0x00000008
2021-01-02 02:46:39 +00:00
# define SPLIT_FLATBAR 0x00000020
2015-01-23 00:32:27 +00:00
# define SPLIT_FIXEDBARSIZE 0x00000010
2008-09-18 03:15:49 +00:00
// Note: SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED/SPLIT_BOTTOMALIGNED are
2021-01-02 02:46:39 +00:00
// mutually exclusive. If both are set, splitter defaults to SPLIT_PROPORTIONAL.
// Also, SPLIT_FLATBAR overrides SPLIT_GRADIENTBAR if both are set.
2008-09-18 03:15:49 +00:00
2021-01-02 02:46:39 +00:00
template < class T >
2008-09-18 03:15:49 +00:00
class CSplitterImpl
{
public :
2021-01-02 02:46:39 +00:00
enum { m_nPanesCount = 2 , m_nPropMax = INT_MAX , m_cxyStep = 10 } ;
2008-09-18 03:15:49 +00:00
2021-01-02 02:46:39 +00:00
bool m_bVertical ;
2008-09-18 03:15:49 +00:00
HWND m_hWndPane [ m_nPanesCount ] ;
RECT m_rcSplitter ;
2021-01-02 02:46:39 +00:00
int m_xySplitterPos ; // splitter bar position
int m_xySplitterPosNew ; // internal - new position while moving
HWND m_hWndFocusSave ;
2008-09-18 03:15:49 +00:00
int m_nDefActivePane ;
int m_cxySplitBar ; // splitter bar width/height
2021-01-02 02:46:39 +00:00
HCURSOR m_hCursor ;
2008-09-18 03:15:49 +00:00
int m_cxyMin ; // minimum pane size
int m_cxyBarEdge ; // splitter bar edge
bool m_bFullDrag ;
2021-01-02 02:46:39 +00:00
int m_cxyDragOffset ; // internal
2008-09-18 03:15:49 +00:00
int m_nProportionalPos ;
bool m_bUpdateProportionalPos ;
2021-01-02 02:46:39 +00:00
DWORD m_dwExtendedStyle ; // splitter specific extended styles
int m_nSinglePane ; // single pane mode
int m_xySplitterDefPos ; // default position
bool m_bProportionalDefPos ; // porportinal def pos
2008-09-18 03:15:49 +00:00
// Constructor
2021-01-02 02:46:39 +00:00
CSplitterImpl ( bool bVertical = true ) :
m_bVertical ( bVertical ) , m_xySplitterPos ( - 1 ) , m_xySplitterPosNew ( - 1 ) , m_hWndFocusSave ( NULL ) ,
m_nDefActivePane ( SPLIT_PANE_NONE ) , m_cxySplitBar ( 4 ) , m_hCursor ( NULL ) , m_cxyMin ( 0 ) , m_cxyBarEdge ( 0 ) ,
m_bFullDrag ( true ) , m_cxyDragOffset ( 0 ) , m_nProportionalPos ( 0 ) , m_bUpdateProportionalPos ( true ) ,
m_dwExtendedStyle ( SPLIT_PROPORTIONAL ) , m_nSinglePane ( SPLIT_PANE_NONE ) ,
m_xySplitterDefPos ( - 1 ) , m_bProportionalDefPos ( false )
2008-09-18 03:15:49 +00:00
{
m_hWndPane [ SPLIT_PANE_LEFT ] = NULL ;
m_hWndPane [ SPLIT_PANE_RIGHT ] = NULL ;
: : SetRectEmpty ( & m_rcSplitter ) ;
}
// Attributes
void SetSplitterRect ( LPRECT lpRect = NULL , bool bUpdate = true )
{
if ( lpRect = = NULL )
{
T * pT = static_cast < T * > ( this ) ;
pT - > GetClientRect ( & m_rcSplitter ) ;
}
else
{
m_rcSplitter = * lpRect ;
}
if ( IsProportional ( ) )
UpdateProportionalPos ( ) ;
else if ( IsRightAligned ( ) )
UpdateRightAlignPos ( ) ;
if ( bUpdate )
UpdateSplitterLayout ( ) ;
}
void GetSplitterRect ( LPRECT lpRect ) const
{
ATLASSERT ( lpRect ! = NULL ) ;
* lpRect = m_rcSplitter ;
}
bool SetSplitterPos ( int xyPos = - 1 , bool bUpdate = true )
{
2021-01-02 02:46:39 +00:00
if ( xyPos = = - 1 ) // -1 == default position
2008-09-18 03:15:49 +00:00
{
2021-01-02 02:46:39 +00:00
if ( m_bProportionalDefPos )
{
ATLASSERT ( ( m_xySplitterDefPos > = 0 ) & & ( m_xySplitterDefPos < = m_nPropMax ) ) ;
if ( m_bVertical )
xyPos = : : MulDiv ( m_xySplitterDefPos , m_rcSplitter . right - m_rcSplitter . left - m_cxySplitBar - m_cxyBarEdge , m_nPropMax ) ;
else
xyPos = : : MulDiv ( m_xySplitterDefPos , m_rcSplitter . bottom - m_rcSplitter . top - m_cxySplitBar - m_cxyBarEdge , m_nPropMax ) ;
}
else if ( m_xySplitterDefPos ! = - 1 )
{
xyPos = m_xySplitterDefPos ;
}
else // not set, use middle position
{
if ( m_bVertical )
xyPos = ( m_rcSplitter . right - m_rcSplitter . left - m_cxySplitBar - m_cxyBarEdge ) / 2 ;
else
xyPos = ( m_rcSplitter . bottom - m_rcSplitter . top - m_cxySplitBar - m_cxyBarEdge ) / 2 ;
}
2008-09-18 03:15:49 +00:00
}
// Adjust if out of valid range
int cxyMax = 0 ;
2021-01-02 02:46:39 +00:00
if ( m_bVertical )
2008-09-18 03:15:49 +00:00
cxyMax = m_rcSplitter . right - m_rcSplitter . left ;
else
cxyMax = m_rcSplitter . bottom - m_rcSplitter . top ;
if ( xyPos < m_cxyMin + m_cxyBarEdge )
xyPos = m_cxyMin ;
else if ( xyPos > ( cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin ) )
xyPos = cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin ;
// Set new position and update if requested
bool bRet = ( m_xySplitterPos ! = xyPos ) ;
m_xySplitterPos = xyPos ;
if ( m_bUpdateProportionalPos )
{
if ( IsProportional ( ) )
StoreProportionalPos ( ) ;
else if ( IsRightAligned ( ) )
StoreRightAlignPos ( ) ;
}
else
{
m_bUpdateProportionalPos = true ;
}
if ( bUpdate & & bRet )
UpdateSplitterLayout ( ) ;
return bRet ;
}
2021-01-02 02:46:39 +00:00
int GetSplitterPos ( ) const
{
return m_xySplitterPos ;
}
2008-09-18 03:15:49 +00:00
void SetSplitterPosPct ( int nPct , bool bUpdate = true )
{
2021-01-02 02:46:39 +00:00
ATLASSERT ( ( nPct > = 0 ) & & ( nPct < = 100 ) ) ;
2008-09-18 03:15:49 +00:00
m_nProportionalPos = : : MulDiv ( nPct , m_nPropMax , 100 ) ;
UpdateProportionalPos ( ) ;
if ( bUpdate )
UpdateSplitterLayout ( ) ;
}
2021-01-02 02:46:39 +00:00
int GetSplitterPosPct ( ) const
2008-09-18 03:15:49 +00:00
{
2021-01-02 02:46:39 +00:00
int cxyTotal = m_bVertical ? ( m_rcSplitter . right - m_rcSplitter . left - m_cxySplitBar - m_cxyBarEdge ) : ( m_rcSplitter . bottom - m_rcSplitter . top - m_cxySplitBar - m_cxyBarEdge ) ;
return ( ( cxyTotal > 0 ) & & ( m_xySplitterPos > = 0 ) ) ? : : MulDiv ( m_xySplitterPos , 100 , cxyTotal ) : - 1 ;
2008-09-18 03:15:49 +00:00
}
bool SetSinglePaneMode ( int nPane = SPLIT_PANE_NONE )
{
2021-01-02 02:46:39 +00:00
ATLASSERT ( ( nPane = = SPLIT_PANE_LEFT ) | | ( nPane = = SPLIT_PANE_RIGHT ) | | ( nPane = = SPLIT_PANE_NONE ) ) ;
if ( ! ( ( nPane = = SPLIT_PANE_LEFT ) | | ( nPane = = SPLIT_PANE_RIGHT ) | | ( nPane = = SPLIT_PANE_NONE ) ) )
2008-09-18 03:15:49 +00:00
return false ;
if ( nPane ! = SPLIT_PANE_NONE )
{
2021-01-02 02:46:39 +00:00
if ( : : IsWindowVisible ( m_hWndPane [ nPane ] ) = = FALSE )
2008-09-18 03:15:49 +00:00
: : ShowWindow ( m_hWndPane [ nPane ] , SW_SHOW ) ;
int nOtherPane = ( nPane = = SPLIT_PANE_LEFT ) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT ;
: : ShowWindow ( m_hWndPane [ nOtherPane ] , SW_HIDE ) ;
if ( m_nDefActivePane ! = nPane )
m_nDefActivePane = nPane ;
}
else if ( m_nSinglePane ! = SPLIT_PANE_NONE )
{
int nOtherPane = ( m_nSinglePane = = SPLIT_PANE_LEFT ) ? SPLIT_PANE_RIGHT : SPLIT_PANE_LEFT ;
: : ShowWindow ( m_hWndPane [ nOtherPane ] , SW_SHOW ) ;
}
m_nSinglePane = nPane ;
UpdateSplitterLayout ( ) ;
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
return true ;
}
int GetSinglePaneMode ( ) const
{
return m_nSinglePane ;
}
DWORD GetSplitterExtendedStyle ( ) const
{
return m_dwExtendedStyle ;
}
DWORD SetSplitterExtendedStyle ( DWORD dwExtendedStyle , DWORD dwMask = 0 )
{
DWORD dwPrevStyle = m_dwExtendedStyle ;
if ( dwMask = = 0 )
m_dwExtendedStyle = dwExtendedStyle ;
else
m_dwExtendedStyle = ( m_dwExtendedStyle & ~ dwMask ) | ( dwExtendedStyle & dwMask ) ;
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
# ifdef _DEBUG
if ( IsProportional ( ) & & IsRightAligned ( ) )
ATLTRACE2 ( atlTraceUI , 0 , _T ( " CSplitterImpl::SetSplitterExtendedStyle - SPLIT_PROPORTIONAL and SPLIT_RIGHTALIGNED are mutually exclusive, defaulting to SPLIT_PROPORTIONAL. \n " ) ) ;
# endif // _DEBUG
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
return dwPrevStyle ;
}
2021-01-02 02:46:39 +00:00
void SetSplitterDefaultPos ( int xyPos = - 1 )
{
m_xySplitterDefPos = xyPos ;
m_bProportionalDefPos = false ;
}
void SetSplitterDefaultPosPct ( int nPct )
{
ATLASSERT ( ( nPct > = 0 ) & & ( nPct < = 100 ) ) ;
m_xySplitterDefPos = : : MulDiv ( nPct , m_nPropMax , 100 ) ;
m_bProportionalDefPos = true ;
}
2008-09-18 03:15:49 +00:00
// Splitter operations
void SetSplitterPanes ( HWND hWndLeftTop , HWND hWndRightBottom , bool bUpdate = true )
{
m_hWndPane [ SPLIT_PANE_LEFT ] = hWndLeftTop ;
m_hWndPane [ SPLIT_PANE_RIGHT ] = hWndRightBottom ;
2021-01-02 02:46:39 +00:00
ATLASSERT ( ( m_hWndPane [ SPLIT_PANE_LEFT ] = = NULL ) | | ( m_hWndPane [ SPLIT_PANE_RIGHT ] = = NULL ) | | ( m_hWndPane [ SPLIT_PANE_LEFT ] ! = m_hWndPane [ SPLIT_PANE_RIGHT ] ) ) ;
2008-09-18 03:15:49 +00:00
if ( bUpdate )
UpdateSplitterLayout ( ) ;
}
bool SetSplitterPane ( int nPane , HWND hWnd , bool bUpdate = true )
{
2021-01-02 02:46:39 +00:00
ATLASSERT ( ( nPane = = SPLIT_PANE_LEFT ) | | ( nPane = = SPLIT_PANE_RIGHT ) ) ;
if ( ( nPane ! = SPLIT_PANE_LEFT ) & & ( nPane ! = SPLIT_PANE_RIGHT ) )
2008-09-18 03:15:49 +00:00
return false ;
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
m_hWndPane [ nPane ] = hWnd ;
2021-01-02 02:46:39 +00:00
ATLASSERT ( ( m_hWndPane [ SPLIT_PANE_LEFT ] = = NULL ) | | ( m_hWndPane [ SPLIT_PANE_RIGHT ] = = NULL ) | | ( m_hWndPane [ SPLIT_PANE_LEFT ] ! = m_hWndPane [ SPLIT_PANE_RIGHT ] ) ) ;
2008-09-18 03:15:49 +00:00
if ( bUpdate )
UpdateSplitterLayout ( ) ;
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
return true ;
}
HWND GetSplitterPane ( int nPane ) const
{
2021-01-02 02:46:39 +00:00
ATLASSERT ( ( nPane = = SPLIT_PANE_LEFT ) | | ( nPane = = SPLIT_PANE_RIGHT ) ) ;
if ( ( nPane ! = SPLIT_PANE_LEFT ) & & ( nPane ! = SPLIT_PANE_RIGHT ) )
return NULL ;
2008-09-18 03:15:49 +00:00
return m_hWndPane [ nPane ] ;
}
bool SetActivePane ( int nPane )
{
2021-01-02 02:46:39 +00:00
ATLASSERT ( ( nPane = = SPLIT_PANE_LEFT ) | | ( nPane = = SPLIT_PANE_RIGHT ) ) ;
if ( ( nPane ! = SPLIT_PANE_LEFT ) & & ( nPane ! = SPLIT_PANE_RIGHT ) )
2008-09-18 03:15:49 +00:00
return false ;
2021-01-02 02:46:39 +00:00
if ( ( m_nSinglePane ! = SPLIT_PANE_NONE ) & & ( nPane ! = m_nSinglePane ) )
2008-09-18 03:15:49 +00:00
return false ;
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
: : SetFocus ( m_hWndPane [ nPane ] ) ;
m_nDefActivePane = nPane ;
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
return true ;
}
int GetActivePane ( ) const
{
int nRet = SPLIT_PANE_NONE ;
HWND hWndFocus = : : GetFocus ( ) ;
if ( hWndFocus ! = NULL )
{
for ( int nPane = 0 ; nPane < m_nPanesCount ; nPane + + )
{
2021-01-02 02:46:39 +00:00
if ( ( hWndFocus = = m_hWndPane [ nPane ] ) | | ( : : IsChild ( m_hWndPane [ nPane ] , hWndFocus ) ! = FALSE ) )
2008-09-18 03:15:49 +00:00
{
nRet = nPane ;
break ;
}
}
}
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
return nRet ;
}
bool ActivateNextPane ( bool bNext = true )
{
int nPane = m_nSinglePane ;
if ( nPane = = SPLIT_PANE_NONE )
{
switch ( GetActivePane ( ) )
{
case SPLIT_PANE_LEFT :
nPane = SPLIT_PANE_RIGHT ;
break ;
case SPLIT_PANE_RIGHT :
nPane = SPLIT_PANE_LEFT ;
break ;
default :
nPane = bNext ? SPLIT_PANE_LEFT : SPLIT_PANE_RIGHT ;
break ;
}
}
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
return SetActivePane ( nPane ) ;
}
bool SetDefaultActivePane ( int nPane )
{
2021-01-02 02:46:39 +00:00
ATLASSERT ( ( nPane = = SPLIT_PANE_LEFT ) | | ( nPane = = SPLIT_PANE_RIGHT ) ) ;
if ( ( nPane ! = SPLIT_PANE_LEFT ) & & ( nPane ! = SPLIT_PANE_RIGHT ) )
2008-09-18 03:15:49 +00:00
return false ;
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
m_nDefActivePane = nPane ;
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
return true ;
}
bool SetDefaultActivePane ( HWND hWnd )
{
for ( int nPane = 0 ; nPane < m_nPanesCount ; nPane + + )
{
if ( hWnd = = m_hWndPane [ nPane ] )
{
m_nDefActivePane = nPane ;
return true ;
}
}
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
return false ; // not found
}
int GetDefaultActivePane ( ) const
{
return m_nDefActivePane ;
}
void DrawSplitter ( CDCHandle dc )
{
ATLASSERT ( dc . m_hDC ! = NULL ) ;
2021-01-02 02:46:39 +00:00
if ( ( m_nSinglePane = = SPLIT_PANE_NONE ) & & ( m_xySplitterPos = = - 1 ) )
2008-09-18 03:15:49 +00:00
return ;
T * pT = static_cast < T * > ( this ) ;
if ( m_nSinglePane = = SPLIT_PANE_NONE )
{
pT - > DrawSplitterBar ( dc ) ;
for ( int nPane = 0 ; nPane < m_nPanesCount ; nPane + + )
{
if ( m_hWndPane [ nPane ] = = NULL )
pT - > DrawSplitterPane ( dc , nPane ) ;
}
}
else
{
if ( m_hWndPane [ m_nSinglePane ] = = NULL )
pT - > DrawSplitterPane ( dc , m_nSinglePane ) ;
}
}
2021-01-02 02:46:39 +00:00
// call to initiate moving splitter bar with keyboard
void MoveSplitterBar ( )
{
T * pT = static_cast < T * > ( this ) ;
int x = 0 ;
int y = 0 ;
if ( m_bVertical )
{
x = m_xySplitterPos + ( m_cxySplitBar / 2 ) + m_cxyBarEdge ;
y = ( m_rcSplitter . bottom - m_rcSplitter . top - m_cxySplitBar - m_cxyBarEdge ) / 2 ;
}
else
{
x = ( m_rcSplitter . right - m_rcSplitter . left - m_cxySplitBar - m_cxyBarEdge ) / 2 ;
y = m_xySplitterPos + ( m_cxySplitBar / 2 ) + m_cxyBarEdge ;
}
POINT pt = { x , y } ;
pT - > ClientToScreen ( & pt ) ;
: : SetCursorPos ( pt . x , pt . y ) ;
m_xySplitterPosNew = m_xySplitterPos ;
pT - > SetCapture ( ) ;
m_hWndFocusSave = pT - > SetFocus ( ) ;
: : SetCursor ( m_hCursor ) ;
if ( ! m_bFullDrag )
DrawGhostBar ( ) ;
if ( m_bVertical )
m_cxyDragOffset = x - m_rcSplitter . left - m_xySplitterPos ;
else
m_cxyDragOffset = y - m_rcSplitter . top - m_xySplitterPos ;
}
void SetOrientation ( bool bVertical , bool bUpdate = true )
{
if ( m_bVertical ! = bVertical )
{
m_bVertical = bVertical ;
m_hCursor = : : LoadCursor ( NULL , m_bVertical ? IDC_SIZEWE : IDC_SIZENS ) ;
T * pT = static_cast < T * > ( this ) ;
pT - > GetSystemSettings ( false ) ;
if ( m_bVertical )
m_xySplitterPos = : : MulDiv ( m_xySplitterPos , m_rcSplitter . right - m_rcSplitter . left , m_rcSplitter . bottom - m_rcSplitter . top ) ;
else
m_xySplitterPos = : : MulDiv ( m_xySplitterPos , m_rcSplitter . bottom - m_rcSplitter . top , m_rcSplitter . right - m_rcSplitter . left ) ;
}
if ( bUpdate )
UpdateSplitterLayout ( ) ;
}
2008-09-18 03:15:49 +00:00
// Overrideables
void DrawSplitterBar ( CDCHandle dc )
{
2021-01-02 02:46:39 +00:00
RECT rect = { } ;
2008-09-18 03:15:49 +00:00
if ( GetSplitterBarRect ( & rect ) )
{
dc . FillRect ( & rect , COLOR_3DFACE ) ;
2015-01-23 00:32:27 +00:00
2021-01-02 02:46:39 +00:00
if ( ( m_dwExtendedStyle & SPLIT_FLATBAR ) ! = 0 )
{
RECT rect1 = rect ;
if ( m_bVertical )
rect1 . right = rect1 . left + 1 ;
else
rect1 . bottom = rect1 . top + 1 ;
dc . FillRect ( & rect1 , COLOR_WINDOW ) ;
rect1 = rect ;
if ( m_bVertical )
rect1 . left = rect1 . right - 1 ;
else
rect1 . top = rect1 . bottom - 1 ;
dc . FillRect ( & rect1 , COLOR_3DSHADOW ) ;
}
else if ( ( m_dwExtendedStyle & SPLIT_GRADIENTBAR ) ! = 0 )
2015-01-23 00:32:27 +00:00
{
RECT rect2 = rect ;
2021-01-02 02:46:39 +00:00
if ( m_bVertical )
2015-01-23 00:32:27 +00:00
rect2 . left = ( rect . left + rect . right ) / 2 - 1 ;
else
rect2 . top = ( rect . top + rect . bottom ) / 2 - 1 ;
2021-01-02 02:46:39 +00:00
dc . GradientFillRect ( rect2 , : : GetSysColor ( COLOR_3DFACE ) , : : GetSysColor ( COLOR_3DSHADOW ) , m_bVertical ) ;
2015-01-23 00:32:27 +00:00
}
2008-09-18 03:15:49 +00:00
// draw 3D edge if needed
T * pT = static_cast < T * > ( this ) ;
if ( ( pT - > GetExStyle ( ) & WS_EX_CLIENTEDGE ) ! = 0 )
2021-01-02 02:46:39 +00:00
dc . DrawEdge ( & rect , EDGE_RAISED , m_bVertical ? ( BF_LEFT | BF_RIGHT ) : ( BF_TOP | BF_BOTTOM ) ) ;
2008-09-18 03:15:49 +00:00
}
}
// called only if pane is empty
void DrawSplitterPane ( CDCHandle dc , int nPane )
{
2021-01-02 02:46:39 +00:00
RECT rect = { } ;
2008-09-18 03:15:49 +00:00
if ( GetSplitterPaneRect ( nPane , & rect ) )
{
T * pT = static_cast < T * > ( this ) ;
if ( ( pT - > GetExStyle ( ) & WS_EX_CLIENTEDGE ) = = 0 )
dc . DrawEdge ( & rect , EDGE_SUNKEN , BF_RECT | BF_ADJUST ) ;
dc . FillRect ( & rect , COLOR_APPWORKSPACE ) ;
}
}
// Message map and handlers
BEGIN_MSG_MAP ( CSplitterImpl )
MESSAGE_HANDLER ( WM_CREATE , OnCreate )
MESSAGE_HANDLER ( WM_PAINT , OnPaint )
MESSAGE_HANDLER ( WM_PRINTCLIENT , OnPaint )
if ( IsInteractive ( ) )
{
MESSAGE_HANDLER ( WM_SETCURSOR , OnSetCursor )
MESSAGE_HANDLER ( WM_MOUSEMOVE , OnMouseMove )
MESSAGE_HANDLER ( WM_LBUTTONDOWN , OnLButtonDown )
MESSAGE_HANDLER ( WM_LBUTTONUP , OnLButtonUp )
MESSAGE_HANDLER ( WM_LBUTTONDBLCLK , OnLButtonDoubleClick )
MESSAGE_HANDLER ( WM_CAPTURECHANGED , OnCaptureChanged )
2021-01-02 02:46:39 +00:00
MESSAGE_HANDLER ( WM_KEYDOWN , OnKeyDown )
2008-09-18 03:15:49 +00:00
}
MESSAGE_HANDLER ( WM_SETFOCUS , OnSetFocus )
MESSAGE_HANDLER ( WM_MOUSEACTIVATE , OnMouseActivate )
MESSAGE_HANDLER ( WM_SETTINGCHANGE , OnSettingChange )
END_MSG_MAP ( )
LRESULT OnCreate ( UINT /*uMsg*/ , WPARAM /*wParam*/ , LPARAM /*lParam*/ , BOOL & bHandled )
{
2015-01-23 00:32:27 +00:00
T * pT = static_cast < T * > ( this ) ;
2021-01-02 02:46:39 +00:00
pT - > Init ( ) ;
2015-01-23 00:32:27 +00:00
2008-09-18 03:15:49 +00:00
bHandled = FALSE ;
return 1 ;
}
2021-01-02 02:46:39 +00:00
LRESULT OnPaint ( UINT /*uMsg*/ , WPARAM wParam , LPARAM /*lParam*/ , BOOL & /*bHandled*/ )
2008-09-18 03:15:49 +00:00
{
T * pT = static_cast < T * > ( this ) ;
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
// try setting position if not set
2021-01-02 02:46:39 +00:00
if ( ( m_nSinglePane = = SPLIT_PANE_NONE ) & & ( m_xySplitterPos = = - 1 ) )
2008-09-18 03:15:49 +00:00
pT - > SetSplitterPos ( ) ;
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
// do painting
2021-01-02 02:46:39 +00:00
if ( wParam ! = NULL )
{
pT - > DrawSplitter ( ( HDC ) wParam ) ;
}
else
{
CPaintDC dc ( pT - > m_hWnd ) ;
pT - > DrawSplitter ( dc . m_hDC ) ;
}
2008-09-18 03:15:49 +00:00
return 0 ;
}
LRESULT OnSetCursor ( UINT /*uMsg*/ , WPARAM wParam , LPARAM lParam , BOOL & bHandled )
{
T * pT = static_cast < T * > ( this ) ;
2021-01-02 02:46:39 +00:00
if ( ( ( HWND ) wParam = = pT - > m_hWnd ) & & ( LOWORD ( lParam ) = = HTCLIENT ) )
2008-09-18 03:15:49 +00:00
{
DWORD dwPos = : : GetMessagePos ( ) ;
POINT ptPos = { GET_X_LPARAM ( dwPos ) , GET_Y_LPARAM ( dwPos ) } ;
pT - > ScreenToClient ( & ptPos ) ;
if ( IsOverSplitterBar ( ptPos . x , ptPos . y ) )
return 1 ;
}
bHandled = FALSE ;
return 0 ;
}
2021-01-02 02:46:39 +00:00
LRESULT OnMouseMove ( UINT /*uMsg*/ , WPARAM /*wParam*/ , LPARAM lParam , BOOL & bHandled )
2008-09-18 03:15:49 +00:00
{
T * pT = static_cast < T * > ( this ) ;
int xPos = GET_X_LPARAM ( lParam ) ;
int yPos = GET_Y_LPARAM ( lParam ) ;
2021-01-02 02:46:39 +00:00
if ( : : GetCapture ( ) = = pT - > m_hWnd )
2008-09-18 03:15:49 +00:00
{
int xyNewSplitPos = 0 ;
2021-01-02 02:46:39 +00:00
if ( m_bVertical )
2008-09-18 03:15:49 +00:00
xyNewSplitPos = xPos - m_rcSplitter . left - m_cxyDragOffset ;
else
xyNewSplitPos = yPos - m_rcSplitter . top - m_cxyDragOffset ;
2021-01-02 02:46:39 +00:00
if ( xyNewSplitPos = = - 1 ) // avoid -1, that means default position
2008-09-18 03:15:49 +00:00
xyNewSplitPos = - 2 ;
if ( m_xySplitterPos ! = xyNewSplitPos )
{
if ( m_bFullDrag )
{
if ( pT - > SetSplitterPos ( xyNewSplitPos , true ) )
pT - > UpdateWindow ( ) ;
}
else
{
DrawGhostBar ( ) ;
pT - > SetSplitterPos ( xyNewSplitPos , false ) ;
DrawGhostBar ( ) ;
}
}
}
else // not dragging, just set cursor
{
if ( IsOverSplitterBar ( xPos , yPos ) )
: : SetCursor ( m_hCursor ) ;
bHandled = FALSE ;
}
return 0 ;
}
LRESULT OnLButtonDown ( UINT /*uMsg*/ , WPARAM /*wParam*/ , LPARAM lParam , BOOL & bHandled )
{
2021-01-02 02:46:39 +00:00
T * pT = static_cast < T * > ( this ) ;
2008-09-18 03:15:49 +00:00
int xPos = GET_X_LPARAM ( lParam ) ;
int yPos = GET_Y_LPARAM ( lParam ) ;
2021-01-02 02:46:39 +00:00
if ( ( : : GetCapture ( ) ! = pT - > m_hWnd ) & & IsOverSplitterBar ( xPos , yPos ) )
2008-09-18 03:15:49 +00:00
{
2021-01-02 02:46:39 +00:00
m_xySplitterPosNew = m_xySplitterPos ;
2008-09-18 03:15:49 +00:00
pT - > SetCapture ( ) ;
2021-01-02 02:46:39 +00:00
m_hWndFocusSave = pT - > SetFocus ( ) ;
2008-09-18 03:15:49 +00:00
: : SetCursor ( m_hCursor ) ;
if ( ! m_bFullDrag )
DrawGhostBar ( ) ;
2021-01-02 02:46:39 +00:00
if ( m_bVertical )
2008-09-18 03:15:49 +00:00
m_cxyDragOffset = xPos - m_rcSplitter . left - m_xySplitterPos ;
else
m_cxyDragOffset = yPos - m_rcSplitter . top - m_xySplitterPos ;
}
2021-01-02 02:46:39 +00:00
else if ( ( : : GetCapture ( ) = = pT - > m_hWnd ) & & ! IsOverSplitterBar ( xPos , yPos ) )
{
: : ReleaseCapture ( ) ;
}
2008-09-18 03:15:49 +00:00
bHandled = FALSE ;
return 1 ;
}
LRESULT OnLButtonUp ( UINT /*uMsg*/ , WPARAM /*wParam*/ , LPARAM /*lParam*/ , BOOL & bHandled )
{
2021-01-02 02:46:39 +00:00
T * pT = static_cast < T * > ( this ) ;
if ( : : GetCapture ( ) = = pT - > m_hWnd )
{
m_xySplitterPosNew = m_xySplitterPos ;
: : ReleaseCapture ( ) ;
}
2008-09-18 03:15:49 +00:00
bHandled = FALSE ;
return 1 ;
}
LRESULT OnLButtonDoubleClick ( UINT /*uMsg*/ , WPARAM /*wParam*/ , LPARAM /*lParam*/ , BOOL & /*bHandled*/ )
{
T * pT = static_cast < T * > ( this ) ;
2021-01-02 02:46:39 +00:00
pT - > SetSplitterPos ( ) ; // default
2008-09-18 03:15:49 +00:00
return 0 ;
}
LRESULT OnCaptureChanged ( UINT /*uMsg*/ , WPARAM /*wParam*/ , LPARAM /*lParam*/ , BOOL & /*bHandled*/ )
{
if ( ! m_bFullDrag )
DrawGhostBar ( ) ;
2021-01-02 02:46:39 +00:00
if ( ( m_xySplitterPosNew ! = - 1 ) & & ( ! m_bFullDrag | | ( m_xySplitterPos ! = m_xySplitterPosNew ) ) )
{
m_xySplitterPos = m_xySplitterPosNew ;
m_xySplitterPosNew = - 1 ;
2008-09-18 03:15:49 +00:00
UpdateSplitterLayout ( ) ;
T * pT = static_cast < T * > ( this ) ;
pT - > UpdateWindow ( ) ;
}
2021-01-02 02:46:39 +00:00
if ( m_hWndFocusSave ! = NULL )
: : SetFocus ( m_hWndFocusSave ) ;
2008-09-18 03:15:49 +00:00
return 0 ;
}
2021-01-02 02:46:39 +00:00
LRESULT OnKeyDown ( UINT /*uMsg*/ , WPARAM wParam , LPARAM /*lParam*/ , BOOL & bHandled )
2008-09-18 03:15:49 +00:00
{
2021-01-02 02:46:39 +00:00
T * pT = static_cast < T * > ( this ) ;
if ( : : GetCapture ( ) = = pT - > m_hWnd )
2008-09-18 03:15:49 +00:00
{
2021-01-02 02:46:39 +00:00
switch ( wParam )
{
case VK_RETURN :
m_xySplitterPosNew = m_xySplitterPos ;
// FALLTHROUGH
case VK_ESCAPE :
: : ReleaseCapture ( ) ;
break ;
case VK_LEFT :
case VK_RIGHT :
if ( m_bVertical )
{
POINT pt = { } ;
: : GetCursorPos ( & pt ) ;
int xyPos = m_xySplitterPos + ( ( wParam = = VK_LEFT ) ? - pT - > m_cxyStep : pT - > m_cxyStep ) ;
int cxyMax = m_rcSplitter . right - m_rcSplitter . left ;
if ( xyPos < ( m_cxyMin + m_cxyBarEdge ) )
xyPos = m_cxyMin ;
else if ( xyPos > ( cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin ) )
xyPos = cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin ;
pt . x + = xyPos - m_xySplitterPos ;
: : SetCursorPos ( pt . x , pt . y ) ;
}
break ;
case VK_UP :
case VK_DOWN :
if ( ! m_bVertical )
{
POINT pt = { } ;
: : GetCursorPos ( & pt ) ;
int xyPos = m_xySplitterPos + ( ( wParam = = VK_UP ) ? - pT - > m_cxyStep : pT - > m_cxyStep ) ;
int cxyMax = m_rcSplitter . bottom - m_rcSplitter . top ;
if ( xyPos < ( m_cxyMin + m_cxyBarEdge ) )
xyPos = m_cxyMin ;
else if ( xyPos > ( cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin ) )
xyPos = cxyMax - m_cxySplitBar - m_cxyBarEdge - m_cxyMin ;
pt . y + = xyPos - m_xySplitterPos ;
: : SetCursorPos ( pt . x , pt . y ) ;
}
break ;
default :
break ;
}
2008-09-18 03:15:49 +00:00
}
else
{
2021-01-02 02:46:39 +00:00
bHandled = FALSE ;
2008-09-18 03:15:49 +00:00
}
2021-01-02 02:46:39 +00:00
return 0 ;
}
LRESULT OnSetFocus ( UINT /*uMsg*/ , WPARAM /*wParam*/ , LPARAM , BOOL & bHandled )
{
T * pT = static_cast < T * > ( this ) ;
if ( : : GetCapture ( ) ! = pT - > m_hWnd )
{
if ( m_nSinglePane = = SPLIT_PANE_NONE )
{
if ( ( m_nDefActivePane = = SPLIT_PANE_LEFT ) | | ( m_nDefActivePane = = SPLIT_PANE_RIGHT ) )
: : SetFocus ( m_hWndPane [ m_nDefActivePane ] ) ;
}
else
{
: : SetFocus ( m_hWndPane [ m_nSinglePane ] ) ;
}
}
2008-09-18 03:15:49 +00:00
bHandled = FALSE ;
return 1 ;
}
LRESULT OnMouseActivate ( UINT uMsg , WPARAM wParam , LPARAM lParam , BOOL & /*bHandled*/ )
{
T * pT = static_cast < T * > ( this ) ;
LRESULT lRet = pT - > DefWindowProc ( uMsg , wParam , lParam ) ;
2021-01-02 02:46:39 +00:00
if ( ( lRet = = MA_ACTIVATE ) | | ( lRet = = MA_ACTIVATEANDEAT ) )
2008-09-18 03:15:49 +00:00
{
DWORD dwPos = : : GetMessagePos ( ) ;
POINT pt = { GET_X_LPARAM ( dwPos ) , GET_Y_LPARAM ( dwPos ) } ;
pT - > ScreenToClient ( & pt ) ;
2021-01-02 02:46:39 +00:00
RECT rcPane = { } ;
2008-09-18 03:15:49 +00:00
for ( int nPane = 0 ; nPane < m_nPanesCount ; nPane + + )
{
2021-01-02 02:46:39 +00:00
if ( GetSplitterPaneRect ( nPane , & rcPane ) & & ( : : PtInRect ( & rcPane , pt ) ! = FALSE ) )
2008-09-18 03:15:49 +00:00
{
m_nDefActivePane = nPane ;
break ;
}
}
}
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
return lRet ;
}
LRESULT OnSettingChange ( UINT /*uMsg*/ , WPARAM /*wParam*/ , LPARAM /*lParam*/ , BOOL & /*bHandled*/ )
{
2015-01-23 00:32:27 +00:00
T * pT = static_cast < T * > ( this ) ;
pT - > GetSystemSettings ( true ) ;
2008-09-18 03:15:49 +00:00
return 0 ;
}
// Implementation - internal helpers
2021-01-02 02:46:39 +00:00
void Init ( )
{
m_hCursor = : : LoadCursor ( NULL , m_bVertical ? IDC_SIZEWE : IDC_SIZENS ) ;
T * pT = static_cast < T * > ( this ) ;
pT - > GetSystemSettings ( false ) ;
}
2008-09-18 03:15:49 +00:00
void UpdateSplitterLayout ( )
{
2021-01-02 02:46:39 +00:00
if ( ( m_nSinglePane = = SPLIT_PANE_NONE ) & & ( m_xySplitterPos = = - 1 ) )
2008-09-18 03:15:49 +00:00
return ;
T * pT = static_cast < T * > ( this ) ;
2021-01-02 02:46:39 +00:00
RECT rect = { } ;
2008-09-18 03:15:49 +00:00
if ( m_nSinglePane = = SPLIT_PANE_NONE )
{
if ( GetSplitterBarRect ( & rect ) )
pT - > InvalidateRect ( & rect ) ;
for ( int nPane = 0 ; nPane < m_nPanesCount ; nPane + + )
{
if ( GetSplitterPaneRect ( nPane , & rect ) )
{
if ( m_hWndPane [ nPane ] ! = NULL )
: : SetWindowPos ( m_hWndPane [ nPane ] , NULL , rect . left , rect . top , rect . right - rect . left , rect . bottom - rect . top , SWP_NOZORDER ) ;
else
pT - > InvalidateRect ( & rect ) ;
}
}
}
else
{
if ( GetSplitterPaneRect ( m_nSinglePane , & rect ) )
{
if ( m_hWndPane [ m_nSinglePane ] ! = NULL )
: : SetWindowPos ( m_hWndPane [ m_nSinglePane ] , NULL , rect . left , rect . top , rect . right - rect . left , rect . bottom - rect . top , SWP_NOZORDER ) ;
else
pT - > InvalidateRect ( & rect ) ;
}
}
}
bool GetSplitterBarRect ( LPRECT lpRect ) const
{
ATLASSERT ( lpRect ! = NULL ) ;
2021-01-02 02:46:39 +00:00
if ( ( m_nSinglePane ! = SPLIT_PANE_NONE ) | | ( m_xySplitterPos = = - 1 ) )
2008-09-18 03:15:49 +00:00
return false ;
2021-01-02 02:46:39 +00:00
if ( m_bVertical )
2008-09-18 03:15:49 +00:00
{
lpRect - > left = m_rcSplitter . left + m_xySplitterPos ;
lpRect - > top = m_rcSplitter . top ;
lpRect - > right = m_rcSplitter . left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge ;
lpRect - > bottom = m_rcSplitter . bottom ;
}
else
{
lpRect - > left = m_rcSplitter . left ;
lpRect - > top = m_rcSplitter . top + m_xySplitterPos ;
lpRect - > right = m_rcSplitter . right ;
lpRect - > bottom = m_rcSplitter . top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge ;
}
return true ;
}
bool GetSplitterPaneRect ( int nPane , LPRECT lpRect ) const
{
2021-01-02 02:46:39 +00:00
ATLASSERT ( ( nPane = = SPLIT_PANE_LEFT ) | | ( nPane = = SPLIT_PANE_RIGHT ) ) ;
2008-09-18 03:15:49 +00:00
ATLASSERT ( lpRect ! = NULL ) ;
bool bRet = true ;
if ( m_nSinglePane ! = SPLIT_PANE_NONE )
{
if ( nPane = = m_nSinglePane )
* lpRect = m_rcSplitter ;
else
bRet = false ;
}
else if ( nPane = = SPLIT_PANE_LEFT )
{
2021-01-02 02:46:39 +00:00
if ( m_bVertical )
2008-09-18 03:15:49 +00:00
{
lpRect - > left = m_rcSplitter . left ;
lpRect - > top = m_rcSplitter . top ;
lpRect - > right = m_rcSplitter . left + m_xySplitterPos ;
lpRect - > bottom = m_rcSplitter . bottom ;
}
else
{
lpRect - > left = m_rcSplitter . left ;
lpRect - > top = m_rcSplitter . top ;
lpRect - > right = m_rcSplitter . right ;
lpRect - > bottom = m_rcSplitter . top + m_xySplitterPos ;
}
}
else if ( nPane = = SPLIT_PANE_RIGHT )
{
2021-01-02 02:46:39 +00:00
if ( m_bVertical )
2008-09-18 03:15:49 +00:00
{
lpRect - > left = m_rcSplitter . left + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge ;
lpRect - > top = m_rcSplitter . top ;
lpRect - > right = m_rcSplitter . right ;
lpRect - > bottom = m_rcSplitter . bottom ;
}
else
{
lpRect - > left = m_rcSplitter . left ;
lpRect - > top = m_rcSplitter . top + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge ;
lpRect - > right = m_rcSplitter . right ;
lpRect - > bottom = m_rcSplitter . bottom ;
}
}
else
{
bRet = false ;
}
2021-01-02 02:46:39 +00:00
2008-09-18 03:15:49 +00:00
return bRet ;
}
bool IsOverSplitterRect ( int x , int y ) const
{
// -1 == don't check
2021-01-02 02:46:39 +00:00
return ( ( ( x = = - 1 ) | | ( ( x > = m_rcSplitter . left ) & & ( x < = m_rcSplitter . right ) ) ) & &
( ( y = = - 1 ) | | ( ( y > = m_rcSplitter . top ) & & ( y < = m_rcSplitter . bottom ) ) ) ) ;
2008-09-18 03:15:49 +00:00
}
bool IsOverSplitterBar ( int x , int y ) const
{
if ( m_nSinglePane ! = SPLIT_PANE_NONE )
return false ;
2021-01-02 02:46:39 +00:00
if ( ( m_xySplitterPos = = - 1 ) | | ! IsOverSplitterRect ( x , y ) )
2008-09-18 03:15:49 +00:00
return false ;
2021-01-02 02:46:39 +00:00
int xy = m_bVertical ? x : y ;
int xyOff = m_bVertical ? m_rcSplitter . left : m_rcSplitter . top ;
return ( ( xy > = ( xyOff + m_xySplitterPos ) ) & & ( xy < ( xyOff + m_xySplitterPos + m_cxySplitBar + m_cxyBarEdge ) ) ) ;
2008-09-18 03:15:49 +00:00
}
void DrawGhostBar ( )
{
2021-01-02 02:46:39 +00:00
RECT rect = { } ;
2008-09-18 03:15:49 +00:00
if ( GetSplitterBarRect ( & rect ) )
{
2015-01-23 00:32:27 +00:00
// convert client to window coordinates
2008-09-18 03:15:49 +00:00
T * pT = static_cast < T * > ( this ) ;
2021-01-02 02:46:39 +00:00
RECT rcWnd = { } ;
2015-01-23 00:32:27 +00:00
pT - > GetWindowRect ( & rcWnd ) ;
: : MapWindowPoints ( NULL , pT - > m_hWnd , ( LPPOINT ) & rcWnd , 2 ) ;
: : OffsetRect ( & rect , - rcWnd . left , - rcWnd . top ) ;
// invert the brush pattern (looks just like frame window sizing)
2021-01-02 02:46:39 +00:00
CBrush brush ( CDCHandle : : GetHalftoneBrush ( ) ) ;
2008-09-18 03:15:49 +00:00
if ( brush . m_hBrush ! = NULL )
{
2021-01-02 02:46:39 +00:00
CWindowDC dc ( pT - > m_hWnd ) ;
2008-09-18 03:15:49 +00:00
CBrushHandle brushOld = dc . SelectBrush ( brush ) ;
dc . PatBlt ( rect . left , rect . top , rect . right - rect . left , rect . bottom - rect . top , PATINVERT ) ;
dc . SelectBrush ( brushOld ) ;
}
}
}
void GetSystemSettings ( bool bUpdate )
{
2015-01-23 00:32:27 +00:00
if ( ( m_dwExtendedStyle & SPLIT_FIXEDBARSIZE ) = = 0 )
{
2021-01-02 02:46:39 +00:00
m_cxySplitBar = : : GetSystemMetrics ( m_bVertical ? SM_CXSIZEFRAME : SM_CYSIZEFRAME ) ;
2015-01-23 00:32:27 +00:00
}
2008-09-18 03:15:49 +00:00
T * pT = static_cast < T * > ( this ) ;
2021-01-02 02:46:39 +00:00
if ( ( pT - > GetExStyle ( ) & WS_EX_CLIENTEDGE ) ! = 0 )
2008-09-18 03:15:49 +00:00
{
2021-01-02 02:46:39 +00:00
m_cxyBarEdge = 2 * : : GetSystemMetrics ( m_bVertical ? SM_CXEDGE : SM_CYEDGE ) ;
2008-09-18 03:15:49 +00:00
m_cxyMin = 0 ;
}
else
{
m_cxyBarEdge = 0 ;
2021-01-02 02:46:39 +00:00
m_cxyMin = 2 * : : GetSystemMetrics ( m_bVertical ? SM_CXEDGE : SM_CYEDGE ) ;
2008-09-18 03:15:49 +00:00
}
: : SystemParametersInfo ( SPI_GETDRAGFULLWINDOWS , 0 , & m_bFullDrag , 0 ) ;
if ( bUpdate )
UpdateSplitterLayout ( ) ;
}
bool IsProportional ( ) const
{
return ( ( m_dwExtendedStyle & SPLIT_PROPORTIONAL ) ! = 0 ) ;
}
void StoreProportionalPos ( )
{
2021-01-02 02:46:39 +00:00
int cxyTotal = m_bVertical ? ( m_rcSplitter . right - m_rcSplitter . left - m_cxySplitBar - m_cxyBarEdge ) : ( m_rcSplitter . bottom - m_rcSplitter . top - m_cxySplitBar - m_cxyBarEdge ) ;
2008-09-18 03:15:49 +00:00
if ( cxyTotal > 0 )
m_nProportionalPos = : : MulDiv ( m_xySplitterPos , m_nPropMax , cxyTotal ) ;
else
m_nProportionalPos = 0 ;
ATLTRACE2 ( atlTraceUI , 0 , _T ( " CSplitterImpl::StoreProportionalPos - %i \n " ) , m_nProportionalPos ) ;
}
void UpdateProportionalPos ( )
{
2021-01-02 02:46:39 +00:00
int cxyTotal = m_bVertical ? ( m_rcSplitter . right - m_rcSplitter . left - m_cxySplitBar - m_cxyBarEdge ) : ( m_rcSplitter . bottom - m_rcSplitter . top - m_cxySplitBar - m_cxyBarEdge ) ;
2008-09-18 03:15:49 +00:00
if ( cxyTotal > 0 )
{
int xyNewPos = : : MulDiv ( m_nProportionalPos , cxyTotal , m_nPropMax ) ;
m_bUpdateProportionalPos = false ;
T * pT = static_cast < T * > ( this ) ;
pT - > SetSplitterPos ( xyNewPos , false ) ;
}
}
bool IsRightAligned ( ) const
{
return ( ( m_dwExtendedStyle & SPLIT_RIGHTALIGNED ) ! = 0 ) ;
}
void StoreRightAlignPos ( )
{
2021-01-02 02:46:39 +00:00
int cxyTotal = m_bVertical ? ( m_rcSplitter . right - m_rcSplitter . left - m_cxySplitBar - m_cxyBarEdge ) : ( m_rcSplitter . bottom - m_rcSplitter . top - m_cxySplitBar - m_cxyBarEdge ) ;
2008-09-18 03:15:49 +00:00
if ( cxyTotal > 0 )
m_nProportionalPos = cxyTotal - m_xySplitterPos ;
else
m_nProportionalPos = 0 ;
ATLTRACE2 ( atlTraceUI , 0 , _T ( " CSplitterImpl::StoreRightAlignPos - %i \n " ) , m_nProportionalPos ) ;
}
void UpdateRightAlignPos ( )
{
2021-01-02 02:46:39 +00:00
int cxyTotal = m_bVertical ? ( m_rcSplitter . right - m_rcSplitter . left - m_cxySplitBar - m_cxyBarEdge ) : ( m_rcSplitter . bottom - m_rcSplitter . top - m_cxySplitBar - m_cxyBarEdge ) ;
2008-09-18 03:15:49 +00:00
if ( cxyTotal > 0 )
{
m_bUpdateProportionalPos = false ;
T * pT = static_cast < T * > ( this ) ;
pT - > SetSplitterPos ( cxyTotal - m_nProportionalPos , false ) ;
}
}
bool IsInteractive ( ) const
{
return ( ( m_dwExtendedStyle & SPLIT_NONINTERACTIVE ) = = 0 ) ;
}
} ;
///////////////////////////////////////////////////////////////////////////////
// CSplitterWindowImpl - Implements a splitter window
2021-01-02 02:46:39 +00:00
template < class T , class TBase = ATL : : CWindow , class TWinTraits = ATL : : CControlWinTraits >
class ATL_NO_VTABLE CSplitterWindowImpl : public ATL : : CWindowImpl < T , TBase , TWinTraits > , public CSplitterImpl < T >
2008-09-18 03:15:49 +00:00
{
public :
2021-01-02 02:46:39 +00:00
DECLARE_WND_CLASS_EX2 ( NULL , T , CS_DBLCLKS , COLOR_WINDOW )
2008-09-18 03:15:49 +00:00
2021-01-02 02:46:39 +00:00
CSplitterWindowImpl ( bool bVertical = true ) : CSplitterImpl < T > ( bVertical )
{ }
BOOL SubclassWindow ( HWND hWnd )
{
BOOL bRet = ATL : : CWindowImpl < T , TBase , TWinTraits > : : SubclassWindow ( hWnd ) ;
if ( bRet ! = FALSE )
{
T * pT = static_cast < T * > ( this ) ;
pT - > Init ( ) ;
this - > SetSplitterRect ( ) ;
}
return bRet ;
}
2008-09-18 03:15:49 +00:00
BEGIN_MSG_MAP ( CSplitterWindowImpl )
MESSAGE_HANDLER ( WM_ERASEBKGND , OnEraseBackground )
MESSAGE_HANDLER ( WM_SIZE , OnSize )
2021-01-02 02:46:39 +00:00
CHAIN_MSG_MAP ( CSplitterImpl < T > )
2008-09-18 03:15:49 +00:00
FORWARD_NOTIFICATIONS ( )
END_MSG_MAP ( )
LRESULT OnEraseBackground ( UINT /*uMsg*/ , WPARAM /*wParam*/ , LPARAM /*lParam*/ , BOOL & /*bHandled*/ )
{
// handled, no background painting needed
return 1 ;
}
LRESULT OnSize ( UINT /*uMsg*/ , WPARAM wParam , LPARAM /*lParam*/ , BOOL & bHandled )
{
if ( wParam ! = SIZE_MINIMIZED )
2021-01-02 02:46:39 +00:00
this - > SetSplitterRect ( ) ;
2008-09-18 03:15:49 +00:00
bHandled = FALSE ;
return 1 ;
}
} ;
///////////////////////////////////////////////////////////////////////////////
2021-01-02 02:46:39 +00:00
// CSplitterWindow/CHorSplitterWindow - Implements splitter windows to be used as is
2008-09-18 03:15:49 +00:00
template < bool t_bVertical = true >
2021-01-02 02:46:39 +00:00
class CSplitterWindowT : public CSplitterWindowImpl < CSplitterWindowT < t_bVertical > >
2008-09-18 03:15:49 +00:00
{
public :
2021-01-02 02:46:39 +00:00
DECLARE_WND_CLASS_EX2 ( _T ( " WTL_SplitterWindow " ) , CSplitterWindowT < t_bVertical > , CS_DBLCLKS , COLOR_WINDOW )
CSplitterWindowT ( ) : CSplitterWindowImpl < CSplitterWindowT < t_bVertical > > ( t_bVertical )
{ }
2008-09-18 03:15:49 +00:00
} ;
typedef CSplitterWindowT < true > CSplitterWindow ;
typedef CSplitterWindowT < false > CHorSplitterWindow ;
2021-01-02 02:46:39 +00:00
} // namespace WTL
2008-09-18 03:15:49 +00:00
# endif // __ATLSPLIT_H__