You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

578 lines
12 KiB
C++

// XTPSkinObjectTab.cpp: implementation of the CXTPSkinObjectTab class.
//
// This file is a part of the XTREME SKINFRAMEWORK MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Common/Uxtheme.h"
#include "Common/Tmschema.h"
#include "Common/XTPColorManager.h"
#include "Common/XTPDrawHelpers.h"
#include "XTPSkinObject.h"
#include "XTPSkinObjectFrame.h"
#include "XTPSkinObjectTab.h"
#include "XTPSkinManager.h"
#include "XTPSkinImage.h"
#if defined(__VSSYM32_H__) && !defined(TMT_STOCKIMAGEFILE)
#define TMT_STOCKIMAGEFILE 3007
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define DT_HIDEPREFIX 0x00100000
AFX_INLINE BOOL IsLeft(DWORD dwStyle)
{
return ((dwStyle & (TCS_VERTICAL|TCS_RIGHT|TCS_BOTTOM)) == TCS_VERTICAL);
}
AFX_INLINE BOOL IsRight(DWORD dwStyle)
{
return ((dwStyle & (TCS_VERTICAL|TCS_RIGHT|TCS_BOTTOM)) == (TCS_VERTICAL|TCS_RIGHT));
}
AFX_INLINE BOOL IsTop(DWORD dwStyle)
{
return ((dwStyle & (TCS_VERTICAL|TCS_RIGHT|TCS_BOTTOM)) == 0);
}
AFX_INLINE BOOL IsBottom(DWORD dwStyle)
{
return ((dwStyle & (TCS_VERTICAL|TCS_RIGHT|TCS_BOTTOM)) == TCS_BOTTOM);
}
AFX_INLINE BOOL IsVert(DWORD dwStyle)
{
return (IsRight(dwStyle) || IsLeft(dwStyle));
}
AFX_INLINE BOOL IsHorz(DWORD dwStyle)
{
return (IsTop(dwStyle) || IsBottom(dwStyle));
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CXTPSkinObjectTab, CXTPSkinObjectFrame)
CXTPSkinObjectTab::CXTPSkinObjectTab()
{
m_strClassName = _T("TAB");
m_nHotItem = -1;
m_bPaint = FALSE;
}
CXTPSkinObjectTab::~CXTPSkinObjectTab()
{
}
BEGIN_MESSAGE_MAP(CXTPSkinObjectTab, CXTPSkinObjectFrame)
//{{AFX_MSG_MAP(CXTPSkinObjectTab)
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient)
ON_WM_MOUSEMOVE()
ON_MESSAGE_VOID(WM_MOUSELEAVE, OnMouseLeave)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CXTPSkinObjectTab message handlers
BOOL CXTPSkinObjectTab::OnEraseBkgnd(CDC* pDC)
{
CXTPClientRect rc(this);
CXTPBufferDC dcMem(pDC->GetSafeHdc(), rc);
FillClient(&dcMem, rc);
return TRUE;
}
CRect CXTPSkinObjectTab::GetHeaderRect()
{
CRect rcHeader;
GetClientRect(&rcHeader);
CTabCtrl* pTabCtrl = (CTabCtrl*)this;
// get the selected tab item rect.
CRect rcItem;
pTabCtrl->GetItemRect(pTabCtrl->GetCurSel(), &rcItem);
DWORD dwStyle = GetStyle();
if (IsRight(dwStyle))
{
rcHeader.left = rcItem.left;
}
else if (IsLeft(dwStyle))
{
rcHeader.right = rcItem.right;
}
else if (IsBottom(dwStyle))
{
rcHeader.top = rcItem.top;
}
else
{
rcHeader.bottom = (rcHeader.top + rcItem.Height()) * pTabCtrl->GetRowCount() + GetMetrics()->m_cyEdge;
}
return rcHeader;
}
void CXTPSkinObjectTab::FillClient(CDC* pDC, CRect rc)
{
FillBackground(pDC, rc);
if (GetStyle() & TCS_BUTTONS)
return;
CXTPSkinManagerClass* pClass = GetSkinClass();
CRect rcClient(rc);
CRect rcHeader = GetHeaderRect();
DWORD dwStyle = GetStyle();
if (IsRight(dwStyle))
{
rcClient.right = rcHeader.left;
}
else if (IsLeft(dwStyle))
{
rcClient.left = rcHeader.right;
}
else if (IsBottom(dwStyle))
{
rcClient.bottom = rcHeader.top;
}
else
{
rcClient.top = rcHeader.bottom;
}
pClass->DrawThemeBackground(pDC, TABP_PANE, 0, &rcClient);
}
void CXTPSkinObjectTab::FillTabFace(CDC* pDC, CRect rcItem, int iItem, int iCount, BOOL bSelected)
{
if (GetStyle() & TCS_BUTTONS)
{
CXTPSkinManagerClass* pClassButton = GetSkinManager()->GetSkinClass(this, _T("BUTTON"));
int nState = bSelected? PBS_PRESSED: PBS_NORMAL;
pClassButton->DrawThemeBackground(pDC, BP_PUSHBUTTON, nState, rcItem);
return;
}
if (bSelected)
{
rcItem.InflateRect(2, 2, 2, 2);
}
CXTPSkinManagerClass* pClass = GetSkinClass();
int nStateId = bSelected ? TIS_SELECTED: m_nHotItem == iItem ? TIS_HOT : TIS_NORMAL;
pClass->DrawThemeBackground(pDC, iItem == 0 ? TABP_TOPTABITEMLEFTEDGE :
iItem == iCount - 1 && !bSelected ? TABP_TOPTABITEMRIGHTEDGE : TABP_TOPTABITEM,
nStateId, &rcItem);
}
void CXTPSkinObjectTab::DrawTabIcon(CDC* pDC, CRect& rcItem, int iItem)
{
CTabCtrl* pTabCtrl = (CTabCtrl*)this;
TC_ITEM tci;
tci.mask = TCIF_IMAGE;
BOOL bResult = pTabCtrl->GetItem(iItem, &tci);
#ifdef _UNICODE
if (!bResult)
{
TC_ITEMA tcia;
::ZeroMemory(&tcia, sizeof(TC_ITEMA));
tcia.mask = TCIF_IMAGE;
bResult = (BOOL)::SendMessage(pTabCtrl->m_hWnd, TCM_GETITEMA, iItem, (LPARAM)&tcia);
tci.iImage = tcia.iImage;
}
#endif
if (!bResult)
return;
CImageList* pImageList = pTabCtrl->GetImageList();
if (!pImageList || tci.iImage < 0)
return;
CPoint point = rcItem.TopLeft();
DWORD dwStyle = GetStyle();
if (IsHorz(dwStyle))
{
point.Offset(GetMetrics()->m_cxEdge * 2, IsTop(dwStyle) ? GetMetrics()->m_cyEdge : 1);
}
else
{
point.Offset(IsLeft(dwStyle) ? GetMetrics()->m_cxEdge : 1, GetMetrics()->m_cyEdge * 2);
}
// Draw any associated icons.
pImageList->Draw(pDC, tci.iImage, point, ILD_TRANSPARENT);
IMAGEINFO info;
::ZeroMemory(&info, sizeof(info));
pImageList->GetImageInfo(tci.iImage, &info);
CRect rcImage(info.rcImage);
if (IsHorz(dwStyle))
{
rcItem.left += rcImage.Width() + GetMetrics()->m_cxEdge;
}
else
{
rcItem.top += rcImage.Height() + GetMetrics()->m_cyEdge;
}
}
void CXTPSkinObjectTab::DrawTabText(CDC* pDC, CRect& rcItem, int iItem, int iCount, BOOL bSelected)
{
CTabCtrl* pTabCtrl = (CTabCtrl*)this;
CString strCaption;
LPTSTR pszText = strCaption.GetBuffer(256);
pszText[0] = 0;
TC_ITEM tci;
tci.mask = TCIF_TEXT;
tci.pszText = pszText;
tci.cchTextMax = 255;
BOOL bResult = pTabCtrl->GetItem(iItem, &tci);
strCaption.ReleaseBuffer();
#ifdef _UNICODE
if (!bResult)
{
char tText[256];
tText[0] = 0;
TC_ITEMA tcia;
::ZeroMemory(&tcia, sizeof(TC_ITEMA));
tcia.mask = TCIF_TEXT;
// Get the header item text and format
tcia.pszText = tText;
tcia.cchTextMax = 255;
::SendMessage(pTabCtrl->m_hWnd, TCM_GETITEMA, iItem, (LPARAM)&tcia);
strCaption = tText;
}
#else
if (!bResult)
return;
#endif
if (strCaption.GetLength() == 0)
return;
pDC->SetTextColor(GetColor(COLOR_BTNTEXT));
// Set the font for the tab label.
DWORD dwStyle = GetStyle();
CXTPSkinManagerClass* pClass = GetSkinClass();
int nStateId = bSelected ? TIS_SELECTED: m_nHotItem == iItem ? TIS_HOT : TIS_NORMAL;
int nPartId = iItem == 0 ? TABP_TOPTABITEMLEFTEDGE :
iItem == iCount - 1 && !bSelected ? TABP_TOPTABITEMRIGHTEDGE : TABP_TOPTABITEM;
// Draw the tab label.
if (IsHorz(dwStyle))
{
UINT dsFlags = DT_SINGLELINE | DT_VCENTER | DT_CENTER | DT_END_ELLIPSIS;
if (SendMessage(WM_QUERYUISTATE) & UISF_HIDEACCEL)
{
dsFlags |= DT_HIDEPREFIX;
}
if (!(GetStyle() & TCS_BUTTONS))
{
rcItem.top += bSelected ? -2 : 1;
rcItem.right -= iItem == 0 ? 3 : 0;
}
else
{
rcItem.top += bSelected ? 0 : -1;
}
pClass->DrawThemeText(pDC, nPartId, nStateId, strCaption, dsFlags, &rcItem);
}
else
{
CSize sz = pDC->GetTextExtent(strCaption);
rcItem.left = rcItem.right-(rcItem.Width()-sz.cy + 1)/ 2;
rcItem.top = rcItem.top+(rcItem.Height()-sz.cx + 1)/ 2;
pClass->DrawThemeText(pDC, nPartId, nStateId, strCaption, DT_SINGLELINE | DT_NOCLIP, &rcItem);
}
}
void CXTPSkinObjectTab::DrawTab(CDC* pDC, int iItem)
{
CXTPClientRect rc(this);
CTabCtrl* pTabCtrl = (CTabCtrl*)this;
// Get the current tab selection.
int iCurSel = pTabCtrl->GetCurSel();
// Get the tab item size.
CRect rcItem;
pTabCtrl->GetItemRect(iItem, &rcItem);
if (!CRect().IntersectRect(rcItem, rc))
return;
CRect rcItemFocus(rcItem);
// Draw the tab item.
BOOL bSelected = (iItem == iCurSel);
FillTabFace(pDC, rcItem, iItem, pTabCtrl->GetItemCount(), bSelected);
if (GetStyle() & TCS_OWNERDRAWFIXED)
{
DRAWITEMSTRUCT dis;
UINT wID = (UINT)GetDlgCtrlID();
dis.CtlType = ODT_TAB;
dis.CtlID = wID;
dis.itemID = iItem;
dis.itemAction = ODA_DRAWENTIRE;
if (iCurSel == iItem)
dis.itemState = ODS_SELECTED;
else
dis.itemState = 0;
dis.hwndItem = m_hWnd;
dis.hDC = pDC->GetSafeHdc();
dis.rcItem = rcItem;
dis.itemData = 0;
::SendMessage(::GetParent(m_hWnd), WM_DRAWITEM, wID, (LPARAM)&dis);
}
else
{
DrawTabIcon(pDC, rcItem, iItem);
DrawTabText(pDC, rcItem, iItem, iItem, bSelected);
}
// draw the focus rect
if (bSelected && ::GetFocus() == m_hWnd && (SendMessage(WM_QUERYUISTATE) & UISF_HIDEFOCUS) == 0)
{
rcItemFocus.DeflateRect(GetMetrics()->m_cxEdge / 2, GetMetrics()->m_cyEdge / 2);
pDC->DrawFocusRect(&rcItemFocus);
}
}
void CXTPSkinObjectTab::OnPaint()
{
CXTPSkinObjectPaintDC dc(this);
if (dc.m_ps.hdc == 0)
{
FillClient(&dc, CXTPClientRect(this));
}
OnDraw(&dc);
}
LRESULT CXTPSkinObjectTab::OnPrintClient(WPARAM wParam, LPARAM /*lParam*/)
{
if (m_bPaint)
{
return Default();
}
CDC* pDC = CDC::FromHandle((HDC)wParam);
if (pDC)
{
OnDraw(pDC);
}
return 1;
}
void CXTPSkinObjectTab::OnDraw(CDC* pDC)
{
CRect rc = GetHeaderRect();
DWORD dwStyle = GetStyle();
if (IsRight(dwStyle))
{
rc.left -= 2;
}
else if (IsLeft(dwStyle))
{
rc.right += 2;
}
else if (IsBottom(dwStyle))
{
rc.top -= 2;
}
else
{
rc.bottom += 2;
}
CXTPBufferDC dcMem(*pDC, rc);
FillClient(&dcMem, CXTPClientRect(this));
if (m_bActiveX)
{
m_bPaint = TRUE;
CXTPBufferDC dcMem2(*pDC, rc);
DefWindowProc(WM_PAINT, (WPARAM)dcMem2.GetSafeHdc(), 0);
dcMem2.Discard();
m_bPaint = FALSE;
}
CTabCtrl* pTabCtrl = (CTabCtrl*)this;
CXTPFontDC font(&dcMem, GetFont());
dcMem.SetBkMode(TRANSPARENT);
for (int iItem = 0; iItem < pTabCtrl->GetItemCount(); ++iItem)
{
DrawTab(&dcMem, iItem);
}
DrawTab(&dcMem, pTabCtrl->GetCurSel());
}
void CXTPSkinObjectTab::OnMouseLeave()
{
OnMouseMove(0,CPoint(-1, -1));
}
void CXTPSkinObjectTab::OnMouseMove(UINT /*nFlags*/, CPoint point)
{
int nHotItem = -1;
CTabCtrl* pTabCtrl = (CTabCtrl*)this;
for (int iItem = 0; iItem < pTabCtrl->GetItemCount(); ++iItem)
{
CRect rcItem;
pTabCtrl->GetItemRect(iItem, &rcItem);
if (rcItem.PtInRect(point))
{
nHotItem = iItem;
break;
}
}
if (nHotItem != m_nHotItem)
{
m_nHotItem = nHotItem;
InvalidateRect(GetHeaderRect(), FALSE);
if (m_nHotItem != -1)
{
TRACKMOUSEEVENT tme = {sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd, HOVER_DEFAULT};
_TrackMouseEvent(&tme);
}
}
}
//////////////////////////////////////////////////////////////////////////
// CXTPSkinObjectTabClient
////////////////////////////////////////////////////////////////////
HBRUSH CXTPSkinObjectFrame::GetClientBrush(HDC hDC, HWND hWnd, UINT nCtlColor)
{
if (m_dwDialogTexture != ETDT_ENABLETAB)
{
GrayCtlColor(hDC, hWnd, nCtlColor, GetMetrics()->m_brushDialog, GetColor(COLOR_BTNTEXT));
return GetMetrics()->m_brushDialog;
}
if (GetMetrics()->m_brushTabControl == NULL)
{
CWindowDC dcWindow(this);
CXTPSkinManagerClass* pClass = GetSkinManager()->GetSkinClass(this, _T("TAB"));
CString strImageFile = pClass->GetThemeString(TABP_BODY, 0, TMT_STOCKIMAGEFILE);
if (strImageFile.IsEmpty())
{
return GetMetrics()->m_brushDialog;
}
CXTPSkinImage* pImage = pClass->GetImages()->LoadFile(m_pManager->GetResourceFile(), strImageFile);
if (!pImage)
{
return GetMetrics()->m_brushDialog;
}
CRect rc(0, 0, pImage->GetWidth(), pImage->GetHeight());
CBitmap bmp;
bmp.CreateCompatibleBitmap(&dcWindow, rc.Width(), rc.Height());
CXTPCompatibleDC dc(&dcWindow, bmp);
pImage->DrawImage(&dc, rc, rc, CRect(0, 0, 0, 0), COLORREF_NULL, ST_TRUESIZE, FALSE);
GetMetrics()->m_brushTabControl = ::CreatePatternBrush(bmp);
}
if (hWnd != m_hWnd)
{
CXTPWindowRect rcPaint(hWnd);
CXTPWindowRect rcBrush(m_hWnd);
::SetBrushOrgEx(hDC, rcBrush.left - rcPaint.left, rcBrush.top - rcPaint.top, NULL);
::SetBkMode(hDC, TRANSPARENT);
::SetTextColor(hDC, GetColor(COLOR_BTNTEXT));
}
return GetMetrics()->m_brushTabControl;
}