The code for the tab window you described may look like this:
#if (! defined __EXT_TAB_FLAT_WND_H)
#include <ExtTabFlatWnd.h>
#endif
class CExtTabButtonsWnd : public CExtTabFlatWnd
{
public:
DECLARE_DYNCREATE( CExtTabButtonsWnd );
CExtTabButtonsWnd();
//{{AFX_VIRTUAL(CExtTabButtonsWnd)
//}}AFX_VIRTUAL
virtual ~CExtTabButtonsWnd();
protected:
void OnTabWndDrawItem(
CDC & dc,
CRect & rcTabItemsArea,
LONG nItemIndex,
TAB_ITEM_INFO * pTii,
bool bTopLeft,
bool bHorz,
bool bSelected,
bool bCenteredText,
bool bGroupedMode,
bool bInGroupActive,
bool bInvertedVerticalMode,
const CRect & rcEntireItem,
CSize sizeTextMeasured,
CFont * pFont,
__EXT_MFC_SAFE_LPCTSTR sText,
CExtCmdIcon * pIcon
);
void OnTabWndMeasureItemAreaMargins(
LONG & nSpaceBefore,
LONG & nSpaceAfter,
LONG & nSpaceOver
);
virtual void OnTabWndUpdateItemMeasure(
TAB_ITEM_INFO * pTii,
CDC & dcMeasure,
CSize & sizePreCalc
);
virtual void OnTabWndEraseClientArea(
CDC & dc,
CRect & rcClient,
CRect & rcTabItemsArea,
CRect & rcTabNearBorderArea,
DWORD dwOrientation,
bool bGroupedMode
);
virtual void OnTabWndDrawEntire(
CDC & dc,
CRect & rcClient
);
virtual INT OnTabWndGetParentSizingMargin(
DWORD dwOrientation
) const;
virtual void OnFlatTabWndQueryItemInclines(
LONG nItemIndex,
bool bSelected,
bool * p_bItemHasInclineBefore,
bool * p_bItemHasInclineAfter
)
{
ASSERT_VALID( this );
nItemIndex;
bSelected;
if( p_bItemHasInclineBefore != NULL )
*p_bItemHasInclineBefore = 0;
if( p_bItemHasInclineAfter != NULL )
*p_bItemHasInclineAfter = 0;
}
//{{AFX_MSG(CExtTabButtonsWnd)
//}}AFX_MSG
afx_msg LRESULT OnSizeParent( WPARAM wParam, LPARAM lParam );
DECLARE_MESSAGE_MAP()
}; // class CExtTabButtonsWnd
Here is implementation:
#if (!defined __AFXPRIV_H__)
#include <AfxPriv.h>
#endif
#if _MFC_VER < 0x700
#include <../src/AfxImpl.h>
#else
#include <../src/mfc/AfxImpl.h>
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE( CExtTabButtonsWnd, CExtTabFlatWnd );
CExtTabButtonsWnd::CExtTabButtonsWnd()
{
}
CExtTabButtonsWnd::~CExtTabButtonsWnd()
{
}
BEGIN_MESSAGE_MAP(CExtTabButtonsWnd, CExtTabFlatWnd)
//{{AFX_MSG_MAP(CExtTabButtonsWnd)
//}}AFX_MSG_MAP
ON_MESSAGE( WM_SIZEPARENT, OnSizeParent )
END_MESSAGE_MAP()
void CExtTabButtonsWnd::OnTabWndDrawItem(
CDC & dc,
CRect & rcTabItemsArea,
LONG nItemIndex,
TAB_ITEM_INFO * pTii,
bool bTopLeft,
bool bHorz,
bool bSelected,
bool bCenteredText,
bool bGroupedMode,
bool bInGroupActive,
bool bInvertedVerticalMode,
const CRect & rcEntireItem,
CSize sizeTextMeasured,
CFont * pFont,
__EXT_MFC_SAFE_LPCTSTR sText,
CExtCmdIcon * pIcon
)
{
ASSERT_VALID( this );
ASSERT_VALID( pTii );
pTii;
ASSERT( dc.GetSafeHdc() != NULL );
ASSERT( pFont != NULL );
ASSERT( pFont->GetSafeHandle() != NULL );
nItemIndex;
rcTabItemsArea;
bGroupedMode;
bInGroupActive;
bHorz;
bTopLeft;
CRect rcItem( rcEntireItem );
switch( OrientationGet() )
{
case __ETWS_ORIENT_TOP:
rcItem.DeflateRect( 0, 1, 0, 0 );
break;
case __ETWS_ORIENT_BOTTOM:
rcItem.DeflateRect( 0, 0, 0, 1 );
break;
case __ETWS_ORIENT_LEFT:
rcItem.DeflateRect( 1, 0, 0, 0 );
break;
case __ETWS_ORIENT_RIGHT:
rcItem.DeflateRect( 0, 0, 1, 0 );
break;
}
CRect rcExtendClip( rcItem );
CRect rcClient;
GetClientRect( &rcClient );
if( bHorz )
{
rcExtendClip.top = rcClient.top;
rcExtendClip.bottom = rcClient.bottom;
rcExtendClip.left = max( rcClient.left, rcTabItemsArea.left );
rcExtendClip.right = min( rcExtendClip.right, rcTabItemsArea.right );
}
else
{
rcExtendClip.left = rcClient.left;
rcExtendClip.right = rcClient.right;
rcExtendClip.top = max( rcClient.top, rcTabItemsArea.top );
rcExtendClip.bottom = min( rcExtendClip.bottom, rcTabItemsArea.bottom );
}
CRgn rgnExtendClip;
if( rgnExtendClip.CreateRectRgnIndirect( &rcExtendClip ) )
dc.SelectClipRgn( &rgnExtendClip, RGN_OR );
bool bSelectedAppearance = false;
if( ( bGroupedMode && bInGroupActive )
|| ( (!bGroupedMode) && bSelected )
)
bSelectedAppearance = true;
COLORREF clrLight;
COLORREF clrShadow;
COLORREF clrDkShadow;
COLORREF clrTabBk;
COLORREF clrText;
OnFlatTabWndGetItemColors(
nItemIndex,
bSelectedAppearance,
clrLight,
clrShadow,
clrDkShadow,
clrTabBk,
clrText
);
if( bSelectedAppearance )
{
dc.FillSolidRect( &rcItem, clrTabBk );
dc.Draw3dRect( &rcItem, clrDkShadow, clrDkShadow );
}
CSize _sizeIcon( 0, 0 );
bool bDrawIcon = (
pIcon != NULL
&& (!pIcon->IsEmpty())
&& (GetTabWndStyle()&__ETWS_HIDE_ICONS) == 0
);
if( bDrawIcon )
{
_sizeIcon = pIcon->GetSize();
ASSERT( _sizeIcon.cx > 0 && _sizeIcon.cy > 0 );
}
CRect rcItemForIcon( rcItem );
if( bDrawIcon
&& _sizeIcon.cx > 0
&& _sizeIcon.cy > 0
)
{
rcItemForIcon.right = rcItemForIcon.left + _sizeIcon.cx;
rcItemForIcon.bottom = rcItemForIcon.top + _sizeIcon.cy;
rcItemForIcon.OffsetRect(
bHorz ? 0 : ((rcItem.Width() - _sizeIcon.cx) / 2),
bHorz ? ((rcItem.Height() - _sizeIcon.cy) / 2) : 0
);
if( rcItemForIcon.left < (rcItem.left+1) )
rcItemForIcon.left = (rcItem.left+1);
if( rcItemForIcon.right < (rcItem.right-1) )
rcItemForIcon.right = (rcItem.right-1);
if( rcItemForIcon.top < (rcItem.top+1) )
rcItemForIcon.top = (rcItem.top+1);
if( rcItemForIcon.bottom < (rcItem.bottom-1) )
rcItemForIcon.bottom = (rcItem.bottom-1);
}
CExtSafeString sItemText( (sText == NULL) ? _T("") : sText );
CRect rcText(
rcItem.left
+ ( bHorz
? (_sizeIcon.cx +
((_sizeIcon.cx > 0) ? __EXTTAB_MARGIN_ICON2TEXT_X : 0)
)
: 0
),
rcItem.top
+ ( bHorz
? 0
: (_sizeIcon.cy +
((_sizeIcon.cy > 0) ? __EXTTAB_MARGIN_ICON2TEXT_Y : 0)
)
),
rcItem.right,
rcItem.bottom
);
if( ! bHorz )
{
int nWidth0 = rcText.Width();
int nWidth1 = rcItem.Width() + __EXTTAB_MARGIN_ICON2TEXT_X*2;
if( nWidth1 > nWidth0 )
{
if( bInvertedVerticalMode )
rcText.left = rcText.right - nWidth1;
else
rcText.right = rcText.left + nWidth1;
}
}
CSize _sizeText = rcText.Size();
bool bDrawText = ( rcText.Width() > 6 && rcText.Height() > 6 ) ? true : false;
if( (!bDrawText) && (!( bGroupedMode && (!bInGroupActive) )) )
{
rcItemForIcon.OffsetRect(
bHorz ? (rcItem.Width() - _sizeIcon.cx)/2 : 0,
bHorz ? 0 : (rcItem.Height() - _sizeIcon.cy)/2
);
}
if( bDrawIcon )
{
if( (bHorz && rcItemForIcon.Width() >= _sizeIcon.cx )
|| (!bHorz && rcItemForIcon.Height() >= _sizeIcon.cy)
)
{
CRect rcTmpText( 0, 0, 0, 0 );
rcItemForIcon.OffsetRect( -4, -1 );
PmBridge_GetPM()->PaintIcon(
dc,
true,
sItemText,
pIcon,
rcItemForIcon,
rcTmpText,
false,
pTii->EnabledGet(),
false,
0
);
}
}
if( bDrawText )
{
ASSERT( pFont != NULL );
ASSERT( pFont->GetSafeHandle() != NULL );
COLORREF clrOldText = dc.SetTextColor( clrText );
INT nOldBkMode = dc.SetBkMode( TRANSPARENT );
CFont * pOldFont = dc.SelectObject( pFont );
if( ! bHorz )
{
if( ! bDrawIcon )
rcText.top += 4;
else
{
rcText.top =
rcItemForIcon.top
+ _sizeIcon.cy
+ __EXTTAB_MARGIN_ICON2TEXT_Y;
}
rcText.OffsetRect(
bInvertedVerticalMode
? ((sizeTextMeasured.cy/2) + 3)
: - ((sizeTextMeasured.cy/2) + 3)
,
0
);
CPoint ptCenter = rcText.CenterPoint();
if( bCenteredText )
{
UINT nOldTA = dc.SetTextAlign( TA_CENTER | TA_BASELINE );
dc.ExtTextOut(
ptCenter.x,
ptCenter.y,
ETO_CLIPPED,
&rcText,
sItemText,
sItemText.GetLength(),
NULL
);
dc.SetTextAlign( nOldTA );
}
else
{
UINT nOldTA = dc.SetTextAlign( TA_TOP | TA_BASELINE );
if( bInvertedVerticalMode )
ptCenter.y =
rcText.bottom - (rcText.Height() - sizeTextMeasured.cx)
;
else
ptCenter.y =
rcText.top
;
dc.ExtTextOut(
ptCenter.x,
ptCenter.y,
ETO_CLIPPED,
&rcText,
sItemText,
sItemText.GetLength(),
NULL
);
dc.SetTextAlign( nOldTA );
}
}
else
{
UINT nFormat =
DT_SINGLELINE|DT_VCENTER|DT_END_ELLIPSIS;
if( bCenteredText )
nFormat |= DT_CENTER;
else
nFormat |= DT_LEFT;
if( ! bDrawIcon )
rcText.left += 4;
else
{
rcText.left =
rcItemForIcon.left
+ _sizeIcon.cx
+ __EXTTAB_MARGIN_ICON2TEXT_X;
}
dc.DrawText(
sItemText,
sItemText.GetLength(),
rcText,
nFormat
);
}
dc.SelectObject( pOldFont );
dc.SetBkMode( nOldBkMode );
dc.SetTextColor( clrOldText );
}
}
void CExtTabButtonsWnd::OnTabWndMeasureItemAreaMargins(
LONG & nSpaceBefore,
LONG & nSpaceAfter,
LONG & nSpaceOver
)
{
ASSERT_VALID( this );
nSpaceBefore;
nSpaceAfter;
nSpaceOver;
}
void CExtTabButtonsWnd::OnTabWndUpdateItemMeasure(
TAB_ITEM_INFO * pTii,
CDC & dcMeasure,
CSize & sizePreCalc
)
{
ASSERT_VALID( this );
ASSERT( dcMeasure.GetSafeHdc() != NULL );
pTii;
dcMeasure;
sizePreCalc;
}
void CExtTabButtonsWnd::OnTabWndEraseClientArea(
CDC & dc,
CRect & rcClient,
CRect & rcTabItemsArea,
CRect & rcTabNearBorderArea,
DWORD dwOrientation,
bool bGroupedMode
)
{
ASSERT_VALID( this );
ASSERT( dc.GetSafeHdc() != NULL );
rcTabItemsArea;
rcTabNearBorderArea;
dwOrientation;
bGroupedMode;
CExtPaintManager * pPM = PmBridge_GetPM();
if( ! pPM->PaintDockerBkgnd( true, dc, this ) )
dc.FillSolidRect(
&rcClient,
pPM->GetColor(
CExtPaintManager::CLR_3DFACE_OUT,
this
)
);
}
void CExtTabButtonsWnd::OnTabWndDrawEntire(
CDC & dc,
CRect & rcClient
)
{
ASSERT_VALID( this );
ASSERT( dc.GetSafeHdc() != NULL );
CExtTabWnd::OnTabWndDrawEntire(
dc,
rcClient
);
}
INT CExtTabButtonsWnd::OnTabWndGetParentSizingMargin(
DWORD dwOrientation
) const
{
ASSERT_VALID( this );
switch( dwOrientation )
{
case __ETWS_ORIENT_TOP:
return 3;
case __ETWS_ORIENT_BOTTOM:
return 1;
case __ETWS_ORIENT_LEFT:
return 3;
case __ETWS_ORIENT_RIGHT:
return 1;
default:
ASSERT( FALSE );
return 0;
}
}
LRESULT CExtTabButtonsWnd::OnSizeParent( WPARAM wParam, LPARAM lParam )
{
ASSERT_VALID( this );
return CExtTabWnd::OnSizeParent( wParam, lParam );
}