Click here to Skip to main content
15,893,486 members
Articles / Desktop Programming / MFC

Professional User Interface Suite

Rate me:
Please Sign up or sign in to vote.
4.99/5 (174 votes)
13 Jan 200423 min read 1.5M   23.6K   641  
MFC extension library enabling software to be provided with a professional UI
// This is part of the Professional User Interface Suite library.
// Copyright (C) 2001-2004 FOSS Software, Inc.
// All rights reserved.
//
// http://www.prof-uis.com
// http://www.fossware.com
// mailto:foss@fossware.com
//
// This source code can be used, modified and redistributed
// under the terms of the license agreement that is included
// in the Professional User Interface Suite package.
//
// Warranties and Disclaimers:
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND
// INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
// IN NO EVENT WILL FOSS SOFTWARE INC. BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES,
// INCLUDING DAMAGES FOR LOSS OF PROFITS, LOSS OR INACCURACY OF DATA,
// INCURRED BY ANY PERSON FROM SUCH PERSON'S USAGE OF THIS SOFTWARE
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

#include "stdafx.h"

#if _MFC_VER < 0x700
	#include <../src/AfxImpl.h>
#else
	#include <../src/mfc/AfxImpl.h>
#endif

#if (!defined __EXT_TOOLCONTROLBAR_H)
	#include <ExtToolControlBar.h>
#endif

#if (!defined __EXT_MENUCONTROLBAR_H)
	#include <ExtMenuControlBar.h>
#endif

#if (!defined __EXTDOCKBAR_H)
	#include "ExtDockBar.h"
#endif

#if( !defined __EXTMINIDOCKFRAMEWND_H)
	#include "ExtMiniDockFrameWnd.h"
#endif

#if (!defined __EXT_PAINT_MANAGER_H)
	#include <ExtPaintManager.h>
#endif

#if (!defined __EXT_MEMORY_DC_H)
	#include <../Src/ExtMemoryDC.h>
#endif

#if (!defined __EXT_POPUP_MENU_WND_H)
	#include <ExtPopupMenuWnd.h>
#endif

#if (!defined __ExtCmdManager_H)
	#include <ExtCmdManager.h>
#endif

#if (!defined __EXT_LOCALIZATION_H)
	#include <../Src/ExtLocalization.h>
#endif

#include <../profuisdll/resource.h>

#include <math.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define CX_BORDER   1
#define CY_BORDER   1

/////////////////////////////////////////////////////////////////////////////
// CExtToolControlBar::CExtToolControlBarCmdUI

class CExtToolControlBar::CExtToolControlBarCmdUI : public CCmdUI
{
	void _SetCheckImpl(
		int nCheck,
		bool bUpdaeteInCmdManager
		);

public: // re-implementations only

	virtual void Enable( BOOL bOn );

	virtual void SetRadio( BOOL bOn );

	virtual void SetCheck( int nCheck )
	{
		_SetCheckImpl(nCheck,true);
	};

	virtual void SetText( LPCTSTR lpszText )
	{
		lpszText;
		// ignore it
	};

}; // class CExtToolControlBar::CExtToolControlBarCmdUI

void CExtToolControlBar::CExtToolControlBarCmdUI::_SetCheckImpl(
	int nCheck,
	bool bUpdaeteInCmdManager
	)
{
	ASSERT(nCheck >= 0 && nCheck <= 2); // 0=>off, 1=>on, 2=>indeterminate
CExtToolControlBar* pToolBar = (CExtToolControlBar*)m_pOther;
	ASSERT(pToolBar != NULL);
	ASSERT_KINDOF(CExtToolControlBar, pToolBar);
	ASSERT(m_nIndex < m_nIndexMax);

	if( pToolBar->IsRightExpandButton(m_nIndex) )
		return;

UINT nNewStyle =
		pToolBar->GetButtonStyle(m_nIndex)
		&
		~(TBBS_CHECKED | TBBS_INDETERMINATE);
	if( nCheck == 1 )
		nNewStyle |= TBBS_CHECKED;
	else if( nCheck == 2 )
		nNewStyle |= TBBS_INDETERMINATE;
	ASSERT( !(nNewStyle & TBBS_SEPARATOR) );
	pToolBar->SetButtonStyle(m_nIndex, nNewStyle | TBBS_CHECKBOX);

	if( bUpdaeteInCmdManager )
	{
		CExtCmdItem * pCmdItem = g_CmdManager->CmdGetPtr(
			g_CmdManager->ProfileNameFromWnd( pToolBar->GetSafeHwnd() ),
			pToolBar->GetButtonID(m_nIndex)
			);
		if( pCmdItem != NULL )
		{
			pCmdItem->StateSetCheck(
				(nNewStyle &
					(TBBS_CHECKED|TBBS_INDETERMINATE)
					) ? true : false
				);
		}
	}
}

void CExtToolControlBar::CExtToolControlBarCmdUI::Enable( BOOL bOn )
{
	CCmdUI::m_bEnableChanged = TRUE;
CExtToolControlBar* pToolBar = (CExtToolControlBar*)m_pOther;
	ASSERT(pToolBar != NULL);
	ASSERT_KINDOF(CExtToolControlBar, pToolBar);
	ASSERT(m_nIndex < m_nIndexMax);

	if( pToolBar->IsRightExpandButton(m_nIndex) )
		return;

UINT nNewStyle = pToolBar->GetButtonStyle(m_nIndex) & ~TBBS_DISABLED;
	if( !bOn )
		nNewStyle |= TBBS_DISABLED;
	ASSERT(!(nNewStyle & TBBS_SEPARATOR));
	pToolBar->SetButtonStyle(m_nIndex, nNewStyle);

CExtCmdItem * pCmdItem = g_CmdManager->CmdGetPtr(
		g_CmdManager->ProfileNameFromWnd( pToolBar->GetSafeHwnd() ),															
		pToolBar->GetButtonID(m_nIndex)
		);
	if( pCmdItem != NULL )
		pCmdItem->StateEnable( bOn ? true : false );
}

void CExtToolControlBar::CExtToolControlBarCmdUI::SetRadio( BOOL bOn )
{
	_SetCheckImpl( bOn ? 1 : 0, false );
	
CExtToolControlBar* pToolBar = (CExtToolControlBar*)m_pOther;
	ASSERT(pToolBar != NULL);
	ASSERT_KINDOF(CExtToolControlBar, pToolBar);
	ASSERT(m_nIndex < m_nIndexMax);

	if( pToolBar->IsRightExpandButton(m_nIndex) )
		return;

CExtCmdItem * pCmdItem = g_CmdManager->CmdGetPtr(
		g_CmdManager->ProfileNameFromWnd( pToolBar->GetSafeHwnd() ),
		pToolBar->GetButtonID(m_nIndex)
		);
	if( pCmdItem != NULL )
		pCmdItem->StateSetRadio( bOn ? true : false );
}

/////////////////////////////////////////////////////////////////////////////
// CExtBarButton

IMPLEMENT_DYNCREATE(CExtBarButton, CObject)

UINT CExtBarButton::GetStyle() const
{
	ASSERT_VALID( this );
	return m_nStyle;
}

void CExtBarButton::SetStyle( UINT nStyle )
{
	ASSERT_VALID( this );
	m_nStyle = nStyle;
	if( (m_nStyle & TBBS_PRESSED) == 0 )
		m_bDropDownHT = FALSE;
	_UpdateCmdIdFromStyle();
	_UpdateCtrl();
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	_UpdateCmdNodeFromStyle();
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
}

void CExtBarButton::ModifyStyle(
	UINT nAdd,
	UINT nRemove // = 0
	)
{
	ASSERT_VALID( this );
	m_nStyle |= nAdd;
	m_nStyle &= ~nRemove;
	if( (m_nStyle & TBBS_PRESSED) == 0 )
		m_bDropDownHT = FALSE;
	_UpdateCmdIdFromStyle();
	_UpdateCtrl();
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	_UpdateCmdNodeFromStyle();
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
}

bool CExtBarButton::IsWrap(
	CExtBarButton::e_wrap_t _evt
	) const
{
	ASSERT_VALID( this );
	ASSERT( __EVT_MIN_VALUE <= _evt && _evt <= __EVT_MAX_VALUE );
	switch( _evt )
	{
	case __EVT_HORZ:
		return m_bWrapH;
	case __EVT_VERT:
		return m_bWrapV;
	default:
		ASSERT( _evt == __EVT_FLOAT );
		return m_bWrapF;
	} // switch( _evt )
}

void CExtBarButton::SetWrap(
	CExtBarButton::e_wrap_t _evt,
	bool bWrap // = true
	)
{
	ASSERT_VALID( this );
	ASSERT( __EVT_MIN_VALUE <= _evt && _evt <= __EVT_MAX_VALUE );
	switch( _evt )
	{
	case __EVT_HORZ:
		m_bWrapH = bWrap;
		break;
	case __EVT_VERT:
		m_bWrapV = bWrap;
		break;
	default:
		ASSERT( _evt == __EVT_FLOAT );
		m_bWrapF = bWrap;
		break;
	} // switch( _evt )
}

bool CExtBarButton::IsLargeIcon() const
{
	ASSERT_VALID( this );
	if( GetBar() == NULL )
		return false;
	if( IsSeparator() )
		return false;
	return GetBar()->IsLargeIcons();
}

bool CExtBarButton::IsDisplayScreenTip() const
{
	ASSERT_VALID( this );
	if( GetBar() == NULL )
		return false;
	if( IsSeparator() )
		return false;
	return GetBar()->IsDisplayScreenTips();
}

bool CExtBarButton::IsDisplayShortcutKeysOnScreenTip() const
{
	ASSERT_VALID( this );
	if( GetBar() == NULL )
		return false;
	if( IsSeparator() )
		return false;
	return GetBar()->IsDisplayShortcutKeysOnScreenTips();
}

UINT CExtBarButton::GetCmdID(
	bool bEffective // = true
	) const
{
	ASSERT_VALID( this );
	return bEffective ? m_nEffectiveCmdID : m_nButtonCmdID;
}

void CExtBarButton::SetCmdID(
	UINT nCmdID,
	bool bEffectiveOnly, // = false
	bool bEffectiveRecalcLayout // = false
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );

bool bRecalcLayout = false;
	if(		bEffectiveRecalcLayout
		&&	m_nEffectiveCmdID != nCmdID
		)
		bRecalcLayout = true; 
	
	m_nEffectiveCmdID = nCmdID;
	
	if( !bEffectiveOnly )
	{
		m_nButtonCmdID = nCmdID;
		if( m_nButtonCmdID == ID_SEPARATOR )
		{
			m_nStyle |= TBBS_SEPARATOR;
			m_nStyle &= ~(TBBS_BUTTON);
		}
		else
		{
			m_nStyle |= TBBS_BUTTON;
			m_nStyle &= ~(TBBS_SEPARATOR);
		}
	} // if( !bEffectiveOnly )
	
	if( bRecalcLayout )
		GetBar()->_RecalcLayoutImpl();
}

bool CExtBarButton::IsAbleToTrackMenu(
	bool bCustomizeMode // = false
	)
{
	ASSERT_VALID( this );
	bCustomizeMode;
	if(		GetMenu() != NULL
		||	IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton))
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
		||	(	m_pCmdNodeC != NULL
			&&	(	(m_pCmdNodeC->GetFlags() & __ECTN_AUTO_POPUP) != 0
				||	m_pCmdNodeC->GetNodeCount() > 0
				)
			)
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
		)
		return true;
	return false;
}

bool CExtBarButton::IsContainerOfPopupLikeMenu()
{
	ASSERT_VALID( this );
	ASSERT(
			( m_hMenu == NULL )
		||	( m_hMenu != NULL && ::IsMenu(m_hMenu) )
		);
	return m_bPopupMenu;
}

CExtSafeString CExtBarButton::GetText() const
{
	ASSERT_VALID( this );
CExtSafeString sText( _T("") );
	if( IsSeparator() )
		return sText;
CExtCmdItem * pCmdItem =
		g_CmdManager->CmdGetPtr(
			g_CmdManager->ProfileNameFromWnd( GetBar()->GetSafeHwnd() ),
			GetCmdID( false )
			);
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode =
		((CExtBarButton*)this)->GetCmdNode();
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		return CExtSafeString( pNode->GetTextInToolbar( pCmdItem ) );
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	ASSERT( pCmdItem != NULL );
	if( !pCmdItem->m_sToolbarText.IsEmpty() )
		sText = pCmdItem->m_sToolbarText;
int nTabChrPos = sText.Find( _T('\t') );
	if( nTabChrPos < 0 )
		return sText;
	return sText.Left( nTabChrPos );
}

bool CExtBarButton::GetSeparatedDropDown() const
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = ((CExtBarButton*)this)->GetCmdNode( false );
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		return (pNode->GetFlags()&__ECTN_TBB_SEPARATED_DROPDOWN) ? true : false;
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	return m_bSeparatedDropDown;
}
void CExtBarButton::SetSeparatedDropDown(
	bool bSeparatedDropDown // = true
	)
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = GetCmdNode( false );
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		pNode->ModifyFlags(
			bSeparatedDropDown ? __ECTN_TBB_SEPARATED_DROPDOWN : 0,
			bSeparatedDropDown ? 0 : __ECTN_TBB_SEPARATED_DROPDOWN
			);
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	if( m_bSeparatedDropDown == bSeparatedDropDown )
		return;
	m_bSeparatedDropDown = bSeparatedDropDown;
	_UpdateCtrl();
}

bool CExtBarButton::GetAutoChangeID() const
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = ((CExtBarButton*)this)->GetCmdNode( false );
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		return (pNode->GetFlags()&__ECTN_TBB_AUTOCHANGE_ID) ? true : false;
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	return m_bAutoChangeID;
}
void CExtBarButton::SetAutoChangeID(
	bool bAutoChangeID // = true
	)
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = GetCmdNode( false );
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		pNode->ModifyFlags(
			bAutoChangeID ? __ECTN_TBB_AUTOCHANGE_ID : 0,
			bAutoChangeID ? 0 : __ECTN_TBB_AUTOCHANGE_ID
			);
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	if( m_bAutoChangeID == bAutoChangeID )
		return;
	m_bAutoChangeID = bAutoChangeID;
	_UpdateCtrl();
}

bool CExtBarButton::GetNoRotateVerticalLayout() const
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = ((CExtBarButton*)this)->GetCmdNode( false );
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		return (pNode->GetFlags()&__ECTN_TBB_NO_ROTATE_VL) ? true : false;
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	return m_bNoRotateVerticalLayout;
}
void CExtBarButton::SetNoRotateVerticalLayout(
	bool bNoRotateVerticalLayout // = true
	)
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = GetCmdNode( false );
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		pNode->ModifyFlags(
			bNoRotateVerticalLayout ? __ECTN_TBB_NO_ROTATE_VL : 0,
			bNoRotateVerticalLayout ? 0 : __ECTN_TBB_NO_ROTATE_VL
			);
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	if( m_bNoRotateVerticalLayout == bNoRotateVerticalLayout )
		return;
	m_bNoRotateVerticalLayout = bNoRotateVerticalLayout;
	_UpdateCtrl();
}

bool CExtBarButton::GetCtrlVisibleVertically() const
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = ((CExtBarButton*)this)->GetCmdNode( false );
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		return (pNode->GetFlags()&__ECTN_TBB_CTRL_VIS_VL) ? true : false;
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	return m_bCtrlVisibleVert;
}
void CExtBarButton::SetCtrlVisibleVertically( bool bVisible )
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = GetCmdNode( false );
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		pNode->ModifyFlags(
			bVisible ? __ECTN_TBB_CTRL_VIS_VL : 0,
			bVisible ? 0 : __ECTN_TBB_CTRL_VIS_VL
			);
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	m_bCtrlVisibleVert = bVisible;
	_UpdateCtrl();
}

BOOL CExtBarButton::PutToPopupMenu(
	CExtPopupMenuWnd * pPopup
	)
{
	ASSERT_VALID( this );
	ASSERT( pPopup != NULL );
	ASSERT( pPopup->GetSafeHwnd() == NULL );
	if( m_pCtrl != NULL )
	{
		if( m_pCtrl->SendMessage(
				CExtToolControlBar::g_nMsgPutToPopupMenu,
				reinterpret_cast <WPARAM> ( pPopup ),
				0
				)
			)
			return TRUE;
	}
	if( IsAbleToTrackMenu() )
	{
		CExtCmdItem * pCmdItem =
			g_CmdManager->CmdGetPtr(
				g_CmdManager->ProfileNameFromWnd( GetBar()->GetSafeHwnd() ),
				GetCmdID( false )
				);
		ASSERT( pCmdItem != NULL );
		CExtSafeString sText = pCmdItem->m_sMenuText;
		if( sText.IsEmpty() )
			sText = pCmdItem->m_sToolbarText;
		HICON hIcon =
			g_CmdManager->CmdGetHICON(
				g_CmdManager->ProfileNameFromWnd( GetBar()->GetSafeHwnd() ),
				GetCmdID( false )
				);
		VERIFY(
			pPopup->ItemInsert(
				(UINT)CExtPopupMenuWnd::TYPE_POPUP,
				-1,
				sText,
				hIcon
				)
			);
		CExtPopupMenuWnd * pChildPopup =
			pPopup->ItemGetPopup(
				pPopup->ItemGetCount() - 1
				);
		ASSERT( pChildPopup != NULL );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
		CExtCustomizeCmdTreeNode * pNode = GetCmdNode();
		if( pNode != NULL )
		{
			ASSERT_VALID( pNode );
			VERIFY(
				pChildPopup->UpdateFromCmdTree(
					GetCmdTargetWnd()->GetSafeHwnd(),
					pNode,
					false
					)
				);
		} // if( pNode != NULL )
		else
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
		{
			HMENU hMenu = GetMenu();
			ASSERT( hMenu != NULL );
			ASSERT( ::IsMenu(hMenu) );
			CMenu _menu;
			_menu.Attach( hMenu );
			pChildPopup->UpdateFromMenu(
				GetCmdTargetWnd()->GetSafeHwnd(),
				&_menu,
				IsContainerOfPopupLikeMenu(),
				false
				);
			_menu.Detach();
		} // else from if( pNode != NULL )
	} // if( IsAbleToTrackMenu() )
	else
	{
		if( !pPopup->ItemInsert( GetCmdID(true) ) )
		{
			ASSERT( FALSE );
			return FALSE;
		}
	} // else from if( IsAbleToTrackMenu() )
	return TRUE;
}

CRect CExtBarButton::RectDropDown() const
{
	ASSERT_VALID( this );
CRect rcBtnDropDownArea = Rect();

BOOL bHorz = TRUE;
	ASSERT_VALID( GetBar() );

	if( (!GetNoRotateVerticalLayout()) && GetBar()->IsDockedVertically() )
		bHorz = FALSE;

	if( bHorz )
	{
		rcBtnDropDownArea.left =
			rcBtnDropDownArea.right
			- __DROPDOWN_ARROW_GAP*2
			- CExtPaintManager::g_glyph_btn_expand_bottom.Size().cx
			;
//		if( m_bSeparatedDropDown )
//			rcBtnDropDownArea.left -= __DROPDOWN_ARROW_GAP;
	} // if( bHorz )
	else
	{
		rcBtnDropDownArea.top =
			rcBtnDropDownArea.bottom
			- __DROPDOWN_ARROW_GAP*2
			- CExtPaintManager::g_glyph_btn_expand_right.Size().cy
			;
//		if( m_bSeparatedDropDown )
//			rcBtnDropDownArea.top -= __DROPDOWN_ARROW_GAP;
	} // else from if( bHorz )

	return rcBtnDropDownArea;
}

CRect CExtBarButton::Rect() const
{
	ASSERT_VALID( this );
CRect rcBtn = m_ActiveRect;
	if(		GetBar() != NULL
		&&	g_PaintManager->GetCb2DbTransparentMode( (CObject *)(this) )
		&&	g_PaintManager->IsMenuMustCombineExcludeArea()
		&&	GetBar()->m_pDockSite != NULL
		&&	(! GetBar()->IsKindOf(RUNTIME_CLASS(CExtMenuControlBar)) )
		)
	{
		CSize sizeToolBarRgnRounders =
			g_PaintManager->GetToolBarRgnRoundersSize();
		CRect rcClient;
		GetBar()->GetClientRect( &rcClient );
		CRect rcBtn2(rcBtn);
		if( GetBar()->IsDockedVertically() )
		{
			rcBtn2.OffsetRect(
				rcBtn.left - rcClient.left,
				rcClient.bottom - rcBtn.bottom
				);
			rcBtn2.top = rcBtn.top - sizeToolBarRgnRounders.cy*2-1;
			rcBtn2.right = rcClient.right;
		} // if( GetBar()->IsDockedVertically() )
		else if( GetBar()->IsDockedHorizontally() )
		{
			rcBtn2.OffsetRect(
				rcClient.right - rcBtn.right,
				rcBtn.top - rcClient.top
				);
			rcBtn2.left = rcBtn.left - sizeToolBarRgnRounders.cx*2-1;
			rcBtn2.bottom = rcClient.bottom;
		} // else if( GetBar()->IsDockedHorizontally() )
	}
	return rcBtn;
}

CSize CExtBarButton::CalculateLayout(
	CDC & dc,
	CSize sizePreCalc,
	BOOL bHorz
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	ASSERT_VALID( (&dc) );

	if( GetNoRotateVerticalLayout() )
		bHorz = TRUE;

	if( (m_pCtrl != NULL) && (!m_bVertDocked || GetCtrlVisibleVertically()) )
	{
		ASSERT_VALID( m_pCtrl );
		CRect rcCtrl;
		m_pCtrl->GetWindowRect( &rcCtrl );
		m_ActiveSize.cx = rcCtrl.Width();
		m_ActiveSize.cy = sizePreCalc.cy;
		return m_ActiveSize;
	} // if( (m_pCtrl != NULL) && (!m_bVertDocked || GetCtrlVisibleVertically()) )
	m_ActiveSize = sizePreCalc;

	if( IsSeparator() )
	{
		if( bHorz )
			m_ActiveSize.cx = __EXT_TB_BUTTON_SEPARATOR_WIDTH;
		else
			m_ActiveSize.cy = __EXT_TB_BUTTON_SEPARATOR_HEIGHT;
	} // if( IsSeparator() )
	else
	{
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
		if( GetCmdNode() == NULL )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
		{
			CExtCmdItem * pCmdItem =
				g_CmdManager->CmdGetPtr(
					g_CmdManager->ProfileNameFromWnd( GetBar()->GetSafeHwnd() ),
					GetCmdID( true )
					);
			if( pCmdItem == NULL )
				return m_ActiveSize; // shutdown mode
		} // if( GetCmdNode() == NULL )

		CExtCmdIcon * pIcon = GetIconPtr();
		CSize _size( 0, 0 );
		if( pIcon != NULL && (! pIcon->IsEmpty() ) )
		{
			_size = pIcon->GetSize();
			if( IsLargeIcon() )
			{
				_size.cx *= 2;
				_size.cy *= 2;
			} // if( IsLargeIcon() )
			_size.cx += __EXT_TB_BUTTON_INNER_MARGIN*2;
			_size.cy += __EXT_TB_BUTTON_INNER_MARGIN*2;
		} // if( pIcon != NULL && (! pIcon->IsEmpty() ) )
		CExtSafeString sMeasureText = GetText();
		if( !sMeasureText.IsEmpty() )
		{
			static TCHAR stat_strDummyAmpSeq[] = _T("\001\001");
			sMeasureText.Replace( _T("&&"), stat_strDummyAmpSeq );
			sMeasureText.Remove( _T('&') );
			sMeasureText.Replace( stat_strDummyAmpSeq, _T("&") );
			CRect rcTextMeasure( 0, 0, 0, 0 );
			dc.DrawText(
				sMeasureText,
				sMeasureText.GetLength(),
				&rcTextMeasure,
				DT_SINGLELINE|DT_LEFT|DT_CALCRECT
				);
			if( bHorz )
			{
				_size.cx +=
					rcTextMeasure.Width()
					+ __EXT_TB_BUTTON_TEXT_MARGIN*2;
				_size.cy =
					max(
						_size.cy,
						rcTextMeasure.Height()
						);
			} // if( bHorz )
			else
			{
				_size.cx =
					max(
						_size.cx,
						rcTextMeasure.Height()
						);
				_size.cy +=
					rcTextMeasure.Width()
					//+ __EXT_TB_BUTTON_TEXT_MARGIN*2
					+ __EXT_TB_BUTTON_TEXT_MARGIN
					;
			} // else from if( bHorz )
			_size.cx += __EXT_TB_BUTTON_INNER_MARGIN*2;
			_size.cy += __EXT_TB_BUTTON_INNER_MARGIN*2;
		} // if( !sMeasureText.IsEmpty() )
		_size.cx += __EXT_TB_BUTTON_OUTER_MARGIN*2;
		_size.cy += __EXT_TB_BUTTON_OUTER_MARGIN*2;
		if( m_ActiveSize.cx < _size.cx )
			m_ActiveSize.cx = _size.cx;
		if( m_ActiveSize.cy < _size.cy )
			m_ActiveSize.cy = _size.cy;
	} // else from if( IsSeparator() )
	if(		IsAbleToTrackMenu()
		&&	(!GetBar()->IsKindOf(RUNTIME_CLASS(CExtMenuControlBar)))
		)
	{
		if( bHorz )
			m_ActiveSize.cx +=
				__DROPDOWN_ARROW_GAP*2
				+ CExtPaintManager::g_glyph_btn_expand_bottom.Size().cx
				;
		else
			m_ActiveSize.cy +=
				__DROPDOWN_ARROW_GAP*2
				+ CExtPaintManager::g_glyph_btn_expand_right.Size().cy
				;
	}
	return m_ActiveSize;
}

CExtCmdIcon * CExtBarButton::GetIconPtr()
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	if( GetBar()->GetSafeHwnd() == NULL )
		return NULL;
__EXT_MFC_SAFE_LPCTSTR strProfile = g_CmdManager->ProfileNameFromWnd( GetBar()->GetSafeHwnd() );
	if( strProfile == NULL )
		return NULL;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	CExtCustomizeCmdTreeNode * pOwnNode = GetCmdNode();
	if( pOwnNode != NULL )
	{
		ASSERT_VALID( pOwnNode );
		if( !CExtCmdManager::IsCommand( GetCmdID( true ) ) )
			return NULL;
		CExtCmdIcon * pIcon =
			pOwnNode->GetIconPtrInToolbar(
				g_CmdManager->CmdGetPtr(
					strProfile,
					GetCmdID( true )
					)
				);
		if( pIcon == NULL )
			return NULL;
		if( (pOwnNode->GetFlags()&__ECTN_TBB_AUTOCHANGE_ID) == 0 )
			return pIcon;
	} // if( pOwnNode != NULL )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	return
		g_CmdManager->CmdGetIconPtr(
			strProfile,
			GetCmdID( true )
			);
}

void CExtBarButton::Paint(
	CDC & dc,
	bool bHorz
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( (&dc) );

	if( GetNoRotateVerticalLayout() )
		bHorz = TRUE;

	if( (m_pCtrl != NULL) && (!m_bVertDocked || GetCtrlVisibleVertically()) )
		return;

	ASSERT( !IsSeparator() );
CRect rcArea( m_ActiveRect );
	rcArea.DeflateRect(
		__EXT_TB_BUTTON_INNER_MARGIN,
		__EXT_TB_BUTTON_INNER_MARGIN
		);
	if( rcArea.right <= rcArea.left
		||
		rcArea.bottom <= rcArea.top
		)
		return;
	if(		(! IsVisible() )
		||	(GetStyle() & TBBS_HIDDEN) != 0
		||	(! dc.RectVisible(&m_ActiveRect) )
		)
		return;
	ASSERT(
			m_ActiveSize.cx >= __EXT_TB_BUTTON_INNER_MARGIN*2
		&&	m_ActiveSize.cy >= __EXT_TB_BUTTON_INNER_MARGIN*2
		);
bool bDockSiteCustomizeMode =
		GetBar()->_IsDockSiteCustomizeMode();
bool bPushed =
		( IsPressed() && (!bDockSiteCustomizeMode) )
			? true : false;
bool bEnabled =
		( IsDisabled() && (!bDockSiteCustomizeMode) )
			? false : true;
bool bHover =
		( IsHover() && (!bDockSiteCustomizeMode) )
			? true : false;
	if( !bDockSiteCustomizeMode )
	{
		if(		CExtToolControlBar::g_bMenuTracking
			||	CExtPopupMenuWnd::IsMenuTracking()
			)
			bHover = false;
		else if( !bHover )
			bHover = IsPressedTracking();
		//if( bPushed && bHover && IsPressedTracking() )
			//bHover = false;
	} // if( !bDockSiteCustomizeMode )

bool bIndeterminate =
		( IsIndeterminate() && (!bDockSiteCustomizeMode) )
			? true : false;
CExtSafeString sText = GetText();

CExtCmdIcon * pIcon = GetIconPtr();
CExtCmdIcon _iconLarge;
	if(		pIcon != NULL
		&&	(! pIcon->IsEmpty() )
		&&	IsLargeIcon()
		)
	{
		CSize _sizeIcon = pIcon->GetSize();
		_sizeIcon.cx *= 2;
		_sizeIcon.cy *= 2;
		if(	_iconLarge.CreateScaledCopy(
				*pIcon,
				_sizeIcon
				)
			)
			pIcon = &_iconLarge;
#ifdef _DEBUG
		else
		{
			ASSERT( FALSE );
		}
#endif // _DEBUG
	}

CExtPaintManager::PAINTPUSHBUTTONDATA _ppbd(
		this,
		bHorz,
		rcArea,
		sText,
		pIcon,
		true,
		bHover,
		bPushed,
		bIndeterminate,
		bEnabled,
		true,false,false,
		CExtPaintManager::__ALIGN_HORIZ_CENTER
			| CExtPaintManager::__ALIGN_VERT,
		(HFONT)GetBar()->OnGetToolbarFont( !bHorz )->GetSafeHandle(), // NULL // (+ 2.23)
		(	IsAbleToTrackMenu()
			&& (!GetBar()->IsKindOf(RUNTIME_CLASS(CExtMenuControlBar)))
			) ? true : false,
		0,
		(!bEnabled) || ( bEnabled && (!bHover) && (!bPushed) )
		);

	if( m_bSeparatedDropDown )
	{
		_ppbd.m_bSeparatedDropDown = true;
		if(		(m_bDropDownHT || CExtToolControlBar::g_bMenuTracking)
			&&	bPushed
			&&	(!bDockSiteCustomizeMode)
			)
		{
			//_ppbd.m_bPushed = false;
			_ppbd.m_bPushedDropDown = true;
		}
	}

	g_PaintManager->PaintPushButton( dc, _ppbd );

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeSite * pSite = GetBar()->GetCustomizeSite();
	if(		pSite != NULL
		&&	pSite->IsCustomizeMode()
		&&	pSite->CustomizedNodeGet() != NULL
		&&	pSite->CustomizedNodeGet() == GetCmdNode( false )
		)
	{
		g_PaintManager->PaintDragSourceRect(
			dc,
			rcArea
			);
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

}

void CExtBarButton::OnUpdateCmdUI(
	CWnd * pTarget,
	BOOL bDisableIfNoHndler,
	int nIndex
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	ASSERT_VALID( pTarget );
	if(		IsSeparator() // ignore separators
		||	(	IsAbleToTrackMenu() // ignore menu drop buttons
			&&	(GetBar()->IsKindOf(RUNTIME_CLASS(CExtMenuControlBar)))
			)
		)
		return;

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeSite * pSite = GetBar()->GetCustomizeSite();
	if( pSite != NULL )
	{
		CExtCustomizeCmdTreeNode * pNode = GetCmdNode( false );
		if(		pNode != NULL
			&&	(pNode->GetFlags() & __ECTN_AUTO_POPUP) != 0
			)
			return;
		if( pSite->IsUserBarCommand( GetCmdID( false ) ) )
			return;
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

	// send the update notification
CExtToolControlBar::CExtToolControlBarCmdUI state;
	state.m_pOther = GetBar();
	state.m_nIndex = nIndex;
	state.m_nIndexMax = GetBar()->GetButtonsCount();
	state.m_nID = GetCmdID( false );
	state.DoUpdate( pTarget, bDisableIfNoHndler );
}

bool CExtBarButton::CanStartCommandDrag()
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	if( IsSeparator() )
		return false;
	if( m_pCtrl->GetSafeHwnd() != NULL )
		return false;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	if( GetCmdNode() == NULL )
		return false;
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	return true;
}

#if (!defined __EXT_MFC_NO_CUSTOMIZE)

void CExtBarButton::_UpdateCmdNodeFromStyle()
{
	ASSERT_VALID( this );
	if( GetBar() == NULL )
		return;
	ASSERT_VALID( GetBar() );
CExtCustomizeCmdTreeNode * pNode = GetCmdNode( false );
	if( pNode == NULL )
		return;
	ASSERT_VALID( pNode );
	if( GetStyle() & TBBS_HIDDEN )
		pNode->ModifyFlags( __ECTN_TBB_HIDDEN, 0 );
	else
		pNode->ModifyFlags( 0, __ECTN_TBB_HIDDEN );
}

bool CExtBarButton::IsCustomizeActiveItem()
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
CExtCustomizeSite * pSite =
		GetBar()->GetCustomizeSite();
	if( pSite == NULL )
		return false;
	return pSite->IsActiveItem( this );
}

void CExtBarButton::SetCustomizeActiveItem()
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	if( IsSeparator() )
		return;
CExtCustomizeSite * pSite =
		GetBar()->GetCustomizeSite();
	if( pSite == NULL )
		return;
	pSite->ActiveItemSet( this, GetBar()->GetSafeHwnd() );
	GetBar()->_GetIndexOf( this );
	RedrawButton();
}

int CExtBarButton::CalculateDropOverEffect(
	CPoint point,
	CExtCustomizeSite::CCmdDragInfo & _dragInfo,
	bool bAllowTrackNodePopup // = true
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	ASSERT( !_dragInfo.IsEmpty() );
	_dragInfo;
	if( IsSeparator() )
		return 0;
	if( !CanStartCommandDrag() )
		return 0;
	if( GetCmdNode() == NULL )
		return false;
//CPoint ptMid = Rect().CenterPoint();
CPoint ptMidL = Rect().TopLeft();
	ptMidL.x += Rect().Size().cx / 4;
	ptMidL.y += Rect().Size().cy / 4;
CPoint ptMidR( ptMidL );
	ptMidR.x += Rect().Size().cx / 2;
	ptMidR.y += Rect().Size().cy / 2;
int nRetVal = 0;
	if( (GetBar()->m_dwStyle & CBRS_ORIENT_HORZ) != 0 )
	{
		if( point.x <= ptMidL.x  )
			nRetVal = -1;
		else if( point.x >= ptMidR.x  )
			nRetVal = 1;
		else
			nRetVal = -2;
	} // if( (GetBar()->m_dwStyle & CBRS_ORIENT_HORZ) != 0 )
	else
	{
		if( point.y <= ptMidL.y  )
			nRetVal = -1;
		else if( point.y >= ptMidR.y  )
			nRetVal = 1;
		else
			nRetVal = -2;
	} // else from if( (GetBar()->m_dwStyle & CBRS_ORIENT_HORZ) != 0 )

	if( bAllowTrackNodePopup )
	{
		CExtCustomizeSite * pSite = GetBar()->GetCustomizeSite();
		ASSERT( pSite != NULL );
		if( IsAbleToTrackMenu( true ) )
		{
			CExtCustomizeCmdTreeNode * pOwnNode = GetCmdNode();
			ASSERT_VALID( pOwnNode );
			CRect rcBtn = Rect();
			GetBar()->ClientToScreen( &rcBtn );
			GetBar()->ClientToScreen( &point );
			DWORD dwTrackFlags = OnGetTrackPopupFlags();
			pSite->DropTargetPopupTrack(
				pOwnNode,
				rcBtn,
				point,
				dwTrackFlags
				);
		} // if( IsAbleToTrackMenu() )
		else
			pSite->DropTargetPopupCancel();
	} // if( bAllowTrackNodePopup )
	else
	{
		CExtCustomizeSite * pSite = GetBar()->GetCustomizeSite();
		if( pSite != NULL )
			pSite->DropTargetPopupCancel();
	} // else from if( bAllowTrackNodePopup )

	return nRetVal;
}

CExtCustomizeCmdTreeNode * CExtBarButton::GetCmdNode(
	bool bInitial // = false
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	if( IsSeparator() )
	{
		ASSERT( m_pCmdNodeI == NULL );
		ASSERT( m_pCmdNodeC == NULL );
		return NULL;
	}
CExtCustomizeCmdTreeNode * pNode =
		bInitial ? m_pCmdNodeI : m_pCmdNodeC;
#ifdef _DEBUG
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
	}
#endif // _DEBUG
	return pNode;
}

void CExtBarButton::OnCustomizeUpdateProps(
	CExtCustomizeCmdTreeNode * pNode // = NULL // update from basic node
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	if( pNode == NULL )
		pNode = m_pCmdNodeI;
	ASSERT_VALID( pNode );
#ifdef _DEBUG
	if( m_pCmdNodeI != NULL )
	{
		ASSERT_VALID( m_pCmdNodeI );
	}
#endif // _DEBUG
	ASSERT( !IsSeparator() );
	SetCmdID( pNode->GetCmdID(false), false ); // reset all IDs
	SetCmdID( pNode->GetCmdID(true), true ); // reset effective ID
DWORD dwNodeFlags = pNode->GetFlags();
	if( dwNodeFlags&__ECTN_TBB_APPEND_MDI_MENU )
		SetAppendMdiWindowsMenu( true );
	if( dwNodeFlags&__ECTN_TBB_SEPARATED_DROPDOWN )
		SetSeparatedDropDown( true );
	if( dwNodeFlags&__ECTN_TBB_AUTOCHANGE_ID )
		SetAutoChangeID( true );
	if( dwNodeFlags&__ECTN_TBB_NO_ROTATE_VL )
		SetNoRotateVerticalLayout( true );
}

void CExtBarButton::SetBasicCmdNode(
	CExtCustomizeCmdTreeNode * pNode
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	ASSERT_VALID( pNode );
	ASSERT( !IsSeparator() );
	m_pCmdNodeI = pNode;
	ASSERT( m_pCmdNodeI->GetCmdID(false) == GetCmdID(false) );
}

void CExtBarButton::SetCustomizedCmdNode(
	CExtCustomizeCmdTreeNode * pNode
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	ASSERT_VALID( pNode );
#ifdef _DEBUG
	if( m_pCmdNodeI != NULL )
	{
		ASSERT_VALID( m_pCmdNodeI );
	}
#endif // _DEBUG
	ASSERT( !IsSeparator() );
	m_pCmdNodeC = pNode;
	ASSERT( m_pCmdNodeC->GetCmdID(false) == GetCmdID(false) );
}

CExtCustomizeCmdTreeNode * CExtBarButton::OnCustomizeNodeInit(
	CExtCustomizeSite * pSite,
	CExtCustomizeCmdTreeNode * pParentNode // toolbar node
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	ASSERT( pSite != NULL );
	ASSERT_VALID( pParentNode );
	if( IsSeparator() )
	{
		ASSERT( m_pCmdNodeI == NULL );
		ASSERT( m_pCmdNodeC == NULL );
		return NULL;
	}
	m_pCmdNodeI = m_pCmdNodeC = NULL;
	m_pCmdNodeI =
		new CExtCustomizeCmdTreeNode(
			GetCmdID( false ),
			GetCmdID( true )
			);
	pParentNode->InsertNode( pSite, m_pCmdNodeI );
INT nOwnIdx = GetBar()->_GetIndexOf( this );
	ASSERT( 0 <= nOwnIdx && nOwnIdx < GetBar()->GetButtonsCount() );
	if( nOwnIdx > 0 )
	{
		CExtBarButton * pPrevTBB =
			GetBar()->GetButton( nOwnIdx - 1 );
		if( pPrevTBB->IsSeparator() )
			m_pCmdNodeI->ModifyFlags( __ECTN_GROUP_START );
	} // __ECTN_GROUP_START
CExtCmdItem * pCmdItem =
		g_CmdManager->CmdGetPtr(
			g_CmdManager->ProfileNameFromWnd( GetBar()->m_hWnd ),
			GetCmdID()
			);
	ASSERT( pCmdItem != NULL );
	m_pCmdNodeI->SetTextInToolbar( pCmdItem->m_sToolbarText );
	m_pCmdNodeI->SetTextInMenu( pCmdItem->m_sMenuText );
DWORD dwAddFlags = 0;
	if( IsAppendMdiWindowsMenu() )
		dwAddFlags |= __ECTN_TBB_APPEND_MDI_MENU;
	if( GetSeparatedDropDown() || pCmdItem->StateIsSeparatedDD() )
		dwAddFlags |= __ECTN_TBB_SEPARATED_DROPDOWN;
	if( GetAutoChangeID() || pCmdItem->StateIsAutochangeID() )
		dwAddFlags |= __ECTN_TBB_AUTOCHANGE_ID;
	if( GetNoRotateVerticalLayout() || pCmdItem->StateIsNoRotateVL() )
		dwAddFlags |= __ECTN_TBB_NO_ROTATE_VL;
	if( GetCtrlVisibleVertically() || pCmdItem->StateIsCtrlVisibleVertically() )
		dwAddFlags |= __ECTN_TBB_CTRL_VIS_VL;
	if( dwAddFlags != 0 )
		m_pCmdNodeI->ModifyFlags( dwAddFlags );

	m_pCmdNodeI->SetLParam( pCmdItem->m_nLParamUserData );

#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
	m_pCmdNodeI->TextFieldWidthSet( pCmdItem->m_nTextFieldWidth );
	m_pCmdNodeI->DropDownWidthSet( pCmdItem->m_nDropDownWidth );
	m_pCmdNodeI->DropDownHeightMaxSet( pCmdItem->m_nDropDownHeightMax );
	if( pCmdItem->StateIsCombo() )
		m_pCmdNodeI->ModifyFlags( __ECTN_TBB_COMBO|__ECTN_TBB_TEXT_FIELD, 0 );
	else if( pCmdItem->StateIsTextField() )
		m_pCmdNodeI->ModifyFlags( __ECTN_TBB_TEXT_FIELD, __ECTN_TBB_COMBO );
	else
		m_pCmdNodeI->ModifyFlags( 0, __ECTN_TBB_TEXT_FIELD|__ECTN_TBB_COMBO|__ECTN_TBB_RESIZABLE );

	if( pCmdItem->StateIsTextFieldNotEditable() )
		m_pCmdNodeI->ModifyFlags( __ECTN_TBB_TF_NE, 0 );
	else
		m_pCmdNodeI->ModifyFlags( 0, __ECTN_TBB_TF_NE );

	if(		( (m_pCmdNodeI->GetFlags() & (__ECTN_TBB_COMBO|__ECTN_TBB_TEXT_FIELD)) != 0 )
		&&	pCmdItem->StateIsResizable()
		)
		m_pCmdNodeI->ModifyFlags( __ECTN_TBB_RESIZABLE, 0 );
#endif // (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)

	if( pCmdItem->StateIsColor() )
		m_pCmdNodeI->ModifyFlags( __ECTN_TBB_COLOR, 0 );
	else
		m_pCmdNodeI->ModifyFlags( 0, __ECTN_TBB_COLOR );
	if( pCmdItem->StateIsColorBtnDefault() )
		m_pCmdNodeI->ModifyFlags( __ECTN_TBB_MCB_DEFAULT, 0 );
	else
		m_pCmdNodeI->ModifyFlags( 0, __ECTN_TBB_MCB_DEFAULT );
	if( pCmdItem->StateIsColorBtnCustom() )
		m_pCmdNodeI->ModifyFlags( __ECTN_TBB_MCB_CUSTOM, 0 );
	else
		m_pCmdNodeI->ModifyFlags( 0, __ECTN_TBB_MCB_CUSTOM );
	
	if( GetMenu() != NULL )
	{
		CMenu * pMenu = CMenu::FromHandle( GetMenu() );
		ASSERT( pMenu != NULL );
		VERIFY(
			m_pCmdNodeI->LoadMenuTree(
				GetBar(),
				GetBar()->GetCustomizeSite(),
				pMenu,
				IsContainerOfPopupLikeMenu()
				)
			);
		SetMenu( NULL, true, true ); // no longer needed
	} // if( GetMenu() != NULL )
	return m_pCmdNodeI;
}

#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
int CExtBarButton::GetInitialResizingStateH( // -1 - left side resizing, 1 - right side resizing, 0 - no resizing at specified point (in bar's client coord)
	CPoint point,
	int * p_nWidthMin, // = NULL
	int * p_nWidthMax // = NULL
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	point;
	p_nWidthMin;
	p_nWidthMax;
	return 0;
}
#endif // (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)

#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

void CExtBarButton::RedrawButton(
	bool bUpdateNow // = false
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	if(		IsVisible()
		&&	(GetStyle() & TBBS_HIDDEN) == 0
		)
		GetBar()->_InvalidateButton( GetBar()->_GetIndexOf(this) );
	if( bUpdateNow )
		GetBar()->UpdateWindow();
}

void CExtBarButton::SetMenu(
	HMENU hMenu,
	bool bPopupMenu,
	bool bAutoDestroyMenu
	)
{
	ASSERT_VALID( this );
	_DestroyMenu();
	m_hMenu = hMenu;
	if( m_hMenu != NULL )
	{
		ASSERT( ::IsMenu(hMenu) );
		VERIFY(
			g_CmdManager->UpdateFromMenu(
				g_CmdManager->ProfileNameFromWnd( GetBar()->GetSafeHwnd() ),
				hMenu
				)
			);
		m_bPopupMenu = bPopupMenu ? true : false;
		ModifyStyle(0,TBBS_DISABLED);
		m_bAutoDestroyMenu = bAutoDestroyMenu;
	}
}

UINT CExtBarButton::OnGetTrackPopupFlags()
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	if( GetBar()->m_bPresubclassDialogMode )
	{
		if( GetBar()->IsDockedAtRight() )
			return TPMX_RIGHTALIGN;
		if( GetBar()->IsDockedAtLeft() )
			return TPMX_LEFTALIGN;
		if( GetBar()->IsDockedAtBottom() )
			return TPMX_BOTTOMALIGN;
		return TPMX_TOPALIGN;
	}

	switch( GetBar()->GetSafeDockBarDlgCtrlID() )
	{
	case AFX_IDW_DOCKBAR_TOP:
		return TPMX_TOPALIGN;
	case AFX_IDW_DOCKBAR_BOTTOM:
		return TPMX_BOTTOMALIGN;
	case AFX_IDW_DOCKBAR_LEFT:
		return TPMX_LEFTALIGN;
	case AFX_IDW_DOCKBAR_RIGHT:
		return TPMX_RIGHTALIGN;
	default: // floating
		return TPMX_TOPALIGN;
	} // switch( GetBar()->GetSafeDockBarDlgCtrlID() )

}

bool CExtBarButton::OnSetCursor( CPoint point )
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	point;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
CExtCustomizeSite * pSite = GetBar()->GetCustomizeSite();
	if( pSite == NULL )
		return false;
	if( pSite->ActiveItemGet() != ((LPVOID)this) )
		return false;
CExtCustomizeCmdTreeNode * pNode = GetCmdNode( false );
	if( pNode == NULL )
		return false;
	ASSERT_VALID( pNode );
	if( (pNode->GetFlags() & __ECTN_TBB_RESIZABLE) == 0 )
		return false;
int nInitialResizingStateH =
		GetInitialResizingStateH( point );
	if( nInitialResizingStateH != 0 )
	{
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
		CExtLocalResourceHelper _LRH;
		CWinApp * pApp = ::AfxGetApp();
		ASSERT_VALID( pApp );
		HCURSOR hCursor =
			pApp->LoadCursor(
				MAKEINTRESOURCE( IDC_EXT_RESIZE_H1 )
				);
		if( hCursor == NULL )
		{
			ASSERT( FALSE );
			hCursor = ::LoadCursor( NULL, IDC_SIZEWE );
		} // if( hCursor == NULL )
#else // if - (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
		HCURSOR hCursor = ::LoadCursor( NULL, IDC_SIZEWE );
#endif // if NOT - (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
		ASSERT( hCursor != NULL );
		::SetCursor( hCursor );
		return true;
	} // if( nInitialResizingStateH != 0 )
#endif // (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	return false;
}

CWnd * CExtBarButton::GetCmdTargetWnd()
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
//CWnd * pWnd = GetBar()->_GetDockingFrameImpl();
//	if( pWnd == NULL )
//		pWnd = GetBar()->GetOwner();
CWnd * pWnd = GetBar()->GetOwner();
	ASSERT_VALID( pWnd );
	return pWnd;
}

UINT CExtBarButton::OnTrackPopup(
	CPoint point,
	bool bSelectAny
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );

bool bDockSiteCustomizeMode =
		GetBar()->_IsDockSiteCustomizeMode();
	if( bDockSiteCustomizeMode )
		return UINT(-1L);

	if( !IsEnabled() )
		return UINT(-1L);

CWnd * pWnd = CtrlGet();
	if( pWnd != NULL )
	{
		LRESULT lResult =
			pWnd->SendMessage(
				CExtToolControlBar::g_nMsgContinueTrackMenu,
				WPARAM( this ),
				bSelectAny ? 1L : 0L
				);
		lResult;
		return UINT(-1L);
	} // if( pWnd != NULL )

	if( !IsAbleToTrackMenu() )
		return UINT(-1L);
	
bool bPrevTBMT = CExtToolControlBar::g_bMenuTracking;
	if( CExtToolControlBar::g_bMenuTracking
		//&& CExtPopupMenuWnd::IsMenuTracking()
		&& GetBar()->_GetIndexOf(this) ==
			GetBar()->m_nBtnIdxMenuTracking
		)
		return UINT(-1L);

	CExtToolControlBar::_CloseTrackingMenus();

	if( GetBar()->IsFloating() )
	{
		GetBar()->ActivateTopParent();
		CFrameWnd * pFrame =
			GetBar()->GetDockingFrame();
		ASSERT_VALID( pFrame );
		pFrame->BringWindowToTop();
	}

CWnd * pWndCmdTarget = GetCmdTargetWnd();
	ASSERT_VALID( pWndCmdTarget );

CExtPopupMenuWnd * pPopup = new CExtPopupMenuWnd;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = GetCmdNode();
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		VERIFY(
			pPopup->UpdateFromCmdTree(
				pWndCmdTarget->GetSafeHwnd(),
				pNode
				)
			);
	} // if( pNode != NULL )
	else
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	{
		HMENU hMenu = GetMenu();
		ASSERT( hMenu != NULL );
		ASSERT( ::IsMenu(hMenu) );
		CMenu _menu;
		_menu.Attach( hMenu );
		VERIFY(
			pPopup->UpdateFromMenu(
				pWndCmdTarget->GetSafeHwnd(),
				&_menu,
				IsContainerOfPopupLikeMenu()
				)
			);
		_menu.Detach();
	} // else from if( pNode != NULL )

	if(		IsAppendMdiWindowsMenu()
		&&	(! GetBar()->_IsDockSiteCustomizeMode() )
		)
		pPopup->UpdateMdiWindowsMenu( pWndCmdTarget );

	CExtToolControlBar::g_bMenuTracking = bPrevTBMT;

CRect rcBtn = Rect();
	GetBar()->ClientToScreen( &rcBtn );
	GetBar()->ClientToScreen( &point );

DWORD dwTrackFlags =
		OnGetTrackPopupFlags()
		| TPMX_COMBINE_DEFAULT
		| TPMX_OWNERDRAW_FIXED
		;
	if( bSelectAny )
		dwTrackFlags |= TPMX_SELECT_ANY;
	if( CExtToolControlBar::g_bMenuTrackingExpanded )
		dwTrackFlags |= TPMX_NO_HIDE_RARELY;

	GetBar()->_SwitchMenuTrackingIndex(
		GetBar()->_GetIndexOf( this )
		);

	if(		GetAutoChangeID()
		&&	(! CExtControlBar::FindHelpMode(GetBar()) )
		)
	{
		HWND hWndBar = GetBar()->GetSafeHwnd();
		CExtToolControlBar::g_bMenuTracking = true;
		UINT nResultCmdID = 0;
		if( !pPopup->TrackPopupMenu(
				dwTrackFlags|TPMX_NO_WM_COMMAND|TPMX_DO_MESSAGE_LOOP,
				point.x,point.y,
				&rcBtn,
				GetBar(),
				CExtToolControlBar::_CbPaintCombinedContent,
				&nResultCmdID,
				true
				)
			)
		{
			delete pPopup;
			CExtToolControlBar::_CloseTrackingMenus();
			return UINT(-1L);
		}
		if( nResultCmdID == 0 )
				return UINT(-1L);
		if( hWndBar != NULL && ::IsWindow(hWndBar) )
		{
			SetCmdID( nResultCmdID, true, true );
			OnDeliverCmd();
		}
	} // if( GetAutoChangeID() )
	else
	{
		if( !pPopup->TrackPopupMenu(
				dwTrackFlags,
				point.x,point.y,
				&rcBtn,
				GetBar(),
				CExtToolControlBar::_CbPaintCombinedContent,
				NULL,
				true
				)
			)
		{
			delete pPopup;
			CExtToolControlBar::_CloseTrackingMenus();
			return UINT(-1L);
		}
		CExtToolControlBar::g_bMenuTracking = true;
		GetBar()->_SwitchMenuTrackingIndex(
			GetBar()->_GetIndexOf( this )
			);
	} // else from if( GetAutoChangeID() )
	return UINT(-1L);
}

void CExtBarButton::OnHover(
	CPoint point,
	bool bOn
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );

bool bDockSiteCustomizeMode =
		GetBar()->_IsDockSiteCustomizeMode();
	if( bDockSiteCustomizeMode )
		return;

	if( bOn )
	{

///		if( CExtToolControlBar::g_bMenuTracking
///			&& CExtPopupMenuWnd::IsMenuTracking()
///			&& GetBar()->m_nBtnIdxHover != GetBar()->m_nBtnIdxMenuTracking
///			)
///			CExtPopupMenuWnd::CancelMenuTracking();
		if( CExtToolControlBar::g_bMenuTracking )
			OnTrackPopup( point, false );
		else
		{
			CExtControlBar::stat_SetMessageString(
				GetCmdTargetWnd(),
				(UINT)(
					(		( ! GetBar()->IsKindOf(RUNTIME_CLASS(CExtMenuControlBar)) )
						&&	( ! IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton)) )
						&&	CExtCmdManager::IsCommand( GetCmdID(false) )
					)
						? GetCmdID(true)
						: AFX_IDS_IDLEMESSAGE
					)
				);
		}
		CWnd * pCtrl = CtrlGet();
		if( pCtrl == NULL
			|| (pCtrl->GetStyle() & WS_VISIBLE) == 0
			)
			((CExtMouseCaptureSink *)GetBar())->SetCapture( GetBar()->GetSafeHwnd() );
	} // if( bOn )
	else
	{
		CExtControlBar::stat_SetMessageString( GetCmdTargetWnd() );
		CExtMouseCaptureSink::ReleaseCapture();
	} // else from if( bOn )
}

void CExtBarButton::OnClick(
	CPoint point,
	bool bDown
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );

bool bDockSiteCustomizeMode =
		GetBar()->_IsDockSiteCustomizeMode();
	if( bDockSiteCustomizeMode )
		return;

bool bDropDownHT = false;
	if( m_bSeparatedDropDown )
	{
		CRect rcBtnDropDownArea = RectDropDown();
		if( rcBtnDropDownArea.PtInRect(point) )
			bDropDownHT = true;
	}

	if( bDown )
	{
		CExtToolControlBar::_CloseTrackingMenus();

		bool bAllowTrackMenu = true;
		m_bDropDownHT = false;
		if( m_bSeparatedDropDown )
		{
			m_bDropDownHT = bDropDownHT;
			if(!bDropDownHT )
				bAllowTrackMenu = false;
		}

		if( bAllowTrackMenu && IsAbleToTrackMenu() )
		{
			CExtToolControlBar::g_bMenuTrackingExpanded = false;
			OnTrackPopup( point, false );
			return;
		}

		CExtControlBar::stat_SetMessageString(
			GetCmdTargetWnd(),
			(WPARAM)GetCmdID(false)
			);

		return;
	} // if( bDown )

	CExtControlBar::stat_SetMessageString( GetCmdTargetWnd() );

	if( !m_bDropDownHT )
		bDropDownHT = false;
	m_bDropDownHT = false;

	if(		(IsAbleToTrackMenu() && (!GetSeparatedDropDown()))
		||	bDropDownHT
		)
		return;

CWnd * pCtrl = CtrlGet();
	if(	pCtrl != NULL
		&& (pCtrl->GetStyle() & WS_VISIBLE)
		)
	{
		ASSERT_VALID( pCtrl );
		CExtToolControlBar * pBar = GetSafeBar();
		ASSERT_VALID( pBar );
		if( CWnd::GetCapture() == pBar )
			pBar->SendMessage( WM_CANCELMODE );
		//pCtrl->SetFocus();
		return;
	}

	OnDeliverCmd();
}

void CExtBarButton::OnDeliverCmd()
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );

	if( !CExtCmdManager::IsCommand( GetCmdID(false) ) )
		return;
CExtCmdItem * pCmdItem =
		g_CmdManager->CmdGetPtr(
			g_CmdManager->ProfileNameFromWnd( GetBar()->GetSafeHwnd() ),
			GetCmdID(true)
			);
	ASSERT( pCmdItem != NULL );
	if( pCmdItem == NULL )
		return;
	VERIFY(
		pCmdItem->Deliver(
			GetBar(),
			true
			)
		);
}

int CExtBarButton::OnToolHitTest(
	CPoint point,
	TOOLINFO * pTI
	)
{
	ASSERT_VALID( this );
	point; // should be inside this button

	if(	!IsDisplayScreenTip() )
		return -1;

int nCmdID = (int)GetCmdID(true);

CExtCmdItem * pCmdItem =
		g_CmdManager->CmdGetPtr(
			g_CmdManager->ProfileNameFromWnd( GetSafeBar()->GetSafeHwnd() ),
			nCmdID
			);
	if( pCmdItem == NULL
		|| pCmdItem->m_sTipTool.IsEmpty()
		)
		return -1;

	if( pTI != NULL )
	{
		CRect rcArea = Rect();
		::CopyRect(
			&(pTI->rect),
			&rcArea
			);

		CExtSafeString strTip = pCmdItem->m_sTipTool;
		if(		IsDisplayShortcutKeysOnScreenTip()
			&&	(! pCmdItem->m_sAccelText.IsEmpty() )
			)
		{
			if( !strTip.IsEmpty() )
				strTip += _T(" ");
			strTip += _T("(");
			strTip += pCmdItem->m_sAccelText;
			strTip += _T(")");
		}

		pTI->uId = (UINT)nCmdID;
		pTI->hwnd = GetSafeBar()->GetSafeHwnd();
		pTI->lpszText = (LPTSTR)
			::calloc(
				(strTip.GetLength() + 1),
				sizeof(TCHAR)
				);
		if( pTI->lpszText != NULL )
			_tcscpy(
				pTI->lpszText,
				strTip
				);
		else
			pTI->lpszText = LPSTR_TEXTCALLBACK;
	} // if( pTI != NULL )

	return nCmdID;
}

LRESULT CExtBarButton::OnHelpHitTest(
	CPoint point
	)
{
	ASSERT_VALID( this );
	point; // should be inside this button

	if( IsSeparator() )
		return -1;

	if( IsAbleToTrackMenu() )
	{
		//CExtToolControlBar::_CloseTrackingMenus();
		//GetBar()->TrackButtonMenu( GetBar()->_GetIndexOf(this), FALSE, TRUE );
		//return -2;
		if(		GetBar()->m_pDockSite == NULL
			||	(! GetBar()->m_pDockSite->m_bHelpMode )
			)
			return -3L;
		OnTrackPopup( point, false );
		return CExtToolControlBar::_ContinueHelpHitTestMode( GetBar() );
	} // if( IsAbleToTrackMenu() )

int nCmdID = (int)GetCmdID(false);

CExtCmdItem * pCmdItem =
		g_CmdManager->CmdGetPtr(
			g_CmdManager->ProfileNameFromWnd( GetSafeBar()->GetSafeHwnd() ),
			nCmdID
			);
	if( pCmdItem == NULL
		//|| pCmdItem->m_sTipTool.IsEmpty()
		)
		return -1;

	return nCmdID;
}

/////////////////////////////////////////////////////////////////////////////
// CExtBarColorButton

IMPLEMENT_DYNCREATE(CExtBarColorButton, CExtBarButton)

void CExtBarColorButton::OnSyncIcon()
{
	ASSERT_VALID( this );

HICON hIcon = NULL;
	OnGenerateColorIcon( &hIcon );
	ASSERT( hIcon != NULL );
	if( hIcon == NULL )
		return;

	VERIFY(
		g_CmdManager->CmdSetIcon(
			g_CmdManager->ProfileNameFromWnd( GetSafeBar()->GetSafeHwnd() ),
			GetCmdID(true),
			hIcon,
			false
			)
		);
}

void CExtBarColorButton::OnGenerateColorIcon( HICON * p_hIcon )
{
	ASSERT_VALID( this );
	ASSERT( p_hIcon != NULL );
	ASSERT( (*p_hIcon) == NULL );

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = GetCmdNode(false);
	if(		pNode != NULL
		&&	GetBar()->GetSafeHwnd() != NULL
		&&	::IsWindow( GetBar()->GetSafeHwnd() )
		)
	{
		ASSERT_VALID( GetBar() );
		ASSERT_VALID( pNode );
		CExtCustomizeSite * pSite =
			GetBar()->GetCustomizeSite();
		if( pSite != NULL )
		{
			(*p_hIcon) =
				pSite->OnColorItemGenerateIcon(
					this,
					pNode,
					ColorGet(true)
					);
			if( (*p_hIcon) != NULL )
				return;
		} // if( pSite != NULL )
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	
	switch( m_eDIT )
	{
	
	case __DIT_FRAME:
	{
		(*p_hIcon) =
			CExtPaintManager::stat_GenerateColorIconFrame(
				ColorGet(true)
				);
		ASSERT( (*p_hIcon) != NULL );
	}
	break;
	
	case __DIT_CHAR:
	{
		LOGFONT lf;
		::memset( &lf, 0 , sizeof(LOGFONT) );
		g_PaintManager->m_FontBold.GetLogFont( &lf );
		_tcscpy( lf.lfFaceName, _T("Times New Roman") );
		lf.lfHeight = ::MulDiv( lf.lfHeight, 3, 2 );
		lf.lfWeight = 900;
		CFont fontForLetter;
		VERIFY(
			fontForLetter.CreateFontIndirect( &lf )
			);
		ASSERT( fontForLetter.GetSafeHandle() != NULL );
		(*p_hIcon) =
			CExtPaintManager::stat_GenerateColorIconChar(
				ColorGet(true),
				(HFONT)fontForLetter.GetSafeHandle()
				);
		ASSERT( (*p_hIcon) != NULL );
	}
	break;

	//case __DIT_BOX:
	default:
	{
		(*p_hIcon) =
			CExtPaintManager::stat_GenerateColorIconBox(
				ColorGet(true)
				);
		ASSERT( (*p_hIcon) != NULL );
	}
	break;
	
	} // switch( m_eDIT )
}

__EXT_MFC_SAFE_LPCTSTR CExtBarColorButton::BtnTextDefaultGet() const
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = ((CExtBarButton*)this)->GetCmdNode(false);
	if(		pNode != NULL
		&&	GetBar()->GetSafeHwnd() != NULL
		&&	::IsWindow( GetBar()->GetSafeHwnd() )
		)
	{
		ASSERT_VALID( GetBar() );
		ASSERT_VALID( pNode );
		CExtCustomizeSite * pSite =
			((CExtToolControlBar *)GetBar())->GetCustomizeSite();
		if( pSite != NULL )
			pSite->OnColorItemGetBtnTextDefault(
				(CExtBarColorButton*)this,
				pNode,
				(CExtSafeString &)m_sBtnTextColorDefault
				);
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	return
		m_sBtnTextColorDefault.IsEmpty()
			? _T("")
			: m_sBtnTextColorDefault
			;
}

void CExtBarColorButton::BtnTextDefaultSet(
	__EXT_MFC_SAFE_LPCTSTR sText // = NULL
	)
{
	ASSERT_VALID( this );
	m_sBtnTextColorDefault =
		(sText == NULL)
			? _T("")
			: sText
			;
}

__EXT_MFC_SAFE_LPCTSTR CExtBarColorButton::BtnTextCustomGet() const
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = ((CExtBarButton*)this)->GetCmdNode(false);
	if(		pNode != NULL
		&&	GetBar()->GetSafeHwnd() != NULL
		&&	::IsWindow( GetBar()->GetSafeHwnd() )
		)
	{
		ASSERT_VALID( GetBar() );
		ASSERT_VALID( pNode );
		CExtCustomizeSite * pSite =
			((CExtToolControlBar *)GetBar())->GetCustomizeSite();
		if( pSite != NULL )
			pSite->OnColorItemGetBtnTextCustom(
				(CExtBarColorButton*)this,
				pNode,
				(CExtSafeString &)m_sBtnTextColorCustom
				);
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	return
		m_sBtnTextColorCustom.IsEmpty()
			? _T("")
			: m_sBtnTextColorCustom
			;
}

void CExtBarColorButton::BtnTextCustomSet(
	__EXT_MFC_SAFE_LPCTSTR sText // = NULL
	)
{
	ASSERT_VALID( this );
	m_sBtnTextColorCustom =
		(sText == NULL)
			? _T("")
			: sText
			;
}

CExtCmdIcon * CExtBarColorButton::GetIconPtr()
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	return CExtBarButton::GetIconPtr();
}

BOOL CExtBarColorButton::PutToPopupMenu(
	CExtPopupMenuWnd * pPopup
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	ASSERT( CtrlGet() == NULL );
	ASSERT( IsAbleToTrackMenu() );

	if( !IsEnabled() )
	{
		if( !pPopup->ItemInsert( GetCmdID(true) ) )
		{
			ASSERT( FALSE );
			return FALSE;
		}
		return TRUE;
	}

CExtCmdItem * pCmdItem =
		g_CmdManager->CmdGetPtr(
			g_CmdManager->ProfileNameFromWnd( GetSafeBar()->GetSafeHwnd() ),
			GetCmdID(false)
			);

CExtCmdIcon * pIcon = GetIconPtr();
CExtPopupColorMenuWnd * pColorPopup = new CExtPopupColorMenuWnd;
	VERIFY(
		pPopup->ItemInsertSpecPopup(
			pColorPopup,
			-1,
			pCmdItem->m_sMenuText,
			(pIcon == NULL || pIcon->IsEmpty()) ? NULL : pIcon->GetIcon()
			)
		);
	pColorPopup->m_lParamCookie = LParamCookieGet();
	pColorPopup->m_bEnableBtnColorDefault = IsEnabledBtnColorDefault();
	pColorPopup->m_bEnableBtnColorCustom = IsEnabledBtnColorCustom();
	pColorPopup->m_clrDefault = ColorGet( false );
	pColorPopup->m_clrInitial = ColorGet( true );
CExtSafeString _s( BtnTextDefaultGet() );
	if( !_s.IsEmpty() )
		pColorPopup->m_sBtnTextColorDefault = _s;
	_s = BtnTextCustomGet();
	if( !_s.IsEmpty() )
		pColorPopup->m_sBtnTextColorCustom = _s;

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	pColorPopup->_CmdNodeSet( GetCmdNode(false) );
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

	return TRUE;
}

bool CExtBarColorButton::IsAbleToTrackMenu(
	bool bCustomizeMode // = false
	)
{
	ASSERT_VALID( this );
	if( bCustomizeMode )
		return false;
	return true;
}

UINT CExtBarColorButton::OnTrackPopup(
	CPoint point,
	bool bSelectAny
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	ASSERT( CtrlGet() == NULL );
	ASSERT( IsAbleToTrackMenu() );

bool bDockSiteCustomizeMode =
		GetBar()->_IsDockSiteCustomizeMode();
	if( bDockSiteCustomizeMode )
		return UINT(-1L);

	if( !IsEnabled() )
		return UINT(-1L);

bool bPrevTBMT = CExtToolControlBar::g_bMenuTracking;
	if( CExtToolControlBar::g_bMenuTracking
		//&& CExtPopupMenuWnd::IsMenuTracking()
		&& GetBar()->_GetIndexOf(this) ==
			GetBar()->GetMenuTrackingButton()
		)
		return UINT(-1L);

	CExtToolControlBar::_CloseTrackingMenus();

	if( GetBar()->IsFloating() )
	{
		GetBar()->ActivateTopParent();
		CFrameWnd * pFrame =
			GetBar()->GetDockingFrame();
		ASSERT_VALID( pFrame );
		pFrame->BringWindowToTop();
	}

CWnd * pWndCmdTarget = GetCmdTargetWnd();
	ASSERT_VALID( pWndCmdTarget );

CExtPopupColorMenuWnd * pPopup = new CExtPopupColorMenuWnd;
	VERIFY(
		pPopup->CreatePopupMenu(
			GetCmdTargetWnd()->GetSafeHwnd()
			)
		);
	pPopup->m_lParamCookie = LParamCookieGet();
	pPopup->m_bEnableBtnColorDefault = IsEnabledBtnColorDefault();
	pPopup->m_bEnableBtnColorCustom = IsEnabledBtnColorCustom();
	pPopup->m_clrDefault = ColorGet( false );
	pPopup->m_clrInitial = ColorGet( true );
CExtSafeString _s( BtnTextDefaultGet() );
	if( !_s.IsEmpty() )
		pPopup->m_sBtnTextColorDefault = _s;
	_s = BtnTextCustomGet();
	if( !_s.IsEmpty() )
		pPopup->m_sBtnTextColorCustom = _s;

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	pPopup->_CmdNodeSet( GetCmdNode(false) );
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

	CExtToolControlBar::g_bMenuTracking = bPrevTBMT;

CRect rcBtn = Rect();
	GetBar()->ClientToScreen( &rcBtn );
	GetBar()->ClientToScreen( &point );

DWORD dwTrackFlags =
		OnGetTrackPopupFlags()
			| TPMX_COMBINE_DEFAULT
			| TPMX_OWNERDRAW_FIXED
			;
	//if( GetBar()->IsKindOf(RUNTIME_CLASS(CExtMenuControlBar)) )
	if( bSelectAny )
		dwTrackFlags |= TPMX_SELECT_ANY;
	if( CExtToolControlBar::g_bMenuTrackingExpanded )
		dwTrackFlags |= TPMX_NO_HIDE_RARELY;

	GetBar()->_SwitchMenuTrackingIndex(
		GetBar()->_GetIndexOf( this )
		);

UINT nResultCmdID = (UINT)-1L;
	if( !pPopup->TrackPopupMenu(
			dwTrackFlags,
			point.x,point.y,
			&rcBtn,
			GetBar(),
			CExtToolControlBar::_CbPaintCombinedContent,
			&nResultCmdID,
			true
			)
		)
	{
		delete pPopup;
		CExtToolControlBar::_CloseTrackingMenus();
		return UINT(-1L);
	}
	CExtToolControlBar::g_bMenuTracking = true;
	GetBar()->_SwitchMenuTrackingIndex(
		GetBar()->_GetIndexOf( this )
		);
	return UINT(-1L);
}

int CExtBarColorButton::OnToolHitTest(
	CPoint point,
	TOOLINFO * pTI
	)
{
	ASSERT_VALID( this );
	return CExtBarButton::OnToolHitTest( point, pTI );
}

LRESULT CExtBarColorButton::OnHelpHitTest(
	CPoint point
	)
{
	ASSERT_VALID( this );
//	return
//		CExtBarButton::OnHelpHitTest( point );
	point;
	return GetCmdID();
}

void CExtBarColorButton::OnUpdateCmdUI(
	CWnd * pTarget,
	BOOL bDisableIfNoHndler,
	int nIndex
	)
{
	ASSERT_VALID( this );
	CExtBarButton::OnUpdateCmdUI(
		pTarget,
		bDisableIfNoHndler,
		nIndex
		);
}

bool CExtBarColorButton::CanStartCommandDrag()
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	if( GetCmdNode() == NULL )
		return false;
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	return true;
}

LPARAM CExtBarColorButton::LParamCookieGet() const
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = ((CExtBarButton*)this)->GetCmdNode(false);
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		return pNode->GetLParam();
	} // if( pNode != NULL )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	return m_lParamCookie;
}

void CExtBarColorButton::LParamCookieSet(
	LPARAM lParamCookie // = 0L
	)
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = ((CExtBarButton*)this)->GetCmdNode(false);
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		pNode->SetLParam( lParamCookie );
	} // if( pNode != NULL )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	m_lParamCookie = lParamCookie;
}

bool CExtBarColorButton::IsEnabledBtnColorDefault() const
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = ((CExtBarButton*)this)->GetCmdNode(false);
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		return ( (pNode->GetFlags() & __ECTN_TBB_MCB_DEFAULT) != 0 ) ? true : false;
	} // if( pNode != NULL )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	return m_bEnableBtnColorDefault;
}
void CExtBarColorButton::EnableBtnColorDefault(
	bool bEnable // = true
	)
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = GetCmdNode(false);
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		pNode->ModifyFlags(
			bEnable ? __ECTN_TBB_MCB_DEFAULT : 0,
			bEnable ? 0 : __ECTN_TBB_MCB_DEFAULT
			);
	} // if( pNode != NULL )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	m_bEnableBtnColorDefault = bEnable;
}
bool CExtBarColorButton::IsEnabledBtnColorCustom() const
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = ((CExtBarButton*)this)->GetCmdNode(false);
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		return ( (pNode->GetFlags() & __ECTN_TBB_MCB_CUSTOM) != 0 ) ? true : false;
	} // if( pNode != NULL )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	return m_bEnableBtnColorCustom;
}
void CExtBarColorButton::EnableBtnColorCustom(
	bool bEnable // = true
	)
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = GetCmdNode(false);
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		pNode->ModifyFlags(
			bEnable ? __ECTN_TBB_MCB_CUSTOM: 0,
			bEnable ? 0 : __ECTN_TBB_MCB_CUSTOM
			);
	} // if( pNode != NULL )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	m_bEnableBtnColorCustom = bEnable;
}

COLORREF CExtBarColorButton::ColorGet( bool bSelected ) const
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = ((CExtBarButton*)this)->GetCmdNode(false);
	if(		pNode != NULL
		&&	GetBar()->GetSafeHwnd() != NULL
		&&	::IsWindow( GetBar()->GetSafeHwnd() )
		)
	{
		ASSERT_VALID( GetBar() );
		ASSERT_VALID( pNode );
		CExtCustomizeSite * pSite =
			((CExtToolControlBar *)GetBar())->GetCustomizeSite();
		if( pSite != NULL )
		{
			COLORREF clr = bSelected ? m_clrDefault : m_clrSelected;
			if(	pSite->OnColorItemValueGet(
					(CExtBarColorButton*)this,
					pNode,
					clr,
					bSelected
					)
				)
				return clr;
		} // if( pSite != NULL )
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	return bSelected ? m_clrDefault : m_clrSelected;
}

void CExtBarColorButton::ColorSet( COLORREF clr, bool bSelected )
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = GetCmdNode(false);
	if(		pNode != NULL
		&&	GetBar()->GetSafeHwnd() != NULL
		&&	::IsWindow( GetBar()->GetSafeHwnd() )
		)
	{
		ASSERT_VALID( GetBar() );
		ASSERT_VALID( pNode );
		CExtCustomizeSite * pSite =
			GetBar()->GetCustomizeSite();
		if( pSite != NULL )
			pSite->OnColorItemValueSet(
				this,
				pNode,
				clr,
				bSelected
				);
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	if( bSelected )
	{
		if( m_clrSelected != clr )
		{
			m_clrSelected = clr;
			OnSyncIcon();
		}
	}
	else
	{
		if( m_clrDefault != clr )
		{
			m_clrDefault = clr;
			OnSyncIcon();
		}
	}
}

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
int CExtBarColorButton::CalculateDropOverEffect(
	CPoint point,
	CExtCustomizeSite::CCmdDragInfo & _dragInfo,
	bool bAllowTrackNodePopup // = true
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	ASSERT( !_dragInfo.IsEmpty() );
	bAllowTrackNodePopup;
	return
		CExtBarButton::CalculateDropOverEffect(
			point,
			_dragInfo,
			false
			);
}
CExtCustomizeCmdTreeNode * CExtBarColorButton::GetCmdNode(
	bool bInitial // = false
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	return CExtBarButton::GetCmdNode( bInitial );
}
void CExtBarColorButton::SetBasicCmdNode(
	CExtCustomizeCmdTreeNode * pNode
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	CExtBarButton::SetBasicCmdNode( pNode );
}
void CExtBarColorButton::SetCustomizedCmdNode(
	CExtCustomizeCmdTreeNode * pNode
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	CExtBarButton::SetCustomizedCmdNode( pNode );
}

CExtCustomizeCmdTreeNode * CExtBarColorButton::OnCustomizeNodeInit(
	CExtCustomizeSite * pSite,
	CExtCustomizeCmdTreeNode * pParentNode // toolbar node
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
CExtCustomizeCmdTreeNode * pNode =
		CExtBarButton::OnCustomizeNodeInit( pSite, pParentNode );
	ASSERT_VALID( pNode );
	return pNode;
}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

void CExtBarColorButton::OnDeliverCmd()
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * pNode = GetCmdNode( false );
	if( pNode != NULL )
	{
		ASSERT_VALID( pNode );
		CExtCustomizeSite * pSite = GetBar()->GetCustomizeSite();
		if(		pSite != NULL
			&&	pSite->OnColorItemChanged(
					this,
					pNode,
					true,
					ColorGet(true),
					LParamCookieGet()
					)
			)
			return;
	} // if( pNode != NULL )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	GetCmdTargetWnd()->SendMessage(
		CExtPopupColorMenuWnd::g_nMsgNotifyColorChangedFinally,
		(WPARAM)ColorGet(true),
		LParamCookieGet()
		);
}


/////////////////////////////////////////////////////////////////////////////
// CExtBarContentExpandButton

IMPLEMENT_DYNCREATE(CExtBarContentExpandButton, CExtBarButton)

CSize CExtBarContentExpandButton::CalculateLayout(
	CDC & dc,
	CSize sizePreCalc,
	BOOL bHorz
	)
{
	dc;
	ASSERT( m_pCtrl == NULL );
	ASSERT( !IsSeparator() );
	ASSERT( GetCmdID(false) == __ID_TOOLBAR_RIGHT_BUTTON__ );
CSize _size(
			bHorz ? __RIGHT_BUTTON_HORZ_DX__ : sizePreCalc.cx,
			bHorz ? sizePreCalc.cy : __RIGHT_BUTTON_VERT_DY__
			);
	m_ActiveSize = _size;
	m_ActiveSize.cx += __EXT_TB_BUTTON_INNER_MARGIN*2;
	m_ActiveSize.cy += __EXT_TB_BUTTON_INNER_MARGIN*2;
	return m_ActiveSize;
}

void CExtBarContentExpandButton::Paint(
	CDC & dc,
	bool bHorz
	)
{
	ASSERT( m_pCtrl == NULL );
	ASSERT_VALID( (&dc) );
	ASSERT( !IsSeparator() );
	ASSERT( GetCmdID(false) == __ID_TOOLBAR_RIGHT_BUTTON__ );
//	ASSERT( !IsDisabled() );

CRect rcArea( m_ActiveRect );
	rcArea.DeflateRect(
		__EXT_TB_BUTTON_INNER_MARGIN,
		__EXT_TB_BUTTON_INNER_MARGIN
		);

	if( rcArea.right <= rcArea.left
		||
		rcArea.bottom <= rcArea.top
		)
		return;
	ASSERT(
		m_ActiveSize.cx >= __EXT_TB_BUTTON_INNER_MARGIN*2
		&&
		m_ActiveSize.cy >= __EXT_TB_BUTTON_INNER_MARGIN*2
		);
bool bDockSiteCustomizeMode =
		GetBar()->_IsDockSiteCustomizeMode();
bool bEnabled = 
		( (!IsDisabled()) || bDockSiteCustomizeMode )
			? true : false;
bool bBarIsCompletelyVisible =
		(GetButtons().GetSize() == 0) ? true : false;
bool bEmpty = 
		(	(!GetBar()->m_bRightButtonDisplayBarsList)
			&& bBarIsCompletelyVisible
		) ? true : false;
bool bPushed =
		( (!bEmpty) && bEnabled && IsPressed() && (!bDockSiteCustomizeMode) )
			? true : false;
bool bHover =
		(	(!bEmpty)
			&& bEnabled
			&& (!bDockSiteCustomizeMode)
			&& IsHover()
			&& !CExtToolControlBar::g_bMenuTracking
			&& !CExtPopupMenuWnd::IsMenuTracking()
		) ? true : false;
	g_PaintManager->PaintToolbarExpandButton(
		dc,
		rcArea,
		bHorz,
		bBarIsCompletelyVisible,
		bEnabled && !bEmpty,
		bPushed,
		bHover,
		this,
		0L,
		( (!bHover) && (!bPushed) )
		);
}

BOOL CExtBarContentExpandButton::PutToPopupMenu(
	CExtPopupMenuWnd * pPopup
	)
{
	pPopup;
	ASSERT( FALSE );
	return FALSE;
}

UINT CExtBarContentExpandButton::OnTrackPopup(
	CPoint point,
	bool bSelectAny
	)
{
	ASSERT_VALID( GetBar() );

bool bDockSiteCustomizeMode =
		GetBar()->_IsDockSiteCustomizeMode();
	if( bDockSiteCustomizeMode )
		return UINT(-1L);

	if( !IsEnabled() )
		return UINT(-1L);

bool bPrevTBMT = CExtToolControlBar::g_bMenuTracking;

	if(		CExtToolControlBar::g_bMenuTracking
			//&&	CExtPopupMenuWnd::IsMenuTracking()
		&&	GetBar()->_GetIndexOf(this) ==
				GetBar()->m_nBtnIdxMenuTracking
		)
		return UINT(-1L);

bool bBarIsCompletelyVisible =
		(GetButtons().GetSize() == 0) ? true : false;
bool bEmpty = 
		(	!GetBar()->m_bRightButtonDisplayBarsList
			&& bBarIsCompletelyVisible
		) ? true : false;
	if( bEmpty )
		return UINT(-1L);

	CExtToolControlBar::_CloseTrackingMenus();

	CExtToolControlBar::g_bMenuTracking = bPrevTBMT;

	if( GetBar()->IsFloating() )
	{
		GetBar()->ActivateTopParent();
		CFrameWnd * pFrame =
			GetBar()->GetParentFrame();
		if( pFrame != NULL )
			pFrame->BringWindowToTop();
	}

HWND hWndTrack = GetCmdTargetWnd()->GetSafeHwnd();
	ASSERT(
		hWndTrack != NULL
		&& ::IsWindow(hWndTrack)
		);

CExtPopupMenuWnd * pPopup = new CExtPopupMenuWnd;
	VERIFY( pPopup->CreatePopupMenu(hWndTrack) );

CExtControlBar::POPUP_MENU_EVENT_DATA _pmed(
		CExtControlBar::POPUP_MENU_EVENT_DATA::__PMED_CTXEXPBTN_TOP,
		pPopup,
		GetBar(),
		CPoint( -1, -1 ),
		WM_NCLBUTTONDOWN,
		this
		);

	if( !_pmed.NotifyTarget( false ) )
	{

		// append hidden buttons
		int nCount = GetButtons().GetSize();
		if( nCount != 0 )
		{
			ASSERT( nCount > 0 );
			int nCountBefore = pPopup->ItemGetCount();
			for( int i=0; i< nCount; i++ )
			{
				CExtBarButton * pTBB = GetButtons() [i];
				ASSERT( pTBB != NULL );
				if( i==0 && pTBB->IsSeparator() )
					continue;
				ASSERT( !pTBB->IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton)) );
				VERIFY( pTBB->PutToPopupMenu(pPopup) );
			} // for( int i=0; i< nCount; i++ )
			int nCountAfter = pPopup->ItemGetCount();
			ASSERT( nCountAfter >= nCountBefore );
			if( nCountAfter != nCountBefore
				&& (!GetBar()->m_bPresubclassDialogMode)
				&& GetBar()->m_bRightButtonDisplayBarsList
				)
			{
				// append separator
				VERIFY(
					pPopup->ItemInsert(
						CExtPopupMenuWnd::TYPE_SEPARATOR
						)
					);
			}
		} // if( nCount != 0 )
		// append show/hide popup

		if(		(!GetBar()->m_bPresubclassDialogMode)
			&&	GetBar()->m_bRightButtonDisplayBarsList
			)
		{
			CFrameWnd * pFrame = GetBar()->_GetDockingFrameImpl();
			if( pFrame != NULL )
			{
				ASSERT_VALID( pFrame );

#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
				CExtLocalResourceHelper _LRH;
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)

				CExtSafeString sShowHidePanels;
				if( !sShowHidePanels.LoadString(IDS_SHOW_HIDE_PANELS) )
				{
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
					ASSERT( FALSE );
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
					sShowHidePanels = _T("&Show/hide panels");
				}

				CExtControlBar::POPUP_MENU_EVENT_DATA _pmed(
					CExtControlBar::POPUP_MENU_EVENT_DATA::__PMED_CTXEXPBTN_APPEND,
					pPopup,
					GetBar(),
					CPoint( -1, -1 ),
					WM_NCLBUTTONDOWN,
					this
					);
			
				if( !_pmed.NotifyTarget( false ) )
				{
					VERIFY(
						pPopup->ItemInsert(
							(UINT)CExtPopupMenuWnd::TYPE_POPUP,
							-1,
							sShowHidePanels
							)
						);
					CExtPopupMenuWnd::MENUITEMDATA & mi = pPopup->ItemGetInfo( pPopup->ItemGetCount() - 1 );
					mi.SetChildCombine();
					mi.SetToolButton();
					CExtPopupMenuWnd * pPopupBars = mi.GetPopup();
					ASSERT( pPopupBars != NULL );
					if( ! CExtDockBar::_ConstructDockSiteControlBarPopupMenu(
							pFrame,
							pPopupBars,
							CExtControlBar::POPUP_MENU_EVENT_DATA::__PMED_CTXEXPBTN_BARS,
							GetBar(),
							WM_NCLBUTTONDOWN,
							this
							)
						)
					{
						VERIFY(
							pPopup->ItemRemove(
								pPopup->ItemGetCount() - 1
								)
							);
					}
				} // if( !_pmed.NotifyTarget( false ) )

				_pmed.NotifyTarget( true );
			
			} // if( pFrame != NULL )

		} // if( (!GetBar()->m_bPresubclassDialogMode) ...
	
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
		if(		GetBar()->m_bCustomizationAllowed
			&&	GetBar()->GetCustomizeSite() != NULL
			)
		{ // if customization allowed
			VERIFY(
				CExtDockBar::_AppendAddRemoveButtonsCustomizeMenu(
					pPopup,
					GetBar()
					)
				);
		} // if customization allowed
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

	} // if( !_pmed.NotifyTarget( false ) )
	_pmed.NotifyTarget( true );

	
	if( pPopup->ItemGetCount() == 0 )
	{
		delete pPopup;
		return UINT(-1L);
	}

CRect rcBtn = Rect();
	GetBar()->ClientToScreen( &rcBtn );
	GetBar()->ClientToScreen( &point );
DWORD dwTrackFlags =
		OnGetTrackPopupFlags()
		| TPMX_COMBINE_DEFAULT
		| TPMX_OWNERDRAW_FIXED
		;
	//if( GetBar()->IsKindOf(RUNTIME_CLASS(CExtMenuControlBar)) )
	if( bSelectAny )
		dwTrackFlags |= TPMX_SELECT_ANY;
	if( CExtToolControlBar::g_bMenuTrackingExpanded )
		dwTrackFlags |= TPMX_NO_HIDE_RARELY;

	GetBar()->_SwitchMenuTrackingIndex(
		GetBar()->_GetIndexOf( this )
		);

	if( !pPopup->TrackPopupMenu(
			dwTrackFlags,
			point.x,point.y,
			&rcBtn,
			GetBar(),
			CExtToolControlBar::_CbPaintCombinedContent,
			NULL,
			true
			)
		)
	{
		delete pPopup;
		CExtToolControlBar::_CloseTrackingMenus();
		return UINT(-1L);
	}

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeSite * pSite = GetBar()->GetCustomizeSite();
	if( pSite != NULL )
		pSite->BarDefCmdTargetSet( GetBar() );
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

	CExtToolControlBar::g_bMenuTracking = true;
	GetBar()->_SwitchMenuTrackingIndex(
		GetBar()->_GetIndexOf( this )
		);
	return UINT(-1L);
}

void CExtBarContentExpandButton::OnHover(
	CPoint point,
	bool bOn
	)
{
	ASSERT_VALID( GetBar() );

bool bDockSiteCustomizeMode =
		GetBar()->_IsDockSiteCustomizeMode();
	if( bDockSiteCustomizeMode )
		return;

	CExtBarButton::OnHover( point, bOn );
}

void CExtBarContentExpandButton::OnClick(
	CPoint point,
	bool bDown
	)
{
	ASSERT_VALID( GetBar() );

bool bDockSiteCustomizeMode =
		GetBar()->_IsDockSiteCustomizeMode();
	if( bDockSiteCustomizeMode )
		return;

	if( !bDown )
		return;

	CExtToolControlBar::g_bMenuTrackingExpanded = false;

	OnTrackPopup( point, false );
}

int CExtBarContentExpandButton::OnToolHitTest(
	CPoint point,
	TOOLINFO * pTI
	)
{
	ASSERT_VALID( this );
	point; // should be inside this button

	if( pTI != NULL )
	{
		CRect rcArea = Rect();
		::CopyRect(
			&(pTI->rect),
			&rcArea
			);

		int nCmdID = AFX_IDS_IDLEMESSAGE; //(int)GetBar()->GetDlgCtrlID();
		
		pTI->uId = (UINT)nCmdID;
		pTI->hwnd = GetSafeBar()->GetSafeHwnd();

#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
		CExtLocalResourceHelper _LRH;
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)

		CExtSafeString sExpandTip;
		if( !sExpandTip.LoadString(IDS_CONTENT_EXPAND_TIP) )
		{
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
			ASSERT( FALSE );
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
			sExpandTip = _T("Where are buttons?");
		}

		pTI->lpszText = (LPTSTR)
			::calloc(
				(sExpandTip.GetLength() + 1),
				sizeof(TCHAR)
				);
		if( pTI->lpszText != NULL )
			_tcscpy(
				pTI->lpszText,
				sExpandTip
				);
		else
			pTI->lpszText = LPSTR_TEXTCALLBACK;

		return nCmdID;
	} // if( pTI != NULL )
	
	return -1;
}

LRESULT CExtBarContentExpandButton::OnHelpHitTest(
	CPoint point
	)
{
	ASSERT_VALID( this );
	return
		CExtBarButton::OnHelpHitTest( point );
}

bool CExtBarContentExpandButton::CanStartCommandDrag()
{
	ASSERT_VALID( this );
	return false;
}

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * CExtBarContentExpandButton::GetCmdNode(
	bool bInitial // = false
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	bInitial;
	ASSERT( m_pCmdNodeI == NULL );
	ASSERT( m_pCmdNodeC == NULL );
	return NULL;
}
void CExtBarContentExpandButton::SetBasicCmdNode(
	CExtCustomizeCmdTreeNode * pNode
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	ASSERT( m_pCmdNodeI == NULL );
	ASSERT( m_pCmdNodeC == NULL );
	ASSERT( FALSE ); // should be never called
	pNode;
}
void CExtBarContentExpandButton::SetCustomizedCmdNode(
	CExtCustomizeCmdTreeNode * pNode
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	ASSERT( m_pCmdNodeI == NULL );
	ASSERT( m_pCmdNodeC == NULL );
	ASSERT( FALSE ); // should be never called
	pNode;
}
CExtCustomizeCmdTreeNode * CExtBarContentExpandButton::OnCustomizeNodeInit(
	CExtCustomizeSite * pSite,
	CExtCustomizeCmdTreeNode * pParentNode // toolbar node
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	ASSERT( pSite != NULL );
	ASSERT_VALID( pParentNode );
	pSite;
	pParentNode;
	return NULL; // no customization support
}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

/////////////////////////////////////////////////////////////////////////////
// CExtBarSliderButton

IMPLEMENT_DYNCREATE(CExtBarSliderButton, CExtBarButton)

ULONG CExtBarSliderButton::ScrollLimitGet() const
{
	ASSERT_VALID( this );
ULONG nScrollPageSize = ScrollPageSizeGet();
ULONG nScrollTotalRange = ScrollTotalRangeGet();
ULONG nScrollLimit = nScrollTotalRange;
	if( nScrollLimit > nScrollPageSize )
		nScrollLimit -= nScrollPageSize;
	else
		nScrollLimit = 0L;
	return nScrollLimit;
}

ULONG CExtBarSliderButton::ScrollTotalRangeGet() const
{
	ASSERT_VALID( this );
	return m_nScrollTotalRange;
}

ULONG CExtBarSliderButton::ScrollTotalRangeSet( ULONG nScrollTotalRange )
{
	ASSERT_VALID( this );
ULONG nScrollPosOld = ScrollPosGet();
	if( nScrollPosOld > nScrollTotalRange )
		ScrollPosSet( nScrollTotalRange );
ULONG nScrollTotalRangeOld = ScrollTotalRangeGet();
	m_nScrollTotalRange = nScrollTotalRange;
	ASSERT_VALID( this );
	RecalcSliderLayout();
	return nScrollTotalRangeOld;
}

ULONG CExtBarSliderButton::ScrollPosGet() const
{
	ASSERT_VALID( this );
	return m_nScrollPos;
}

ULONG CExtBarSliderButton::ScrollPosSet( ULONG nScrollPos )
{
	ASSERT_VALID( this );
ULONG nScrollPosOld = ScrollPosGet();
	m_nScrollPos = nScrollPos;
	ASSERT_VALID( this );
	RecalcSliderLayout();
	return nScrollPosOld;
}

ULONG CExtBarSliderButton::ScrollPageSizeGet() const
{
	ASSERT_VALID( this );
	return m_nScrollPageSize;
}

ULONG CExtBarSliderButton::ScrollPageSizeSet( ULONG nScrollPageSize )
{
	ASSERT_VALID( this );
ULONG nScrollPageSizeOld = ScrollPageSizeGet();
	m_nScrollPageSize = nScrollPageSize;
	ASSERT_VALID( this );
	RecalcSliderLayout();
	return nScrollPageSizeOld;
}

INT CExtBarSliderButton::ScrollButtonExtentHorzGet() const
{
	ASSERT_VALID( this );
	return m_nScrollButtonExtentH;
}

INT CExtBarSliderButton::ScrollButtonExtentHorzSet( INT nScrollButtonExtent )
{
	ASSERT_VALID( this );
INT nScrollButtonExtentOld = ScrollButtonExtentHorzGet();
	m_nScrollButtonExtentH = nScrollButtonExtent;
	ASSERT_VALID( this );
	RecalcSliderLayout();
	return nScrollButtonExtentOld;
}

INT CExtBarSliderButton::ScrollButtonExtentVertGet() const
{
	ASSERT_VALID( this );
	return m_nScrollButtonExtentV;
}

INT CExtBarSliderButton::ScrollButtonExtentVertSet( INT nScrollButtonExtent )
{
	ASSERT_VALID( this );
INT nScrollButtonExtentOld = ScrollButtonExtentVertGet();
	m_nScrollButtonExtentV = nScrollButtonExtent;
	ASSERT_VALID( this );
	RecalcSliderLayout();
	return nScrollButtonExtentOld;
}

INT CExtBarSliderButton::ScrollControlExtentHorzGet() const
{
	ASSERT_VALID( this );
	return m_nScrollControlExtentH;
}

INT CExtBarSliderButton::ScrollControlExtentHorzSet( INT nScrollControlExtent )
{
	ASSERT_VALID( this );
INT nScrollControlExtentOld = ScrollControlExtentHorzGet();
	m_nScrollControlExtentH = nScrollControlExtent;
	ASSERT_VALID( this );
	RecalcSliderLayout();
	return nScrollControlExtentOld;
}

INT CExtBarSliderButton::ScrollControlExtentVertGet() const
{
	ASSERT_VALID( this );
	return m_nScrollControlExtentV;
}

INT CExtBarSliderButton::ScrollControlExtentVertSet( INT nScrollControlExtent )
{
	ASSERT_VALID( this );
INT nScrollControlExtentOld = ScrollControlExtentVertGet();
	m_nScrollControlExtentV = nScrollControlExtent;
	ASSERT_VALID( this );
	RecalcSliderLayout();
	return nScrollControlExtentOld;
}

#ifdef _DEBUG
void CExtBarSliderButton::AssertValid() const
{
	CExtBarButton::AssertValid();
	ASSERT( m_nScrollPos <= m_nScrollTotalRange );
	ASSERT( m_nScrollButtonExtentH >= 0 );
	ASSERT( m_nScrollButtonExtentV >= 0 );
	ASSERT( m_nScrollControlExtentH >= 0 );
	ASSERT( m_nScrollControlExtentV >= 0 );
	ASSERT( m_pCtrl == NULL );
}
void CExtBarSliderButton::Dump(CDumpContext& dc) const
{
	CExtBarButton::Dump( dc );
}
#endif

void CExtBarSliderButton::SetMenu(
	HMENU hMenu,
	bool bPopupMenu,
	bool bAutoDestroyMenu
	)
{
	ASSERT_VALID( this );
	ASSERT( FALSE ); // should not be used with text-field button
	hMenu;
	bPopupMenu;
	bAutoDestroyMenu;
}

HMENU CExtBarSliderButton::GetMenu()
{
	ASSERT_VALID( this );
	return NULL;
}

//bool CExtBarSliderButton::IsLargeIcon() const
//{
//	ASSERT_VALID( this );
//	return false;
//}
//
//bool CExtBarSliderButton::IsDisplayScreenTip() const
//{
//	ASSERT_VALID( this );
//	return false;
//}
//
//bool CExtBarSliderButton::IsDisplayShortcutKeysOnScreenTip() const
//{
//	ASSERT_VALID( this );
//	return false;
//}

void CExtBarSliderButton::SetRect( const RECT & rectButton )
{
	ASSERT_VALID( this );
	m_ActiveRect = rectButton;
	RecalcSliderLayout();
}

bool CExtBarSliderButton::IsAbleToTrackMenu(
	bool bCustomizeMode // = false
	)
{
	ASSERT_VALID( this );
	bCustomizeMode;
	return false;
}

bool CExtBarSliderButton::IsContainerOfPopupLikeMenu()
{
	ASSERT_VALID( this );
	return false;
}

//CExtCmdIcon * CExtBarSliderButton::GetIconPtr()
//{
//	ASSERT_VALID( this );
//	return NULL; // no icon at all for text-fields
//}

CSize CExtBarSliderButton::CalculateLayout(
	CDC & dc,
	CSize sizePreCalc,
	BOOL bHorz
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( GetBar() );
	ASSERT_VALID( (&dc) );
	if( GetNoRotateVerticalLayout() )
		bHorz = TRUE;
	m_ActiveSize = sizePreCalc;
	ASSERT( ! IsSeparator() );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	if( GetCmdNode() == NULL )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	{
		CExtCmdItem * pCmdItem =
			g_CmdManager->CmdGetPtr(
				g_CmdManager->ProfileNameFromWnd( GetBar()->GetSafeHwnd() ),
				GetCmdID( true )
				);
		if( pCmdItem == NULL )
			return m_ActiveSize; // shutdown mode
	} // if( GetCmdNode() == NULL )
CSize _size( 0, 0 );
	// update size for icon
bool bIconEmpty = true;
CExtCmdIcon * pIcon = GetIconPtr();
	if( pIcon != NULL && (! pIcon->IsEmpty() ) )
	{
		bIconEmpty = false;
		_size = pIcon->GetSize();
		if( IsLargeIcon() )
		{
			_size.cx *= 2;
			_size.cy *= 2;
		} // if( IsLargeIcon() )
		_size.cx += __EXT_TB_BUTTON_INNER_MARGIN*2;
		_size.cy += __EXT_TB_BUTTON_INNER_MARGIN*2;
	} // if( pIcon != NULL && (! pIcon->IsEmpty() ) )
	// update size for text
bool bTextEmpty = true;
CExtSafeString sMeasureText = GetText();
	if( sMeasureText.IsEmpty() )
	{
		CSize sizeAlign = m_pBar->_GetDefButtonSize();
		if( bHorz )
		{
			sizeAlign.cy -= 7;
			_size.cy = max( _size.cy, sizeAlign.cy );
		} // if( bHorz )
		else
		{
			sizeAlign.cx -= 7;
			_size.cx = max( _size.cx, sizeAlign.cx );
		} // else from if( bHorz )
	} // if( sMeasureText.IsEmpty() )
	else
	{
		bTextEmpty = false;
		static TCHAR stat_strDummyAmpSeq[] = _T("\001\001");
		sMeasureText.Replace( _T("&&"), stat_strDummyAmpSeq );
		sMeasureText.Remove( _T('&') );
		sMeasureText.Replace( stat_strDummyAmpSeq, _T("&") );
		CRect rcTextMeasure( 0, 0, 0, 0 );
		dc.DrawText(
			sMeasureText,
			sMeasureText.GetLength(),
			&rcTextMeasure,
			DT_SINGLELINE|DT_LEFT|DT_CALCRECT
			);
		if( bHorz )
		{
			_size.cx +=
				rcTextMeasure.Width()
				+ __EXT_TB_BUTTON_TEXT_MARGIN*2;
			_size.cy =
				max(
					_size.cy,
					rcTextMeasure.Height()
					);
		} // if( bHorz )
		else
		{
			_size.cx =
				max(
					_size.cx,
					rcTextMeasure.Height()
					);
			_size.cy +=
				rcTextMeasure.Width()
				//+ __EXT_TB_BUTTON_TEXT_MARGIN*2
				+ __EXT_TB_BUTTON_TEXT_MARGIN
				;
		} // else from if( bHorz )
		_size.cx += __EXT_TB_BUTTON_INNER_MARGIN*2;
		_size.cy += __EXT_TB_BUTTON_INNER_MARGIN*2;
	} // else from if( sMeasureText.IsEmpty() )
	// update size for slider control
	if( bHorz )
	{
		INT nExtentCtrl = ScrollControlExtentHorzGet();
		ASSERT( nExtentCtrl >= 0 );
		_size.cx += nExtentCtrl;
		if( bTextEmpty && bIconEmpty )
			_size.cy += __EXT_TB_BUTTON_OUTER_MARGIN*2-2;
	} // if( bHorz )
	else
	{
		INT nExtentCtrl = ScrollControlExtentVertGet();
		ASSERT( nExtentCtrl >= 0 );
		_size.cy += nExtentCtrl;
		if( bTextEmpty && bIconEmpty )
			_size.cx += __EXT_TB_BUTTON_OUTER_MARGIN*2-2;
	} // else from if( bHorz )
	if( !( bTextEmpty && bIconEmpty ) )
	{
		_size.cx += __EXT_TB_BUTTON_OUTER_MARGIN*2;
		_size.cy += __EXT_TB_BUTTON_OUTER_MARGIN*2;
		if( m_ActiveSize.cx < _size.cx )
			m_ActiveSize.cx = _size.cx;
		if( m_ActiveSize.cy < _size.cy )
			m_ActiveSize.cy = _size.cy;
	} // if( !( bTextEmpty && bIconEmpty ) )
	m_ActiveSize = _size;
	return m_ActiveSize;
}

void CExtBarSliderButton::RecalcSliderLayout()
{
	ASSERT_VALID( this );
CRect rcAll = Rect();
	rcAll.DeflateRect(
		__EXT_TB_BUTTON_INNER_MARGIN,
		__EXT_TB_BUTTON_INNER_MARGIN
		);
bool bHorz = GetBar()->IsDockedVertically() ? false : true;
	if( GetNoRotateVerticalLayout() )
		bHorz = true;
INT nExtentCtrl = bHorz
		? ScrollControlExtentHorzGet()
		: ScrollControlExtentVertGet();
	m_arrAreaRects[__ESA_ICON_AND_TEXT] = rcAll;
	m_arrAreaRects[__ESA_SLIDER] = rcAll;
	m_arrAreaRects[__ESA_ICON_AND_TEXT].DeflateRect(
		0,
		0,
		bHorz ? nExtentCtrl : 0,
		bHorz ? 0 : nExtentCtrl
		);
	m_arrAreaRects[__ESA_SLIDER].DeflateRect(
		bHorz ? m_arrAreaRects[__ESA_ICON_AND_TEXT].Width() : 0,
		bHorz ? 0 : m_arrAreaRects[__ESA_ICON_AND_TEXT].Height(),
		0,
		0
		);
INT nExtentBtn = bHorz
		? ScrollButtonExtentHorzGet()
		: ScrollButtonExtentVertGet();
	m_arrAreaRects[__ESA_SCROLLABLE] = m_arrAreaRects[__ESA_SLIDER];
	m_arrAreaRects[__ESA_LINE_UP] = m_arrAreaRects[__ESA_SLIDER];
	m_arrAreaRects[__ESA_LINE_DOWN] = m_arrAreaRects[__ESA_SLIDER];
	m_arrAreaRects[__ESA_THUMB].SetRect( 0, 0, 0, 0 );
	m_arrAreaRects[__ESA_PAGE_UP].SetRect( 0, 0, 0, 0 );
	m_arrAreaRects[__ESA_PAGE_DOWN].SetRect( 0, 0, 0, 0 );
ULONG nScrollPos = ScrollPosGet();
ULONG nScrollPageSize = ScrollPageSizeGet();
ULONG nScrollTotalRange = ScrollTotalRangeGet();
ULONG nScrollLimit = ScrollLimitGet();
ULONG nExtentMD = 0L;
INT nExtentThumb = 0;
	if( nScrollLimit > 0L )
	{
		if( nScrollPageSize == 0 )
		{
			nExtentThumb = nExtentBtn;
			if( nExtentThumb == 0 )
				nExtentThumb = 6;
		} // if( nScrollPageSize == 0 )
		else
		{
			if( nScrollTotalRange > nScrollPageSize )
			{
				nExtentMD = nScrollTotalRange/nScrollPageSize;
			} // if( nScrollTotalRange > nScrollPageSize )
		} // else from if( nScrollPageSize == 0 )
	} // if( nScrollLimit > 0L )
	if( bHorz )
	{
		m_arrAreaRects[__ESA_SCROLLABLE].DeflateRect( nExtentBtn, 0 );
		m_arrAreaRects[__ESA_LINE_UP].right = m_arrAreaRects[__ESA_LINE_UP].left + nExtentBtn;
		m_arrAreaRects[__ESA_LINE_DOWN].left = m_arrAreaRects[__ESA_LINE_DOWN].right - nExtentBtn;
		if( m_arrAreaRects[__ESA_SCROLLABLE].Width() > 5 )
		{
			if( nExtentThumb == 0 && nExtentMD != 0L )
				nExtentThumb =
					::MulDiv( m_arrAreaRects[__ESA_SCROLLABLE].Width(), nScrollPageSize, nScrollTotalRange );
			if( nExtentThumb != 0 && nExtentThumb < 4 )
				nExtentThumb = 4;
			if( nExtentThumb != 0 )
			{
				m_arrAreaRects[__ESA_THUMB] = m_arrAreaRects[__ESA_SCROLLABLE];
				m_arrAreaRects[__ESA_THUMB].right = m_arrAreaRects[__ESA_THUMB].left + nExtentThumb;
				if( nScrollLimit > 0 )
				{
					INT nRestSpace = m_arrAreaRects[__ESA_SCROLLABLE].Width() - m_arrAreaRects[__ESA_THUMB].Width();
					ASSERT( nRestSpace > 0 );
					INT nOffset = ::MulDiv( nRestSpace, nScrollPos, nScrollLimit );
					m_arrAreaRects[__ESA_THUMB].OffsetRect( nOffset, 0 );
					if( nScrollPos > 0 )
					{
						m_arrAreaRects[__ESA_PAGE_UP] = m_arrAreaRects[__ESA_SCROLLABLE];
						m_arrAreaRects[__ESA_PAGE_UP].right = m_arrAreaRects[__ESA_THUMB].left;
					}
					if( nScrollPos < nScrollLimit )
					{
						m_arrAreaRects[__ESA_PAGE_DOWN] = m_arrAreaRects[__ESA_SCROLLABLE];
						m_arrAreaRects[__ESA_PAGE_DOWN].left = m_arrAreaRects[__ESA_THUMB].right;
					}
				} // if( nScrollLimit > 0 )
			} // if( nExtentThumb != 0 )
		} // if( m_arrAreaRects[__ESA_SCROLLABLE].Width() > 5 )
	} // if( bHorz )
	else
	{
		m_arrAreaRects[__ESA_SCROLLABLE].DeflateRect( 0, nExtentBtn );
		m_arrAreaRects[__ESA_LINE_UP].bottom = m_arrAreaRects[__ESA_LINE_UP].top + nExtentBtn;
		m_arrAreaRects[__ESA_LINE_DOWN].top = m_arrAreaRects[__ESA_LINE_DOWN].bottom - nExtentBtn;
		if( m_arrAreaRects[__ESA_SCROLLABLE].Height() > 5 )
		{
			if( nExtentThumb == 0 && nExtentMD != 0L )
				nExtentThumb =
					::MulDiv( m_arrAreaRects[__ESA_SCROLLABLE].Height(), nScrollPageSize, nScrollTotalRange );
			if( nExtentThumb != 0 && nExtentThumb < 4 )
				nExtentThumb = 4;
			if( nExtentThumb != 0 )
			{
				m_arrAreaRects[__ESA_THUMB] = m_arrAreaRects[__ESA_SCROLLABLE];
				m_arrAreaRects[__ESA_THUMB].bottom = m_arrAreaRects[__ESA_THUMB].top + nExtentThumb;
				if( nScrollLimit > 0 )
				{
					INT nRestSpace = m_arrAreaRects[__ESA_SCROLLABLE].Height() - m_arrAreaRects[__ESA_THUMB].Height();
					ASSERT( nRestSpace > 0 );
					INT nOffset = ::MulDiv( nRestSpace, nScrollPos, nScrollLimit );
					m_arrAreaRects[__ESA_THUMB].OffsetRect( 0, nOffset );
					if( nScrollPos > 0 )
					{
						m_arrAreaRects[__ESA_PAGE_UP] = m_arrAreaRects[__ESA_SCROLLABLE];
						m_arrAreaRects[__ESA_PAGE_UP].bottom = m_arrAreaRects[__ESA_THUMB].top;
					}
					if( nScrollPos < nScrollLimit )
					{
						m_arrAreaRects[__ESA_PAGE_DOWN] = m_arrAreaRects[__ESA_SCROLLABLE];
						m_arrAreaRects[__ESA_PAGE_DOWN].top = m_arrAreaRects[__ESA_THUMB].bottom;
					}
				} // if( nScrollLimit > 0 )
			} // if( nExtentThumb != 0 )
		} // if( m_arrAreaRects[__ESA_SCROLLABLE].Height() > 5 )
	} // else from if( bHorz )
}

void CExtBarSliderButton::Paint(
	CDC & dc,
	bool bHorz
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( (&dc) );
	if( GetNoRotateVerticalLayout() )
		bHorz = TRUE;
	ASSERT( ! IsSeparator() );
	if(		(! IsVisible() )
		||	(GetStyle() & TBBS_HIDDEN) != 0
		||	(! dc.RectVisible(&m_ActiveRect) )
		)
		return;
CRect rcArea( m_ActiveRect );
	rcArea.DeflateRect(
		__EXT_TB_BUTTON_INNER_MARGIN,
		__EXT_TB_BUTTON_INNER_MARGIN
		);
INT nExtentCtrl = bHorz
		? ScrollControlExtentHorzGet()
		: ScrollControlExtentVertGet();
	rcArea.DeflateRect(
		0,
		0,
		bHorz ? nExtentCtrl : 0,
		bHorz ? 0 : nExtentCtrl
		);
	if(		rcArea.right > rcArea.left
		&&	rcArea.bottom > rcArea.top
		&&	dc.RectVisible( &rcArea )
		)
	{ // if icon/text area is not empty and visible
		bool bDockSiteCustomizeMode =
			GetBar()->_IsDockSiteCustomizeMode();
		bool bPushed = false;
		//	( IsPressed() && (!bDockSiteCustomizeMode) )
		//		? true : false;
		bool bEnabled =
			( IsDisabled() && (!bDockSiteCustomizeMode) )
				? false : true;
		bool bHover = false;
		//	( IsHover() && (!bDockSiteCustomizeMode) )
		//		? true : false;
		//if( !bDockSiteCustomizeMode )
		//{
		//	if(		CExtToolControlBar::g_bMenuTracking
		//		||	CExtPopupMenuWnd::IsMenuTracking()
		//		)
		//		bHover = false;
		//	else if( !bHover )
		//		bHover = IsPressedTracking();
		//} // if( !bDockSiteCustomizeMode )
		bool bIndeterminate = false;
		//	( IsIndeterminate() && (!bDockSiteCustomizeMode) )
		//		? true : false;
		CExtSafeString sText = GetText();
		CExtCmdIcon * pIcon = GetIconPtr();
		CExtCmdIcon _iconLarge;
		if(		pIcon != NULL
			&&	(! pIcon->IsEmpty() )
			&&	IsLargeIcon()
			)
		{
			CSize _sizeIcon = pIcon->GetSize();
			_sizeIcon.cx *= 2;
			_sizeIcon.cy *= 2;
			if(	_iconLarge.CreateScaledCopy(
					*pIcon,
					_sizeIcon
					)
				)
				pIcon = &_iconLarge;
#ifdef _DEBUG
			else
			{
				ASSERT( FALSE );
			}
#endif // _DEBUG
		}
		CExtPaintManager::PAINTPUSHBUTTONDATA _ppbd(
			this,
			bHorz,
			rcArea,
			sText,
			pIcon,
			true,
			bHover,
			bPushed,
			bIndeterminate,
			bEnabled,
			true,false,false,
			CExtPaintManager::__ALIGN_HORIZ_CENTER
				| CExtPaintManager::__ALIGN_VERT,
			(HFONT)GetBar()->OnGetToolbarFont( !bHorz )->GetSafeHandle(), // NULL // (+ 2.23)
			(	IsAbleToTrackMenu()
				&& (!GetBar()->IsKindOf(RUNTIME_CLASS(CExtMenuControlBar)))
				) ? true : false,
			0,
			(!bEnabled) || ( bEnabled && (!bHover) && (!bPushed) )
			);
		//if( m_bSeparatedDropDown )
		//{
		//	_ppbd.m_bSeparatedDropDown = true;
		//	if(		(m_bDropDownHT || CExtToolControlBar::g_bMenuTracking)
		//		&&	bPushed
		//		&&	(!bDockSiteCustomizeMode)
		//		)
		//	{
		//		//_ppbd.m_bPushed = false;
		//		_ppbd.m_bPushedDropDown = true;
		//	}
		//}
		g_PaintManager->PaintPushButton( dc, _ppbd );
	} // if icon/text area is not empty and visible

	
	if(		m_arrAreaRects[__ESA_SLIDER].right > m_arrAreaRects[__ESA_SLIDER].left
		&&	m_arrAreaRects[__ESA_SLIDER].bottom > m_arrAreaRects[__ESA_SLIDER].top
		&&	dc.RectVisible( &m_arrAreaRects[__ESA_SLIDER] )
		)
	{ // if slider area is not empty and visible
		for(	int nRectNo = __ESA_PAINT_RANGE_FIRST;
				nRectNo <= __ESA_PAINT_RANGE_LAST;
				nRectNo++
				)
		{ // walk and paint all areas
			if(		m_arrAreaRects[nRectNo].right <= m_arrAreaRects[nRectNo].left
				||	m_arrAreaRects[nRectNo].bottom <= m_arrAreaRects[nRectNo].top
				||	( ! dc.RectVisible( &m_arrAreaRects[nRectNo] ) )
				)
				continue;
			OnPaintScrollArea(
				dc,
				(CExtBarSliderButton::e_SliderArea_t)nRectNo,
				bHorz
				);
		} // walk and paint all areas
	} // if slider area is not empty and visible

	rcArea = m_ActiveRect;
	rcArea.DeflateRect(
		__EXT_TB_BUTTON_INNER_MARGIN,
		__EXT_TB_BUTTON_INNER_MARGIN
		);
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeSite * pSite = GetBar()->GetCustomizeSite();
	if(		pSite != NULL
		&&	pSite->IsCustomizeMode()
		&&	pSite->CustomizedNodeGet() != NULL
		&&	pSite->CustomizedNodeGet() == GetCmdNode( false )
		)
	{
		g_PaintManager->PaintDragSourceRect(
			dc,
			rcArea
			);
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

}

void CExtBarSliderButton::OnPaintScrollArea(
	CDC & dc,
	CExtBarSliderButton::e_SliderArea_t eSA,
	bool bHorz
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( (&dc) );
	ASSERT_VALID( m_pBar );
	ASSERT( 0 <= eSA && eSA < __ESA_COUNT );
CRect rcArea = GetAreaRect( eSA );
	if(		rcArea.right < rcArea.left
		||	rcArea.bottom < rcArea.top
		||	( ! dc.RectVisible(&rcArea) )
		)
		return;
bool bFlatButton = false;
bool bDockSiteCustomizeMode =
		GetBar()->_IsDockSiteCustomizeMode();
bool bEnabled =
		(	IsDisabled()
		&& (!bDockSiteCustomizeMode)
		)
		? false : true;
	if( bEnabled )
	{
		ULONG nScrollPageSize = ScrollPageSizeGet();
		ULONG nScrollTotalRange = ScrollTotalRangeGet();
		if(		nScrollPageSize >= nScrollTotalRange
			||	nScrollTotalRange == 0L
			)
			bEnabled = false;
	} // if( bEnabled )
bool bHover =
		(	IsHover()
		&&	bEnabled
		&&	(!bDockSiteCustomizeMode)
		)
		? true : false;
bool bPushed =
		(	GetPressedArea() == eSA
		&&	bEnabled
		&&	(!bDockSiteCustomizeMode)
		)
		? true : false;
	if( !bDockSiteCustomizeMode )
	{
		if(		CExtToolControlBar::g_bMenuTracking
			||	CExtPopupMenuWnd::IsMenuTracking()
			)
			bHover = false;
		else if( !bHover )
			bHover = IsPressedTracking();
	} // if( !bDockSiteCustomizeMode )
CExtPaintManager::glyph_t * pBtnGlyph = NULL;
bool bPaintAsButton = false;
INT nExtentBtn = bHorz
		? ScrollButtonExtentHorzGet()
		: ScrollButtonExtentVertGet();
	switch( eSA )
	{
	case __ESA_LINE_UP:
		bPaintAsButton = true;
		pBtnGlyph = bHorz
			? CExtPaintManager::g_DockingCaptionGlyphs[
				CExtPaintManager::__DCBT_ARROW_LEFT ]
			: CExtPaintManager::g_DockingCaptionGlyphs[
				CExtPaintManager::__DCBT_ARROW_UP ];
		bFlatButton = bPushed;
//		bPushed = false;
	break;
	case __ESA_LINE_DOWN:
		bPaintAsButton = true;
		pBtnGlyph = bHorz
			? CExtPaintManager::g_DockingCaptionGlyphs[
				CExtPaintManager::__DCBT_ARROW_RIGHT ]
			: CExtPaintManager::g_DockingCaptionGlyphs[
				CExtPaintManager::__DCBT_ARROW_DOWN ];
		bFlatButton = bPushed;
//		bPushed = false;
	break;
	case __ESA_THUMB:
		bPaintAsButton = true;
		//bFlatButton = bPushed;
		bPushed = false;
	break;
	case __ESA_SCROLLABLE:
		if( nExtentBtn != 0 )
		{
			dc.FillRect(
				rcArea,
				(bHover && bEnabled)
					? ( & g_PaintManager->m_brushLightestDefault )
					: ( & g_PaintManager->m_brushLightDefault )
				);
			rcArea.InflateRect(
				bHorz ? 1 : 0,
				bHorz ? 0 : 1
				);
		} // if( nExtentBtn != 0 )
		else
		{
			rcArea.DeflateRect(
				bHorz ? 0 : (rcArea.Width()/2),
				bHorz ? (rcArea.Height()/2) : 0
				);
			rcArea.InflateRect(
				bHorz ? 0 : 1,
				bHorz ? 1 : 0
				);
			if( bEnabled && bHover )
			{
				dc.FillSolidRect( &rcArea, g_PaintManager->GetColor(COLOR_3DDKSHADOW) );
				rcArea.DeflateRect( 1, 1 );
				dc.FillRect( &rcArea, &g_PaintManager->m_brushLightestDefault );
			} // if( bEnabled && bHover )
			else
			{
				dc.FillRect( &rcArea, &g_PaintManager->m_brushDarkestDefault );
				rcArea.DeflateRect( 1, 1 );
				dc.FillRect( &rcArea, &g_PaintManager->m_brushLighterDefault );
			} // else from if( bEnabled && bHover )
		} // else from if( nExtentBtn != 0 )
		return;
	case __ESA_PAGE_UP:
	case __ESA_PAGE_DOWN:
		if( nExtentBtn != 0 )
		{
			if( bHover || bPushed )
				dc.FillRect(
					rcArea,
					bPushed
						? &g_PaintManager->m_brushDarkestDefault
						: &g_PaintManager->m_brushLightestDefault
					);
		} // if( nExtentBtn != 0 )
		return;
	} // switch( eSA )
	if( bPaintAsButton )
	{
		bool bIndeterminate =
			( IsIndeterminate() && (!bDockSiteCustomizeMode) )
				? true : false;
		CExtPaintManager::PAINTPUSHBUTTONDATA _ppbd(
			this,
			bHorz,
			rcArea,
			_T(""),
			NULL,
			bFlatButton,
			bHover,
			bPushed,
			bIndeterminate,
			bEnabled,
			!bFlatButton, //true,
			false,
			false,
			CExtPaintManager::__ALIGN_HORIZ_CENTER
				| CExtPaintManager::__ALIGN_VERT,
			NULL,
			false,
			0,
			false
			);
		g_PaintManager->PaintPushButton( dc, _ppbd );
		if( pBtnGlyph != NULL )
		{
			if( bPushed )
				rcArea.OffsetRect(
					g_PaintManager->GetPushedOffset()
					);
			COLORREF ColorValues[] =
			{
				RGB(0,0,0),
				g_PaintManager->GetColor(
					bEnabled
						? (
							(bHover || bPushed)
								? CExtPaintManager::CLR_TEXT_IN
								: CExtPaintManager::CLR_TEXT_OUT
							)
						: CExtPaintManager::CLR_TEXT_DISABLED
					)
			};
			g_PaintManager->PaintGlyphCentered(
				dc,
				rcArea,
				*pBtnGlyph,
				ColorValues
				);
		} // if( pBtnGlyph != NULL )
		return;
	} // if( bPaintAsButton )
}

CExtBarSliderButton::e_SliderArea_t
	CExtBarSliderButton::GetTrackedArea() const
{
	ASSERT_VALID( this );
	ASSERT_VALID( m_pBar );
	return m_eAreaTracked;
}

CExtBarSliderButton::e_SliderArea_t
	CExtBarSliderButton::GetPressedArea() const
{
	ASSERT_VALID( this );
	ASSERT_VALID( m_pBar );
	return m_eAreaPressed;
}

CRect CExtBarSliderButton::GetAreaRect(
	CExtBarSliderButton::e_SliderArea_t eSA
	) const
{
	ASSERT_VALID( this );
	ASSERT_VALID( m_pBar );
	ASSERT( 0 <= eSA && eSA < __ESA_COUNT );
	return m_arrAreaRects[eSA];
}

UINT CExtBarSliderButton::OnTrackPopup(
	CPoint point,
	bool bSelectAny
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( m_pBar );
	point;
	bSelectAny;
	return UINT(-1L);
}

void CExtBarSliderButton::OnHover(
	CPoint point,
	bool bOn
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( m_pBar );
bool bDockSiteCustomizeMode =
		m_pBar->_IsDockSiteCustomizeMode();
	if( bDockSiteCustomizeMode )
		return;
	CExtBarButton::OnHover( point, bOn );
}

void CExtBarSliderButton::OnClick(
	CPoint point,
	bool bDown
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( m_pBar );
bool bDockSiteCustomizeMode =
		m_pBar->_IsDockSiteCustomizeMode();
	if( bDockSiteCustomizeMode )
		return;
	CExtBarButton::OnClick( point, bDown );
	if( m_pBar->m_pDockSite != NULL )
	{
		if( m_pBar->m_pDockSite->m_bHelpMode )
			return;
	} // if( m_pBar->m_pDockSite != NULL )

	m_eAreaTracked = m_eAreaPressed = __ESA_UNKNOWN_OR_NOWHERE;
	if( !bDown )
	{
		RedrawButton( true );
		return;
	}
ULONG nScrollLimit = ScrollLimitGet();
	if( nScrollLimit == 0L )
	{
		RedrawButton( true );
		return;
	}
ULONG nScrollPos = ScrollPosGet();
ULONG nScrollPosStart = nScrollPos;
	for(	int nRectNo = __ESA_CLICKABLE_RANGE_FIRST;
			nRectNo <= __ESA_CLICKABLE_RANGE_LAST;
			nRectNo++
			)
	{
		if(		m_arrAreaRects[nRectNo].right <= m_arrAreaRects[nRectNo].left
			||	m_arrAreaRects[nRectNo].bottom <= m_arrAreaRects[nRectNo].top
			)
			continue;
		if( m_arrAreaRects[nRectNo].PtInRect(point) )
		{
			m_eAreaTracked = (e_SliderArea_t)nRectNo;
			break;
		}
	}
	RedrawButton( true );
	if( m_eAreaTracked == __ESA_UNKNOWN_OR_NOWHERE )
		return;
bool bHorz = GetBar()->IsDockedVertically() ? false : true;
	if( GetNoRotateVerticalLayout() )
		bHorz = true;
e_SliderArea_t eSA = m_eAreaTracked;
CRect rcArea = GetAreaRect( eSA );
const UINT nTimerID = 401;
const UINT nTimerEllapse = 50;
HWND hWndOwnBar = m_pBar->GetSafeHwnd();
	ASSERT( hWndOwnBar != NULL && ::IsWindow( hWndOwnBar ) );
bool bStopFlag = false;
CPoint ptCursor( point );
ULONG nStepSize = 0L;
bool bUpStep = false;
	switch( eSA )
	{
	case __ESA_LINE_UP:
		bUpStep = true;
	case __ESA_LINE_DOWN:
		nStepSize = 1L;
		break;
	case __ESA_PAGE_UP:
		bUpStep = true;
	case __ESA_PAGE_DOWN:
		nStepSize = ScrollPageSizeGet();
		if( nStepSize == 0L )
			nStepSize = 1L;
		break;
	case __ESA_THUMB:
		m_eAreaPressed = eSA;
		RedrawButton();
		break;
	} // switch( eSA )
	if( nStepSize > nScrollLimit )
		nStepSize = nScrollLimit;
	::SetCapture( hWndOwnBar );
	if( nStepSize != 0L )
		::SetTimer( hWndOwnBar, nTimerID, nTimerEllapse, NULL );
	for( MSG msg; ::IsWindow( hWndOwnBar ) && (!bStopFlag); )
	{
		if( !PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) )
		{
			if( ! ::IsWindow( hWndOwnBar ) )
				break;
			::WaitMessage();
			continue;
		} // if( !PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) )

		bool bAnalyzeThumb = false;
		switch( msg.message )
		{
		case WM_LBUTTONDBLCLK:
		case WM_LBUTTONUP:
		case WM_RBUTTONDBLCLK:
		case WM_RBUTTONDOWN:
		case WM_RBUTTONUP:
		case WM_MBUTTONDBLCLK:
		case WM_MBUTTONDOWN:
		case WM_MBUTTONUP:
		case WM_CANCELMODE:
		case WM_ACTIVATEAPP:
		case WM_KEYDOWN:
		case WM_KEYUP:
			bStopFlag = true;
		break;
		case WM_CAPTURECHANGED:
			if( (HWND)msg.wParam != hWndOwnBar )
				bStopFlag = true;
		break;
		case WM_MOUSEMOVE:
			if( eSA == __ESA_THUMB )
			{
				if(		( ! CExtPopupMenuWnd::IsKeyPressed(VK_LBUTTON) )
					||	CExtPopupMenuWnd::IsKeyPressed(VK_MBUTTON)
					||	CExtPopupMenuWnd::IsKeyPressed(VK_RBUTTON)
					||	CExtPopupMenuWnd::IsMenuTracking()
					)
				{
					bStopFlag = true;
					break;
				}
				PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
				bAnalyzeThumb = true;
				::GetCursorPos( &ptCursor );
				::ScreenToClient( hWndOwnBar, &ptCursor );
				break;
			} // if( eSA == __ESA_THUMB )
			if( nStepSize == 0 )
				break;
		case WM_TIMER:
			if(		( ! CExtPopupMenuWnd::IsKeyPressed(VK_LBUTTON) )
				||	CExtPopupMenuWnd::IsKeyPressed(VK_MBUTTON)
				||	CExtPopupMenuWnd::IsKeyPressed(VK_RBUTTON)
				||	CExtPopupMenuWnd::IsMenuTracking()
				)
			{
				bStopFlag = true;
				break;
			}
			if( msg.message == WM_TIMER )
			{
				if( msg.wParam != nTimerID )
					break;
			} // if( msg.message == WM_TIMER )
			ASSERT( nStepSize != 0L );
			PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
			::GetCursorPos( &ptCursor );
			::ScreenToClient( hWndOwnBar, &ptCursor );
			if( ! rcArea.PtInRect(ptCursor) )
			{
				if( m_eAreaPressed != __ESA_UNKNOWN_OR_NOWHERE )
				{
					m_eAreaPressed = __ESA_UNKNOWN_OR_NOWHERE;
					RedrawButton( true );
				}
				continue;
			}
			if( bUpStep )
			{
				if( nScrollPos == 0L )
				{
					nScrollPos = ScrollPosGet();
					nScrollLimit = ScrollLimitGet();
					break;
				}
				if( nScrollPos < nStepSize )
					nScrollPos = 0L;
				else
					nScrollPos -= nStepSize;
			} // if( bUpStep )
			else
			{
				if( nScrollPos >= nScrollLimit )
				{
					nScrollPos = ScrollPosGet();
					nScrollLimit = ScrollLimitGet();
					break;
				}
				if( nStepSize > (nScrollLimit-nScrollPos) )
					nScrollPos = nScrollLimit;
				else
					nScrollPos += nStepSize;
				ASSERT( nScrollPos <= nScrollLimit );
			} // else from if( bUpStep )
			ScrollPosSet( nScrollPos );
			nScrollPos = ScrollPosGet();
			nScrollLimit = ScrollLimitGet();
			RecalcSliderLayout();
			rcArea = GetAreaRect( eSA );
			m_eAreaPressed = eSA;
			RedrawButton( true );
		break;
		default:
			if(		( ! CExtPopupMenuWnd::IsKeyPressed(VK_LBUTTON) )
				||	CExtPopupMenuWnd::IsKeyPressed(VK_MBUTTON)
				||	CExtPopupMenuWnd::IsKeyPressed(VK_RBUTTON)
				||	CExtPopupMenuWnd::IsMenuTracking()
				)
				bStopFlag = true;
		break;
		} // switch( msg.message )
		if( bStopFlag || nScrollLimit == 0L )
			break;
		if( bAnalyzeThumb )
		{
			LONG nPixelOffset = bHorz
				? (ptCursor.x - point.x)
				: (ptCursor.y - point.y);
			LONG nPixelExtent = bHorz
				? (m_arrAreaRects[__ESA_SCROLLABLE].Width() - m_arrAreaRects[__ESA_THUMB].Width())
				: (m_arrAreaRects[__ESA_SCROLLABLE].Height() - m_arrAreaRects[__ESA_THUMB].Height());
			if( nPixelExtent <= 0 )
			{
				bStopFlag = true;
				break;
			} // if( nPixelExtent <= 0 )
			if( abs(nPixelOffset) > nPixelExtent )
				nPixelOffset =
					(nPixelOffset < 0)
						? (-nPixelExtent)
						: nPixelExtent;
			ULONG nShift =
				( nPixelExtent == 0 || nPixelOffset == 0 )
					? 0
					: ::MulDiv( nScrollLimit, abs(nPixelOffset), nPixelExtent );
			nScrollPos = nScrollPosStart;
			if( nPixelOffset < 0 )
			{
				if( nShift >= nScrollPos )
					nScrollPos = 0;
				else
					nScrollPos -= nShift;
			} // if( nPixelOffset < 0 )
			else
			{
				if( nScrollPos >= nScrollLimit )
				{
					nScrollPos = ScrollPosGet();
					nScrollLimit = ScrollLimitGet();
					break;
				}
				if( nShift > (nScrollLimit-nScrollPos) )
					nScrollPos = nScrollLimit;
				else
					nScrollPos += nShift;
				ASSERT( nScrollPos <= nScrollLimit );
			} // else from if( nPixelOffset < 0 )
			ScrollPosSet( nScrollPos );
			nScrollPos = ScrollPosGet();
			nScrollLimit = ScrollLimitGet();
			RecalcSliderLayout();
			rcArea = GetAreaRect( eSA );
			m_eAreaPressed = eSA;
			RedrawButton( true );
			continue;
		} // if( bAnalyzeThumb )
		if( !AfxGetThread()->PumpMessage() )
			break;
	} // for( MSG msg; ::IsWindow( hWndOwnBar ) && (!bStopFlag); )
	if( ! ::IsWindow( hWndOwnBar ) )
		return;
	if( nStepSize != 0L )
		::KillTimer( hWndOwnBar, nTimerID );
	m_eAreaTracked = m_eAreaPressed = __ESA_UNKNOWN_OR_NOWHERE;
	RedrawButton( true );
	if( ::GetCapture() == hWndOwnBar )
		::ReleaseCapture();
}

void CExtBarSliderButton::OnDeliverCmd()
{
	ASSERT_VALID( this );
	ASSERT_VALID( m_pBar );
	//CExtBarButton::OnDeliverCmd();
}

int CExtBarSliderButton::OnToolHitTest(
	CPoint point,
	TOOLINFO * pTI
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( m_pBar );
	return CExtBarButton::OnToolHitTest( point, pTI );
}

LRESULT CExtBarSliderButton::OnHelpHitTest(
	CPoint point
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( m_pBar );
	return CExtBarButton::OnHelpHitTest( point );
}

void CExtBarSliderButton::OnUpdateCmdUI(
	CWnd * pTarget,
	BOOL bDisableIfNoHndler,
	int nIndex
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( m_pBar );
	CExtBarButton::OnUpdateCmdUI(
		pTarget,
		bDisableIfNoHndler,
		nIndex
		);
}

bool CExtBarSliderButton::OnSetCursor( CPoint point )
{
	ASSERT_VALID( this );
	ASSERT_VALID( m_pBar );
	return CExtBarButton::OnSetCursor( point );
}

/////////////////////////////////////////////////////////////////////////////
// CExtToolControlBar

const UINT CExtToolControlBar::g_nMsgTrackButtonMenu =
	::RegisterWindowMessage(
		_T("CExtToolControlBar::g_nMsgTrackButtonMenu")
		);
const UINT CExtToolControlBar::g_nMsgContinueTrackMenu =
	::RegisterWindowMessage(
		_T("CExtToolControlBar::g_nMsgContinueTrackMenu")
		);

IMPLEMENT_DYNCREATE(CExtToolControlBar, CExtControlBar)

CExtBarButton * CExtToolControlBar::_GetButtonPtr(int nIndex) const
{
int nButtonsCount = m_buttons.GetSize();
	if( !(nIndex >= 0 && nIndex < nButtonsCount) )
	{
		ASSERT( FALSE );
		return NULL;
	}
CExtBarButton * pTBB =
		m_buttons[nIndex];
	ASSERT_VALID( pTBB );
	return pTBB;
}

void CExtToolControlBar::_RemoveAllButtonsImpl()
{
	if( m_pRightBtn != NULL )
		m_pRightBtn->GetButtons().RemoveAll();
	for( INT nBtnIdx = 0; nBtnIdx < m_buttons.GetSize(); nBtnIdx++ )
	{
		CExtBarButton * pTBB = m_buttons[nBtnIdx];
		ASSERT( pTBB != NULL );
		delete pTBB;
	}
	m_buttons.RemoveAll();
	m_pRightBtn = NULL;
	m_nBtnIdxCapture = -1;      // nothing captured
	m_nBtnIdxHover = -1;
	m_nBtnIdxMenuTracking = -1;
}

int CExtToolControlBar::_GetButtonsCountImpl() const
{
int nCountOfButtons = m_buttons.GetSize();
	return nCountOfButtons;
}

void CExtToolControlBar::_SetCursor(
	const CPoint & point
	)
{
	ASSERT_VALID( this );
int nBtnIdx = _HitTestImpl(point);
	if( nBtnIdx >= 0 )
	{
		CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
		ASSERT_VALID( pTBB );
		if( pTBB->OnSetCursor(point) )
			return;
	} // if( nBtnIdx >= 0 )
	CExtControlBar::_SetCursor( point );
}

bool CExtToolControlBar::g_bMenuTracking = false;
bool CExtToolControlBar::g_bMenuTrackingExpanded = false;
bool CExtToolControlBar::g_bToolbarLargeIcons = false;
bool CExtToolControlBar::g_bToolbarScreenTips = true;
bool CExtToolControlBar::g_bToolbarShortcutKeysOnScreenTips = false;

const CSize CExtToolControlBar::g_sizeDefTBB( 23, 22 );

CExtToolControlBar::CExtToolControlBar()
{
	m_bGripperStaticallyAtTop = false;

	m_pRightBtn = NULL;
	m_bRightButtonDisplayBarsList = true;
	m_bPaletteMode = false;
	m_bHelperTempFullRowMode = false;
	m_bInsideCalcLayout = false;

	m_bFixedMode = true;
	m_bReposSingleChildMode = false;
	m_nBtnIdxCapture = -1;
	m_nBtnIdxHover = -1;
	m_nBtnIdxMenuTracking = -1;

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	m_bCustomizationAllowed = true;
	m_pCustomizeSite = NULL;
	m_bVisibleInCustomizeListBox = true;
	m_pDragSourceTBB = NULL;
	m_pDragTargetTBB = NULL;
	m_nDragTargetShift = 0;
	m_bHelperSeparatorAction = false;
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

	 // additional spaces
	m_cxLeftBorder		= 1;
	m_cxRightBorder		= 1;
	m_cyTopBorder		= 0; //1;
	m_cyBottomBorder	= 0; //1;

	m_nGripWidthAtLeft = 8;
	m_nGripHeightAtTop = 10;
}

CExtToolControlBar::~CExtToolControlBar()
{
	_RemoveAllButtonsImpl();

CSingleLock _slCsCB( &g_csCB );
	_slCsCB.Lock();
int nCountOfBars = g_AllBars.GetSize();
	for( int i=0; i<nCountOfBars; i++ )
	{
		CExtControlBar * pBar = g_AllBars[i];
		ASSERT( pBar != NULL );
		if( pBar == this )
		{
			g_AllBars.RemoveAt( i );
			break;
		}
	}
	_slCsCB.Unlock();
}

BOOL CExtToolControlBar::LoadToolBar(
	__EXT_MFC_SAFE_LPCTSTR  lpszResourceName
	)
{
LPUINT pCmdArray = NULL;
INT nCmdCount = 0;
	if( !g_CmdManager->UpdateFromToolBar(
			g_CmdManager->ProfileNameFromWnd( GetSafeHwnd() ),
			lpszResourceName,
			&pCmdArray,
			&nCmdCount
			)
		)
	{
		ASSERT( FALSE );
		return FALSE;
	}
	ASSERT( pCmdArray != NULL && nCmdCount > 0 );
BOOL bRetVal =  SetButtons( pCmdArray, nCmdCount );
	ASSERT( bRetVal );
	delete [] pCmdArray;
	return bRetVal;
}

bool CExtToolControlBar::_IsShowContentWhenDragging() const
{
//BOOL bDragShowContent = FALSE;
//    ::SystemParametersInfo(
//		SPI_GETDRAGFULLWINDOWS,
//		0,
//        &bDragShowContent,
//		0
//		);
//	return bDragShowContent ? true : false;

//	if( IsKindOf(RUNTIME_CLASS(CExtToolControlBar)) )
//		return true;
//	return false;

//	if( CExtPopupMenuWnd::IsKeyPressed(VK_CONTROL) )
//		return false;

	return true;
}

BOOL CExtToolControlBar::RemoveButton(
	int nPos,
	BOOL bDoRecalcLayout // = TRUE
	)
{
	if( nPos < 0 )
	{
		ASSERT( FALSE );
		return FALSE;
	}
int nCountOfButtons = _GetButtonsCountImpl();
	if( nPos >= nCountOfButtons )
	{
		ASSERT( FALSE );
		return FALSE;
	}
CExtBarButton * pTBB =
		_GetButtonPtr( nPos );
	ASSERT_VALID( pTBB );
	if( pTBB->IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton)) )
	{
		ASSERT( FALSE );
		return FALSE;
	}
	delete pTBB;
	m_buttons.RemoveAt( nPos );
	m_nBtnIdxCapture = -1;      // nothing captured
	m_nBtnIdxHover = -1;
	m_nBtnIdxMenuTracking = -1;
	if( bDoRecalcLayout )
		_RecalcLayoutImpl();
	return TRUE;
}

BOOL CExtToolControlBar::InsertSpecButton(
	int nPos, // -1 - append
	CExtBarButton * pButton,
	BOOL bDoRecalcLayout // = TRUE
	)
{
int nCountOfButtons = _GetButtonsCountImpl();
	if( nPos < 0 )
		nPos = nCountOfButtons;
	if( nPos > nCountOfButtons )
	{
		ASSERT( FALSE );
		return FALSE;
	}
	if( nCountOfButtons > 0
		&& nPos == nCountOfButtons
		)
	{
		CExtBarButton * pTBB =
			_GetButtonPtr( nCountOfButtons - 1 );
		ASSERT_VALID( pTBB );
		if( pTBB->IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton)) )
			nPos--;
	}
	ASSERT_VALID( pButton );
	ASSERT( pButton->GetSafeBar() != NULL );
	ASSERT( pButton->GetSafeBar() == this );
	if( _GetIndexOf(pButton) >= 0 )
	{
		ASSERT( FALSE ); // already inserted
		return FALSE;
	}
	m_buttons.InsertAt( nPos, pButton );
	ASSERT( _GetIndexOf(pButton) >= 0 );
	if( bDoRecalcLayout )
		_RecalcLayoutImpl();
	return TRUE;
}

BOOL CExtToolControlBar::InsertButton(
	int nPos, // = -1, // append
	UINT nCmdID, // = ID_SEPARATOR
	BOOL bDoRecalcLayout // = TRUE
	)
{
int nCountOfButtons = _GetButtonsCountImpl();
	if( nPos < 0 )
		nPos = nCountOfButtons;
	if( nPos > nCountOfButtons )
	{
		ASSERT( FALSE );
		return FALSE;
	}
	if( nCountOfButtons > 0
		&& nPos == nCountOfButtons
		)
	{
		CExtBarButton * pTBB =
			_GetButtonPtr( nCountOfButtons - 1 );
		ASSERT_VALID( pTBB );
		if( pTBB->IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton)) )
			nPos--;
	}
	try
	{
		CExtBarButton * pTBB = OnCreateBarCommandBtn( nCmdID );
		ASSERT_VALID( pTBB );
		m_buttons.InsertAt( nPos, pTBB );
		if( bDoRecalcLayout )
			_RecalcLayoutImpl();
	} // try
//	catch( std::exception * pXept )
//	{
//		delete pXept;
//		ASSERT( FALSE );
//		return FALSE;
//	} // catch( std::exception * pXept )
	catch( CException * pXept )
	{
		pXept->Delete();
		ASSERT( FALSE );
		return FALSE;
	} // catch( CException * pXept )
	catch( ... )
	{
		ASSERT( FALSE );
		return FALSE;
	} // catch( ... )
	return TRUE;
}

CExtBarButton * CExtToolControlBar::OnCreateBarCommandBtn(
	UINT nCmdID,
	UINT nStyle // = 0
	)
{
	ASSERT_VALID( this );
CExtBarButton * pTBB = new CExtBarButton( this, nCmdID, nStyle );
	ASSERT_VALID( pTBB );
	return pTBB;
}

CExtBarContentExpandButton * CExtToolControlBar::OnCreateBarRightBtn()
{
	ASSERT_VALID( this );
	if( m_bPaletteMode )
		return NULL;
CExtBarContentExpandButton * pRightBtn =
		new CExtBarContentExpandButton( this );
	ASSERT_VALID( pRightBtn );
	return pRightBtn;
}

BOOL CExtToolControlBar::SetButtons(
	const UINT * lpIDArray, // = NULL
	int nIDCount // = 0
	)
{
	ASSERT_VALID( this );
	ASSERT(
		lpIDArray == NULL
		|| nIDCount == 0
		|| AfxIsValidAddress(
			lpIDArray,
			sizeof(UINT) * nIDCount,
			FALSE
			)
		);
	_RemoveAllButtonsImpl();
	if( lpIDArray == NULL
		|| nIDCount == 0
		)
		return TRUE;
	try
	{
		for( int i = 0; i < nIDCount; i++ )
		{
			CExtBarButton * pTBB = OnCreateBarCommandBtn( *lpIDArray++, 0 );
			ASSERT_VALID( pTBB );
			m_buttons.Add( pTBB );
		} // for( int i = 0; i < nIDCount; i++ )
		ASSERT( m_pRightBtn == NULL );
		m_pRightBtn = OnCreateBarRightBtn();
		if( m_pRightBtn != NULL )
		{
			ASSERT_VALID( m_pRightBtn );
			ASSERT_KINDOF( CExtBarContentExpandButton, m_pRightBtn );
			m_buttons.Add( m_pRightBtn );
		} // if( m_pRightBtn != NULL )
	} // try
	catch( CException * pXept )
	{
		pXept->Delete();
		ASSERT( FALSE );
		return FALSE;
	} // catch( CException * pXept )
	catch( ... )
	{
		ASSERT( FALSE );
		return FALSE;
	} // catch( ... )
	return TRUE;
}

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
BOOL CExtToolControlBar::SetButtons(
	CExtCustomizeCmdTreeNode * pNode
	)
{
	ASSERT_VALID( this );
	SetButtons();
	if( pNode == NULL )
		return TRUE;
	ASSERT_VALID( pNode );
CExtCustomizeSite * pSite = GetCustomizeSite();
	if( pSite == NULL )
	{
		ASSERT( FALSE );
		return FALSE;
	}
int nCount = pNode->GetNodeCount();
	for( int i = 0; i < nCount; i++ )
	{
		CExtCustomizeCmdTreeNode * pNodeBtn =
			pNode->ElementAt( i );
		ASSERT_VALID( pNodeBtn );
		if( pNodeBtn->GetFlags() & __ECTN_GROUP_START )
		{
			if( i == 0 )
			{
				ASSERT( FALSE );
				continue;
			}
			VERIFY( InsertButton(-1,ID_SEPARATOR,FALSE) ); // separator
		}
		ASSERT( CExtCmdManager::IsCommand(pNodeBtn->GetCmdID(false)) || pNodeBtn->GetCmdID(false) == UINT(-1) );
		ASSERT( CExtCmdManager::IsCommand(pNodeBtn->GetCmdID(true)) || pNodeBtn->GetCmdID(true) == UINT(-1) );
		CExtBarButton * pTBB =
			pSite->OnCreateToolbarButton(
				this,
				NULL,
				pNodeBtn
				);
		if( pTBB == NULL )
		{
			ASSERT( FALSE );
			return FALSE;
		}
		ASSERT_VALID( pTBB );
		m_buttons.Add( pTBB );
	} // for( int i = 0; i < nCount; i++ )
	ASSERT( m_pRightBtn == NULL );
	m_pRightBtn = OnCreateBarRightBtn();
	if( m_pRightBtn != NULL )
	{
		ASSERT_VALID( m_pRightBtn );
		ASSERT_KINDOF( CExtBarContentExpandButton, m_pRightBtn );
		m_buttons.Add( m_pRightBtn );
	} // if( m_pRightBtn != NULL )
	return TRUE;
}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

bool CExtToolControlBar::IsLargeIcons() const
{
	ASSERT_VALID( this );
	return g_bToolbarLargeIcons;
}

bool CExtToolControlBar::IsDisplayScreenTips() const
{
	ASSERT_VALID( this );
	return g_bToolbarScreenTips;
}

bool CExtToolControlBar::IsDisplayShortcutKeysOnScreenTips() const
{
	ASSERT_VALID( this );
	return g_bToolbarShortcutKeysOnScreenTips;
}

LRESULT CExtToolControlBar::DoHelpHitTest( CPoint ptHelpHitTest )
{
	ASSERT_VALID( this );

LRESULT nHelpHit =
		((CExtToolControlBar*)this)->
			HitTest(ptHelpHitTest);
	if( nHelpHit >= 0 )
	{
		CExtBarButton * pTBB =
			_GetButtonPtr( nHelpHit );
		ASSERT_VALID( pTBB );
		if( pTBB != NULL )
		{
			nHelpHit = pTBB->OnHelpHitTest( ptHelpHitTest );
			if( nHelpHit == -1 || nHelpHit == -2 )
				return -2;
			return nHelpHit;
		}
	} // if( nHelpHit >= 0 )
	return CExtControlBar::DoHelpHitTest( ptHelpHitTest );
}

/////////////////////////////////////////////////////////////////////////////
// CExtToolControlBar attribute access

int CExtToolControlBar::CommandToIndex(UINT nIDFind) const
{
	ASSERT_VALID(this);

int nCountOfButtons = _GetButtonsCountImpl();
	for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
	{
		CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
		ASSERT_VALID( pTBB );
		if( pTBB->GetCmdID(false) == nIDFind )
			return nBtnIdx;
	}
	return -1;
}

UINT CExtToolControlBar::GetButtonID(int nIndex) const
{
//	ASSERT_VALID(this);
CExtBarButton * pTBB =
		_GetButtonPtr(nIndex);
	if( pTBB == NULL )
		return ID_SEPARATOR;
	ASSERT_VALID( pTBB );
	return pTBB->GetCmdID(false);
}

void CExtToolControlBar::GetButtonRect(int nIndex, LPRECT lpRect) const
{
//	ASSERT_VALID(this);
	ASSERT(AfxIsValidAddress(lpRect, sizeof(RECT)));
CExtBarButton * pTBB =
		_GetButtonPtr(nIndex);
	if( pTBB == NULL )
	{
		::memset( lpRect, 0, sizeof(RECT) );
		return;
	}
	ASSERT_VALID( pTBB );
	*lpRect = *pTBB;
}

UINT CExtToolControlBar::GetButtonStyle(int nIndex) const
{
CExtBarButton * pTBB =
		_GetButtonPtr(nIndex);
	if( pTBB == NULL )
		return 0;
	ASSERT_VALID( pTBB );
	return pTBB->GetStyle();
}

void CExtToolControlBar::SetButtonStyle(int nIndex, UINT nStyle)
{
CExtBarButton * pTBB =
		_GetButtonPtr(nIndex);
	if( pTBB == NULL )
		return;
	ASSERT_VALID( pTBB );
UINT nOldStyle = pTBB->GetStyle();
	if( nOldStyle != nStyle )
	{
		pTBB->SetStyle( nStyle );
		_InvalidateButton( nIndex );
		UpdateWindow();
	}
}

CWnd * CExtToolControlBar::GetButtonCtrl(
	int nIndex
	)
{
CExtBarButton * pTBB =
		_GetButtonPtr(nIndex);
	ASSERT( pTBB != NULL );
	if( pTBB == NULL )
		return NULL;
	ASSERT_VALID( pTBB );
CWnd * pCtrl = pTBB->CtrlGet();
	return pCtrl;
}

void CExtToolControlBar::SetButtonCtrlVisibleVertically(
	int nIndex,
	bool bVisible // = true
	)
{
CExtBarButton * pTBB =
		_GetButtonPtr(nIndex);
	ASSERT( pTBB != NULL );
	if( pTBB == NULL )
		return;
	pTBB->SetCtrlVisibleVertically( bVisible );
}

bool CExtToolControlBar::GetButtonCtrlVisibleVertically(
	int nIndex
	) const
{
CExtBarButton * pTBB =
		_GetButtonPtr(nIndex);
	ASSERT( pTBB != NULL );
	if( pTBB == NULL )
		return false;
	return pTBB->GetCtrlVisibleVertically();
}


bool CExtToolControlBar::SetButtonCtrl(
	int nIndex,
	CWnd * pCtrl, // = NULL
	bool bCtrlAutoDestroyed // = TRUE
	)
{
CExtBarButton * pTBB =
		_GetButtonPtr(nIndex);
	ASSERT( pTBB != NULL );
	if( pTBB == NULL )
		return FALSE;
	ASSERT_VALID( pTBB );
	if( pCtrl != NULL )
	{
		ASSERT_VALID( pCtrl );
		DWORD dwCtrlStyle = pCtrl->GetStyle();
		ASSERT( (dwCtrlStyle&WS_CHILD) != 0 );
		if( (dwCtrlStyle&WS_CHILD) == 0 )
			return FALSE;
		ASSERT( IsChild( pCtrl ) );
		if( !IsChild( pCtrl ) )
			return FALSE;
		UINT nDlgCtrlID = (UINT)pCtrl->GetDlgCtrlID();
		ASSERT( nDlgCtrlID == pTBB->GetCmdID(false) );
		if( nDlgCtrlID != pTBB->GetCmdID(false) )
			return FALSE;
	}
	pTBB->CtrlSet(
		pCtrl,
		bCtrlAutoDestroyed
		);
	_RecalcLayoutImpl();
	return TRUE;
}

int CExtToolControlBar::GetButtonByAccessKey(__EXT_MFC_SAFE_TCHAR vkTCHAR)
{
int nCountOfButtons = _GetButtonsCountImpl();
	ASSERT( nCountOfButtons >= 0 );
	if( nCountOfButtons == 0 )
		return -1;
	for( int nBtnIdx=0; nBtnIdx<nCountOfButtons; nBtnIdx++ )
	{
		CExtBarButton * pTBB = _GetButtonPtr(nBtnIdx);
		ASSERT_VALID( pTBB );
		if(		pTBB->IsSeparator()
			||	(! pTBB->IsVisible() )
			||	( pTBB->GetStyle() & TBBS_HIDDEN )
			||	pTBB->IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton))
			||	pTBB->IsKindOf(RUNTIME_CLASS(CExtBarMdiDocButton))
			||	pTBB->IsKindOf(RUNTIME_CLASS(CExtBarMdiRightButton))
			)
			continue;
		ASSERT( CExtCmdManager::IsCommand(pTBB->GetCmdID(false)) );
		ASSERT( CExtCmdManager::IsCommand(pTBB->GetCmdID(true)) );

		CExtSafeString strButtonText( pTBB->GetText() );
		if( strButtonText.IsEmpty() )
			continue;

		int nTextLen = strButtonText.GetLength();
		ASSERT( nTextLen > 0 );
		int nAmdIndex = strButtonText.Find(_T('&'));
		if( nAmdIndex == nTextLen - 1 ) // !?!?!
			continue;
		TCHAR vk = strButtonText[nAmdIndex+1];
		TCHAR szChar[2] = { vk, _T('\0') };
		::CharUpper( szChar );
		vk = szChar[0];

		if( vkTCHAR == ((TCHAR)vk) )
		{
			if(		( !pTBB->IsVisible() )
				||	(pTBB->GetStyle() & TBBS_HIDDEN) != 0
				)
			{
				if( m_pRightBtn != NULL )
					return _GetIndexOf( m_pRightBtn );
				continue;
			}
			return nBtnIdx;
		} // if( vkTCHAR == ((TCHAR)vk) )
	} // for( int nBtnIdx=0; nBtnIdx<nCountOfButtons; nBtnIdx++ )
	return -1;
}

HMENU CExtToolControlBar::GetButtonMenu(
	int nIndex
	)
{
CExtBarButton * pTBB = _GetButtonPtr(nIndex);
	ASSERT( pTBB != NULL );
	if( pTBB == NULL )
		return NULL;
	ASSERT_VALID( pTBB );
	return ((HMENU)(*pTBB));
}

bool CExtToolControlBar::MarkButtonAsMdiWindowsMenu(
	int nIndex,
	bool bAppendMdiWindowsMenu // = TRUE
	)
{
CExtBarButton * pTBB =
		_GetButtonPtr(nIndex);
	ASSERT( pTBB != NULL );
	if( pTBB == NULL )
		return false;
	ASSERT_VALID( pTBB );
	pTBB->SetAppendMdiWindowsMenu(
		bAppendMdiWindowsMenu
		);
	return true;
}

bool CExtToolControlBar::SetButtonMenu(
	int nIndex,
	HMENU hMenu, // = NULL
	bool bPopupMenu, // = TRUE
	bool bAutoDestroyMenu, // = TRUE
	bool bDoRecalcLayout // = TRUE
	)
{
CExtBarButton * pTBB =
		_GetButtonPtr(nIndex);
	ASSERT( pTBB != NULL );
	if( pTBB == NULL )
		return false;
	ASSERT_VALID( pTBB );
	pTBB->SetMenu(
		hMenu,
		bPopupMenu,
		bAutoDestroyMenu
		);
	if( bDoRecalcLayout )
		_RecalcLayoutImpl();
	return true;
}

int CExtToolControlBar::GetVisibleButton(
	int nBtnIdx,
	BOOL bNext,
	BOOL bPassDisabled // = TRUE
	)
{
int nCountOfButtons = _GetButtonsCountImpl();
	ASSERT( nCountOfButtons >= 0 );
	if( nCountOfButtons == 0 )
		return -1;
	if( nCountOfButtons == 1 )
		return 0;
	if( bNext )
	{
		int iNewButton = nBtnIdx + 1;
		if( iNewButton >= nCountOfButtons )
			iNewButton = 0;
		while( iNewButton != nBtnIdx )
		{
			CExtBarButton * pTBB =
				_GetButtonPtr(iNewButton);
			ASSERT_VALID( pTBB );
			if(		pTBB->IsVisible()
				&&	(pTBB->GetStyle() & TBBS_HIDDEN) == 0
				&&	(!pTBB->IsSeparator())
				&&	(!pTBB->IsKindOf(RUNTIME_CLASS(CExtBarMdiRightButton)))
				&&	(	(!bPassDisabled)
						|| (bPassDisabled && (!pTBB->IsDisabled()))
					)
				)
			{
				return iNewButton;
			}
			iNewButton++;
			if( iNewButton >= nCountOfButtons )
				iNewButton = 0;
		}
		return iNewButton;
	} // if( bNext )
	else
	{
		int iNewButton =
			nBtnIdx - 1;
		if( iNewButton < 0 )
			iNewButton = nCountOfButtons - 1;
		while( iNewButton != nBtnIdx )
		{
			CExtBarButton * pTBB =
				_GetButtonPtr(iNewButton);
			ASSERT_VALID( pTBB );
			if(		pTBB->IsVisible()
				&&	(pTBB->GetStyle() & TBBS_HIDDEN ) == 0
				&&	(!pTBB->IsSeparator())
				&&	(!pTBB->IsKindOf(RUNTIME_CLASS(CExtBarMdiRightButton)))
				&&	(	(!bPassDisabled)
						|| (bPassDisabled && (!pTBB->IsDisabled()))
					)
				)
				return iNewButton;
			iNewButton--;
			if( iNewButton < 0 )
				iNewButton = nCountOfButtons - 1;
		}
		return iNewButton;
	} // else from if( bNext )
}

BOOL CExtToolControlBar::TrackButtonMenu(
	int nIndex,
	BOOL bSelectAny, // = FALSE
	BOOL bDelayedTracking // = FALSE
	)
{
bool bDockSiteCustomizeMode =
		_IsDockSiteCustomizeMode();
	if( bDockSiteCustomizeMode )
		return FALSE;

	if( g_bMenuTracking
		&& m_nBtnIdxMenuTracking == nIndex
		)
		return TRUE;

	if( !SafeDisplayBar() )
		return FALSE;

CExtBarButton * pTBB =
		_GetButtonPtr(nIndex);
	ASSERT( pTBB != NULL );
	if( pTBB == NULL )
		return FALSE;
	ASSERT_VALID( pTBB );
	if( pTBB->GetStyle() & (TBBS_HIDDEN|TBBS_DISABLED) )
		return FALSE;
	if( !pTBB->IsAbleToTrackMenu() )
		return FALSE;
CPoint point;
	if( ! ::GetCursorPos(&point) )
		return FALSE;
	ScreenToClient( &point );
	if( bDelayedTracking )
		PostMessage(
			g_nMsgTrackButtonMenu,
			(WPARAM)nIndex
			);
	else
		pTBB->OnTrackPopup( point, bSelectAny ? true : false );
	return TRUE;
}

CSize CExtToolControlBar::CalcDynamicLayout(int nLength, DWORD dwMode)
{
	if(	(nLength == -1)
		&& !(dwMode & (LM_MRUWIDTH|LM_COMMIT))
		&&  (dwMode & (LM_HORZDOCK|LM_VERTDOCK))
		)
		return
			CalcFixedLayout(
				dwMode & LM_STRETCH,
				dwMode & LM_HORZDOCK
				);
	ASSERT(
		(dwMode&(LM_HORZ|LM_HORZDOCK))
		||
		(!(dwMode&LM_HORZDOCK))
		);
	return _CalcLayout( dwMode, nLength );
}

CSize CExtToolControlBar::CalcFixedLayout(
	BOOL bStretch,
	BOOL bHorz
	)
{
DWORD dwMode = bStretch ? LM_STRETCH : 0;
	dwMode |= bHorz ? LM_HORZ : 0;
	ASSERT(
		(dwMode&(LM_HORZ|LM_HORZDOCK))
		||
		(!(dwMode&LM_HORZDOCK))
		);
	return _CalcLayout( dwMode );
}

CSize CExtToolControlBar::_CalcLayout(
	DWORD dwMode,
	int nLength
	)
{
	ASSERT_VALID(this);
	if( !m_bInsideCalcLayout )
		m_bHelperTempFullRowMode = false;
CSize sizeDefButton = _GetDefButtonSize();
CSize sizeCalcLayout = sizeDefButton;
	if( _GetButtonsCountImpl() > 0 )
	{
		if( m_pRightBtn != NULL )
			m_pRightBtn->ClearContent( false );
		BOOL bDynamic = m_dwStyle & CBRS_SIZE_DYNAMIC;
		INT nLengthToSizeTB =
			(dwMode & LM_HORZ) ? 32767 : 0;
		BOOL bVertSizeTB = FALSE;
		if( bDynamic )
		{
			if( dwMode & LM_MRUWIDTH )
				nLengthToSizeTB = m_nMRUWidth;
			else if( dwMode & LM_HORZDOCK )
				nLengthToSizeTB = 32767;
			else if( dwMode & LM_VERTDOCK )
				nLengthToSizeTB = 0;
			else if( nLength != -1 )
			{
				CRect rcInside( 0, 0, 0, 0 );
				_CalcInsideRect(
					rcInside,
					(dwMode & LM_HORZ)
					);
				bVertSizeTB = (dwMode & LM_LENGTHY);
				nLengthToSizeTB =
					nLength +
					( bVertSizeTB ?
						rcInside.Height() : rcInside.Width()
					);
			}
			else if( (m_dwStyle & CBRS_FLOATING) != 0 )
					nLengthToSizeTB = m_nMRUWidth;
		} // if( bDynamic )

		bool bMultiRowLayout =
			OnQueryMultiRowLayout();
		if(		bMultiRowLayout
			&&	((dwMode & LM_HORZ) == 0)
			&&	(!m_bPaletteMode)
			)
		{
			CRect rcDockBarClient;
			if( m_pDockBar != NULL )
				m_pDockBar->GetClientRect( &rcDockBarClient );
			else
				GetParent()->GetClientRect( &rcDockBarClient );
			nLength = nLengthToSizeTB = rcDockBarClient.Height();
			bVertSizeTB = TRUE;
		}

		_SizeToolBar( nLengthToSizeTB, bVertSizeTB );
		sizeCalcLayout =
			_CalcSize(
				( (dwMode & LM_HORZ) == 0 ) ? TRUE : FALSE
				);
		if(		bDynamic
			&&	bMultiRowLayout
			&&	(!m_bPaletteMode)
			)
		{
			CSize sizeDiff(
				__EXT_TB_BUTTON_OUTER_MARGIN*2,
				__EXT_TB_BUTTON_OUTER_MARGIN*2
				);
			if(		m_pRightBtn != NULL
				&&	m_pRightBtn->IsVisible()
				)
			{
				CSize sizeRb = m_pRightBtn->Size();
				sizeDiff +=
					CSize(
						((dwMode&LM_HORZ) == 0) ? 0 : sizeRb.cx,
						((dwMode&LM_HORZ) == 0) ? sizeRb.cy : 0
						);
			}
			CRect rcDockBarClient;
			if( m_pDockBar != NULL )
				m_pDockBar->GetClientRect( &rcDockBarClient );
			else
				GetParent()->GetClientRect( &rcDockBarClient );
			CSize _sizeDockBarClient = rcDockBarClient.Size();
			INT nNewLengthToSizeTB = nLengthToSizeTB;
			if( (dwMode & LM_HORZ) == 0 )
			{
				if( (sizeCalcLayout.cy+sizeDiff.cy) > _sizeDockBarClient.cy )
					nNewLengthToSizeTB = _sizeDockBarClient.cy-sizeDiff.cy;
			} // if( (dwMode & LM_HORZ) == 0 )
			else
			{
				if( (sizeCalcLayout.cx+sizeDiff.cx) > _sizeDockBarClient.cx )
					nNewLengthToSizeTB = _sizeDockBarClient.cx-sizeDiff.cx;
			} // else from if( (dwMode & LM_HORZ) == 0 )
			if( nNewLengthToSizeTB < 1 )
				nNewLengthToSizeTB = 1;
			if( nNewLengthToSizeTB != nLengthToSizeTB )
			{
				if( !m_bInsideCalcLayout )
				{
					m_bHelperTempFullRowMode = true;
					m_bInsideCalcLayout = true;
					sizeCalcLayout = _CalcLayout( dwMode, nNewLengthToSizeTB );
					if( nLengthToSizeTB != 32767 )
						_RecalcPositionsImpl();
					m_bInsideCalcLayout = false;
					return sizeCalcLayout;
				}
			}
			if( nLengthToSizeTB != 32767 )
				_RecalcPositionsImpl();
		}
		if(		m_pRightBtn != NULL
			&&	m_pRightBtn->GetButtons().GetSize() == 0
			)
		{
			m_pRightBtn->ClearContent();
			sizeCalcLayout = _CalcSize( (dwMode & LM_HORZ) == 0 );
		}
		if( dwMode & LM_COMMIT )
			if( (m_dwStyle & (CBRS_FLOATING|CBRS_SIZE_DYNAMIC)) != 0 )
				if( dwMode & LM_HORZ )
					m_nMRUWidth = sizeCalcLayout.cx;
		CRect rcInside( 0, 0, 0, 0 );
		_CalcInsideRect(
			rcInside,
			(dwMode & LM_HORZ)
			);
		sizeCalcLayout.cy -= rcInside.Height();
		sizeCalcLayout.cx -= rcInside.Width();
		CSize sizeCalcFixedLayout =
			CControlBar::CalcFixedLayout(
				dwMode & LM_STRETCH,
				(dwMode & LM_HORZ)
				);
		sizeCalcLayout.cx =
			max( sizeCalcLayout.cx, sizeCalcFixedLayout.cx );
		sizeCalcLayout.cy =
			max( sizeCalcLayout.cy, sizeCalcFixedLayout.cy );
		if( IsFloating() && IsBarWithGripper() )
		{
			int nCyGripper = min( m_rcGrip.Width(), m_rcGrip.Height() );
			sizeCalcLayout.cy += nCyGripper;
		}
	} // if( _GetButtonsCountImpl() > 0 )

	if( IsDockedHorizontally() )
	{
		m_sizeDockedH = sizeCalcLayout;
		m_nMinHW = sizeCalcLayout.cy;
	}
	else if( IsDockedVertically() )
	{
		m_sizeDockedV = sizeCalcLayout;
		m_nMinVH = sizeCalcLayout.cx;
	}
	else if( IsFloating() )
	{
		if( sizeCalcLayout.cx < sizeDefButton.cx * 2 ) // (+ 2.23 )
			sizeCalcLayout.cx = sizeDefButton.cx * 2;
		m_sizeFloated = sizeCalcLayout;
	}

	if( m_pDockSite == NULL )
	{ // specific for dialog mode
		if( IsDockedHorizontally() )
			sizeCalcLayout.cy += 4;
		else
			sizeCalcLayout.cx += 4;
	} // specific for dialog mode

//	_RecalcPositionsImpl();

	return sizeCalcLayout;
}

CSize CExtToolControlBar::_CalcSize( BOOL bVerticallyDocked )
{
int nCountOfButtons = _GetButtonsCountImpl();
	if( nCountOfButtons == 0 )
		return _GetDefButtonSize();
CClientDC dc( this );
CFont * pOldFont =
		dc.SelectObject(
			OnGetToolbarFont(
				( bVerticallyDocked && (!m_bPaletteMode) )
					? true : false
				)
			);
	ASSERT( pOldFont != NULL );
bool bMultiRowLayout = OnQueryMultiRowLayout();
CExtBarButton::e_wrap_t _evt = GetBtnWrapCode();
CSize sizeDefButton = _GetDefButtonSize();
CSize sizeCalc( sizeDefButton );
CPoint ptCurrent( __EXT_TB_BUTTON_INNER_MARGIN, __EXT_TB_BUTTON_INNER_MARGIN );
int nRowExtent = sizeDefButton.cy;
	if( bMultiRowLayout && bVerticallyDocked && (!m_bPaletteMode) )
		nRowExtent = sizeDefButton.cx;
INT nRowDistance = g_PaintManager->FixedBar_GetRowDistance( this ); // (+ v.2.22)
INT nWrapCount = 0;
	for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
	{
		CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
		ASSERT_VALID( pTBB );
		
		if( pTBB->GetStyle() & TBBS_HIDDEN )
			continue;
		if(		pTBB->IsSeparator()
			&&	nBtnIdx < (nCountOfButtons-1)
			)
		{
			CExtBarButton * pNextTBB = _GetButtonPtr( nBtnIdx+1 );
			ASSERT_VALID( pNextTBB );
			if( pNextTBB->GetStyle() & TBBS_HIDDEN )
				continue;
		}
		
		CSize sizeTBB(
			pTBB->CalculateLayout(
				dc,
				sizeDefButton,
				(!bVerticallyDocked) || m_bPaletteMode
				)
			);
		if(		nBtnIdx == (nCountOfButtons-1)
			&&	m_pRightBtn != NULL
			&&	(IsFloating() || bMultiRowLayout)
			)
		{
			ASSERT_VALID( m_pRightBtn );
			ASSERT( m_pRightBtn == pTBB );
			if( bMultiRowLayout )
			{
				if( bVerticallyDocked )
					sizeCalc.cy += sizeTBB.cy;
				else
					sizeCalc.cx += sizeTBB.cx;
				if( nWrapCount > 0 && (!m_bPaletteMode) )
					m_bHelperTempFullRowMode = true;
			}
			break;
		}
		if( bMultiRowLayout && bVerticallyDocked && (!m_bPaletteMode) )
		{
			if(		( ptCurrent.y == __EXT_TB_BUTTON_INNER_MARGIN
						|| pTBB->IsWrap(_evt) )
				&&	pTBB->IsSeparator()
				)
				sizeTBB = CSize( 0, 0 );
			nRowExtent = max( nRowExtent, sizeTBB.cx );
			sizeCalc.cx =
				max(
					ptCurrent.x + sizeTBB.cx,
					sizeCalc.cx
					);
			sizeCalc.cy =
				max(
					ptCurrent.y + sizeTBB.cy,
					sizeCalc.cy
					);
			ptCurrent.y += sizeTBB.cy;
			if( pTBB->IsWrap(_evt) )
			{
				ptCurrent.y = __EXT_TB_BUTTON_INNER_MARGIN;
				ptCurrent.x +=
					nRowExtent
					+ nRowDistance;
				nRowExtent = sizeDefButton.cx;
				nWrapCount++;
			}
		} // if( bMultiRowLayout && bVerticallyDocked && (!m_bPaletteMode) )
		else
		{
			if(		( (!bVerticallyDocked) || m_bPaletteMode )
				&&	( ptCurrent.x == __EXT_TB_BUTTON_INNER_MARGIN
						|| pTBB->IsWrap(_evt) )
				&&	pTBB->IsSeparator()
				)
				sizeTBB = CSize( 0, 0 );
			nRowExtent = max( nRowExtent, sizeTBB.cy );
			sizeCalc.cx =
				max(
					ptCurrent.x + sizeTBB.cx,
					sizeCalc.cx
					);
			sizeCalc.cy =
				max(
					ptCurrent.y + sizeTBB.cy,
					sizeCalc.cy
					);
			if(		bVerticallyDocked
					&&	(!m_bPaletteMode)
				)
			{
				ptCurrent.x = __EXT_TB_BUTTON_INNER_MARGIN;
				ptCurrent.y += sizeTBB.cy;
			} // if( bVerticallyDocked && (!m_bPaletteMode) ...
			else
			{
				ptCurrent.x += sizeTBB.cx;
				if( pTBB->IsWrap(_evt) )
				{
					ptCurrent.x = __EXT_TB_BUTTON_INNER_MARGIN;
					ptCurrent.y +=
						nRowExtent
						+ nRowDistance;
					nRowExtent = sizeDefButton.cy;
					nWrapCount++;
				}
			} // else from if( bVerticallyDocked && (!m_bPaletteMode) ...
		} // else from if( bMultiRowLayout && bVerticallyDocked && (!m_bPaletteMode) )
	} // for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
	dc.SelectObject( pOldFont );

	if( !bVerticallyDocked )
	{
		sizeCalc.cx += m_cxLeftBorder + m_cxRightBorder;
		sizeCalc.cx += nRowDistance/2; // (+ v.2.22)
	}
	else
	{
		sizeCalc.cx += 1;
		sizeCalc.cy += m_cyTopBorder + m_cyBottomBorder;
		sizeCalc.cy += nRowDistance; // (+ v.2.22)
	}

	if( IsFloating() ) // (+ v.2.22)
	{
		sizeCalc.cx += 1;
		sizeCalc.cy += 1;
	}

	if( m_bPaletteMode && m_bPresubclassDialogMode )
	{
		CRect rcTest( 0, 0, 1, 1 );
		CSize _sizeInitial = rcTest.Size();
		CalcWindowRect( &rcTest );
		CSize _sizeUpdated = rcTest.Size();
		ASSERT(
				_sizeUpdated.cx >= _sizeInitial.cx
			&&	_sizeUpdated.cy >= _sizeInitial.cy
			);
		sizeCalc += _sizeUpdated - _sizeInitial;
		sizeCalc.cx += m_cxLeftBorder + m_cxRightBorder;
		sizeCalc.cy += m_cyTopBorder + m_cyBottomBorder;
	}

	return sizeCalc;
}

void CExtToolControlBar::_SizeToolBar(int nLength, BOOL bVert)
{
	if( m_bPaletteMode )
		return;
int nCountOfButtons = _GetButtonsCountImpl();
	if( nCountOfButtons == 0 )
		return;
bool bMultiRowLayout = OnQueryMultiRowLayout();
	if( !(		IsFloating()
			||	bMultiRowLayout
			)
		)
	{
		_WrapToolBarH(
			bVert ? 32767 : nLength,
			bVert ? nLength : 32767
			);
		return;
	}
CSize sizeDefButton = _GetDefButtonSize();
	if( bMultiRowLayout )
	{
		if( bVert )
		{
			int nLengthCurr = nLength - sizeDefButton.cy;
			if( nLengthCurr < sizeDefButton.cy )
				nLengthCurr = sizeDefButton.cy;
			for( ; true;  )
			{
				_WrapToolBarV( nLengthCurr );
				CSize _size = _CalcSize( TRUE );
				if( _size.cy <= nLength )
					break;
				nLengthCurr -= sizeDefButton.cy / 2;
				if( nLengthCurr <= 0 )
					break;
			}
		} // if( bVert )
		else
			_WrapToolBarH( nLength );
		return;
	} // if( bMultiRowLayout )
INT nMinExtent = sizeDefButton.cx / 2;
	ASSERT( nMinExtent > 0 );
	if( bVert )
	{
		CExtPaintManager::monitor_parms_t _mp;
		CExtPaintManager::stat_GetMonitorParms( _mp, this );
		INT nCalcExtentMax = _mp.m_rcWorkArea.Width() + nMinExtent;
		// NOTES:
		// 1) bug was found by Eugene Pl.
		// 2) there is no reason to make toolbar wider
		//    then nCalcExtentMax value
		// 3) loop is locked when toolbar button icons are higher
		//    then 16px and user drags top/bottom border of a
		//    floating toolbar with 1-row layout (and attempting
		//    to decrease toolbar height)
		CSize _size( 32767, 32767 );
		for(	INT nCalcExtent = nMinExtent;
				nLength < _size.cy;
				nCalcExtent += nMinExtent
				)
		{
			_WrapToolBarH( nCalcExtent );
			_size = _CalcSize( FALSE );
			if( nCalcExtent > nCalcExtentMax )
				return;
		}
		_WrapToolBarH( _size.cx );
		return;
	}
INT nCountOfRowsDesired = _WrapToolBarH( nLength );
INT nCountOfRowsCurrent = _WrapToolBarH( nMinExtent );
	if( nCountOfRowsCurrent == nCountOfRowsDesired
		|| nMinExtent >= nLength
		)
	{
		_WrapToolBarH( _CalcSize(FALSE).cx );
		return;
	}
	while( nMinExtent < nLength )
	{
		INT nCurrentExtent = (nMinExtent + nLength) / 2;
		nCountOfRowsCurrent = _WrapToolBarH( nCurrentExtent );
		if( nCountOfRowsCurrent == nCountOfRowsDesired )
		{
			nLength = nCurrentExtent;
			continue;
		}
		if( nMinExtent == nCurrentExtent )
		{
			_WrapToolBarH( nLength );
			break;
		}
		nMinExtent = nCurrentExtent;
	}
	_WrapToolBarH( _CalcSize(FALSE).cx );
}

void CExtToolControlBar::_DraggingUpdateState(
	const CPoint & point,
	bool bForceFloatMode
	)
{
	CExtControlBar::_DraggingUpdateState( point, bForceFloatMode );
//	if( IsFloating() )
//		return;
//	if(		_IsDockSiteCustomizeMode()
//		&&	(! IsSingleOnRow() )
//		)
//		MakeSingleOnRow();
}

int CExtToolControlBar::_WrapToolBarV(
	int nHeight
	)
{
	ASSERT( !m_bPaletteMode );
//	ASSERT( !IsFloating() );

CClientDC dc( this );
CFont * pOldFont = dc.SelectObject( OnGetToolbarFont(true) );
	ASSERT( pOldFont != NULL );
CSize sizeDefButton = _GetDefButtonSize();
CRect rcClient;
	GetClientRect( &rcClient );
CPoint ptCurrent( rcClient.right, rcClient.top );
    if( m_pRightBtn != NULL )
        nHeight -=
			m_pRightBtn->CalculateLayout(
				dc, sizeDefButton, FALSE ).cy;
CExtBarButton::e_wrap_t _evt = GetBtnWrapCode();
int nCountOfColumns = 1;
int nCountOfButtons = _GetButtonsCountImpl();
CExtBarButton * pPrevButton = NULL;
INT nRowDistance = g_PaintManager->FixedBar_GetRowDistance( this );
	for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
	{
		CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
		ASSERT_VALID( pTBB );
		pTBB->SetWrap( _evt, false );
		if( nBtnIdx == (nCountOfButtons-1)
			&& m_pRightBtn != NULL
			)
		{
			ASSERT_VALID( m_pRightBtn );
			ASSERT( m_pRightBtn == pTBB );
			break;
		}
		
		if( pTBB->GetStyle() & TBBS_HIDDEN )
			continue;
		if(		pTBB->IsSeparator()
			&&	nBtnIdx < (nCountOfButtons-1)
			)
		{
			CExtBarButton * pNextTBB = _GetButtonPtr( nBtnIdx+1 );
			ASSERT_VALID( pNextTBB );
			if( pNextTBB->GetStyle() & TBBS_HIDDEN )
				continue;
		}
		
		CSize sizeTBB =
			pTBB->CalculateLayout(
				dc,
				sizeDefButton,
				FALSE
				);
		if( ptCurrent.y == 0 && pTBB->IsSeparator() )
			sizeTBB = CSize(0, 0);
		if(	pPrevButton != NULL
			&&	( (ptCurrent.y + sizeTBB.cy) > nHeight )
			&&	(! pTBB->IsSeparator() )
			)
		{
			ASSERT_VALID( pPrevButton );
			pPrevButton->SetWrap( _evt );
			ptCurrent.x -=
				sizeTBB.cx
				+ nRowDistance;
			ptCurrent.y = 0;
			nCountOfColumns++;
		}
		ptCurrent.y += sizeTBB.cy;
		pPrevButton = pTBB;
	} // for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
	dc.SelectObject( pOldFont );
	return nCountOfColumns;
}

int CExtToolControlBar::_WrapToolBarH(int nWidth, int nHeight /*= 32767*/)
{
bool bVerticallyDocked =
		((m_dwStyle & CBRS_ORIENT_HORZ) == 0)
			? true : false;
bool bFloatLikeMode =
		(	IsFloating()
		||	nHeight == 32767 // (+ v.2.22)
		||	OnQueryMultiRowLayout()
		) ? true : false;
CClientDC dc( this );
CFont* pOldFont =
		dc.SelectObject(
			OnGetToolbarFont(
				( bVerticallyDocked && (!m_bPaletteMode) )
					? true : false
				)
			);
	ASSERT( pOldFont != NULL );
CSize sizeDefButton = _GetDefButtonSize();
CRect rcClient;
	GetClientRect( &rcClient );
CPoint ptCurrent( 0, rcClient.top );
    if(		(!bFloatLikeMode)
		&&	(!bVerticallyDocked)
		&&	m_pRightBtn != NULL
		&&	(!m_bPaletteMode)
		)
        nWidth -=
			m_pRightBtn->CalculateLayout(
				dc, sizeDefButton, TRUE ).cx;
CExtBarButton::e_wrap_t _evt = GetBtnWrapCode();
int nCountOfRows = 1;
int nCountOfButtons = _GetButtonsCountImpl();
CExtBarButton * pPrevButton = NULL;
INT nRowDistance = g_PaintManager->FixedBar_GetRowDistance( this );
	for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
	{
		CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
		ASSERT_VALID( pTBB );
		if( !m_bPaletteMode )
			pTBB->SetWrap( _evt, false );
		if( nBtnIdx == (nCountOfButtons-1)
			&& m_pRightBtn != NULL
			)
		{
			ASSERT_VALID( m_pRightBtn );
			ASSERT( m_pRightBtn == pTBB );
			break;
		}

		if( pTBB->GetStyle() & TBBS_HIDDEN )
			continue;
		if(		pTBB->IsSeparator()
			&&	nBtnIdx < (nCountOfButtons-1)
			)
		{
			CExtBarButton * pNextTBB = _GetButtonPtr( nBtnIdx+1 );
			ASSERT_VALID( pNextTBB );
			if( pNextTBB->GetStyle() & TBBS_HIDDEN )
				continue;
		}
		
		CSize sizeTBB =
			pTBB->CalculateLayout(
				dc,
				sizeDefButton,
				(!bVerticallyDocked)
					|| m_bPaletteMode
				);
		if( ptCurrent.x == 0 && pTBB->IsSeparator() )
			sizeTBB = CSize(0, 0);
		if(		(	m_bPaletteMode
				&&	pPrevButton != NULL
				&&	pPrevButton->IsWrap( _evt )
				)
			||	(	(!m_bPaletteMode)
				&&	bFloatLikeMode
				&&	pPrevButton != NULL
				&&	(bFloatLikeMode || ptCurrent.y + sizeTBB.cy < nHeight)
				&&	ptCurrent.x + sizeTBB.cx > nWidth
				&&	(!pTBB->IsSeparator())
				)
			)
		{
			ASSERT_VALID( pPrevButton );
			if( !m_bPaletteMode )
				pPrevButton->SetWrap( _evt );
			ptCurrent.x = 0;
			ptCurrent.y +=
				sizeTBB.cy
				+ nRowDistance;
			nCountOfRows++;
		}
		ptCurrent.x += sizeTBB.cx;
		pPrevButton = pTBB;
	} // for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
	dc.SelectObject( pOldFont );
	return nCountOfRows;
}

CSize CExtToolControlBar::_CalcDesiredMinOuterSize( BOOL bHorz )
{
	ASSERT_VALID( this );
	if( m_bPaletteMode )
		return CalcFixedLayout( FALSE, bHorz );
CSize sizeDefButton = _GetDefButtonSize();
CSize _size( 0, 0 );
	if( m_pRightBtn != NULL ) 
	{
		CClientDC dc( this );
		CFont * pOldFont =
			dc.SelectObject(
				OnGetToolbarFont(
					( (!bHorz) && (!m_bPaletteMode) )
						? true : false
					)
				);
		CSize sizeTBBRight =
			m_pRightBtn->CalculateLayout(
				dc,
				sizeDefButton,
				bHorz //|| m_bPaletteMode
				);
		_size += sizeTBBRight;
		if( bHorz )
			_size.cx += __EXT_TB_BUTTON_INNER_MARGIN*2;
		else
			_size.cy += __EXT_TB_BUTTON_INNER_MARGIN*2;
		dc.SelectObject( pOldFont );
	}
//	if( IsFloating() )
//		return _size;

int nCountOfButtons = GetButtonsCount();
	if( nCountOfButtons > 0 )
	{
		CSize _sizeAdjust( 0, 0 );
		CClientDC dc( this );
		CFont * pOldFont =
			dc.SelectObject(
				OnGetToolbarFont(
					( (!bHorz) && (!m_bPaletteMode) )
						? true : false
					)
				);
		for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
		{
			CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
			ASSERT_VALID( pTBB );
			
			if( pTBB->IsSeparator() )
				continue;
			if( pTBB->GetStyle() & TBBS_HIDDEN )
				continue;

			if(		nBtnIdx == (nCountOfButtons-1)
				&&	m_pRightBtn != NULL
				)
			{
				ASSERT_VALID( m_pRightBtn );
				ASSERT( m_pRightBtn == pTBB );
				break;
			}
			CSize sizeTBB(
				pTBB->CalculateLayout(
					dc,
					sizeDefButton,
					bHorz
					)
				);
			if( bHorz )
			{
				if( _sizeAdjust.cx > 0 )
					_sizeAdjust.cx = min( _sizeAdjust.cx, sizeTBB.cx );
				else
					_sizeAdjust = sizeTBB;
			}
			else
			{
				if( _sizeAdjust.cy > 0 )
					_sizeAdjust.cy = min( _sizeAdjust.cy, sizeTBB.cy );
				else
					_sizeAdjust = sizeTBB;
			}
		} // for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
		if( bHorz )
		{
			if( _sizeAdjust.cx > 0 )
				_size.cx += _sizeAdjust.cx + __EXT_TB_BUTTON_INNER_MARGIN*2;
		}
		else
		{
			if( _sizeAdjust.cy > 0 )
				_size.cy += _sizeAdjust.cy + __EXT_TB_BUTTON_INNER_MARGIN*2;
		}
		dc.SelectObject( pOldFont );
	} // if( nCountOfButtons > 0 )
	
	return _size;
}

bool CExtToolControlBar::_GetFullRowMode() const
{
	if( m_bHelperTempFullRowMode )
		return true;
	return CExtControlBar::_GetFullRowMode();
}

bool CExtToolControlBar::OnQueryMultiRowLayout() const
{
	ASSERT_VALID( this );
	if(		m_bPresubclassDialogMode
		||	m_pDockSite == NULL
		||	m_bPaletteMode
		)
		return false;
	if( IsFloating() )
		return false;
	if( !_IsDockSiteCustomizeMode() )
		return false;
	return true;
}

CExtControlBar::InternalAffixmentData *
	CExtToolControlBar::_AffixmentGetOuter()
{
	ASSERT_VALID( this );
	return &m_AffixmentData;
}

void CExtToolControlBar::_AffixmentSetOuter(
	CExtControlBar::InternalAffixmentData * pAffixmentData
	)
{
	ASSERT_VALID( this );
	ASSERT( pAffixmentData != NULL );
	m_AffixmentData = *pAffixmentData;
}

bool CExtToolControlBar::_AffixmentIsAlignedHW() const
{
	ASSERT_VALID( this );
	if( m_bPaletteMode )
		return false;
	return true;
}

LRESULT CExtToolControlBar::_ContinueHelpHitTestMode(
	CExtToolControlBar * pBar
	)
{
	ASSERT_VALID( pBar );
	ASSERT( pBar->GetSafeHwnd() != NULL && ::IsWindow(pBar->GetSafeHwnd()) );
	if(		pBar->m_pDockSite == NULL
		||	(! pBar->m_pDockSite->m_bHelpMode )
		)
		return -3L;
static bool g_bContinuedMode = false;
	if( g_bContinuedMode )
		return -3L;
HWND hWndDockSite = pBar->m_pDockSite->m_hWnd;
HWND hWndBar = pBar->m_hWnd;
MSG msg;
	g_bContinuedMode = true;
LRESULT lResult = -3L;
	for( ; true; )
	{
		if( !PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) )
		{
			if(!(	::IsWindow( hWndDockSite )
				&&	::IsWindow( hWndBar )
				&&	pBar->m_pDockSite->m_bHelpMode
				))
				break;
			::WaitMessage();
			continue;
		} // if( !PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) )
		
		if( msg.hwnd != NULL )
		{
			if( msg.message == WM_LBUTTONDOWN )
			{
				CWnd * pWndPerm = CWnd::FromHandlePermanent(msg.hwnd);
				if( pWndPerm != NULL )
				{
					CExtControlBar * pTestBar =
						DYNAMIC_DOWNCAST( CExtControlBar, pWndPerm );
					if( pTestBar != NULL )
					{
						lResult = pTestBar->DoHelpHitTest( CPoint(msg.lParam) );
						if( lResult > 0 )
						{
							PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
							break;
						}
						lResult = -3L;
					} // if( pTestBar != NULL )
				} // if( pWndPerm != NULL )
			} // if( msg.message == WM_LBUTTONDOWN )
			else if( msg.message == WM_MOUSEMOVE )
			{
				CWnd * pWndPerm = CWnd::FromHandlePermanent(msg.hwnd);
				if( pWndPerm != NULL )
				{
					CExtControlBar * pTestBar =
						DYNAMIC_DOWNCAST( CExtControlBar, pWndPerm );
					if( pTestBar != NULL )
					{
						CPoint pt( (DWORD)msg.lParam );
						if( pTestBar->_OnMouseMoveMsg((UINT)msg.wParam,pt) )
						{
							PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
							continue;
						} // if( pTestBar->_OnMouseMoveMsg((UINT)msg.wParam,pt) )
					} // if( pTestBar != NULL )
				} // if( pWndPerm != NULL )
			} // else if( msg.message == WM_MOUSEMOVE )
			else if( msg.message == WM_COMMAND )
			{
				if( ((HIWORD(msg.wParam))==0) || ((HIWORD(msg.wParam))==1) )
				{
					lResult = (LRESULT)( LOWORD(msg.wParam) );
					PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
					break;
				} // if( ((HIWORD(msg.wParam))==0) || ((HIWORD(msg.wParam))==1) )
			} // else if( msg.message == WM_COMMAND )
			else if( msg.message == WM_SYSCOMMAND )
			{
				switch( msg.wParam )
				{
				case SC_SIZE:
				case SC_MOVE:
				case SC_MINIMIZE:
				case SC_MAXIMIZE:
				case SC_NEXTWINDOW:
				case SC_PREVWINDOW:
				case SC_CLOSE:
				case SC_RESTORE:
				case SC_TASKLIST:
					lResult =
						HID_BASE_COMMAND +
							ID_COMMAND_FROM_SC( msg.wParam );
					PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
					break;
				default:
					lResult = (LRESULT)( msg.wParam );
					PeekMessage(&msg,NULL,msg.message,msg.message,PM_REMOVE);
					break;
				}
				break;
			} // else if( msg.message == WM_SYSCOMMAND )
		} // if( msg.hwnd != NULL )

		if( !AfxGetThread()->PumpMessage() )
			break;
	} // for( LRESULT lResult = -3L; true; )
	g_bContinuedMode = false;
	return lResult;
}

void CExtToolControlBar::GetButtonInfo(int nIndex, UINT& nID, UINT& nStyle) const
{
	ASSERT_VALID(this);

CExtBarButton * pTBB =
		_GetButtonPtr(nIndex);
	if( pTBB == NULL )
	{
		ASSERT( FALSE );
		nID = 0;
		nStyle = 0;
		return;
	}
	ASSERT_VALID( pTBB );
	nID = pTBB->GetCmdID(false);
	nStyle = pTBB->GetStyle();
}

void CExtToolControlBar::SetButtonInfo(int nIndex, UINT nID, UINT nStyle)
{
	ASSERT_VALID(this);

CExtBarButton * pTBB =
		_GetButtonPtr(nIndex);
	if( pTBB == NULL )
	{
		ASSERT( FALSE );
		return;
	}
	ASSERT_VALID( pTBB );
	pTBB->SetCmdID( nID );
	pTBB->SetStyle( nStyle );
	_InvalidateButton(nIndex);
	UpdateWindow();
}

CFont * CExtToolControlBar::OnGetToolbarFont( bool bVert )
{
	ASSERT_VALID(this);
	ASSERT( g_PaintManager->m_FontNormal.GetSafeHandle() != NULL );
	ASSERT( g_PaintManager->m_FontNormalVert.GetSafeHandle() != NULL );
	return ( bVert )
		? ( & g_PaintManager->m_FontNormalVert )
		: ( & g_PaintManager->m_FontNormal )
		;
}

void CExtToolControlBar::DoPaint(CDC* pDC)
{
	ASSERT_VALID(this);
	ASSERT_VALID(pDC);
	CExtPaintManager::stat_ExcludeChildAreas(
		*pDC,
		*this
		);
CExtBarButton::e_wrap_t _evt = GetBtnWrapCode();
CRect rcClient;
	GetClientRect( &rcClient );
CExtMemoryDC dc( pDC, &rcClient );
	ASSERT( dc.GetSafeHdc() != NULL );
	if( dc.GetSafeHdc() != NULL )
		pDC = &dc;
	DoEraseBk( pDC, &rcClient );

	pDC->SetTextColor(
		g_PaintManager->GetColor(CExtPaintManager::CLR_TEXT_OUT)
		);
	pDC->SetBkMode( TRANSPARENT );
CFont * pOldFont =
		pDC->SelectObject(
			OnGetToolbarFont(
				( ( ( m_dwStyle & CBRS_ORIENT_HORZ ) == 0 ) && (!m_bPaletteMode) )
					? true : false
				)
			);
	ASSERT( pOldFont != NULL );
int nCountOfButtons = _GetButtonsCountImpl();
INT nRowDistance = g_PaintManager->FixedBar_GetRowDistance( this );
bool bPaintRowBkMode = g_PaintManager->FixedBar_IsPaintRowBkMode( this );
bool bMultiRowLayout = OnQueryMultiRowLayout();
	if( bPaintRowBkMode )
	{
		CRect rcRowBk( rcClient );
		rcRowBk.bottom = rcRowBk.top;
		for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
		{
			CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
			ASSERT_VALID( pTBB );
			
			if(		(! pTBB->IsVisible() )
				||	(pTBB->GetStyle() & TBBS_HIDDEN) != 0
				)
				continue;
			if(		pTBB->IsSeparator()
				&&	nBtnIdx < (nCountOfButtons-1)
				)
			{
				CExtBarButton * pNextTBB = _GetButtonPtr( nBtnIdx+1 );
				ASSERT_VALID( pNextTBB );
				if( pNextTBB->GetStyle() & TBBS_HIDDEN )
					continue;
			}
			
			if( !pTBB->IsSeparator() )
			{
				CRect rcTBB = *pTBB;
				rcRowBk.top = min( rcRowBk.top, rcTBB.top );
				rcRowBk.bottom = max( rcRowBk.bottom, rcTBB.bottom );
			}
			if( pTBB->IsWrap(_evt) && ( m_dwStyle & CBRS_ORIENT_HORZ ) )
			{
				if(		!rcRowBk.IsRectEmpty()
					&&	pDC->RectVisible( &rcRowBk )
					)
					g_PaintManager->PaintFloatToolbarRowBk(
						*pDC,
						this,
						nBtnIdx,
						rcRowBk
						);
				rcRowBk.top = rcRowBk.bottom + 1;
			}
		} // for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
		if(		!rcRowBk.IsRectEmpty()
			&&	pDC->RectVisible( &rcRowBk )
			)
			g_PaintManager->PaintFloatToolbarRowBk(
				*pDC,
				this,
				nBtnIdx,
				rcRowBk
				);
	} // pre-fill row backgrounds

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtBarButton * pCustomizeActiveTBB = NULL;
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
	{
		CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
		ASSERT_VALID( pTBB );
		
		if(		(! pTBB->IsVisible() )
			||	(pTBB->GetStyle() & TBBS_HIDDEN) != 0
			)
			continue;
		if(		pTBB->IsSeparator()
			&&	nBtnIdx < (nCountOfButtons-1)
			)
		{
			CExtBarButton * pNextTBB = _GetButtonPtr( nBtnIdx+1 );
			ASSERT_VALID( pNextTBB );
			if( pNextTBB->GetStyle() & TBBS_HIDDEN )
				continue;
		}
		
		CRect rcTBB = *pTBB;
		if( !pDC->RectVisible( &rcTBB ) )
			continue;
		if( !pTBB->IsSeparator() )
		{
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
			if(		GetCustomizeSite() != NULL
				&&	pTBB->IsCustomizeActiveItem()
				)
			{
				ASSERT( pCustomizeActiveTBB == NULL );
				pCustomizeActiveTBB = pTBB;
			} // if( GetCustomizeSite() != NULL ...
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
			pTBB->Paint(
				*pDC,
				(		( m_dwStyle & CBRS_ORIENT_HORZ ) != 0
					||	m_bPaletteMode
					)
					? true : false
				);
			continue;
		} // if( !pTBB->IsSeparator() )
		bool bSeparatorHorz =
			(		( m_dwStyle & CBRS_ORIENT_HORZ ) != 0
				||	m_bPaletteMode
				)
				? true : false;
		bool bSeparatorRotate = false;
		CRect rectSeparator( rcTBB );
		if( (!bSeparatorHorz) && (!bMultiRowLayout) )
		{
			bSeparatorHorz = true;
			rcTBB.OffsetRect( 0, -rcTBB.Height() );
		}
		if( pTBB->IsWrap(_evt) )
		{
			if( bSeparatorHorz )
			{
				rectSeparator.left = rcClient.left;
				rectSeparator.right = rcClient.right;
				rectSeparator.top = rcTBB.bottom;
				rectSeparator.bottom =
					rectSeparator.top
					+ nRowDistance;
				bSeparatorRotate = true;
			} // if( bSeparatorHorz )
			else
			{
				rectSeparator.top = rcClient.top;
				rectSeparator.bottom = rcClient.bottom;
				rectSeparator.left =
					rcTBB.left
					- nRowDistance;
				rectSeparator.right =
					rectSeparator.left
					+ nRowDistance;
				bSeparatorRotate = true;
			} // else from if( bSeparatorHorz )
		} // if( pTBB->IsWrap(_evt) )
		if( nRowDistance == 0 && bSeparatorRotate )
			continue;
		if( bSeparatorRotate )
			bSeparatorHorz = !bSeparatorHorz;
		rectSeparator.DeflateRect(
			bSeparatorHorz ? 0 : 1,
			bSeparatorHorz ? 1 : 0
			);
		if(		bMultiRowLayout
			&&	m_pRightBtn != NULL
			&&	m_pRightBtn->IsVisible()
			&&	bSeparatorRotate
			)
		{
			CRect rcRightBtn = *m_pRightBtn;
			if( bSeparatorHorz )
			{
				if( ( m_dwStyle & CBRS_ORIENT_HORZ ) == 0 )
				{
					if( rectSeparator.bottom > (rcRightBtn.top-__EXT_TB_BUTTON_OUTER_MARGIN) )
						rectSeparator.bottom = (rcRightBtn.top-__EXT_TB_BUTTON_OUTER_MARGIN);
				}
			} // if( bSeparatorHorz )
			else
			{
				if( ( m_dwStyle & CBRS_ORIENT_HORZ ) != 0 )
				{
					if( rectSeparator.right > (rcRightBtn.left-__EXT_TB_BUTTON_OUTER_MARGIN) )
						rectSeparator.right = (rcRightBtn.left-__EXT_TB_BUTTON_OUTER_MARGIN);
				}
			} // else from if( bSeparatorHorz )
		}
		g_PaintManager->PaintSeparator(
			*pDC,
			rectSeparator,
			bSeparatorHorz,
			true,
			this
			);
		// DEBUG SEPARATOR AREA PAINTING:
		// pDC->FillSolidRect( &rectSeparator, RGB(0,255,0) );
	} // for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	if( m_pDragTargetTBB != NULL && (abs(m_nDragTargetShift)) == 1 )
	{
		CRect rcItem = *m_pDragTargetTBB;
		g_PaintManager->PaintDropDivider(
			*pDC,
			rcItem,
			(m_nDragTargetShift < 0) ? true : false,
			( ( m_dwStyle & CBRS_ORIENT_HORZ ) != 0 ) ? true : false
			);
	} // if( m_pDragTargetTBB != NULL && (abs(m_nDragTargetShift)) == 1 )
	if(		m_pDragSourceTBB != NULL
		||	pCustomizeActiveTBB != NULL
		)
	{
		CRect rcItem =
			(pCustomizeActiveTBB != NULL)
			? (*pCustomizeActiveTBB)
			: (*m_pDragSourceTBB)
			;
		g_PaintManager->PaintDragSourceRect(
			*pDC,
			rcItem
			);
	} // if( m_pDragSourceTBB != NULL ...
CExtCustomizeSite * pSite = GetCustomizeSite();
	if( pSite != NULL )
	{
		CExtCustomizeCmdTreeNode * pPopupDropTargetNode =
			pSite->GetPopupDropTargetNode();
		if( pPopupDropTargetNode != NULL )
		{
			ASSERT_VALID( pPopupDropTargetNode );
			for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
			{
				CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
				ASSERT_VALID( pTBB );
				if(		(! pTBB->IsVisible() )
					||	(pTBB->GetStyle() & TBBS_HIDDEN) != 0
					)
					continue;
				if( pTBB->IsSeparator() )
					continue;
				CRect rcTBB = *pTBB;
				if( !pDC->RectVisible( &rcTBB ) )
					continue;
				CExtCustomizeCmdTreeNode * pNode =
					pTBB->GetCmdNode();
				if( ((LPVOID)pNode) != ((LPVOID)pPopupDropTargetNode) )
					continue;
				g_PaintManager->PaintDragSourceRect(
					*pDC,
					rcTBB
					);
				break;
			} // for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
		} // if( pPopupDropTargetNode != NULL )
	} // if( pSite != NULL )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

	pDC->SelectObject( pOldFont );
	g_PaintManager->OnPaintSessionComplete( this );
}

void CExtToolControlBar::_InvalidateButton(int nIndex)
{
CExtBarButton * pTBB =
		_GetButtonPtr(nIndex);
	if( pTBB == NULL )
	{
		ASSERT( FALSE );
		return;
	}
	ASSERT_VALID( pTBB );
CRect rect = pTBB->Rect();
	if( rect.IsRectEmpty() )
		return;
	if(		pTBB->IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton))
		&&	g_PaintManager->GetCb2DbTransparentMode(this)
		)
	{
		CSize sizeToolBarRgnRounders =
			g_PaintManager->GetToolBarRgnRoundersSize();
		rect.InflateRect(
			sizeToolBarRgnRounders.cx + 1,
			sizeToolBarRgnRounders.cy + 1
			);
	}
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	if(		pTBB == m_pDragSourceTBB
		||	pTBB == m_pDragTargetTBB
		)
	{
		CSize _sizeDDM = g_PaintManager->GetDropDividerMerics();
		rect.InflateRect( _sizeDDM );
		rect.InflateRect( 1, 1 );
	} // if( pTBB == m_pDragSourceTBB )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	InvalidateRect( &rect );
}

int CExtToolControlBar::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
{
	ASSERT_VALID( this );

	if(		CExtToolControlBar::g_bMenuTracking
		||	CExtPopupMenuWnd::IsMenuTracking()
		)
		return -1;

int nToolTipHit =
		((CExtToolControlBar*)this)->
			HitTest(point);
	if( nToolTipHit >= 0 )
	{
		CExtBarButton * pTBB =
			_GetButtonPtr( nToolTipHit );
		ASSERT_VALID( pTBB );
		if( pTBB != NULL )
		{
			nToolTipHit = pTBB->OnToolHitTest( point, pTI );
			if( nToolTipHit != -1 )
				return nToolTipHit;
		}
	} // if( nToolTipHit >= 0 )

	nToolTipHit =
		CExtControlBar::OnToolHitTest(
			point,
			pTI
			);
	return nToolTipHit;
}

int CExtToolControlBar::_HitTestImpl(
	CPoint point,
	UINT nButtonStyleInclude, // = 0, // button must have style
	UINT nButtonStyleExclude, // = 0  // button must have not style
	bool bAllowFindNearest // = false // if did not hit - find nearest
	) const
{
	ASSERT_VALID( this );
	if( m_hWnd == NULL || (! ::IsWindow(m_hWnd) )  )
		return -1; // nowhere
	if( (!bAllowFindNearest) && ::GetCapture() == m_hWnd )
	{
		CPoint ptScreen( point );
		ClientToScreen( &ptScreen );
		if( ::WindowFromPoint(ptScreen) != m_hWnd )
			return -1; // nowhere
	}
int nCountOfButtons = _GetButtonsCountImpl();
int nNearestIdx = -1;
int nNearestDistance = 32767;
bool bNearestRowMatch = false;
	for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
	{
		CExtBarButton * pTBB =
			_GetButtonPtr(nBtnIdx);
		ASSERT_VALID( pTBB );
		
		if(		(! pTBB->IsVisible() )
			||	(pTBB->GetStyle() & TBBS_HIDDEN) != 0
			)
			continue;
		if(		pTBB->IsSeparator()
			&&	nBtnIdx < (nCountOfButtons-1)
			)
		{
			CExtBarButton * pNextTBB = _GetButtonPtr( nBtnIdx+1 );
			ASSERT_VALID( pNextTBB );
			if( pNextTBB->GetStyle() & TBBS_HIDDEN )
				continue;
		}
		
		if( (pTBB->GetStyle() & nButtonStyleInclude)
				!= nButtonStyleInclude
			)
			continue;
		if( (pTBB->GetStyle() & nButtonStyleExclude)
				!= 0
			)
			continue;
		CRect rect = *pTBB;
		if( rect.PtInRect(point) )
			return nBtnIdx;
		if( !bAllowFindNearest )
			continue;
		CPoint ptCenter = rect.CenterPoint();
		double lfDX = double( point.x - ptCenter.x );
		double lfDY = double( point.y - ptCenter.y );
		int nDistance = (int)
			::sqrt( lfDX*lfDX + lfDY*lfDY );
		bool bRowMatch = false;
		if( (m_dwStyle & CBRS_ORIENT_HORZ) != 0 )
		{
			bRowMatch =
				(rect.top <= point.y && point.y <= rect.bottom)
					? true : false;
		} // if( (m_dwStyle & CBRS_ORIENT_HORZ) != 0 )
		else
		{
			bRowMatch =
				(rect.left <= point.x && point.x <= rect.right)
					? true : false;
		} // if( (m_dwStyle & CBRS_ORIENT_HORZ) != 0 )
		if( (!bNearestRowMatch) && bRowMatch )
		{
			nNearestIdx = nBtnIdx;
			nNearestDistance = nDistance;
			bNearestRowMatch = true;
		} // if( (!bNearestRowMatch) && bRowMatch )
		else if(
				bNearestRowMatch == bRowMatch
			&&	nNearestDistance > nDistance
			)
		{
			nNearestIdx = nBtnIdx;
			nNearestDistance = nDistance;
		}
	} // for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
	if( bAllowFindNearest && nNearestIdx >= 0 )
		return nNearestIdx;
	return -1; // nowhere
}

int CExtToolControlBar::HitTest(
	CPoint point // in window relative coords
	) const
{
	return
		_HitTestImpl(
			point,
			0,
			TBBS_SEPARATOR
			);
}

/////////////////////////////////////////////////////////////////////////////
// CExtToolControlBar message handlers

BEGIN_MESSAGE_MAP(CExtToolControlBar, CExtControlBar)
	//{{AFX_MSG_MAP(CExtToolControlBar)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_RBUTTONUP()
	ON_WM_CANCELMODE()
	ON_WM_SIZE()
	ON_WM_TIMER()
	ON_WM_CAPTURECHANGED()
	//}}AFX_MSG_MAP
	__EXT_MFC_SAFE_ON_WM_SETTINGCHANGE()
	ON_REGISTERED_MESSAGE(CExtToolControlBar::g_nMsgTrackButtonMenu, OnTrackButtonMenu)
END_MESSAGE_MAP()

LRESULT CExtToolControlBar::OnTrackButtonMenu(WPARAM wParam,LPARAM lParam)
{
	lParam;
	if( !(	::IsWindowEnabled(
				m_bPresubclassDialogMode
					? GetOwner()->GetSafeHwnd()
					: _GetDockingFrameImpl()->GetSafeHwnd()
				)
			)
		) 
		return 0;
int nCountOfButtons = GetButtonsCount();
	ASSERT( nCountOfButtons >= 0 );
	if( nCountOfButtons == 0 )
		return 0;
int nIndex = int(wParam);
	if( nIndex < 0 || nIndex>=nCountOfButtons )
	{
		_CloseTrackingMenus();
		return 0;
	}
CExtBarButton * pTBB = _GetButtonPtr(nIndex);
	ASSERT_VALID( pTBB );
BOOL bDroppedMode =
		CExtPopupMenuWnd::IsMenuTracking();
	if( !pTBB->IsAbleToTrackMenu() )
		bDroppedMode = FALSE;
	if( bDroppedMode )
	{
		CExtToolControlBar::TrackButtonMenu( nIndex, true );
		return 0;
	}
	_CloseTrackingMenus();
	if( CExtMouseCaptureSink::GetCapture() == GetSafeHwnd() )
		CExtMouseCaptureSink::ReleaseCapture();

	return 0;
}

void CExtToolControlBar::OnLButtonDown(UINT nFlags, CPoint point)
{
    if( m_bRowResizing || m_bRowRecalcing || m_bDragging )
	{
		CExtControlBar::OnLButtonDown(nFlags, point);
		return;
	}
	
	_ActivateOnClick();

	if( (m_nBtnIdxCapture = HitTest(point)) < 0 ) // nothing hit
	{
		CExtControlBar::OnLButtonDown(nFlags, point);
		return;
	}

CExtBarButton * pTBB =
		_GetButtonPtr(m_nBtnIdxCapture);
	ASSERT_VALID( pTBB );
	ASSERT( !(pTBB->IsSeparator()) );

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeSite * pSite = GetCustomizeSite();
	if( pSite != NULL )
	{
		CExtCustomizeCmdTreeNode * pNodeC =
			pTBB->GetCmdNode( false );
		if( pNodeC != NULL )
		{
			ASSERT_VALID( pNodeC );
			bool bCustomizeMode = pSite->IsCustomizeMode();
			bool bAlt =
				( (::GetAsyncKeyState(VK_MENU)&0x8000) != 0 )
					? true : false;
			if( bAlt || bCustomizeMode )
			{
				int nBtnDragSrc = m_nBtnIdxCapture;
				m_nBtnIdxCapture = -1;
				if( !pTBB->CanStartCommandDrag() )
					return;
				if( bCustomizeMode )
				{
#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
					int nWidthMin = 0, nWidthMax = 0;
					int nInitialResizingStateH =
						pTBB->GetInitialResizingStateH(
							point,
							&nWidthMin,
							&nWidthMax
							);
					if(		pTBB->IsCustomizeActiveItem()
						&&	nInitialResizingStateH != 0
						)
					{ // if can resize button horizontally
						bool bCtrl =
							( (::GetAsyncKeyState(VK_CONTROL)&0x8000) != 0 )
								? true : false;
						bool bShift =
							( (::GetAsyncKeyState(VK_SHIFT)&0x8000) != 0 )
								? true : false;
						if( !( bAlt || bCtrl || bShift ) )
						{
							CRect rcItem = pTBB->Rect();
							if( !pSite->OnCmdNodeResizeH(
									nInitialResizingStateH,
									m_hWnd,
									pTBB,
									pNodeC,
									nWidthMin,
									nWidthMax,
									rcItem
									)
								)
								return; // resizing is canceled
							CFrameWnd * pFrame = GetParentFrame();
							if( pFrame != NULL )
							{
								pFrame->RecalcLayout();
								pSite->ActiveItemSet( pTBB, GetSafeHwnd() );
							}
							return;
						} // if( !( bAlt || bCtrl || bShift ) )
					} // if can resize button horizontally
#endif // (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
					pTBB->SetCustomizeActiveItem();
				} // if( bCustomizeMode )
//				CExtCmdItem * pCmdItem =
//					g_CmdManager->CmdGetPtr(
//						g_CmdManager->ProfileNameFromWnd( m_hWnd ),
//						pTBB->GetCmdID()
//						);
//				if( pCmdItem == NULL )
//				{
//					ASSERT( FALSE );
//					return;
//				}
				CExtCustomizeCmdTreeNode * pNodeI =
					pTBB->GetCmdNode( true );
				SendMessage( WM_CANCELMODE );
				CRect rcItem( 0, 0, 1, 1 );

				CExtCustomizeCmdTreeNode * pPopupDropTargetNode =
					pSite->GetPopupDropTargetNode();
				if(		bCustomizeMode
					&&	pTBB->IsAbleToTrackMenu( true )
					&&	pPopupDropTargetNode != pNodeC
					)
				{
					pSite->DropTargetPopupCancel();
					pSite->DropTargetPopupCancel();
					CRect rcBtn = *pTBB;
					ClientToScreen( &rcBtn );
					CPoint ptTrack( point );
					ClientToScreen( &ptTrack );
					DWORD dwTrackFlags = pTBB->OnGetTrackPopupFlags();
					pSite->DropTargetPopupTrack(
						pNodeC,
						rcBtn,
						ptTrack,
						dwTrackFlags
						);
				} // if( bCustomizeMode && pTBB->IsAbleToTrackMenu() ...
				else
					pSite->DropTargetPopupCancel();

				m_pDragSourceTBB = pTBB;
				m_pDragTargetTBB = NULL;
				m_nDragTargetShift = 0;
				m_bHelperSeparatorAction = false;
				_InvalidateButton( nBtnDragSrc );
				UpdateWindow();
				pSite->DoDragCmdNode( this, pNodeI, pNodeC, rcItem );
				m_pDragSourceTBB = NULL;
				m_pDragTargetTBB = NULL;
				m_nDragTargetShift = 0;
				m_bHelperSeparatorAction = false;
				return;
			} // if( bAlt || bCustomizeMode )
		} // if( pNodeC != NULL )
	} // if( pSite != NULL )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

	// update the button before checking for disabled status
	_UpdateButton(m_nBtnIdxCapture);

	if( pTBB->IsDisabled()
		|| m_nBtnIdxMenuTracking == m_nBtnIdxCapture
		)
	{
		m_nBtnIdxCapture = -1;
		return;     // don't press it
	}

	pTBB->ModifyStyle( TBBS_PRESSED );
	pTBB->OnPressedTrackingStart();
	_InvalidateButton( m_nBtnIdxCapture );
	UpdateWindow(); // immediate feedback

CWnd * pCtrlTBB = pTBB->CtrlGet();
	pTBB->OnClick( point, true );
	
	if( !g_bMenuTracking )
	{
		if( pCtrlTBB == NULL
			|| (pCtrlTBB->GetStyle() & WS_VISIBLE) == 0
			)
			CExtMouseCaptureSink::SetCapture( GetSafeHwnd() );
		else
			m_nBtnIdxCapture = -1;
	}
	else
		m_nBtnIdxCapture = -1;
}

bool CExtToolControlBar::_OnMouseMoveMsg(UINT nFlags, CPoint point)
{
	if( CExtPopupMenuWnd::IsMenuTracking()
		&& !CExtToolControlBar::g_bMenuTracking
		)
		return true;
	if( IsFloating()
		&& CExtMiniDockFrameWnd::g_bAutoMakeTopmostOnMouseEvent
		)
	{
		CFrameWnd * pParentFrame = GetParentFrame();
		if( pParentFrame != NULL )
			pParentFrame->BringWindowToTop();
	}
    if( m_bRowResizing || m_bRowRecalcing || m_bDragging )
		return CExtControlBar::_OnMouseMoveMsg(nFlags, point);;
	if( m_nBtnIdxCapture >= 0 )
	{
		CExtBarButton* pTBB =
			_GetButtonPtr(m_nBtnIdxCapture);
		ASSERT_VALID( pTBB );
		ASSERT(!(pTBB->IsSeparator()));

		UINT nNewStyle = ( pTBB->GetStyle() & (~TBBS_PRESSED) );
		int nBtnIdxCapture = m_nBtnIdxCapture;
		if( CExtMouseCaptureSink::GetCapture() != m_hWnd )
		{
			m_nBtnIdxCapture = -1; // lost capture
		}
		else
		{
			// should be pressed if still hitting the captured button
			if( HitTest(point) == m_nBtnIdxCapture )
				nNewStyle |= TBBS_PRESSED;
		}
//		if( (nNewStyle & TBBS_PRESSED) == 0 )
//			pTBB->OnPressedTrackingStop();
//		else
//			pTBB->OnPressedTrackingStart();
		SetButtonStyle( nBtnIdxCapture, nNewStyle );
		UpdateWindow(); // immediate feedback
		return true;
	} // if( m_nBtnIdxCapture >= 0 )

bool bHoverChanged =
		_UpdateHoverButton( point );

	if(		CExtMouseCaptureSink::GetCapture() == GetSafeHwnd()
		&&	m_nBtnIdxHover < 0
		&&	m_nBtnIdxMenuTracking < 0
		&&	m_nBtnIdxCapture < 0
		)
	{
		CPoint ptScreen;
		if( ! ::GetCursorPos(&ptScreen) )
			return false;
		HWND hWnd = ::WindowFromPoint(ptScreen);
		if( hWnd != m_hWnd )
			CExtMouseCaptureSink::ReleaseCapture();
	}
	if( bHoverChanged )
		return true;

	return CExtControlBar::_OnMouseMoveMsg(nFlags,point);
}

bool CExtToolControlBar::_UpdateHoverButton(
	CPoint point // = CPoint(-1,-1) // default is use ::GetCursorPos()
	)
{
	if( point.x < 0 || point.y < 0 )
	{
		if( ! ::GetCursorPos(&point) )
			return false;
		ScreenToClient( &point );
	}

bool bHoverChanged = false;
int nBtnIdxHoverNew =
		(	CExtPopupMenuWnd::TestHoverEnabledFromActiveHWND( GetSafeHwnd() )
			|| CExtPopupMenuWnd::IsMenuTracking()
		) ? HitTest(point) : (-1);

int nBtnIdxHoverOld =  m_nBtnIdxHover;
	if( nBtnIdxHoverOld != nBtnIdxHoverNew )
	{
		bHoverChanged = true;
		m_nBtnIdxHover = -1;
		if( nBtnIdxHoverOld >= 0 )
		{
			CExtBarButton * pTBB =
				_GetButtonPtr(nBtnIdxHoverOld);
			ASSERT_VALID( pTBB );
			pTBB->SetHover( false );
			_InvalidateButton( nBtnIdxHoverOld );
			UpdateWindow();
			pTBB->OnHover( point, false );
		}
		if(		CExtControlBar::FindHelpMode(this)
			&&	nBtnIdxHoverNew >= 0
			)
		{
			CExtBarButton * pTBB = _GetButtonPtr(nBtnIdxHoverNew);
			if(		pTBB->IsAbleToTrackMenu()
				&&	pTBB->OnHelpHitTest(point) == -3
				)
				m_nBtnIdxHover = nBtnIdxHoverNew;
		}
		else
			m_nBtnIdxHover = nBtnIdxHoverNew;
		if( m_nBtnIdxHover >= 0 )
		{
			CExtBarButton * pTBB =
				_GetButtonPtr(m_nBtnIdxHover);
			ASSERT_VALID( pTBB );
			bool bEnableHoverOnNewBtn = true;
			if( pTBB->IsKindOf(RUNTIME_CLASS(CExtBarMdiRightButton))
				|| pTBB->IsDisabled()
				)
			{
				if( g_bMenuTracking )
					bEnableHoverOnNewBtn = false;
			}
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
			if( bEnableHoverOnNewBtn )
			{
				CExtCustomizeSite * pSite =
					GetCustomizeSite();
				if(		pSite != NULL
					&&	(	pSite->IsCustomizeMode()
						||	pSite->GetPopupDropTargetNode() != NULL
						||	pSite->DraggedNodeGet() != NULL
						)
					)
					bEnableHoverOnNewBtn = false;
			} // if( bEnableHoverOnNewBtn )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
			if( bEnableHoverOnNewBtn )
			{
				pTBB->SetHover();
				_InvalidateButton( m_nBtnIdxHover );
				UpdateWindow();
				pTBB->OnHover( point, true );
			}
		}
	} // if( nBtnIdxHoverOld != nBtnIdxHoverNew )
	return bHoverChanged;
}

void CExtToolControlBar::OnLButtonUp(UINT nFlags, CPoint point)
{
	if( (m_nBtnIdxCapture < 0 && m_nBtnIdxHover < 0)
		|| m_bRowResizing || m_bRowRecalcing || m_bDragging )
	{
		CExtControlBar::OnLButtonUp(nFlags, point);
		return;     // not captured
	}

int nBtnIdxHover = m_nBtnIdxHover;
int nBtnIdxCapture = m_nBtnIdxCapture;

CExtBarButton * pHoverTBB = NULL;
	if( m_nBtnIdxHover >= 0 )
	{
		pHoverTBB =
			_GetButtonPtr( m_nBtnIdxHover );
		ASSERT_VALID( pHoverTBB );
		m_nBtnIdxHover = -1;
	} // if( m_nBtnIdxHover >= 0 )

	if( m_nBtnIdxCapture >= 0 )
	{
		CExtBarButton * pTempTBB = _GetButtonPtr( nBtnIdxCapture );
		ASSERT_VALID( pTempTBB );
		ASSERT( !(pTempTBB->IsSeparator()) );
		if( pTempTBB->IsPressedTracking() )
		{
			pTempTBB->OnPressedTrackingStop();
			_InvalidateButton( m_nBtnIdxCapture );
		}
		m_nBtnIdxCapture = -1;
		CExtBarButton * pCaptureTBB = NULL;
		UINT nNewStyle = 0;
		if( nBtnIdxCapture == HitTest(point) )
		{
			pCaptureTBB = pTempTBB;
			nNewStyle = ( pCaptureTBB->GetStyle() & ~TBBS_PRESSED );
			// give button a chance to update
			_UpdateButton( nBtnIdxCapture );
			// then check for disabled state
			if( !(pCaptureTBB->IsDisabled()) )
			{
				if( pCaptureTBB->GetStyle() & TBBS_CHECKBOX )
				{
					// auto check: three state => down
					if( nNewStyle & TBBS_INDETERMINATE )
						nNewStyle &= ~TBBS_INDETERMINATE;
					nNewStyle ^= TBBS_CHECKED;
				}
			} // if( !(pCaptureTBB->IsDisabled()) )
		} // if( nBtnIdxCapture == HitTest(point) )
		CExtMouseCaptureSink::ReleaseCapture();

		if( pCaptureTBB != NULL )
			pCaptureTBB->OnClick( point, false );

		if( !(::IsWindow(GetSafeHwnd())) )
			return;
		if( !g_bMenuTracking )
		{
			SetButtonStyle( nBtnIdxCapture, nNewStyle );
			_UpdateButton( nBtnIdxCapture );
		} // if( bUpdateBtnState )
	} // if( m_nBtnIdxCapture >= 0 )

	if( pHoverTBB != NULL )
	{
		ASSERT_VALID( pHoverTBB );
		pHoverTBB->SetHover( false );
		pHoverTBB->OnHover( point, false );
		_InvalidateButton( nBtnIdxHover );
	} // if( pHoverTBB != NULL )

	UpdateWindow(); // immediate feedback
}

void CExtToolControlBar::OnRButtonUp(UINT nFlags, CPoint point)
{
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	if( _IsDockSiteCustomizeMode() )
	{
		CExtCustomizeSite * pSite = GetCustomizeSite();
		if( pSite != NULL )
		{
			ASSERT( pSite->IsCustomizeMode() );
			INT nButton = HitTest( point );
			if( nButton < 0 )
				return;
			CExtBarButton * pTBB = _GetButtonPtr( nButton );
			ASSERT_VALID( pTBB );
			if(		pTBB->IsSeparator()
				||	pTBB->IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton))
				||	pTBB->IsKindOf(RUNTIME_CLASS(CExtBarMdiDocButton))
				||	pTBB->IsKindOf(RUNTIME_CLASS(CExtBarMdiRightButton))
				)
				return;
			CExtCustomizeCmdTreeNode * pNodeC = pTBB->GetCmdNode( false );
			if( pNodeC == NULL )
				return;
			ASSERT_VALID( pNodeC );
			CExtCustomizeCmdTreeNode * pNodeI = pTBB->GetCmdNode( true );
#ifdef _DEBUG
			if( pNodeI != NULL )
			{
				ASSERT_VALID( pNodeI );
			}
#endif // _DEBUG
			pSite->DropTargetPopupCancel();
			pTBB->SetCustomizeActiveItem();
			CExtCmdItem * pCmdItem =
				g_CmdManager->CmdGetPtr(
					g_CmdManager->ProfileNameFromWnd(m_hWnd),
					pTBB->GetCmdID( false )
					);
			ASSERT( pCmdItem != NULL );
			if( !pSite->CustomizedNodeSet( pNodeC ) )
				return;
			Invalidate();
			UpdateWindow();
			bool bCanAddRemoveSeparator = false;
			if(		nButton > 0
				&&	(! _GetButtonPtr(nButton-1)->IsKindOf(RUNTIME_CLASS(CExtBarMdiDocButton)) )
				)
				bCanAddRemoveSeparator = true;
			bool bDelete = false;
			if( !pSite->OnCustomizeTreeNode(
					pNodeI,
					pNodeC,
					pCmdItem,
					bDelete,
					bCanAddRemoveSeparator,
					this
					)
				)
			{
				VERIFY( pSite->CustomizedNodeSet( NULL ) );
				Invalidate();
				UpdateWindow();
				return;
			}
			VERIFY( pSite->CustomizedNodeSet( NULL ) );
			if( bDelete )
			{
				pNodeC->RemoveSelf( pCmdItem );
				RemoveButton( nButton );
				if(		nButton > 0
					&&	_GetButtonPtr(nButton-1)->IsSeparator()
					)
					RemoveButton( nButton-1 );
				if(		nButton < (GetButtonsCount()-1)
					&&	_GetButtonPtr(nButton)->IsSeparator()
					)
				{
					RemoveButton( nButton );
					CExtBarButton * pTBB = _GetButtonPtr(nButton);
					ASSERT_VALID( pTBB );
					CExtCustomizeCmdTreeNode * pNodeNext = pTBB->GetCmdNode( false );
					ASSERT_VALID( pNodeNext );
					pNodeNext->ModifyFlags( 0, __ECTN_GROUP_START );
				}
			} // if( bDelete )
			else
			{
				if( pNodeC->GetFlags() & __ECTN_GROUP_START )
				{
					if(		nButton > 0
						&&	(! _GetButtonPtr(nButton-1)->IsSeparator() )
						)
						InsertButton( nButton, ID_SEPARATOR, FALSE );
				} // if( pNodeC->GetFlags() & __ECTN_GROUP_START )
				else
				{
					if(		nButton > 0
						&&	_GetButtonPtr(nButton-1)->IsSeparator()
						)
						RemoveButton( nButton-1, FALSE );
				} // else from if( pNodeC->GetFlags() & __ECTN_GROUP_START )
			} // else from if( bDelete )
			if( IsKindOf(RUNTIME_CLASS(CExtMenuControlBar)) )
				((CExtMenuControlBar*)this)->UpdateMenuBar();
			if( m_pDockSite == NULL )
			{
				_RecalcPositionsImpl();
				Invalidate();
				UpdateWindow();
				return;
			} // if( m_pDockSite == NULL )
			ASSERT_VALID( m_pDockSite );
			if( IsFloating() )
			{
				_RecalcLayoutImpl();
				Invalidate();
				UpdateWindow();
			}
			else
				m_pDockSite->RecalcLayout();
			return;
		} // if( pSite != NULL )
	} // if( _IsDockSiteCustomizeMode() )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	CExtControlBar::OnRButtonUp(nFlags,point);
}

void CExtToolControlBar::OnLButtonDblClk(UINT nFlags, CPoint point)
{
    if( m_bRowResizing || m_bRowRecalcing || m_bDragging )
	{
		CExtControlBar::OnLButtonDblClk(nFlags, point);
		return;
	}
int nBtnIdx = _HitTestImpl(point);
	if( nBtnIdx >= 0 )
		return;
	CExtControlBar::OnLButtonDblClk(nFlags,point);
}

void CExtToolControlBar::OnCancelMode()
{
	CExtControlBar::OnCancelMode();

//	ASSERT( !CExtPopupMenuWnd::IsMenuTracking() );

bool bUpdateState = false;
	if( m_nBtnIdxCapture >= 0 )
	{
		CExtBarButton* pTBB =
			_GetButtonPtr(m_nBtnIdxCapture);
		ASSERT_VALID( pTBB );
		ASSERT( !(pTBB->IsSeparator()) );

		if( m_nBtnIdxMenuTracking != m_nBtnIdxCapture )
		{
			UINT nNewStyle = (pTBB->GetStyle() & ~TBBS_PRESSED);
			SetButtonStyle(m_nBtnIdxCapture, nNewStyle);
		}
		pTBB->OnPressedTrackingStop();

		m_nBtnIdxCapture = -1;
		bUpdateState = true;
	}
	if( m_nBtnIdxHover >= 0 )
	{
		CExtBarButton * pTBB =
			_GetButtonPtr(m_nBtnIdxHover);
		ASSERT_VALID( pTBB );
		pTBB->SetHover( false );
		m_nBtnIdxHover = -1;
		bUpdateState = true;
		CPoint point( 0, 0 );
		::GetCursorPos( &point );
		ScreenToClient( &point );
		pTBB->OnHover( point, false );
	}

	if( bUpdateState )
	{
		if( CExtMouseCaptureSink::GetCapture() == GetSafeHwnd() )
			CExtMouseCaptureSink::ReleaseCapture();
		Invalidate();
		UpdateWindow();
	}
}

void CExtToolControlBar::OnSettingChange(UINT uFlags, __EXT_MFC_SAFE_LPCTSTR lpszSection)
{
	CExtControlBar::OnSettingChange(uFlags,lpszSection);

	if( m_bPresubclassDialogMode )
	{
		_RecalcLayoutImpl();
		return;
	}

CFrameWnd* pFrame = GetParentFrame();
	ASSERT_VALID(pFrame);
	pFrame->DelayRecalcLayout();
}

bool CExtToolControlBar::IsRightExpandButton( int nBtnIdx )
{
CExtBarButton * pTBB =
		_GetButtonPtr( nBtnIdx );
	if( pTBB == NULL )
		return false;
	ASSERT_VALID( pTBB );
	if( pTBB->IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton)) )
		return true;
	return false;
}

void CExtToolControlBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
{
CWnd * pTargetUpdateWnd = pTarget;
	if( !m_bPresubclassDialogMode )
	{
		CExtControlBar::OnUpdateCmdUI(pTarget, bDisableIfNoHndler);

		//if( CExtPopupMenuWnd::IsMenuTracking() )
		//	return;
		if( _DraggingGetBar() != NULL )
			return;
	} // if( !m_bPresubclassDialogMode )
	else
	{
		if( pTargetUpdateWnd != NULL 
			&& pTargetUpdateWnd->IsKindOf( RUNTIME_CLASS(CFrameWnd) )
			)
			return;
		//ASSERT( pTargetUpdateWnd == NULL );
//		if( pTargetUpdateWnd == NULL )
			pTargetUpdateWnd = GetOwner();
		if( pTargetUpdateWnd == NULL )
			pTargetUpdateWnd = GetParent();
		ASSERT( pTargetUpdateWnd != NULL );
	}

	if( pTargetUpdateWnd == NULL )
		return;

	ASSERT_VALID( pTargetUpdateWnd );

	if( (GetStyle() & WS_VISIBLE) == 0 )
		return;

int nCountOfButtons = _GetButtonsCountImpl();
	for( int nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
	{
		CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
		ASSERT_VALID( pTBB );
		pTBB->OnUpdateCmdUI(
			pTargetUpdateWnd,
			bDisableIfNoHndler,
			nBtnIdx
			);
	}

	// update the dialog controls added to the toolbar
	UpdateDialogControls(pTargetUpdateWnd, bDisableIfNoHndler);
}

void CExtToolControlBar::_UpdateButton(int nIndex)
{
CWnd * pTarget = GetOwner();
	if( pTarget == NULL && (!m_bPresubclassDialogMode) )
		pTarget = GetParentFrame();

	if( pTarget == NULL )
		return;
BOOL bDisableIfNoHandler = TRUE;
	if( pTarget->IsKindOf( RUNTIME_CLASS(CFrameWnd) ) )
		bDisableIfNoHandler = ((CFrameWnd *)pTarget)->m_bAutoMenuEnable;

CExtBarButton * pTBB =
		_GetButtonPtr(nIndex);
	ASSERT_VALID( pTBB );
	pTBB->OnUpdateCmdUI(
		pTarget,
		bDisableIfNoHandler,
		nIndex
		);
}

/////////////////////////////////////////////////////////////////////////////
// CExtToolControlBar diagnostics

#ifdef _DEBUG
void CExtToolControlBar::AssertValid() const
{
	CExtControlBar::AssertValid();
}

void CExtToolControlBar::Dump(CDumpContext& dc) const
{
	CExtControlBar::Dump(dc);
}
#endif

// input CRect should be client rectangle size
void CExtToolControlBar::_CalcInsideRect(CRect& rect, BOOL bHorz) const
{
	ASSERT_VALID(this);
	CControlBar::CalcInsideRect(rect,bHorz);
}

void CExtToolControlBar::_RecalcPositionsImpl()
{
	if( GetSafeHwnd() == NULL
		|| !::IsWindow( GetSafeHwnd() )
		)
		return;
	ASSERT_VALID(this);

int nCountOfButtons = _GetButtonsCountImpl();
	if( nCountOfButtons == 0 )
		return;

CExtBarButton::e_wrap_t _evt = GetBtnWrapCode();
BOOL bHorz = (m_dwStyle & CBRS_ORIENT_HORZ) ? TRUE : FALSE;
BOOL bFloating = IsFloating();
bool bMultiRowLayout = OnQueryMultiRowLayout();

CRect rcInner;
	GetClientRect( &rcInner );
	//rcInner.DeflateRect( __EXT_TB_BUTTON_INNER_MARGIN, __EXT_TB_BUTTON_INNER_MARGIN );
	rcInner.DeflateRect(
		m_cxLeftBorder,
		m_cyTopBorder,
		m_cxRightBorder,
		m_cyBottomBorder
		);
CPoint ptLimitTL = rcInner.TopLeft();
CPoint ptLimitBR = rcInner.BottomRight();

CClientDC dc(this);
CFont* pOldFont =
		dc.SelectObject(
			OnGetToolbarFont(
				( ( ( m_dwStyle & CBRS_ORIENT_HORZ ) == 0 ) && (!m_bPaletteMode) )
					? true : false
				)
			);
	ASSERT( pOldFont != NULL );

CSize sizeDefButton = _GetDefButtonSize();
int nReviewCount = nCountOfButtons;
CSize sizeTBBRight( 0, 0 );
	if( m_pRightBtn != NULL )
	{
		nReviewCount--;
		ASSERT_VALID( m_pRightBtn );
		ASSERT( m_buttons.GetSize() > 0 );
		ASSERT( m_buttons[nReviewCount] == m_pRightBtn );
		m_pRightBtn->GetButtons().RemoveAll();
		m_pRightBtn->ClearContent();
		sizeTBBRight =
			m_pRightBtn->CalculateLayout(
				dc,
				sizeDefButton,
				bHorz || m_bPaletteMode
				);
		if( bFloating || m_bPaletteMode )
		{
			m_pRightBtn->Show( false );
			m_pRightBtn->SetRect(
				CRect( ptLimitTL, sizeTBBRight )
				);
			if( nReviewCount == 0 )
				return;
		} // if( bFloating || m_bPaletteMode )
		else
		{
			CRect rcCalcRightBtn(
				bHorz ? (ptLimitBR.x - sizeTBBRight.cx) : ptLimitTL.x,
				bHorz ? ptLimitTL.y : (ptLimitBR.y - sizeTBBRight.cy),
				ptLimitBR.x,
				ptLimitBR.y
				);
			m_pRightBtn->SetRect( rcCalcRightBtn );
			m_pRightBtn->Show( true );
			CSize sizeRounders =
				g_PaintManager->GetToolBarRgnRoundersSize();
			if( bHorz )
				rcInner.right -=
					sizeTBBRight.cx
					+ __EXT_TB_BUTTON_INNER_MARGIN
					+ sizeRounders.cx
					;
			else
				rcInner.bottom -=
					sizeTBBRight.cy
					+ __EXT_TB_BUTTON_INNER_MARGIN
					+ sizeRounders.cy
					;
		} // else from if( bFloating || m_bPaletteMode )
	} // if( m_pRightBtn != NULL )

CArray < CRect, CRect >	arrBtnRects;
CArray < BOOL, BOOL >	arrBtnVisibility;
CArray < BOOL, BOOL >	arrBtnSeparators;
//CArray < BOOL, BOOL >	arrBtnEnabled;
	arrBtnRects.SetSize( nReviewCount );
	arrBtnVisibility.SetSize( nReviewCount );
	arrBtnSeparators.SetSize( nReviewCount );
//	arrBtnEnabled.SetSize( nReviewCount );
CSize sizeLastWrappedRow( 0, 0 );
bool bDockerTrasparentMode =
		g_PaintManager->GetCb2DbTransparentMode( this );
	if( (!bFloating) && bMultiRowLayout )
	{
		if( bHorz && bDockerTrasparentMode )
			ptLimitTL.y += 1;
		else if( !bHorz )
		{
			if( bDockerTrasparentMode )
				ptLimitBR.x -= 2;
			else
				ptLimitBR.x -= 1;
			ptLimitTL.y -= 1;
		}
	} // if( (!bFloating) && bMultiRowLayout )
CPoint ptBtnPosCurr( ptLimitTL );
INT nRowExtent = sizeDefButton.cy;
	if( bMultiRowLayout && (!bHorz) )
	{
		ptBtnPosCurr.x = ptLimitBR.x;
		nRowExtent = sizeDefButton.cx;
	}
BOOL bSeparatorPrev = FALSE, bPostResyncAllowed = FALSE;
INT nRowDistance = g_PaintManager->FixedBar_GetRowDistance( this );
	for( int nBtnIdx = 0; nBtnIdx < nReviewCount; nBtnIdx++ )
	{
		CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
		ASSERT_VALID( pTBB );
		BOOL bVisibleTBB =
			( pTBB->GetStyle() & TBBS_HIDDEN ) ? FALSE : TRUE;
		if(		pTBB->IsSeparator()
			&&	nBtnIdx < (nReviewCount-1)
			)
		{
			CExtBarButton * pNextTBB = _GetButtonPtr( nBtnIdx+1 );
			ASSERT_VALID( pNextTBB );
			if( pNextTBB->GetStyle() & TBBS_HIDDEN )
				bVisibleTBB = FALSE;
		}
		arrBtnVisibility.SetAt( nBtnIdx, bVisibleTBB );
		if( !bVisibleTBB )
			continue;
		pTBB->SetVertDocked( (bHorz || m_bPaletteMode) ? false : true );
//		arrBtnEnabled.SetAt( nBtnIdx, pTBB->IsEnabled() );
		BOOL bSeparator = pTBB->IsSeparator();
		arrBtnSeparators.SetAt( nBtnIdx, bSeparator );
		if( (bSeparatorPrev && bSeparator) || (bSeparator && nBtnIdx == 0) )
		{ // remove double separators
			arrBtnVisibility.SetAt( nBtnIdx, FALSE );
			continue;
		} // remove double separators

		CSize sizeTBB =
			pTBB->CalculateLayout(
				dc,
				sizeDefButton,
				bHorz || m_bPaletteMode
				);
		
		CRect rcTBB( ptBtnPosCurr, sizeTBB );
		if( bMultiRowLayout && (!bHorz) )
			nRowExtent = max( nRowExtent, sizeTBB.cx );
		else
			nRowExtent = max( nRowExtent, sizeTBB.cy );

		if( (bFloating || bMultiRowLayout || m_bPaletteMode)
				&& pTBB->IsWrap(_evt)
			)
		{
			if( bMultiRowLayout && (!bHorz) )
			{
				ptBtnPosCurr.y = ptLimitTL.y;
				ptBtnPosCurr.x -=
					nRowExtent
					+ nRowDistance;
				sizeLastWrappedRow = CSize( 0, 0 );
				nRowExtent = sizeDefButton.cx;
			} // if( bMultiRowLayout && (!bHorz) )
			else
			{
				ptBtnPosCurr.x = ptLimitTL.x;
				ptBtnPosCurr.y +=
					nRowExtent // sizeDefButton.cy (+ v.2.22)
					+ nRowDistance;
				sizeLastWrappedRow = CSize( 0, 0 );
				nRowExtent = sizeDefButton.cy;
			} // else from if( bMultiRowLayout && (!bHorz) )
		} // if( (bFloating || ...
		else
		{
			bool bResyncVisibleTBB = false;
			if( bHorz || m_bPaletteMode )
			{
				ptBtnPosCurr.x += sizeTBB.cx;
				if(		(!bMultiRowLayout)
					&&	ptBtnPosCurr.x > rcInner.right
					)
					bResyncVisibleTBB = true;
			} // if( bHorz || m_bPaletteMode )
			else
			{
				ptBtnPosCurr.y += sizeTBB.cy;
				if(		(!bMultiRowLayout)
					&&	ptBtnPosCurr.y > rcInner.bottom
					)
					bResyncVisibleTBB = true;
			} // else from if( bHorz || m_bPaletteMode )
			if( bResyncVisibleTBB )
			{
				int nSpaceToFind =
					( bHorz || m_bPaletteMode )
						? ptBtnPosCurr.x - rcInner.right
						: ptBtnPosCurr.y - rcInner.bottom;
				int nBtnWithNearestWidth = nBtnIdx;
				int nNearestMetric =
					( bHorz || m_bPaletteMode )
						? rcTBB.Width() : rcTBB.Height();
				int nNearestDiff = nSpaceToFind - nNearestMetric;
				// hide nearest by size reviewed visible
				for( int nBtnIdx2 = nBtnIdx-1; nBtnIdx2 >= 0; nBtnIdx2-- )
				{
					if( !arrBtnVisibility[nBtnIdx2] )
						continue;
					if( arrBtnSeparators[nBtnIdx2] )
						continue;

#ifdef _DEBUG
					CExtBarButton * pTBB2 =
						_GetButtonPtr( nBtnIdx2 );
					ASSERT( (pTBB2->GetStyle() & TBBS_HIDDEN) == 0 );
#endif // _DEBUG

					int nMetric =
						( bHorz || m_bPaletteMode )
							? arrBtnRects[nBtnIdx2].Width()
							: arrBtnRects[nBtnIdx2].Height();
					//if( nMetric <= nNearestMetric ) // <<-- widest search algorithm
					//	continue;
					if( nMetric > nSpaceToFind )
						continue;
					int nDiff = nSpaceToFind - nMetric;
//					if( !arrBtnEnabled[nBtnIdx2] )
//					{ // hide disabled buttons first
//						nNearestDiff = nDiff;
//						nNearestMetric = nMetric;
//						nBtnWithNearestWidth = nBtnIdx2;
//						break;
//					} // hide disabled buttons first
					if( nDiff >= nNearestDiff )
						continue;
					nNearestDiff = nDiff;
					nNearestMetric = nMetric;
					nBtnWithNearestWidth = nBtnIdx2;
				} // for( int nBtnIdx2 = nBtnIdx-1; nBtnIdx2 >= 0; nBtnIdx2-- )
				if( nBtnWithNearestWidth < nBtnIdx )
				{
					ASSERT( bVisibleTBB );
					arrBtnVisibility.SetAt( nBtnWithNearestWidth, FALSE );
					if( (!m_bPaletteMode) && (!bMultiRowLayout) && (!IsFloating()) )
						bPostResyncAllowed = TRUE;
					if( m_pRightBtn!=NULL && !arrBtnSeparators[nBtnWithNearestWidth] )
					{
						CExtBarButton * pTBB2 =
							_GetButtonPtr( nBtnWithNearestWidth );
						ASSERT_VALID( pTBB2 );
						m_pRightBtn->GetButtons().Add( pTBB2 );
					}
					if( nBtnWithNearestWidth > 0 && nBtnWithNearestWidth < nReviewCount-1 )
					{ // remove double separators
						if(		arrBtnSeparators[nBtnWithNearestWidth-1]
							&&	arrBtnSeparators[nBtnWithNearestWidth+1]
							)
						{
							arrBtnVisibility.SetAt( nBtnWithNearestWidth-1, FALSE );
							nNearestMetric +=
								( bHorz || m_bPaletteMode )
									? arrBtnRects[nBtnWithNearestWidth-1].Width()
									: arrBtnRects[nBtnWithNearestWidth-1].Height();
						}
					} // remove double separators
					rcTBB.OffsetRect(
						( bHorz || m_bPaletteMode ) ? -nNearestMetric : 0,
						( bHorz || m_bPaletteMode ) ? 0 : -nNearestMetric
						);
					( ( bHorz || m_bPaletteMode ) ? ptBtnPosCurr.x : ptBtnPosCurr.y) -= nNearestMetric;
					for( nBtnIdx2 = nBtnWithNearestWidth+1; nBtnIdx2 < nBtnIdx; nBtnIdx2++ )
					{
						if( !arrBtnVisibility[nBtnIdx2] )
							continue;
						CRect rcTBB2 = arrBtnRects[nBtnIdx2];
						rcTBB2.OffsetRect(
							( bHorz || m_bPaletteMode ) ? -nNearestMetric : 0,
							( bHorz || m_bPaletteMode ) ? 0 : -nNearestMetric
							);
						arrBtnRects.SetAt( nBtnIdx2, rcTBB2 );
					} // for( nBtnIdx2 = nBtnWithNearestWidth+1; nBtnIdx2 < nBtnIdx; nBtnIdx2++ )
				} // if( nBtnWithNearestWidth < nBtnIdx )
				else
				{
					ASSERT( nBtnWithNearestWidth == nBtnIdx );
					bVisibleTBB = FALSE;
					if( (!m_bPaletteMode) && (!bMultiRowLayout) && (!IsFloating()) )
						bPostResyncAllowed = TRUE;
					( (bHorz || m_bPaletteMode ) ? ptBtnPosCurr.x : ptBtnPosCurr.y) -=
						( (bHorz || m_bPaletteMode ) ? sizeTBB.cx : sizeTBB.cy);
				} // else from if( nBtnWithNearestWidth < nBtnIdx )
			} // if( bResyncVisibleTBB )
		} // else from if( (bFloating || ...

		arrBtnVisibility.SetAt( nBtnIdx, bVisibleTBB );
		if( bMultiRowLayout && (!bHorz) )
		{
			CRect rcTBB2( rcTBB );
			rcTBB2.OffsetRect( -rcTBB.Width(), 0 );
			arrBtnRects.SetAt( nBtnIdx, rcTBB2 );
		}
		else
			arrBtnRects.SetAt( nBtnIdx, rcTBB );
		if( bVisibleTBB )
			bSeparatorPrev = bSeparator;

		if(		m_pRightBtn != NULL
			&&	(!bMultiRowLayout)
			&&	(!bVisibleTBB)
			&&	(!bSeparator)
			)
			m_pRightBtn->GetButtons().Add( pTBB );
	} // for( int nBtnIdx = 0; nBtnIdx < nReviewCount; nBtnIdx++ )

	dc.SelectObject( pOldFont );

	if( bPostResyncAllowed )
	{
		ASSERT( !IsFloating() );
		ASSERT( !m_bPaletteMode );
		ASSERT( !bMultiRowLayout );
		INT nVisIdx0 = -1, nVisIdx1 = -1;
		for( nBtnIdx = 0; nBtnIdx < nReviewCount; nBtnIdx++ )
		{
			if( ! arrBtnVisibility[nBtnIdx] )
				continue;
			CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
			ASSERT_VALID( pTBB );
			if( pTBB->IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton)) )
				break;
			if( nVisIdx0 < 0 )
				nVisIdx0 = nBtnIdx;
			nVisIdx1 = nBtnIdx;
		} // for( nBtnIdx = 0; nBtnIdx < nReviewCount; nBtnIdx++ )
		if( nVisIdx0 >= 0 )
		{
			ASSERT( nVisIdx1 >= nVisIdx0 );
			INT nShiftMetric = 0;
			for( ; nVisIdx0 <= nVisIdx1; nVisIdx0++ )
			{
				if( ! arrBtnVisibility[nVisIdx0] )
					break;
				CExtBarButton * pTBB = _GetButtonPtr( nVisIdx0 );
				ASSERT_VALID( pTBB );
				ASSERT( !pTBB->IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton)) );
				if( !pTBB->IsSeparator() )
					break;
				arrBtnVisibility[nVisIdx0] = FALSE;
				if( bHorz )
					nShiftMetric -= arrBtnRects[nVisIdx0].Width();
				else
					nShiftMetric -= arrBtnRects[nVisIdx0].Height();
			}
			for( ; nVisIdx1 >= nVisIdx0; nVisIdx1-- )
			{
				if( ! arrBtnVisibility[nVisIdx1] )
					break;
				CExtBarButton * pTBB = _GetButtonPtr( nVisIdx1 );
				ASSERT_VALID( pTBB );
				ASSERT( !pTBB->IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton)) );
				if( !pTBB->IsSeparator() )
					break;
				arrBtnVisibility[nVisIdx1] = FALSE;
			}
			if( nShiftMetric != 0 )
			{
				for( nBtnIdx = 0; nBtnIdx < nReviewCount; nBtnIdx++ )
				{
					if( ! arrBtnVisibility[nBtnIdx] )
						continue;
					CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
					ASSERT_VALID( pTBB );
					if( pTBB->IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton)) )
						break;
					arrBtnRects.ElementAt( nBtnIdx ).OffsetRect(
						bHorz ? nShiftMetric : 0,
						bHorz ? 0 : nShiftMetric
						);
				} // for( nBtnIdx = 0; nBtnIdx < nReviewCount; nBtnIdx++ )
			} // if( nShiftMetric != 0 )
		} // if( nVisIdx0 >= 0 )
	} // if( bPostResyncAllowed )

INT nRowStart = 0;
INT nSizeRow = 0;
int nSubRowCount = 0;
bool bReAlignHorz =
		(	bHorz
		||	bFloating
		||	m_bPaletteMode
		) ? true : false;
	if( bMultiRowLayout && (!bHorz) )
		bReAlignHorz = false;
	for( nBtnIdx = 0; nBtnIdx < nReviewCount; nBtnIdx++ )
	{
		CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
		ASSERT_VALID( pTBB );
		//BOOL bVis = arrBtnVisibility[nBtnIdx];
		//if( bVis )
		//{
			CSize sizeTBB = *pTBB; // arrBtnRects[nBtnIdx].Size();
			INT nSizeBtn = bReAlignHorz ? sizeTBB.cy : sizeTBB.cx;
			nSizeRow = max( nSizeRow, nSizeBtn );
		//} // if( bVis )
		if(	( (bFloating || bMultiRowLayout || m_bPaletteMode ) && pTBB->IsWrap(_evt) )
			|| nBtnIdx == nReviewCount-1
			)
		{
			for( INT nBtnIdx2 = nRowStart; nBtnIdx2 <= nBtnIdx; nBtnIdx2++ )
			{
				CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx2 );
				ASSERT_VALID( pTBB );
				BOOL bVis = arrBtnVisibility[nBtnIdx2];
				pTBB->Show( bVis ? true : false );
				if( !bVis )
					continue;
				CRect rcBtn = arrBtnRects[nBtnIdx2];
				if( pTBB->IsSeparator() )
				{
					if( bReAlignHorz )
						rcBtn.bottom = rcBtn.top + nSizeRow;
					else
						rcBtn.left = rcBtn.right - nSizeRow;
				} // if( pTBB->IsSeparator() )
				else
				{
					if( bReAlignHorz )
						rcBtn.OffsetRect(
							0,
							( nSizeRow - rcBtn.Height() ) / 2
							);
					else 
						rcBtn.OffsetRect(
							- ( nSizeRow - rcBtn.Width() ) / 2,
							0
							);
				} // else from if( pTBB->IsSeparator() )
				if( bFloating || bMultiRowLayout )
					rcBtn.OffsetRect( 0, 1 );
				pTBB->SetRect( rcBtn );
			}
			nRowStart = nBtnIdx + 1;
			nSizeRow = 0;
			nSubRowCount++;
		}
	} // for( nBtnIdx = 0; nBtnIdx < nReviewCount; nBtnIdx++ )

	if( nSubRowCount == 1 && (!m_bPaletteMode) && (!bFloating) && (!bMultiRowLayout) )
	{
		CRect rcBarClient;
		GetClientRect( &rcBarClient );
		nSizeRow = bHorz
			? rcBarClient.Height()
			: rcBarClient.Width()
			;
		for( nBtnIdx = 0; nBtnIdx < nReviewCount; nBtnIdx++ )
		{
			CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
			ASSERT_VALID( pTBB );
			BOOL bVis = arrBtnVisibility[nBtnIdx];
			if( !bVis )
				continue;
			CRect rcBtn( pTBB->Rect() );
			if( pTBB->IsSeparator() )
			{
				if( bHorz )
				{
					rcBtn.top = m_cyTopBorder;
					rcBtn.bottom = m_cyBottomBorder + nSizeRow;
				} // if( bHorz )
				else
				{
					rcBtn.left = m_cxLeftBorder;
					rcBtn.right = m_cxRightBorder + nSizeRow;
				} // else from if( bHorz )
			} // if( pTBB->IsSeparator() )
			else
			{
				rcBtn.OffsetRect(
					bHorz
						? 0
						: ( ( nSizeRow - rcBtn.Width() ) / 2  - rcBtn.left)
					,
					bHorz
						? ( ( nSizeRow - rcBtn.Height() ) / 2 - rcBtn.top) 
						: 0
					);
			} // else from if( pTBB->IsSeparator() )
			pTBB->SetRect( rcBtn );
		} // for( nBtnIdx = 0; nBtnIdx < nReviewCount; nBtnIdx++ )
	} // if( nSubRowCount == 1 && (!m_bPaletteMode) && (!bFloating) && (!bMultiRowLayout) )
	else if( !m_bPaletteMode )
	{ // just re-align separators in each row
		INT nRowMinLoc = 0, nRowMaxLoc = 0;
		INT nRowStart = 0;
		for( nBtnIdx = 0; nBtnIdx < nReviewCount; nBtnIdx++ )
		{
			CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
			ASSERT_VALID( pTBB );
			if(		pTBB->IsVisible()
				&&	(pTBB->GetStyle() & TBBS_HIDDEN) == 0
				)
			{
				CRect rcTBB = *pTBB;
				if( nBtnIdx == nRowStart )
				{
					if( bHorz )
					{
						nRowMinLoc = rcTBB.top;
						nRowMaxLoc = rcTBB.bottom;
					} // if( bHorz )
					else
					{
						nRowMinLoc = rcTBB.left;
						nRowMaxLoc = rcTBB.right;
					} // else from if( bHorz )
				} // if( nBtnIdx == nRowStart )
				else
				{
					if( bHorz )
					{
						nRowMinLoc = min( nRowMinLoc, rcTBB.top );
						nRowMaxLoc = max( nRowMaxLoc, rcTBB.bottom );
					} // if( bHorz )
					else
					{
						nRowMinLoc = min( nRowMinLoc, rcTBB.left );
						nRowMaxLoc = max( nRowMaxLoc, rcTBB.right );
					} // else from if( bHorz )
				} // else from if( nBtnIdx == nRowStart )
			} // if( pTBB->IsVisible() ...
			if(		(! pTBB->IsWrap(_evt) )
				&&	nBtnIdx != (nReviewCount-1)
				)
				continue;
			for( INT nBtnIdx2 = nRowStart; nBtnIdx2 < nBtnIdx; nBtnIdx2++ )
			{
				CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx2 );
				ASSERT_VALID( pTBB );
				if(		(! pTBB->IsVisible() )
					||	(pTBB->GetStyle() & TBBS_HIDDEN) != 0
					||	(! pTBB->IsSeparator() )
					)
					continue;
				CRect rcTBB = *pTBB;
				if( bHorz )
				{
					rcTBB.top = nRowMinLoc;
					rcTBB.bottom = nRowMaxLoc;
					rcTBB.InflateRect(
						0,
						bDockerTrasparentMode ? 2 : 1
						);
				} // if( bHorz )
				else
				{
					rcTBB.left = nRowMinLoc;
					rcTBB.right = nRowMaxLoc;
					rcTBB.InflateRect(
						bDockerTrasparentMode ? 2 : 1,
						0,
						bDockerTrasparentMode ? 3 : 2,
						0
						);
				} // else from if( bHorz )
				pTBB->SetRect( rcTBB );
			} // for( INT nBtnIdx2 = nRowStart; nBtnIdx2 < nBtnIdx; nBtnIdx2++ )
			nRowStart = nBtnIdx + 1;
		} // for( nBtnIdx = 0; nBtnIdx < nReviewCount; nBtnIdx++ )
	} // just re-align separators in each row

	// remove TBBS_HIDDEN in right menu
	if( (!m_bPaletteMode) && m_pRightBtn != NULL )
	{
		int nMenuCount = m_pRightBtn->GetButtons().GetSize();
		for( int nMenuIdx = 0; nMenuIdx < nMenuCount; )
		{
			CExtBarButton * pTBB = 
				m_pRightBtn->GetButtons().
					GetAt( nMenuIdx );
			ASSERT_VALID( pTBB );
			if( pTBB->GetStyle() & TBBS_HIDDEN )
			{
				m_pRightBtn->GetButtons().RemoveAt( nMenuIdx );
				nMenuCount--;
			} // if( pTBB->GetStyle() & TBBS_HIDDEN )
			else
				nMenuIdx++;
		} // for( int nMenuIdx = 0; nMenuIdx < nMenuCount; )
	} // if( (!m_bPaletteMode) && m_pRightBtn != NULL )
	
	if(	m_pRightBtn != NULL && m_bPresubclassDialogMode )
	{
		if( m_pRightBtn->GetButtons().GetSize() == 0 )
			m_pRightBtn->ModifyStyle( TBBS_DISABLED, 0 );
		else
			m_pRightBtn->ModifyStyle( 0, TBBS_DISABLED );
	}

	// insert separators into right button
	if(		bFloating
		||	bMultiRowLayout
		||	m_bPaletteMode
		||	bMultiRowLayout
		||	m_pRightBtn == NULL
		||	(	m_pRightBtn != NULL
				&& m_pRightBtn->GetButtons().GetSize() == 0
			)
		)
	{
		return;
	}

int nHiddenCount = m_pRightBtn->GetButtons().GetSize();
	if( nHiddenCount < 2 )
		return;
int nEndMeasure = nHiddenCount-1;
	for( int iHidden = 0; iHidden < nEndMeasure; iHidden++ )
	{
		CExtBarButton * pTbbHidden0 =
			m_pRightBtn->GetButtons().GetAt(iHidden);
		ASSERT( pTbbHidden0 != NULL );
		ASSERT( ! pTbbHidden0->IsSeparator() );
		ASSERT( (! pTbbHidden0->IsVisible()) && (pTbbHidden0->GetStyle() & TBBS_HIDDEN) == 0 );
		CExtBarButton * pTbbHidden1 =
			m_pRightBtn->GetButtons().GetAt(iHidden+1);
		ASSERT( pTbbHidden1 != NULL );
		ASSERT( ! pTbbHidden1->IsSeparator() );
		ASSERT( (! pTbbHidden1->IsVisible()) && (pTbbHidden1->GetStyle() & TBBS_HIDDEN) == 0 );
		CExtBarButton * pTbbSeparatorToInsert = NULL;
		int nIdx0=-1,nIdx1=-1;
		for( nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
		{
			CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
			ASSERT_VALID( pTBB );
			if( pTBB == pTbbHidden0 )
			{
				nIdx0 = nBtnIdx;
				ASSERT( nIdx1 < 0 );
				continue;
			}
			if( nIdx0 >= 0
				&& pTBB->IsSeparator()
				&& pTbbSeparatorToInsert == NULL
				)
				pTbbSeparatorToInsert = pTBB;
			if( pTBB == pTbbHidden1 )
			{
				nIdx1 = nBtnIdx;
				ASSERT( nIdx0 >= 0 && nIdx0 < nIdx1 );
				break;
			}
		}
		ASSERT(
			nIdx0 < nIdx1
			&&
			nIdx0 >= 0 && nIdx0 < nCountOfButtons
			&& 
			nIdx1 >= 0 && nIdx1 < nCountOfButtons
			);
		if( (nIdx0+1) == nIdx1 )
			continue;
		if( pTbbSeparatorToInsert != NULL )
		{
			nEndMeasure++;
			iHidden++;
			m_pRightBtn->GetButtons().InsertAt(
				iHidden,
				pTbbSeparatorToInsert
				);
		}
	} // for( int iHidden = 0; iHidden < nEndMeasure; iHidden++ )
}

DWORD CExtToolControlBar::RecalcDelayShow(AFX_SIZEPARENTPARAMS* lpLayout)
{
DWORD dwRes = CControlBar::RecalcDelayShow( lpLayout );
	if( (!IsFloating()) && IsVisible() )
		_RecalcPositionsImpl();
	return dwRes;
}

void CExtToolControlBar::OnSize(UINT nType, int cx, int cy) 
{
	CExtControlBar::OnSize(nType, cx, cy);
	_RecalcLayoutImpl();
}

void CExtToolControlBar::_RecalcLayoutImpl()
{
	if( GetSafeHwnd() == NULL
		|| !::IsWindow( GetSafeHwnd() )
		)
		return;
	CExtControlBar::_RecalcLayoutImpl();
	_RecalcPositionsImpl();
	if( m_bPresubclassDialogMode )
	{
		Invalidate();
		UpdateWindow();
		return;
	}
	if(		m_pDockSite != NULL
		&&	m_pDockBar != NULL
		&&	OnQueryMultiRowLayout()
		&&	m_pDockBar->IsKindOf(RUNTIME_CLASS(CExtDockOuterBar))
		)
		((CExtDockOuterBar*)m_pDockBar)->_DelayDockSiteRecalc();
}

LRESULT CExtToolControlBar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	if( message == WM_TIMER && wParam == 0x444 )
	{
		if(		CExtPopupMenuWnd::IsMenuTracking()
			||	g_bMenuTracking
			||	_DraggingGetBar() != NULL
			)
			return 0;
		KillTimer( 0x444 );
		CFrameWnd * pFrame = GetParentFrame();
		if( pFrame != NULL )
		{
			ASSERT_VALID( pFrame );
			pFrame->RecalcLayout();
		}
		return 0;
	} // if( message == WM_TIMER && wParam == 0x444 )
	if( message == WM_WINDOWPOSCHANGED )
	{
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
		CExtCustomizeSite * pSite = GetCustomizeSite();
		if( pSite != NULL && pSite->IsCustomizeMode() )
			pSite->ActiveItemSet();
#endif //(!defined __EXT_MFC_NO_CUSTOMIZE)
		_RecalcLayoutImpl();
	} // if( message == WM_WINDOWPOSCHANGED )
	return CExtControlBar::WindowProc(message,wParam,lParam);
}


void CExtToolControlBar::OnTimer(UINT nIDEvent) 
{
	CExtControlBar::OnTimer(nIDEvent);
}

void CExtToolControlBar::_SwitchMenuTrackingIndex(
	int iNewMenuTrackingIndex  // = -1
	)
{
	if( m_nBtnIdxMenuTracking >= 0 )
	{
		CExtBarButton * pTBB =
			_GetButtonPtr( m_nBtnIdxMenuTracking );
		ASSERT_VALID( pTBB );
		ASSERT( !(pTBB->IsSeparator()) );
		UINT nNewStyle =
			pTBB->GetStyle()
			&
			~(TBBS_PRESSED|TBBS_CHECKED|TBBS_INDETERMINATE);
		pTBB->SetStyle( nNewStyle );
		pTBB->OnPressedTrackingStop();
		_InvalidateButton( m_nBtnIdxMenuTracking );
		m_nBtnIdxMenuTracking = -1;
	} // if( m_nBtnIdxMenuTracking >= 0 )

	if( iNewMenuTrackingIndex >= 0 )
	{
		m_nBtnIdxMenuTracking = iNewMenuTrackingIndex;
		CExtBarButton * pTBB =
			_GetButtonPtr( m_nBtnIdxMenuTracking );
		ASSERT_VALID( pTBB );
		ASSERT( !(pTBB->IsSeparator()) );
		UINT nNewStyle =
			pTBB->GetStyle()
			&
			~(TBBS_CHECKED|TBBS_INDETERMINATE);
		nNewStyle |= TBBS_PRESSED;
		pTBB->SetStyle( nNewStyle );
		pTBB->OnPressedTrackingStart();
		_InvalidateButton( m_nBtnIdxMenuTracking );
	} // if( iNewMenuTrackingIndex >= 0 )

	UpdateWindow();
}

CExtToolControlBar * CExtToolControlBar::_GetMenuTrackingBar()
{
CSingleLock _slCsCB( &g_csCB );
	_slCsCB.Lock();
CExtToolControlBar * pRetVal = NULL;
	for( INT iBar=0; iBar<g_AllBars.GetSize(); ++iBar )
	{
		CExtControlBar * pBar = g_AllBars[iBar];
		ASSERT_VALID( pBar );
		CExtToolControlBar * pToolControlBar =
			DYNAMIC_DOWNCAST(CExtToolControlBar,pBar);
		if( pToolControlBar == NULL )
			continue;
		if( pToolControlBar->m_nBtnIdxMenuTracking >= 0 )
		{
			pRetVal = pToolControlBar;
			break;
		}
	}
	_slCsCB.Unlock();
	return NULL;
}

void CExtToolControlBar::_CloseTrackingMenus()
{
	g_bMenuTracking = false;

CSingleLock _slCsCB( &g_csCB );
	_slCsCB.Lock();
	for( INT iBar=0; iBar<g_AllBars.GetSize(); ++iBar )
	{
		CExtControlBar * pBar = g_AllBars[iBar];
		ASSERT_VALID( pBar );
		CExtToolControlBar * pToolControlBar =
			DYNAMIC_DOWNCAST(CExtToolControlBar,pBar);
		if( pToolControlBar == NULL )
			continue;
		pToolControlBar->_SwitchMenuTrackingIndex();
	}
	_slCsCB.Unlock();

//	CExtPopupMenuWnd::CancelMenuTracking();
//	CWnd::CancelToolTips();

	if( !CExtPopupMenuSite::g_DefPopupMenuSite.IsEmpty()
		&& !CExtPopupMenuSite::g_DefPopupMenuSite.IsShutdownMode()
		)
		CExtPopupMenuSite::g_DefPopupMenuSite->PostMessage( WM_CANCELMODE );
	CWnd::CancelToolTips();

// 	TO FIX: can be tracked other menu
//	ASSERT( !CExtPopupMenuWnd::IsMenuTracking() );
}

void CExtToolControlBar::_CbPaintCombinedContent(
	LPVOID pCookie,
	CDC & dc,
	const CWnd & refWndMenu,
	const CRect & rcExcludeArea, // in screen coords
	int eCombineAlign // CExtPopupMenuWnd::e_combine_align_t values
	)
{
	pCookie;
	dc;
	refWndMenu;
	rcExcludeArea;
	eCombineAlign;
	ASSERT( dc.GetSafeHdc() != NULL );
	ASSERT( refWndMenu.GetSafeHwnd() != NULL );
CExtToolControlBar * pBar = (CExtToolControlBar *)pCookie;
	ASSERT_VALID( pBar );
	ASSERT( pBar->IsKindOf(RUNTIME_CLASS(CExtToolControlBar)) );
	ASSERT( eCombineAlign != CExtPopupMenuWnd::__CMBA_NONE );

	if( rcExcludeArea.IsRectEmpty() )
		return;
	if( pBar->m_nBtnIdxMenuTracking < 0 )
		return;
	ASSERT(
		pBar->m_nBtnIdxMenuTracking <
			pBar->GetButtonsCount()
		);

CExtBarButton * pTBB =
		pBar->_GetButtonPtr(
			pBar->m_nBtnIdxMenuTracking
			);
	ASSERT_VALID( pTBB );

	if(		g_PaintManager->GetCb2DbTransparentMode(pTBB)
		&&	pTBB->IsKindOf( RUNTIME_CLASS(CExtBarContentExpandButton) )
		&&	(! pBar->IsKindOf(RUNTIME_CLASS(CExtMenuControlBar)) )
		&&	(! pBar->m_bPresubclassDialogMode )
		&&	CExtPaintManager::stat_GetBPP() > 8
		)
		return;

UINT nStyle = pTBB->GetStyle();
bool bHover = pTBB->IsHover();
	pTBB->SetHover( false );
	pTBB->ModifyStyle(
		0,
		TBBS_PRESSED|TBBS_CHECKED|TBBS_CHECKBOX
		);
CRect rcClientBar,rcClientExcludeArea;
	pBar->GetClientRect( &rcClientBar );
	pBar->ClientToScreen( &rcClientBar );
	refWndMenu.GetClientRect( &rcClientExcludeArea );
	refWndMenu.ClientToScreen( &rcClientExcludeArea );
CPoint ptOffset =
		rcClientBar.TopLeft()
		- rcClientExcludeArea.TopLeft()
		;
CPoint ptViewportOrg = dc.GetViewportOrg();
	dc.SetViewportOrg( ptOffset );
bool bHorz = pBar->IsDockedVertically() ? false : true;
	pTBB->Paint(dc,bHorz);
	dc.SetViewportOrg( ptViewportOrg );
	pTBB->SetHover( bHover );
	pTBB->SetStyle(nStyle);
}

CExtBarButton * CExtToolControlBar::GetButton( int nIndex )
{
	return _GetButtonPtr( nIndex );
}

CExtBarContentExpandButton * CExtToolControlBar::GetRightButton()
{
	return m_pRightBtn;
}

void CExtToolControlBar::OnCaptureChanged(CWnd *pWnd) 
{
	if(	(m_nBtnIdxCapture >= 0 || m_nBtnIdxHover >= 0)
		&& pWnd != this
		)
		SendMessage( WM_CANCELMODE );
	CExtControlBar::OnCaptureChanged(pWnd);
}

BOOL CExtToolControlBar::InitContentExpandButton()
{
	if( m_pRightBtn != NULL )
		return TRUE;
	m_pRightBtn = OnCreateBarRightBtn();
	if( m_pRightBtn == NULL )
		return FALSE;
	ASSERT_VALID( m_pRightBtn );
	ASSERT_KINDOF( CExtBarContentExpandButton, m_pRightBtn );
	m_buttons.Add( m_pRightBtn );
	return TRUE;
}

bool CExtToolControlBar::_CanDockToInnerCircles() const
{
	return false;
}

bool CExtToolControlBar::_CanDockToTabbedContainers(
	CExtControlBar * pDestBar
	) const
{
	pDestBar;
	return false;
}

void CExtToolControlBar::ToggleDocking()
{
	ASSERT_VALID( this );
	ASSERT_VALID( m_pDockSite );

	ASSERT_VALID( m_pDockBar );
#ifdef _DEBUG
	if( !IsFloating() )
	{
		ASSERT_KINDOF( CExtDockBar, m_pDockBar );
	}
#endif // _DEBUG
	ASSERT( m_pDockContext != NULL );
	
	m_pDockContext->ToggleDocking();

CFrameWnd * pFrame = _GetDockingFrameImpl();
	ASSERT_VALID( pFrame );
	pFrame->DelayRecalcLayout();
	_RecalcNcArea();
}


CExtBarButton::e_wrap_t CExtToolControlBar::GetBtnWrapCode() const
{
	ASSERT_VALID( this );
	if(		m_bPresubclassDialogMode
		||	GetSafeHwnd() == NULL
		||	( ! ::IsWindow(GetSafeHwnd()) )
		||	IsFloating()
		)
		return CExtBarButton::e_wrap_t::__EVT_FLOAT;
	if( IsDockedVertically() )
		return CExtBarButton::e_wrap_t::__EVT_VERT;
	return CExtBarButton::e_wrap_t::__EVT_HORZ;
}

#if (!defined __EXT_MFC_NO_CUSTOMIZE)

bool CExtToolControlBar::_IsDockSiteCustomizeMode() const
{
CExtCustomizeSite * pSite = GetCustomizeSite();
	if( pSite == NULL )
//		return CExtControlBar::_IsDockSiteCustomizeMode();
		return false;
	return pSite->IsCustomizeMode();
}

CExtCustomizeSite * CExtToolControlBar::GetCustomizeSite()
{
	ASSERT_VALID( this );
	return m_pCustomizeSite;
}

CExtCustomizeSite * CExtToolControlBar::GetCustomizeSite() const
{
	ASSERT_VALID( this );
	return ((CExtToolControlBar*)this)->GetCustomizeSite();
}

bool CExtToolControlBar::OnCustomizeRegisterBar(
	CExtCustomizeSite * pCustomizeSite
	)
{
	ASSERT_VALID( this );
	ASSERT( m_pCustomizeSite == NULL ); // should called only once
	ASSERT( pCustomizeSite != NULL );
	if(		(! m_bCustomizationAllowed )
		||	m_bPaletteMode
		)
		return false;
	m_pCustomizeSite = pCustomizeSite;
	return true;
}

void CExtToolControlBar::OnCustomizeGetBarInfo(
	CExtCustomizeSite::CToolBarCustomizeInfo * pInfo
	)
{
	ASSERT_VALID( this );
	ASSERT( m_pCustomizeSite != NULL );
	ASSERT( pInfo != NULL );
	ASSERT( m_hWnd != NULL && ::IsWindow(m_hWnd) );

UINT nBarID = (UINT)GetDlgCtrlID();
CExtCmdItem * pCmd =
		g_CmdManager->CmdGetPtr(
			g_CmdManager->ProfileNameFromWnd(m_hWnd),
			nBarID
			);
	if( pCmd != NULL )
		pInfo->m_strDisplayName =
			pCmd->OnGetToolBarCustomizeName();
	if( pInfo->m_strDisplayName.IsEmpty() )
	{
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
		CExtLocalResourceHelper _LRH;
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
		if( !pInfo->m_strDisplayName.LoadString(nBarID) )
		{
//#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
//			ASSERT( FALSE );
//#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
			int nTextLen = GetWindowTextLength();
			if( nTextLen > 0 )
			{
				GetWindowText( pInfo->m_strDisplayName.GetBuffer(nTextLen+1), nTextLen+1 );
				pInfo->m_strDisplayName.ReleaseBuffer();
			} // if( nTextLen > 0 )
			if( pInfo->m_strDisplayName.IsEmpty() )
				pInfo->m_strDisplayName.Format(
					_T("Toolbar #%08X"),
					nBarID
					);
		} // if( !pInfo->m_strDisplayName.LoadString(nBarID) )
	} // if( pInfo->m_strDisplayName.IsEmpty() )
	if( pInfo->m_pHelperBarButtonsI != NULL )
	{
		CExtCustomizeSite * pCustomizeSite = GetCustomizeSite();
		ASSERT( pCustomizeSite != NULL );
		ASSERT_VALID( pInfo->m_pHelperBarButtonsI );
		ASSERT( pInfo->m_pHelperBarButtonsI->GetCmdID() == ((UINT)GetDlgCtrlID()) );
		ASSERT( pInfo->m_pHelperBarButtonsI->GetNodeCount() == 0 );
		pInfo->m_pHelperBarButtonsI->SetTextUser( pInfo->m_strDisplayName );
		INT nCountOfButtons = _GetButtonsCountImpl();
		for( INT nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
		{
			CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
			ASSERT_VALID( pTBB );
			pTBB->OnCustomizeNodeInit(
				pCustomizeSite,
				pInfo->m_pHelperBarButtonsI
				);
		} // for( INT nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
	} // if( pInfo->m_pHelperBarButtonsI != NULL )
}

void CExtToolControlBar::OnCustomizeUpdateInitialBarState(
	CExtCustomizeCmdTreeNode * pParentNode,
	bool bRecalcLayout
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( pParentNode );
	ASSERT( m_pCustomizeSite != NULL );
INT nNodeCount = pParentNode->GetNodeCount();
INT nCountOfButtons = _GetButtonsCountImpl();
	ASSERT( nNodeCount <= nCountOfButtons );
INT nNodePos = 0;
	for( INT nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
	{
		CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
		ASSERT_VALID( pTBB );
		CExtCustomizeCmdTreeNode * pCmdNodeI =
			pTBB->GetCmdNode( true );
		if( pCmdNodeI == NULL )
			continue;
		ASSERT( !pTBB->IsSeparator() );
		ASSERT_VALID( pCmdNodeI );
		CExtCustomizeCmdTreeNode * pCmdNodeC =
			pParentNode->ElementAt( nNodePos++ );
		ASSERT_VALID( pCmdNodeC );
//		pTBB->SetCustomizedCmdNode( pCmdNodeC );
		
		// re-init spec buttons
		pTBB =
			m_pCustomizeSite->OnCreateToolbarButton(
				this,
				pCmdNodeI,
				pCmdNodeI
				);
		ASSERT_VALID( pTBB );
		VERIFY( InsertSpecButton( nBtnIdx, pTBB, FALSE ) );
		pTBB->SetBasicCmdNode( pCmdNodeI );
		pTBB->SetCustomizedCmdNode( pCmdNodeC );
		pTBB->OnCustomizeUpdateProps();
		RemoveButton( nBtnIdx + 1 );

	} // for( INT nBtnIdx = 0; nBtnIdx < nCountOfButtons; nBtnIdx++ )
	if( bRecalcLayout )
		_RecalcLayoutImpl();
}

void CExtToolControlBar::OnCustomizeModeEnter()
{
	ASSERT_VALID( this );
	if(		m_pDockSite == NULL
		||	m_pDockBar == NULL
		||	(! m_pDockBar->IsKindOf(RUNTIME_CLASS(CExtDockOuterBar)) )
		)
		return;
	ASSERT_VALID( m_pDockSite );
	ASSERT_VALID( m_pDockBar );

CExtCustomizeSite * pSite = GetCustomizeSite();
	if( pSite != NULL )
		pSite->RegisterCommandDropTarget( this, this );

	if(		(! IsDocked() )
		||	_GetFullRowMode()
		)
		return;
INT nCountOfButtons = _GetButtonsCountImpl();
	if( nCountOfButtons == 0 )
		return;
	if( m_pRightBtn == NULL )
		return;
	if( m_pRightBtn->GetButtons().GetSize() == 0 )
		return;
INT nOwnIdxInDocker = m_pDockBar->FindBar(this);
	ASSERT( 0 < nOwnIdxInDocker && nOwnIdxInDocker < (m_pDockBar->m_arrBars.GetSize()-1) );
	if( m_pDockBar->m_arrBars[nOwnIdxInDocker+1] != NULL )
		m_pDockBar->m_arrBars.InsertAt( nOwnIdxInDocker+1, (CControlBar *)NULL );
	if( m_pDockBar->m_arrBars[nOwnIdxInDocker-1] != NULL )
		m_pDockBar->m_arrBars.InsertAt( nOwnIdxInDocker, (CControlBar *)NULL );
	Invalidate();
}

void CExtToolControlBar::OnCustomizeModeLeave()
{
	ASSERT_VALID( this );
}

void CExtToolControlBar::OnCustomizeListBoxUpdate( CExtCustomizeToolbarsListBox * pWndList )
{
	ASSERT_VALID( this );
	ASSERT_VALID( pWndList );
	CExtControlBar::OnCustomizeListBoxUpdate( pWndList );
}

DROPEFFECT CExtToolControlBar::OnCustomizeTargetOver(
	CExtCustomizeSite::CCmdDragInfo & _dragInfo,
	CPoint point,
	DWORD dwKeyState
	)
{
	ASSERT_VALID( this );
	ASSERT( !_dragInfo.IsEmpty() );
	_dragInfo;
	if(		m_pDockBar != NULL
		&&	IsFloating()
		)
		GetParentFrame()->SetWindowPos(
			&CWnd::wndTop, 0, 0, 0, 0,
			SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE
			);

//CExtCustomizeSite * pSite = GetCustomizeSite();
//	ASSERT( pSite != NULL );
//CExtCustomizeCmdTreeNode * pPopupDropTargetNode =
//		pSite->GetPopupDropTargetNode();
//	if(		pSite->IsCustomizeMode()
//		&&	m_pDragTargetTBB != NULL
//		&&	m_pDragTargetTBB->IsAbleToTrackMenu()
//		&&	pPopupDropTargetNode == m_pDragTargetTBB->GetCmdNode()
//		)
//		pSite->DropTargetPopupCancel();

int nCountTest = _GetButtonsCountImpl();
int nCountReal = nCountTest;
	if( m_pRightBtn != NULL )
	{
		nCountTest--;
		ASSERT( nCountTest >= 0 );
	}
	if(		nCountTest > 0
		&&	_GetButtonPtr(0)->IsKindOf(RUNTIME_CLASS(CExtBarMdiDocButton))
		)
	{
		nCountTest--;
		ASSERT( nCountTest >= 0 );
	}
	if(		nCountReal > 1
		&&	_GetButtonPtr(
				( m_pRightBtn != NULL )
					? (nCountReal-2)
					: (nCountReal-1)
				)->IsKindOf(RUNTIME_CLASS(CExtBarMdiDocButton))
		)
	{
		nCountTest--;
		ASSERT( nCountTest >= 0 );
	}
	if( nCountTest == 0 )
	{
		if( (dwKeyState & MK_CONTROL) != NULL )
			return DROPEFFECT_COPY;
		return DROPEFFECT_MOVE;
	}

	if( m_pDragTargetTBB != NULL )
		_InvalidateButton( _GetIndexOf(m_pDragTargetTBB) );
int nHitIdx = _HitTestImpl( point, 0, 0, true );
	if( nHitIdx < 0 )
	{
		m_pDragTargetTBB = NULL;
		m_nDragTargetShift = 0;
		UpdateWindow();
		return DROPEFFECT_NONE;
	}
CExtBarButton * pHitTBB = _GetButtonPtr( nHitIdx );
	ASSERT_VALID( pHitTBB );
	if( pHitTBB->IsSeparator() )
	{
		nHitIdx--;
		if( nHitIdx < 0 )
		{
			m_pDragTargetTBB = NULL;
			m_nDragTargetShift = 0;
			UpdateWindow();
			return DROPEFFECT_NONE;
		}
		pHitTBB = _GetButtonPtr( nHitIdx );
		ASSERT_VALID( pHitTBB );
		if( pHitTBB->IsSeparator() )
		{
			ASSERT( FALSE ); // double  separators?!
			m_pDragTargetTBB = NULL;
			m_nDragTargetShift = 0;
			UpdateWindow();
			return DROPEFFECT_NONE;
		} // if( pHitTBB->IsSeparator() )
	} // if( pHitTBB->IsSeparator() )
	m_nDragTargetShift =
		pHitTBB->CalculateDropOverEffect( point, _dragInfo );
	if( m_nDragTargetShift == 0 )
	{
		m_pDragTargetTBB = NULL;
		m_nDragTargetShift = 0;
		UpdateWindow();
		return DROPEFFECT_NONE;
	} // if( m_nDragTargetShift == 0 )
	if( m_pDragTargetTBB != pHitTBB )
	{
		m_pDragTargetTBB = pHitTBB;
		_InvalidateButton( _GetIndexOf(m_pDragTargetTBB) );
	}
	UpdateWindow();
	if( (dwKeyState & MK_CONTROL) != NULL )
		return DROPEFFECT_COPY;
	return DROPEFFECT_MOVE;
}

void CExtToolControlBar::OnCustomizeTargetLeave()
{
	ASSERT_VALID( this );
	if( m_pDragTargetTBB == NULL )
		return;
	_InvalidateButton( _GetIndexOf(m_pDragTargetTBB) );
	m_pDragTargetTBB = NULL;
	m_nDragTargetShift = 0;
	UpdateWindow();
}

bool CExtToolControlBar::OnCustomizeTargetDrop(
	CExtCustomizeSite::CCmdDragInfo & _dragInfo,
	CPoint point,
	DROPEFFECT de
	)
{
	// returns true if drop with any effect
	// has been performed
	ASSERT_VALID( this );
	ASSERT( !_dragInfo.IsEmpty() );
	_dragInfo;
	point;
	ASSERT(
			de == DROPEFFECT_NONE
		||	de == DROPEFFECT_MOVE
		||	de == DROPEFFECT_COPY
		);
	if(		de == DROPEFFECT_NONE
//		||	m_pDragTargetTBB == NULL
//		||	m_nDragTargetShift == 0
		)
		return false;
	if( m_pDragTargetTBB == NULL )
	{
		CExtCustomizeSite * pSite =
			GetCustomizeSite();
		ASSERT( pSite != NULL );
		int nInsertPos = 0;
		if(		GetButtonsCount() > 0
			&&	_GetButtonPtr(0)->IsKindOf(RUNTIME_CLASS(CExtBarMdiDocButton))
			)
			nInsertPos = 1;
		pSite->OnInsertToolbarCmdNode(
			_dragInfo,
			this,
			nInsertPos,
			true
			);
		if(		m_pDockBar != NULL
			&&	IsFloating()
			)
		{
			GetParentFrame()->RecalcLayout();
			Invalidate();
		}
		return true;
	} // if( m_pDragTargetTBB == NULL )

	ASSERT_VALID( m_pDragTargetTBB );
	
int nBtn = _GetIndexOf(m_pDragTargetTBB);
	ASSERT( 0 <= nBtn && nBtn < _GetButtonsCountImpl() );
	_InvalidateButton( nBtn );

bool bSeparatorAdd = false;
bool bSeparatorRemove = false;
	if( de == DROPEFFECT_MOVE )
	{
		if( m_pDragSourceTBB == m_pDragTargetTBB )
		{
			if( m_nDragTargetShift == -2 )
				return false; // no reinsert
			if( m_nDragTargetShift < 0 )
			{ // if remove separator
				if(		nBtn > 0
					&&	_GetButtonPtr(nBtn-1)->IsSeparator()
					)
					bSeparatorRemove = true;
				else
					return false; // no reinsert
			} // if remove separator
			else
			{ // if add separator
				if(	(	nBtn > 1
					||	(	nBtn == 1
						&&	(! _GetButtonPtr(0)->IsKindOf(RUNTIME_CLASS(CExtBarMdiDocButton)) )
						)
					)
					&&	(! _GetButtonPtr(nBtn-1)->IsSeparator() )
					)
					bSeparatorAdd = true;
				else
					return false; // no reinsert
			} // if add separator
		} // if( m_pDragSourceTBB == m_pDragTargetTBB )
		else if(
			m_pDragSourceTBB != NULL
			&&	nBtn > 0
			&&	m_nDragTargetShift < 0
			&&	_GetIndexOf(m_pDragSourceTBB) == (nBtn-1)
			&&	(!(	nBtn == 2
				&&	_GetButtonPtr(0)->IsKindOf(RUNTIME_CLASS(CExtBarMdiDocButton))
				))
			)
		{
			if(	(	nBtn > 1
				&&	(! _GetButtonPtr(nBtn-2)->IsSeparator() )
				)
				||	nBtn <= 1
				)
			{ // avoid unwanted separator insert
				bSeparatorAdd = true;
				nBtn--;
			} // avoid unwanted separator insert
		}
	} // if( de == DROPEFFECT_MOVE )

	if( bSeparatorRemove )
	{
		CExtBarButton * pModifyTBB = _GetButtonPtr(nBtn);
		ASSERT_VALID( pModifyTBB );
		CExtCustomizeCmdTreeNode * pNode = pModifyTBB->GetCmdNode();
		ASSERT_VALID( pNode );
		pNode->ModifyFlags( 0, __ECTN_GROUP_START );
		RemoveButton(nBtn-1);
		UpdateWindow();
		if(		m_pDockBar != NULL
			&&	IsFloating()
			)
		{
			GetParentFrame()->RecalcLayout();
			Invalidate();
		}
		m_bHelperSeparatorAction = true;
	} // if( bSeparatorRemove )
	else if( bSeparatorAdd )
	{
		CExtBarButton * pModifyTBB = _GetButtonPtr(nBtn);
		ASSERT_VALID( pModifyTBB );
		CExtCustomizeCmdTreeNode * pNode = pModifyTBB->GetCmdNode();
		ASSERT_VALID( pNode );
		pNode->ModifyFlags( __ECTN_GROUP_START );
		InsertButton(nBtn);
		UpdateWindow();
		if(		m_pDockBar != NULL
			&&	IsFloating()
			)
		{
			GetParentFrame()->RecalcLayout();
			Invalidate();
		}
		m_bHelperSeparatorAction = true;
	} // else if( bSeparatorAdd )
	else
	{ // if command drop
		int nInsertPos = (m_nDragTargetShift < 0) ? nBtn : (nBtn+1);
		m_pDragTargetTBB = NULL;
		m_nDragTargetShift = 0;
		UpdateWindow();
		//InsertButton( nInsertPos, pCmdItem->m_nCmdID );
		CExtCustomizeSite * pSite =
			GetCustomizeSite();
		ASSERT( pSite != NULL );
		pSite->OnInsertToolbarCmdNode(
			_dragInfo,
			this,
			nInsertPos,
			true
			);
		if(		m_pDockBar != NULL
			&&	IsFloating()
			)
		{
			GetParentFrame()->RecalcLayout();
			Invalidate();
		}
	} // if command drop
	return true;
}

void CExtToolControlBar::OnCustomizeSourceDragComplete(
	DROPEFFECT de,
	bool bCanceled,
	bool * p_bNoResetActiveItem
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( m_pDragSourceTBB );
	ASSERT( p_bNoResetActiveItem != NULL );
	ASSERT(
			de == DROPEFFECT_NONE
		||	de == DROPEFFECT_MOVE
		||	de == DROPEFFECT_COPY
		);
int nBtnSrc = _GetIndexOf(m_pDragSourceTBB);
	if( (!bCanceled) && (!m_bHelperSeparatorAction) )
	{
//		if(		de == DROPEFFECT_NONE
//			||	(	de == DROPEFFECT_MOVE
//				&&	m_pDragSourceTBB != m_pDragTargetTBB
//				)
//			)
		CExtBarButton * pHtCurrTBB = NULL;
		if( GetButtonsCount() > 0 )
		{
			CPoint point( 0, 0 );
			::GetCursorPos( &point );
			ScreenToClient( &point );
			INT nButton = HitTest( point );
			if( nButton >= 0 )
				pHtCurrTBB = _GetButtonPtr( nButton );
		} // if( GetButtonsCount() > 0 )
		if( de == DROPEFFECT_NONE || de == DROPEFFECT_MOVE )
		{
			if(		m_pDragSourceTBB == m_pDragTargetTBB
				||	m_pDragSourceTBB == pHtCurrTBB
				)
			{ // if keep source button active
				m_pDragSourceTBB = NULL;
				if( _IsDockSiteCustomizeMode() )
					*p_bNoResetActiveItem = true;
			} // if keep source button active
			else
			{ // if remove source button
				m_pDragSourceTBB = NULL;
				CExtCustomizeSite * pSite = GetCustomizeSite();
				ASSERT( pSite != NULL );
				CExtCustomizeCmdTreeNode * pNode =
					pSite->DraggedNodeGet();
				ASSERT_VALID( pNode );
				ASSERT( ((LPVOID)pNode) == ((LPVOID)_GetButtonPtr(nBtnSrc)->GetCmdNode(false)) );
				if( pSite->GetPopupDropTargetNode() == pNode )
				{
					pSite->DropTargetPopupCancel();
					ASSERT( pSite->GetPopupDropTargetNode() != pNode );
				}
				RemoveButton( nBtnSrc );
				pSite->DraggedNodeSet( NULL );
				CExtCmdItem * pCmdItem =
					g_CmdManager->CmdGetPtr(
						g_CmdManager->ProfileNameFromWnd(m_hWnd),
						pNode->GetCmdID( false )
						);
				ASSERT( pCmdItem != NULL );
				ASSERT_VALID( pNode->GetParentNode() );
				int nOwnNodeIndex = pNode->GetOwnIndex();
				int nSiblingCount = pNode->GetParentNode()->GetNodeCount();
				bool bRemovePrevSeparator =
					(pNode->GetFlags() & __ECTN_GROUP_START)
						? true : false;
				bool bRemoveNextSeparator = false;
				if(		bRemovePrevSeparator
					&&	nOwnNodeIndex < (nSiblingCount-1)
					)
				{
					ASSERT( nOwnNodeIndex > 0 );
					ASSERT( nBtnSrc > 0 );
					if( (pNode->GetParentNode()->ElementAt(nOwnNodeIndex+1)
							->GetFlags()&__ECTN_GROUP_START) == 0
						)
					{
						pNode->GetParentNode()->ElementAt(nOwnNodeIndex+1)
							->ModifyFlags( __ECTN_GROUP_START );
						bRemovePrevSeparator = false;
					}
				}
				if(		nOwnNodeIndex == 0
					&&	nSiblingCount > 1
					&&	(pNode->GetParentNode()->ElementAt(1)
							->GetFlags()&__ECTN_GROUP_START) != 0
					)
				{
					pNode->GetParentNode()->ElementAt(1)->ModifyFlags( 0, __ECTN_GROUP_START );
					bRemoveNextSeparator = true;
				}
				pNode->RemoveSelf( pCmdItem );
				if( bRemoveNextSeparator )
				{
					ASSERT( _GetButtonPtr(nBtnSrc)->IsSeparator() );
					RemoveButton( nBtnSrc );
				}
				if( bRemovePrevSeparator )
				{
					ASSERT( _GetButtonPtr(nBtnSrc-1)->IsSeparator() );
					RemoveButton( nBtnSrc-1 );
				}
				if(		m_pDockBar != NULL
					&&	IsFloating()
					)
				{
					GetParentFrame()->RecalcLayout();
					Invalidate();
				}
			} // if remove source button
		}  // if( de == DROPEFFECT_NONE || de == DROPEFFECT_MOVE )
		else
			_InvalidateButton( nBtnSrc );
	} // if( (!bCanceled) && (!m_bHelperSeparatorAction) )
	else
		_InvalidateButton( nBtnSrc );
	m_pDragSourceTBB = NULL;
	m_pDragTargetTBB = NULL;
	m_nDragTargetShift = 0;
	m_bHelperSeparatorAction = false;
	UpdateWindow();
}

INT CExtToolControlBar::OnCustomizeCalcCmdNodePos(
	INT nButtonPos,
	bool * p_bReinitGroupStart // = NULL
	)
{
	ASSERT_VALID( this );
	if( p_bReinitGroupStart != NULL )
		(*p_bReinitGroupStart) = false;
INT nButtonsCount = _GetButtonsCountImpl();
	ASSERT( nButtonPos <= nButtonsCount );
	if( nButtonsCount == 0 )
		return 0;
INT nCmdPos = 0;
	for( INT nBtnIdx = 0; nBtnIdx < nButtonPos; nBtnIdx++  )
	{
		CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
		ASSERT_VALID( pTBB );
		if( pTBB->GetCmdNode() == NULL )
			continue;
		ASSERT( !pTBB->IsSeparator() );
		ASSERT_VALID( pTBB->GetCmdNode() );
		nCmdPos ++;
	} // for( INT nBtnIdx = 0; nBtnIdx < nButtonPos; nBtnIdx++  )
	ASSERT( nCmdPos <= nButtonsCount );
	if( p_bReinitGroupStart != NULL && nButtonPos > 0 )
	{
		CExtBarButton * pTBB = _GetButtonPtr( nButtonPos - 1 );
		ASSERT_VALID( pTBB );
		if( pTBB->IsSeparator() )
			(*p_bReinitGroupStart) = true;
	} // if( p_bReinitGroupStart != NULL && nButtonPos > 0 )
	return nCmdPos;
}

bool CExtToolControlBar::OnCustomizeCanShowHideButtons()
{
	ASSERT_VALID( this );
	if(		m_bPaletteMode
		||	IsKindOf(RUNTIME_CLASS(CExtPanelControlBar))
		||	IsKindOf(RUNTIME_CLASS(CExtMenuControlBar))
		||	(! IsVisible() )
		)
		return false;
INT nButtonsCount = _GetButtonsCountImpl();
	if( nButtonsCount == 0 )
		return false;
	for( INT nBtnIdx = 0; nBtnIdx < nButtonsCount; nBtnIdx++  )
	{
		CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
		ASSERT_VALID( pTBB );
		if(		pTBB->IsSeparator()
			||	pTBB->IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton))
			||	pTBB->IsKindOf(RUNTIME_CLASS(CExtBarMdiDocButton))
			||	pTBB->IsKindOf(RUNTIME_CLASS(CExtBarMdiRightButton))
			||	pTBB->GetCmdNode() == NULL
			)
			continue;
		ASSERT_VALID( pTBB->GetCmdNode() );
		if(	(pTBB->GetCmdNode()->GetFlags()&__ECTN_TBB_CANNOT_HIDE) != 0 )
			continue;
		return true;
	} // for( INT nBtnIdx = 0; nBtnIdx < nButtonPos; nBtnIdx++  )
	return false;
}

void CExtToolControlBar::OnCustomizeInitShowHideButtonMenu(
	CExtPopupMenuWnd * pFolder
	)
{
	ASSERT_VALID( this );
	ASSERT( OnCustomizeCanShowHideButtons() );
	ASSERT_VALID( pFolder );
	ASSERT( IsVisible() );

INT nButtonsCount = _GetButtonsCountImpl();
	ASSERT( nButtonsCount > 0 );
INT nInsertPos = 0;
	for( INT nBtnIdx = 0; nBtnIdx < nButtonsCount; nBtnIdx++  )
	{
		CExtBarButton * pTBB = _GetButtonPtr( nBtnIdx );
		ASSERT_VALID( pTBB );
		if(		pTBB->IsSeparator()
			||	pTBB->IsKindOf(RUNTIME_CLASS(CExtBarContentExpandButton))
			||	pTBB->IsKindOf(RUNTIME_CLASS(CExtBarMdiDocButton))
			||	pTBB->IsKindOf(RUNTIME_CLASS(CExtBarMdiRightButton))
			||	pTBB->GetCmdNode() == NULL
			)
			continue;
		ASSERT_VALID( pTBB->GetCmdNode() );
		if(	(pTBB->GetCmdNode()->GetFlags()&__ECTN_TBB_CANNOT_HIDE) != 0 )
			continue;
		VERIFY(
			pFolder->ItemInsert(
				pTBB->GetCmdID(false),
				nInsertPos
				)
			);
		CExtPopupMenuWnd::MENUITEMDATA & mi =
			pFolder->ItemGetInfo( nInsertPos );
		mi.SetForceEnabled();
		mi.SetExtraMark(
			(CExtPopupMenuWnd::MENUITEMDATA::pCbItemClick)
				stat_CbXtraMarkState
			);
		mi.LParamSet( (LPARAM)pTBB );
		pFolder->ItemSetDisplayed( nInsertPos, true );
		mi.SetExtraChecked(
			( (pTBB->GetStyle() & TBBS_HIDDEN) != 0 )
				? false : true
			);
		nInsertPos++;
	} // for( INT nBtnIdx = 0; nBtnIdx < nButtonPos; nBtnIdx++  )
}

bool CExtToolControlBar::stat_CbXtraMarkState(
	CExtPopupMenuWnd * pPopup,
	LPVOID pItemData
	)
{
	ASSERT_VALID( pPopup );
	pPopup;
	ASSERT( pItemData != NULL );
CExtPopupMenuWnd::MENUITEMDATA & mi =
		*((CExtPopupMenuWnd::MENUITEMDATA *)pItemData);
	ASSERT( mi.IsExtraMark() );
	mi.SetExtraChecked( !mi.IsExtraChecked() );
CExtBarButton * pTBB = (CExtBarButton*)mi.LParamGet();
	ASSERT_VALID( pTBB );
	ASSERT_VALID( pTBB->GetBar() );
	ASSERT( pTBB->GetBar()->_GetIndexOf(pTBB) >= 0 );
	//pTBB->RedrawButton( false );
	if( mi.IsExtraChecked() )
	{
		pTBB->ModifyStyle( 0, TBBS_HIDDEN );
		pTBB->Show( true );
	} // if( mi.IsExtraChecked() )
	else
	{
		pTBB->ModifyStyle( TBBS_HIDDEN, 0 );
		pTBB->Show( false );
	} // else from if( mi.IsExtraChecked() )
CExtToolControlBar * pBar = pTBB->GetBar();
	ASSERT_VALID( pBar );
	pBar->_RecalcPositionsImpl();
	pBar->Invalidate();
	pBar->UpdateWindow();
	if( pBar->m_bPresubclassDialogMode )
		return true; // not important
	if(		pBar->m_pDockSite != NULL
		&&	pBar->IsFloating()
		)
	{
		CFrameWnd * pFrame = pBar->GetParentFrame();
		ASSERT_VALID( pFrame );
		ASSERT_KINDOF( CMiniDockFrameWnd, pFrame );
		pFrame->RecalcLayout();
		return true; // not important
	}
	pBar->SetTimer( 0x444, 1, NULL );
	return true; // not important
}

bool CExtToolControlBar::stat_CbCmdDeliver(
	CExtPopupMenuWnd * pPopup,
	LPVOID pItemData
	)
{
	ASSERT_VALID( pPopup );
	pPopup;
	ASSERT( pItemData != NULL );
CExtPopupMenuWnd::MENUITEMDATA & mi =
		*((CExtPopupMenuWnd::MENUITEMDATA *)pItemData);
	if( mi.IsExtraMark() )
		return false;
	if( mi.IsSeparator() )
		return false;
	if( mi.IsPopup() )
		return false;
	if( mi.GetCmdID() != ID_EXT_RESET_TOOLBAR )
		return false;
	ASSERT(
			pPopup->GetSafeHwnd() != NULL
		&&	::IsWindow( pPopup->GetSafeHwnd() )
		);
CExtCustomizeSite * pSite =
		CExtCustomizeSite::GetCustomizeSite(
			pPopup->GetSafeHwnd()
			);
	if( pSite == NULL )
		return false;
CExtToolControlBar * pBar = (CExtToolControlBar *)
		mi.LParamGet();
	ASSERT_VALID( pBar );
	ASSERT_KINDOF( CExtToolControlBar, pBar );
	ASSERT( pSite->BarIsRegistered( pBar ) );
	pSite->BarDefCmdTargetSet( pBar );
	return false;
}

#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

/////////////////////////////////////////////////////////////////////////////
// CExtPanelControlBar

IMPLEMENT_DYNCREATE(CExtPanelControlBar, CExtToolControlBar)

CExtPanelControlBar::CExtPanelControlBar()
	: m_rcMargins( 5, 5, 5, 5 )
{
	m_bPaletteMode = true;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	m_bVisibleInCustomizeListBox = false;
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
}

CExtPanelControlBar::~CExtPanelControlBar()
{
}

BEGIN_MESSAGE_MAP(CExtPanelControlBar, CExtToolControlBar)
	//{{AFX_MSG_MAP(CExtPanelControlBar)
	ON_WM_SIZE()
	ON_WM_PAINT()
	ON_WM_WINDOWPOSCHANGED()
	ON_WM_SETFOCUS()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CExtToolControlBar message handlers

CSize CExtPanelControlBar::CalcDynamicLayout(int nLength, DWORD dwMode)
{
	ASSERT_VALID( this );

	if(	(nLength == -1)
		&& !(dwMode & (LM_MRUWIDTH|LM_COMMIT))
		&&  (dwMode & (LM_HORZDOCK|LM_VERTDOCK))
		)
		return
			CalcFixedLayout(
				dwMode & LM_STRETCH,
				dwMode & LM_HORZDOCK
				);
	ASSERT(
		(dwMode&(LM_HORZ|LM_HORZDOCK))
		||
		(!(dwMode&LM_HORZDOCK))
		);
CSize sizeCalcLayout = _CalcLayout( dwMode, nLength );
	return sizeCalcLayout;
}

CSize CExtPanelControlBar::CalcFixedLayout(
	BOOL bStretch,
	BOOL bHorz
	)
{
	ASSERT_VALID( this );

DWORD dwMode = bStretch ? LM_STRETCH : 0;
	dwMode |= bHorz ? LM_HORZ : 0;
	ASSERT(
		(dwMode&(LM_HORZ|LM_HORZDOCK))
		||
		(!(dwMode&LM_HORZDOCK))
		);
CSize sizeCalcLayout = _CalcLayout( dwMode );
	_RecalcNcArea();
	return sizeCalcLayout;
}

CSize CExtPanelControlBar::_CalcLayout(
	DWORD dwMode,
	int nLength // = -1
	)
{
	ASSERT_VALID( this );
	dwMode;
	nLength;

CSize sizeCalcLayout( 0, 0 );
	if( !IsFloating() )
	{
		sizeCalcLayout += CSize( 2, 2 );
		bool bGripperAtTop = false;
		if( IsBarWithGripper( &bGripperAtTop ) )
		{
			CSize sizeGrip = _GetRectGrip().Size();
			if( bGripperAtTop )
				sizeCalcLayout.cy += sizeGrip.cy;
			else
				sizeCalcLayout.cx += sizeGrip.cx;
		}
	}

	if( IsDockedHorizontally() )
	{
		sizeCalcLayout += _QueryFixedBarNewSize( __FSQ_DOCKED_H );
		SetInitDesiredSizeHorizontal( sizeCalcLayout );
		m_nMinHW = sizeCalcLayout.cx;
	}
	else if( IsDockedVertically() )
	{
		sizeCalcLayout += _QueryFixedBarNewSize( __FSQ_DOCKED_V );
		SetInitDesiredSizeVertical( sizeCalcLayout );
		m_nMinVH = sizeCalcLayout.cy;
	}
	else if( IsFloating() )
	{
		sizeCalcLayout += _QueryFixedBarNewSize( __FSQ_FLOATING );
		SetInitDesiredSizeFloating( sizeCalcLayout );
	}
	else
	{
		sizeCalcLayout += CSize( 20, 20 );
	}

	if( m_pDockSite == NULL )
	{ // specific for dialog mode
		if( IsDockedHorizontally() )
			sizeCalcLayout.cy += 4;
		else
			sizeCalcLayout.cx += 4;
	} // specific for dialog mode

	return sizeCalcLayout;
}

INT CExtPanelControlBar::_CalcDesiredMinHW() const
{
	ASSERT_VALID( this );

CSize sizeCalcLayout = _QueryFixedBarNewSize( __FSQ_DOCKED_H );
	return sizeCalcLayout.cx;
}

CSize CExtPanelControlBar::_CalcDesiredMinOuterSize( BOOL bHorz )
{
	ASSERT_VALID( this );

CSize sizeCalcLayout =
		_QueryFixedBarNewSize(
			bHorz ? __FSQ_DOCKED_H : __FSQ_DOCKED_V
			);
	return sizeCalcLayout;
}

INT CExtPanelControlBar::_CalcDesiredMinVH() const
{
	ASSERT_VALID( this );

CSize sizeCalcLayout = _QueryFixedBarNewSize( __FSQ_DOCKED_V );
	return sizeCalcLayout.cy;
}

CSize CExtPanelControlBar::_CalcDesiredMinFloatedSize() const
{
	ASSERT_VALID( this );

CSize sizeCalcLayout = _QueryFixedBarNewSize( __FSQ_FLOATING );
	return sizeCalcLayout;
}

CSize CExtPanelControlBar::_QueryFixedBarNewSize(
	CExtPanelControlBar::e_fixed_bar_size_query_t eWhichSizeNeedToKnow
	) const
{
CSize sizeResult( OnQueryFixedBarNewSize(eWhichSizeNeedToKnow) );
//	if( eWhichSizeNeedToKnow != __FSQ_FLOATING )
//	{
//		CRect rcClient, rcWnd;
//		GetClientRect( &rcClient );
//		GetWindowRect( &rcWnd );
//		CSize sizeClient( rcClient.Size() );
//		CSize sizeWnd( rcWnd.Size() );
//		sizeResult += sizeWnd;
//		sizeResult -= sizeClient;
//	}
	return sizeResult;
}

CSize CExtPanelControlBar::OnQueryFixedBarNewSize(
	CExtPanelControlBar::e_fixed_bar_size_query_t eWhichSizeNeedToKnow
	) const
{
	ASSERT_VALID( this );
	eWhichSizeNeedToKnow;

//CSize sizeResult;
//	switch( eWhichSizeNeedToKnow )
//	{
//	case __FSQ_DOCKED_H:
//		sizeResult = CSize( 20, 20 );
//	break;
//	case __FSQ_DOCKED_V:
//		sizeResult = CSize( 20, 20 );
//	break;
//	default:
//		ASSERT( eWhichSizeNeedToKnow == __FSQ_FLOATING );
//		sizeResult = CSize( 20, 20 );
//	break;
//	}
//	return sizeResult;

CSize sizeResult( _GetChildSize() );
CRect rcMargins = OnQueryFixedBarChildWindowMargins();
	sizeResult.cx += rcMargins.left + rcMargins.right;
	sizeResult.cy += rcMargins.top + rcMargins.bottom;
	return sizeResult;
}

CRect CExtPanelControlBar::OnQueryFixedBarChildWindowMargins() const
{
	ASSERT_VALID( this );

	return m_rcMargins;
}

CSize CExtPanelControlBar::_GetChildSize() const
{
	ASSERT_VALID( this );
	if(		GetSafeHwnd() == NULL
		||	(! ::IsWindow(GetSafeHwnd()))
		)
		return CSize( 0, 0 );

CWnd * pWndChild = GetWindow( GW_CHILD );
	if(		pWndChild->GetSafeHwnd() == NULL
		||	(! ::IsWindow(pWndChild->GetSafeHwnd()))
		)
		return CSize( 0, 0 );
CRect rcChild;
	pWndChild->GetWindowRect( &rcChild );
CSize sizeChild( rcChild.Size() );
	return sizeChild;
}

void CExtPanelControlBar::_RepositionChild(
	bool bRedraw // = true
	)
{
	ASSERT_VALID( this );

CWnd * pWndChild = GetWindow( GW_CHILD );
	if( pWndChild == NULL )
		return;
CRect rcMargins = OnQueryFixedBarChildWindowMargins();
CRect rcRequired, rcReal;
	GetClientRect( &rcRequired );
	rcRequired.DeflateRect( &rcMargins );
	pWndChild->GetWindowRect( &rcReal );
	ScreenToClient( &rcReal );
//	if( rcReal == rcRequired )
	if( rcReal.TopLeft() == rcRequired.TopLeft() )
		return;
	rcReal.OffsetRect( - rcReal.TopLeft() + rcRequired.TopLeft() );
	pWndChild->MoveWindow(
		&rcReal, // &rcRequired,
		bRedraw ? TRUE : FALSE
		);
}

void CExtPanelControlBar::OnSize(UINT nType, int cx, int cy) 
{
	ASSERT_VALID( this );

	CExtToolControlBar::OnSize(nType, cx, cy);
	_RepositionChild();	
}

void CExtPanelControlBar::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos) 
{
	ASSERT_VALID( this );

	CExtToolControlBar::OnWindowPosChanged(lpwndpos);
	_RepositionChild();
}

void CExtPanelControlBar::OnSetFocus(CWnd* pOldWnd) 
{
	ASSERT_VALID( this );

	CExtToolControlBar::OnSetFocus(pOldWnd);
CWnd * pWndChild = GetWindow( GW_CHILD );
	if( pWndChild == NULL )
		return;	
	pWndChild->SetFocus();
}

void CExtPanelControlBar::OnPaint() 
{
	ASSERT_VALID( this );

CPaintDC dcPaint( this );
CExtMemoryDC dc( &dcPaint );

CRect rcClient;
	GetClientRect( &rcClient );

CWnd * pWndChild = GetWindow( GW_CHILD );
	if( pWndChild == NULL )
	{ // if no child - fill entire client area
		bool bFillBk = true;
		if(		g_PaintManager->GetCb2DbTransparentMode(this)
			&&	g_PaintManager->PaintDockerBkgnd( dc, this )
			)
			bFillBk = false;
		if( bFillBk )
			dc.FillSolidRect(
				&rcClient,
				g_PaintManager->GetColor(
					CExtPaintManager::CLR_3DFACE_OUT
					)
				);
//
// DEBUG BLOCK BEGIN: - fill gradient & draw text
//
//		rcClient.DeflateRect( 2, 2 );
//		COLORREF clrFc = g_PaintManager->GetColor(COLOR_3DFACE);
//		COLORREF clrDk = g_PaintManager->GetColor(COLOR_3DDKSHADOW);
//		COLORREF clrHi = g_PaintManager->GetColor(COLOR_3DHILIGHT);
//		COLORREF clrLo = g_PaintManager->GetColor(COLOR_3DSHADOW);
//		dc.Draw3dRect( &rcClient, clrFc, clrDk );
//		rcClient.DeflateRect( 1, 1 );
//		dc.Draw3dRect( &rcClient, clrHi, clrLo );
//		rcClient.DeflateRect( 1, 1 );
//		dc.Draw3dRect( &rcClient, clrLo, clrHi );
//		rcClient.DeflateRect( 1, 1 );
//		dc.Draw3dRect( &rcClient, clrDk, clrFc );
//		rcClient.DeflateRect( 2, 2 );
//		UINT nDockBarID = GetSafeDockBarDlgCtrlID();
//		CExtPaintManager::stat_PaintGradientRect(
//			dc,
//			rcClient,
//			RGB( 128, 128, 255 ),
//			RGB( 0, 0, 0 ),
//			(nDockBarID==AFX_IDW_DOCKBAR_LEFT || nDockBarID==AFX_IDW_DOCKBAR_RIGHT)
//				? true : false
//			);
//		
//		CRect rcDrawText( rcClient );
//		rcDrawText.DeflateRect( 5, 5 );
//		CRect rcDrawTextShadow( rcDrawText );
//		CExtSafeString sText;
//		CFont * pFont = &g_PaintManager->m_FontNormal;
//		switch( nDockBarID )
//		{
//		case AFX_IDW_DOCKBAR_TOP:
//			sText = _T("Docked at top");
//			rcDrawTextShadow.OffsetRect( 1, 1 );
//		break;
//		case AFX_IDW_DOCKBAR_BOTTOM:
//			sText = _T("Docked at bottom");
//			rcDrawTextShadow.OffsetRect( 1, 1 );
//		break;
//		case AFX_IDW_DOCKBAR_LEFT:
//			sText = _T("Docked at left");
//			pFont = &g_PaintManager->m_FontNormalVert;
//			rcDrawText.OffsetRect( rcDrawText.Width(), 0 );
//			rcDrawText.OffsetRect( -1, -2 );
//			rcDrawTextShadow = rcDrawText;
//			rcDrawTextShadow.OffsetRect( 1, 1 );
//		break;
//		case AFX_IDW_DOCKBAR_RIGHT:
//			sText = _T("Docked at right");
//			pFont = &g_PaintManager->m_FontNormalVert;
//			rcDrawText.OffsetRect( rcDrawText.Width(), 0 );
//			rcDrawText.OffsetRect( -1, -2 );
//			rcDrawTextShadow = rcDrawText;
//			rcDrawTextShadow.OffsetRect( 1, 1 );
//		break;
//		default:
//			ASSERT( nDockBarID == AFX_IDW_DOCKBAR_FLOAT );
//			sText = _T("Floating");
//			rcDrawTextShadow.OffsetRect( 1, 1 );
//		break;
//		} // switch( nDockBarID )
//		CFont * pOldFont = dc.SelectObject( pFont );
//		int nOldBkMode = dc.SetBkMode( TRANSPARENT );
//		COLORREF clrOldTextColor = dc.SetTextColor( RGB(128,128,128) );
//		dc.DrawText( sText, &rcDrawTextShadow, DT_SINGLELINE|DT_NOCLIP );
//		dc.SetTextColor( RGB(255,255,255) );
//		dc.DrawText( sText, &rcDrawText, DT_SINGLELINE|DT_NOCLIP );
//		dc.SetTextColor( clrOldTextColor );
//		dc.SetBkMode( nOldBkMode );
//		dc.SelectObject( pOldFont );
//
// DEBUG BLOCK END: - fill gradient & draw text
//
	} // if no child - fill entire client area
	else
	{ // if has child - fill margins around child
//		CRect rcMargins = OnQueryFixedBarChildWindowMargins();
//		CRect rcExclude( rcClient );
//		rcExclude.DeflateRect( &rcMargins );
//		dc.ExcludeClipRect( &rcExclude );
		CExtPaintManager::stat_ExcludeChildAreas(
			dc,
			m_hWnd
			);
		bool bFillBk = true;
		if(		g_PaintManager->GetCb2DbTransparentMode(this)
			&&	g_PaintManager->PaintDockerBkgnd( dc, this )
			)
			bFillBk = false;
		if( bFillBk )
			dc.FillSolidRect(
				&rcClient,
				g_PaintManager->GetColor(
					CExtPaintManager::CLR_3DFACE_OUT
					)
				);
		dc.SelectClipRgn( NULL );
	} // if has child - fill margins around child
}

bool CExtPanelControlBar::_AffixmentIsAlignedHW() const
{
	ASSERT_VALID( this );
	return false;
}

LRESULT CExtPanelControlBar::DoHelpHitTest( CPoint ptHelpHitTest )
{
	ASSERT_VALID( this );
	return CExtControlBar::DoHelpHitTest( ptHelpHitTest );
}

bool CExtPanelControlBar::OnQueryMultiRowLayout() const
{
	ASSERT_VALID( this );
	return false;
}

#if (!defined __EXT_MFC_NO_CUSTOMIZE)

CExtCustomizeSite * CExtPanelControlBar::GetCustomizeSite()
{
	ASSERT_VALID( this );
	return NULL;
}

bool CExtPanelControlBar::OnCustomizeRegisterBar(
	CExtCustomizeSite * pCustomizeSite
	)
{
	ASSERT_VALID( this );
	ASSERT( pCustomizeSite != NULL );
	pCustomizeSite;
	return false;
}

void CExtPanelControlBar::OnCustomizeModeEnter()
{
	ASSERT_VALID( this );
}

void CExtPanelControlBar::OnCustomizeModeLeave()
{
	ASSERT_VALID( this );
}

void CExtPanelControlBar::OnCustomizeListBoxUpdate( CExtCustomizeToolbarsListBox * pWndList )
{
	ASSERT_VALID( this );
	ASSERT_VALID( pWndList );
	CExtToolControlBar::OnCustomizeListBoxUpdate( pWndList );
}

#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect Foss Software Inc
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions