📄 cooltabctrls.h
字号:
// using public member methods to access all variables.
//
// You need to add the...
// REFLECT_NOTIFICATIONS()
// macro to the parent's message map.
//
class CButtonTabCtrl :
public CCustomTabCtrl<CButtonTabCtrl>,
public CCustomDraw<CButtonTabCtrl>
{
public:
DECLARE_WND_CLASS(_T("WTL_CoolButtonTabCtrl"))
BEGIN_MSG_MAP(CButtonTabCtrl)
REFLECTED_NOTIFY_CODE_HANDLER(TCN_INITIALIZE, OnInitialize)
CHAIN_MSG_MAP(CCustomTabCtrl<CButtonTabCtrl>)
CHAIN_MSG_MAP_ALT(CCustomDraw<CButtonTabCtrl>, 1)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
LRESULT OnInitialize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
{
TCMETRICS metrics;
GetMetrics(&metrics);
metrics.cxButtonSpacing = 3;
metrics.cxMargin = 10;
SetMetrics(&metrics);
return 0;
}
DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
{
return CDRF_NOTIFYITEMDRAW; // We need per-item notifications
}
DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
{
::SetBkMode(lpNMCustomDraw->hdc, TRANSPARENT);
::SetTextColor(lpNMCustomDraw->hdc, ::GetSysColor(COLOR_BTNTEXT));
UINT state = 0;
if( lpNMCustomDraw->uItemState & CDIS_SELECTED ) state |= DFCS_PUSHED;
if( lpNMCustomDraw->uItemState & CDIS_DISABLED ) state |= DFCS_INACTIVE;
::DrawFrameControl(lpNMCustomDraw->hdc, &lpNMCustomDraw->rc, DFC_BUTTON, DFCS_BUTTONPUSH | state );
TCITEM item = { 0 };
TCHAR szText[128] = { 0 };
item.mask = TCIF_TEXT;
item.pszText = szText;
item.cchTextMax = (sizeof(szText)/sizeof(TCHAR)) - 1;
GetItem(lpNMCustomDraw->dwItemSpec, &item);
if( lpNMCustomDraw->uItemState & CDIS_SELECTED ) {
lpNMCustomDraw->rc.left += 2;
lpNMCustomDraw->rc.top += 2;
}
::DrawText(lpNMCustomDraw->hdc, item.pszText, ::lstrlen(item.pszText), &lpNMCustomDraw->rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
return CDRF_SKIPDEFAULT;
}
};
class CFolderTabCtrl :
public CCustomTabCtrl<CFolderTabCtrl>,
public CCustomDraw<CFolderTabCtrl>
{
public:
DECLARE_WND_CLASS(_T("WTL_CoolFolderTabCtrl"))
CFont m_font;
enum { CXOFFSET = 8 }; // defined pitch of trapezoid slant
enum { CXMARGIN = 2 }; // left/right text margin
enum { CYMARGIN = 1 }; // top/bottom text margin
enum { CYBORDER = 1 }; // top border thickness
BEGIN_MSG_MAP(CFolderTabCtrl)
MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
REFLECTED_NOTIFY_CODE_HANDLER(TCN_INITIALIZE, OnInitialize)
CHAIN_MSG_MAP(CCustomTabCtrl<CFolderTabCtrl>)
CHAIN_MSG_MAP_ALT(CCustomDraw<CFolderTabCtrl>, 1)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
LRESULT OnInitialize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
{
TCMETRICS metrics;
GetMetrics(&metrics);
metrics.cxIndent = CXOFFSET;
metrics.cxPadding = CXOFFSET + 3;
metrics.cxOverlap = CXOFFSET;
metrics.cxImagePadding = 2;
SetMetrics(&metrics);
return 0;
}
DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
{
return CDRF_NOTIFYITEMDRAW; // We need per-item notifications
}
DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
{
CDCHandle dc( lpNMCustomDraw->hdc );
bool bSelected = lpNMCustomDraw->uItemState & CDIS_SELECTED;
COLORREF bgColor = ::GetSysColor(bSelected ? COLOR_WINDOW : COLOR_3DFACE);
COLORREF fgColor = ::GetSysColor(bSelected ? COLOR_WINDOWTEXT : COLOR_BTNTEXT);
CBrush brush;
brush.CreateSolidBrush(bgColor); // background brush
dc.SetBkColor(bgColor); // text background
dc.SetTextColor(fgColor); // text color = fg color
CPen shadowPen;
shadowPen.CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW));
// Fill trapezoid
POINT pts[4];
RECT rc = lpNMCustomDraw->rc;
_GetTrapezoid(rc, pts);
CPenHandle hOldPen = dc.SelectStockPen(BLACK_PEN);
CRgn rgn;
rgn.CreatePolygonRgn(pts, 4, WINDING);
dc.FillRgn(rgn, brush);
// Draw edges. This requires two corrections:
// 1) Trapezoid dimensions don't include the right and bottom edges,
// so must use one pixel less on bottom (cybottom)
// 2) the endpoint of LineTo is not included when drawing the line, so
// must add one pixel (cytop)
pts[1].y--; // correction #1: true bottom edge y-coord
pts[2].y--; // ...ditto
pts[3].y--; // correction #2: extend final LineTo
dc.MoveTo(pts[0]); // upper left
dc.LineTo(pts[1]); // bottom left
dc.SelectPen(shadowPen); // bottom line is shadow color
dc.MoveTo(pts[1]); // line is inside trapezoid bottom
dc.LineTo(pts[2]); // ...
dc.SelectStockPen(BLACK_PEN); // upstroke is black
dc.LineTo(pts[3]); // y-1 to include endpoint
if( !bSelected ) {
// If not highlighted, upstroke has a 3D shadow, one pixel inside
pts[2].x--; // offset left one pixel
pts[3].x--; // ...ditto
dc.SelectPen(shadowPen);
dc.MoveTo(pts[2]);
dc.LineTo(pts[3]);
}
dc.SelectPen(hOldPen);
TCITEM item = { 0 };
TCHAR szText[128] = { 0 };
item.mask = TCIF_TEXT;
item.pszText = szText;
item.cchTextMax = (sizeof(szText) / sizeof(TCHAR)) - 1;
GetItem(lpNMCustomDraw->dwItemSpec, &item);
// Draw text
::InflateRect(&rc, -(CXOFFSET + CXMARGIN), -CYMARGIN);
HFONT hOldFont = dc.SelectFont(bSelected ? GetSelFont() : GetFont());
dc.DrawText(item.pszText, ::lstrlen(item.pszText), &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
dc.SelectFont(hOldFont);
return CDRF_SKIPDEFAULT;
}
void _GetTrapezoid(const RECT& rc, POINT* pts) const
{
pts[0].x = rc.left;
pts[0].y = rc.top;
pts[1].x = rc.left + CXOFFSET;
pts[1].y = rc.bottom;
pts[2].x = rc.right - CXOFFSET - 1;
pts[2].y = rc.bottom;
pts[3].x = rc.right - 1, rc.top;
pts[3].y = rc.top;
}
LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
// Initialize font
if( !m_font.IsNull() ) m_font.DeleteObject();
LOGFONT lf = { 0 };
lf.lfHeight = ::GetSystemMetrics(SM_CYHSCROLL) - CYMARGIN;
lf.lfWeight = FW_NORMAL;
lf.lfCharSet = DEFAULT_CHARSET;
::lstrcpy(lf.lfFaceName, _T("Arial"));
m_font.CreateFontIndirect(&lf);
SetFont(m_font);
bHandled = FALSE;
return 0;
}
};
class CDotNetTabCtrl :
public CCustomTabCtrl<CDotNetTabCtrl>,
public CCustomDraw<CDotNetTabCtrl>
{
public:
DECLARE_WND_CLASS(_T("WTL_DotNetTabCtrl"))
CFont m_font;
CFont m_fontBold;
CBrush m_hbrBack;
BEGIN_MSG_MAP(CDotNetTabCtrl)
MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
REFLECTED_NOTIFY_CODE_HANDLER(TCN_INITIALIZE, OnInitialize)
CHAIN_MSG_MAP(CCustomTabCtrl<CDotNetTabCtrl>)
CHAIN_MSG_MAP_ALT(CCustomDraw<CDotNetTabCtrl>, 1)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
LRESULT OnInitialize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
{
TCMETRICS metrics;
GetMetrics(&metrics);
metrics.cxIndent = 6;
metrics.cxPadding = 0;
metrics.cxMargin = 4;
metrics.cxSelMargin = 2;
metrics.cxOverlap = 2;
metrics.cxImagePadding = 2;
SetMetrics(&metrics);
return 0;
}
DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
{
CDCHandle dc( lpNMCustomDraw->hdc );
RECT rc;
GetClientRect(&rc);
HBRUSH hOldBrush = dc.SelectBrush(m_hbrBack);
dc.PatBlt(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY);
if( GetStyle() & TCS_BOTTOM )
{
dc.SelectStockPen(BLACK_PEN);
dc.MoveTo(rc.left, rc.top + 1);
dc.LineTo(rc.right, rc.top + 1);
}
else
{
dc.SelectStockPen(WHITE_PEN);
dc.MoveTo(rc.left, rc.bottom - 1);
dc.LineTo(rc.right, rc.bottom - 1);
}
dc.SelectBrush(hOldBrush);
dc.SetBkMode(TRANSPARENT);
return CDRF_NOTIFYITEMDRAW; // We need per-item notifications
}
DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
{
CDCHandle dc( lpNMCustomDraw->hdc );
RECT rc = lpNMCustomDraw->rc;
bool bSelected = (lpNMCustomDraw->uItemState & CDIS_SELECTED) != 0;
int iCurSel = GetCurSel();
DWORD dwStyle = GetStyle();
DWORD dwExtStyle = GetExtendedStyle();
if( dwStyle & TCS_BUTTONS ) /* */;
else if( dwStyle & TCS_BOTTOM ) rc.bottom -= 3;
else rc.top += 3;
// Paint separators if needed
if( dwExtStyle & TCS_EX_FLATSEPARATORS )
{
if( (int) lpNMCustomDraw->dwItemSpec != iCurSel
&& (int) lpNMCustomDraw->dwItemSpec != iCurSel - 1
&& (int) lpNMCustomDraw->dwItemSpec != GetItemCount() - 1 )
{
RECT rcLine = { rc.right - 1, rc.top + 2, rc.right, rc.bottom - 2 };
dc.FillRect(&rcLine, ::GetSysColorBrush(COLOR_GRAYTEXT));
rc.right -= 2;
}
}
rc.right--;
RECT rcText = rc;
// Tab is selected, so paint tab folder
if( dwStyle & TCS_BUTTONS )
{
::InflateRect(&rc, -4, -3);
::InflateRect(&rcText, -2, -2);
if( bSelected )
{
dc.FillRect(&rc, ::GetSysColorBrush(COLOR_HIGHLIGHTTEXT));
dc.Draw3dRect(&rc, ::GetSysColor(COLOR_HIGHLIGHT), ::GetSysColor(COLOR_HIGHLIGHT));
}
}
else if( dwStyle & TCS_BOTTOM )
{
if( bSelected )
{
dc.FillRect(&rc, ::GetSysColorBrush(COLOR_BTNFACE));
dc.SelectStockPen(WHITE_PEN);
dc.MoveTo(rc.left, rc.top);
dc.LineTo(rc.left, rc.bottom);
dc.SelectStockPen(BLACK_PEN);
dc.LineTo(rc.right, rc.bottom);
dc.LineTo(rc.right, rc.top);
}
rcText.top += 4;
rcText.bottom -= 1;
}
else
{
if( bSelected )
{
dc.FillRect(&rc, ::GetSysColorBrush(COLOR_BTNFACE));
dc.SelectStockPen(WHITE_PEN);
dc.MoveTo(rc.left, rc.bottom);
dc.LineTo(rc.left, rc.top);
dc.LineTo(rc.right, rc.top);
dc.SelectStockPen(BLACK_PEN);
dc.LineTo(rc.right, rc.bottom);
}
rcText.top += 1;
}
// Get some item information
COOLTCITEM item;
::ZeroMemory(&item, sizeof(item));
TCHAR szText[128] = { 0 };
item.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_TEXTCOLOR;
item.pszText = szText;
item.cchTextMax = (sizeof(szText) / sizeof(TCHAR)) - 1;
GetItem(lpNMCustomDraw->dwItemSpec, &item);
TCMETRICS metrics;
GetMetrics(&metrics);
CImageList Images = GetImageList();
rcText.left += 2;
::InflateRect(&rcText, -metrics.cxPadding, 0);
if( item.iImage >= 0 && (item.mask & TCIF_IMAGE) != 0 && !Images.IsNull() )
{
SIZE szIcon;
Images.GetIconSize(szIcon);
if( szIcon.cx * 2 < rcText.right - rcText.left ) {
Images.Draw(dc, item.iImage, rcText.left + metrics.cxImagePadding, rcText.top + (((rcText.bottom - rcText.top)/2) - (szIcon.cy/2)), ILD_TRANSPARENT);
rcText.left += szIcon.cx + (metrics.cxImagePadding * 2);
}
}
if( item.mask & TCIF_TEXT )
{
dc.SetTextColor(::GetSysColor(COLOR_BTNTEXT));
if( item.mask & TCIF_TEXTCOLOR ) dc.SetTextColor(item.clrText);
HFONT hOldFont = dc.SelectFont(bSelected ? GetSelFont() : GetFont());
dc.DrawText(item.pszText, -1, &rcText, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_END_ELLIPSIS);
dc.SelectFont(hOldFont);
}
return CDRF_SKIPDEFAULT;
}
LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
// Initialize font
if( !m_font.IsNull() ) m_font.DeleteObject();
NONCLIENTMETRICS ncm = { 0 };
ncm.cbSize = sizeof(ncm);
::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
ncm.lfSmCaptionFont.lfWeight = FW_NORMAL;
m_font.CreateFontIndirect(&ncm.lfSmCaptionFont);
SetFont(m_font);
if( !m_fontBold.IsNull() ) m_fontBold.DeleteObject();
ncm.lfSmCaptionFont.lfWeight = FW_BOLD;
m_fontBold.CreateFontIndirect(&ncm.lfSmCaptionFont);
SetSelFont(m_fontBold);
// Background brush
if( !m_hbrBack.IsNull() ) m_hbrBack.DeleteObject();
CWindowDC dc(NULL);
int nBitsPerPixel = dc.GetDeviceCaps(BITSPIXEL);
if( nBitsPerPixel > 8 ) {
COLORREF clrBtnHilite = ::GetSysColor(COLOR_BTNHILIGHT);
COLORREF clrBtnFace = ::GetSysColor(COLOR_BTNFACE);
COLORREF clrLight =
RGB( GetRValue(clrBtnFace) + ((GetRValue(clrBtnHilite) - GetRValue(clrBtnFace)) / 2),
GetGValue(clrBtnFace) + ((GetGValue(clrBtnHilite) - GetGValue(clrBtnFace)) / 2),
GetBValue(clrBtnFace) + ((GetBValue(clrBtnHilite) - GetBValue(clrBtnFace)) / 2) );
m_hbrBack.CreateSolidBrush(clrLight);
}
else {
m_hbrBack = CDCHandle::GetHalftoneBrush();
}
bHandled = FALSE;
return 0;
}
};
#endif // __COOLTABCTRLS_H__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -