概述:
CQsTabCtrl 继承与 CTabCtrl,通过自绘来背景的绘制,以及各种选中状态的的绘制,以及选中和非选中字体的颜色等一些属性。
代码实现如下:
#pragma once;
#include "QsInclude.h"
#define MAX_TABCTRL_TEXT 256 //TabCtrl中Item最大的字符数
#define QS_TAB_SYSYSTEM 0x00000001 //TabCtrl系统样式
#define QS_TAB_OWNERDRAW 0x00000002 //TabCtrl自绘样式,默认为自绘样式
class CQsTabCtrl :
public CWindowImpl<CQsTabCtrl, CTabCtrl>,
public CImageMgrCtrlBase< CQsTabCtrl>,
public COwnerDraw< CQsTabCtrl >
{
typedef CWindowImpl< CQsTabCtrl, CTabCtrl > theBaseClass;
typedef CImageMgrCtrlBase< CQsTabCtrl> theImageCtrlBaseClass;
Color m_SelColor; //选中时字体的颜色
Color m_UnSelColor; //未选中字体的颜色
public:
BEGIN_MSG_MAP( CQsTabCtrl )
MESSAGE_HANDLER( WM_PAINT, OnPaint )
MESSAGE_HANDLER( WM_ERASEBKGND, OnEraseBKGnd )
CHAIN_MSG_MAP( theImageCtrlBaseClass )
CHAIN_MSG_MAP_ALT( COwnerDraw< CQsTabCtrl >, 1 )
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
/**
*@method CQsTabCtrl
*@brief CQsTabCtrl类构造函数
*
*@return
*/
CQsTabCtrl():
m_SelColor(255, 0, 0, 0),
m_UnSelColor(255, 128, 128, 128)
{
m_uFirstPos = CONTROL_TAB_FIRST;
m_uLastPos = CONTROL_TAB_LAST;
SetQsStyle(QS_RAD_OWNERDRAW);
}
/**
*@method ~CQsTabCtrl
*@brief 析构造函数
*
*@return
*/
virtual ~CQsTabCtrl()
{
}
/**
*@method Create
*@brief 通过Create来创建窗口
*
*@param HWND hWndParent parent window
*@param ATL::_U_RECT rect window rect
*@param LPCTSTR szWindowName the window name
*@param DWORD dwStyle base window style
*@param DWORD dwExStyle extended window style
*@param ATL::_U_MENUorID MenuOrID menu or ID
*@param LPVOID lpCreateParam create param
*@return HWND
*/
HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
{
return theBaseClass::Create( hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam);
}
/**
*@method SetSelTextColor
*@brief 设置选中Item时绘制字体的颜色
*
*@param Color SelColor 设置的选中时字体的颜色
*@return void
*/
void SetSelTextColor(Color SelColor)
{
m_SelColor = SelColor;
}
/**
*@method SetUnSelTextColor
*@brief 设置未选中Item时绘制字体的颜色
*
*@param Color UnSelColor 设置的未选中时字体的颜色
*@return void
*/
void SetUnSelTextColor(Color UnSelColor)
{
m_UnSelColor = UnSelColor;
}
/**
*@method SubclassWindow
*@brief 类对象关联
*
*@param HWND hWnd 对象句柄
*@return BOOL 成功返回TRUE,失败返回FALSE
*/
BOOL SubclassWindow( HWND hWnd )
{
BOOL bRet = theBaseClass::SubclassWindow( hWnd );
ModifyStyle( TCS_RIGHTJUSTIFY, TCS_FIXEDWIDTH );
if(m_dwQsStyle&QS_TAB_OWNERDRAW)
{
//设置标签尺寸
Image *pImage = GetImage( CONTROL_TAB_ACTIVE );
if( pImage )
{
SetItemSize( CSize( pImage->GetWidth(), pImage->GetHeight() ) );
}
}
return bRet;
}
/**
*@method DeleteItem
*@brief 按钮重画函数
*
*@param LPDELETEITEMSTRUCT lpdis 详见MSN
*@return BOOL
*/
BOOL DeleteItem(LPDELETEITEMSTRUCT /*lpdis*/)
{
return TRUE;
}
/**
*@method RefreshItemSize
*@brief 根据当前图片更新ITEM长宽
*
*@param int nItemWidth 标签页宽度
*@param int nItemHeight 标签页高度
*@return void
*/
void RefreshItemSize( int nItemWidth, int nItemHeight)
{
SetItemSize( CSize( nItemWidth, nItemHeight ) );
}
protected:
/**
*@method OnPaint
*@brief 绘制消息函数
*
*@param UINT uMsg 消息类型
*@param WPARAM wParam 未被使用
*@param LPARAM lParam 详见MSDN
*@param BOOL & 详见MSDN
*@return LRESULT 详见MSDN
*/
LRESULT OnPaint( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ )
{
if(m_dwQsStyle&QS_TAB_SYSYSTEM)
{
return DefWindowProc( uMsg, wParam, lParam );
}
WTL::CPaintDC paintDC( m_hWnd );
paintDC.SetBkMode( TRANSPARENT );
CRect rc;
GetClientRect( rc );
//创建内存作图对象
WTL::CDC memDC;
memDC.CreateCompatibleDC( paintDC.m_hDC );
WTL::CBitmap memBitmap;
memBitmap.CreateCompatibleBitmap( paintDC.m_hDC, rc.Width(), rc.Height() );
HBITMAP hOldBmp = memDC.SelectBitmap( memBitmap );
//获得控件背景
memDC.SetBkMode( TRANSPARENT );
::SendMessage( GetParent(), WM_DRAWBKGNDUI, ( WPARAM )memDC.m_hDC, ( LPARAM )m_hWnd );
Image *pBkImage = GetImage( CONTROL_TAB_BKGND );
if( pBkImage )
{
Graphics graph( memDC.m_hDC );
graph.SetPageScale( 1.0 );
graph.SetPageUnit( UnitPixel );
graph.SetSmoothingMode( SmoothingModeNone );
graph.DrawImage( pBkImage, Rect( 0, 0, rc.Width(), rc.Height() ), 0, 0, pBkImage->GetWidth(),
pBkImage->GetHeight(), UnitPixel );
graph.ReleaseHDC( memDC.m_hDC );
}
int count = GetItemCount();
int cursel = GetCurSel();
for( int i = 0; i < count; i++ )
{
Image *pImage = NULL;
if( i == cursel )
{
pImage = GetImage( CONTROL_TAB_ACTIVE_0 + i );
if( !pImage )
pImage = GetImage( CONTROL_TAB_ACTIVE );
memDC.SetTextColor( m_SelColor.ToCOLORREF());
}
else
{
pImage = GetImage( CONTROL_TAB_NORMAL_0 + i );
if( !pImage )
pImage = GetImage( CONTROL_TAB_NORMAL );
memDC.SetTextColor( m_UnSelColor.ToCOLORREF() );
}
//绘制图片
CRect rcItem;
GetItemRect( i, rcItem );
//准备GDI+作图对象
if( pImage )
{
Graphics graph( memDC.m_hDC );
graph.DrawImage( pImage, Rect( rcItem.left, rcItem.top, rcItem.Width(), rcItem.Height() ),
0, 0, pImage->GetWidth(), pImage->GetHeight(), UnitPixel );
graph.ReleaseHDC( memDC.m_hDC );
}
//绘制文字
CString strText = _T("");
TCITEM tcItem;
ZeroMemory( &tcItem, sizeof( TCITEM ) );
tcItem.mask = TCIF_TEXT;
tcItem.pszText = strText.GetBuffer( MAX_TABCTRL_TEXT );
tcItem.cchTextMax = MAX_TABCTRL_TEXT;
GetItem( i, &tcItem );
strText.ReleaseBuffer();
//获得控件当前使用的字体, //标签非活动状态
//标签活动状态
HFONT hFont = NULL;
if( i == cursel )
{
hFont = GetStateFont( CONTROL_TAB_ACTIVE );
}
else
{
hFont = GetStateFont( CONTROL_TAB_NORMAL);
}
if( hFont == NULL )
{
hFont = GetDefaultFont();
}
HFONT hOldFont = memDC.SelectFont( hFont );
memDC.DrawText( strText, -1, &rcItem, DT_SINGLELINE|DT_CENTER|DT_VCENTER );
memDC.SelectFont( hOldFont );
::DeleteObject( hFont );
}
//提交图像
paintDC.BitBlt( 0, 0, rc.Width(), rc.Height(), memDC.m_hDC, 0, 0, SRCCOPY );
memDC.SelectBitmap( hOldBmp );
memBitmap.DeleteObject();
memDC.DeleteDC();
return 0;
}
/**
*@method OnEraseBKGnd
*@brief 背景绘制消息函数
*
*@param UINT uMsg 消息类型
*@param WPARAM 详见MSDN
*@param LPARAM 详见MSDN
*@param BOOL & 详见MSDN
*@return LRESULT 详见MSDN
*/
LRESULT OnEraseBKGnd( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/ )
{
//禁止绘制底色
return 0;
}
};