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.

996 lines
26 KiB
C++

// XTPHeaderCtrlTheme.cpp: implementation of the CXTPHeaderCtrlTheme class.
//
// This file is a part of the XTREME CONTROLS 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/XTPWinThemeWrapper.h"
#include "Common/XTPColorManager.h"
#include "Common/XTPResourceImage.h"
#include "Common/XTPDrawHelpers.h"
#include "Common/XTPImageManager.h"
#include "../Util/XTPControlTheme.h"
#include "XTPHeaderCtrlTheme.h"
#include "XTPHeaderCtrl.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif
//=============================================================================
// CXTPHeaderCtrlTheme
//=============================================================================
CXTPHeaderCtrlTheme::CXTPHeaderCtrlTheme()
: m_sizePadding(6, 0)
, m_sizeArrow(8, 7)
, m_dwDrawStyle(0)
, m_iArrowPadding(10)
, m_bUseWinThemes(false)
{
m_dwDrawStyle = HDR_XTP_WINDEF | HDR_XTP_HOTTRACKING | HDR_XTP_SORTARROW;
m_themeHeader = new CXTPWinThemeWrapper();
}
CXTPHeaderCtrlTheme::~CXTPHeaderCtrlTheme()
{
SAFE_DELETE(m_themeHeader);
}
void CXTPHeaderCtrlTheme::RefreshMetrics(CXTPHeaderCtrl* /*pHeader*/)
{
m_crText = GetXtremeColor(COLOR_BTNTEXT);
m_cr3DFace = GetXtremeColor(COLOR_3DFACE);
m_cr3DShadow = GetXtremeColor(COLOR_3DSHADOW);
m_cr3DDkShadow = GetXtremeColor(COLOR_3DDKSHADOW);
m_cr3DHighLight = GetXtremeColor(COLOR_3DHIGHLIGHT);
m_themeHeader->OpenThemeData(0, L"HEADER");
}
void CXTPHeaderCtrlTheme::OnDrawBackground(LPDRAWITEMSTRUCT lpDIS)
{
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
CRect rcItem = lpDIS->rcItem;
// fill background
pDC->FillSolidRect(&rcItem, m_cr3DFace);
rcItem.right += 2;
// draw 3D borders.
pDC->Draw3dRect(&rcItem, m_cr3DHighLight, m_cr3DDkShadow);
rcItem.DeflateRect(1, 1);
pDC->Draw3dRect(&rcItem, m_cr3DFace, m_cr3DShadow);
}
void CXTPHeaderCtrlTheme::OnDrawItemBackground(LPDRAWITEMSTRUCT lpDIS)
{
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
if (lpDIS->itemState == ODS_SELECTED)
{
pDC->Draw3dRect(&lpDIS->rcItem, m_cr3DShadow, m_cr3DShadow);
CXTPPenDC penDC(pDC->m_hDC, m_cr3DHighLight);
pDC->MoveTo(lpDIS->rcItem.right, 1);
pDC->LineTo(lpDIS->rcItem.right, lpDIS->rcItem.bottom-1);
penDC.Color(m_cr3DFace);
pDC->MoveTo(lpDIS->rcItem.left+1, lpDIS->rcItem.bottom-2);
pDC->LineTo(lpDIS->rcItem.right-1, lpDIS->rcItem.bottom-2);
}
else
{
CXTPPenDC penDC(pDC->m_hDC, m_cr3DShadow);
pDC->MoveTo(lpDIS->rcItem.right-2, 1);
pDC->LineTo(lpDIS->rcItem.right-2, lpDIS->rcItem.bottom-1);
penDC.Color(m_cr3DDkShadow);
pDC->MoveTo(lpDIS->rcItem.right-1, 0);
pDC->LineTo(lpDIS->rcItem.right-1, lpDIS->rcItem.bottom-1);
penDC.Color(m_cr3DHighLight);
pDC->MoveTo(lpDIS->rcItem.right, 1);
pDC->LineTo(lpDIS->rcItem.right, lpDIS->rcItem.bottom-1);
}
}
BOOL CXTPHeaderCtrlTheme::OnDrawBackgroundWinThemed(LPDRAWITEMSTRUCT lpDIS)
{
if ((GetDrawStyle() & HDR_XTP_HOTTRACKING) == 0)
return FALSE;
if (m_themeHeader->DrawThemeBackground(lpDIS->hDC,
0, HIS_NORMAL, &lpDIS->rcItem, NULL) != S_OK)
{
TRACE0("Error drawing background using WinTheme API.\n");
return FALSE;
}
return TRUE;
}
BOOL CXTPHeaderCtrlTheme::OnDrawItemBackgroundWinThemed(LPDRAWITEMSTRUCT lpDIS)
{
int iState = HIS_NORMAL;
if (lpDIS->itemState & ODS_HOTLIGHT)
iState = HIS_HOT;
if (lpDIS->itemState & ODS_SELECTED)
iState = HIS_PRESSED;
if (m_themeHeader->DrawThemeBackground(lpDIS->hDC,
HP_HEADERITEM, iState, &lpDIS->rcItem, NULL) != S_OK)
{
TRACE0("Error drawing background using WinTheme API.\n");
return FALSE;
}
return TRUE;
}
void CXTPHeaderCtrlTheme::DrawSortArrow(CDC* pDC, LPPOINT ptsArrow, BOOL bAscending)
{
CXTPPenDC dcPen(pDC->m_hDC, bAscending ? m_cr3DHighLight : m_cr3DShadow);
pDC->MoveTo(ptsArrow[2]);
pDC->LineTo(ptsArrow[bAscending ? 1 : 0]);
pDC->LineTo(ptsArrow[bAscending ? 0 : 1]);
dcPen.Color(bAscending ? m_cr3DShadow : m_cr3DHighLight);
pDC->MoveTo(ptsArrow[bAscending ? 0 : 2]);
pDC->LineTo(ptsArrow[bAscending ? 2 : 1]);
}
void CXTPHeaderCtrlTheme::OnDrawItemSortArrow(LPDRAWITEMSTRUCT lpDIS, BOOL bAscending)
{
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
CRect rcItem = lpDIS->rcItem;
CPoint point;
point.x = rcItem.right + m_iArrowPadding;
point.y = (rcItem.top - 1) + (rcItem.Height() - m_sizeArrow.cy) / 2;
if (point.x < rcItem.left)
return;
if (lpDIS->itemState == ODS_SELECTED)
point.Offset(1, 1);
CRect rcArrow;
rcArrow.left = point.x;
rcArrow.top = point.y;
rcArrow.right = point.x + m_sizeArrow.cx;
rcArrow.bottom = point.y + m_sizeArrow.cy;
int x = point.x + (m_sizeArrow.cx/2);
// int y = point.y + (m_sizeArrow.cy/2);
POINT ptsArrow[3];
ptsArrow[0].x = x-m_sizeArrow.cx/2;
ptsArrow[0].y = bAscending ? rcArrow.bottom : rcArrow.top;
ptsArrow[1].x = x+m_sizeArrow.cx/2;
ptsArrow[1].y = bAscending ? rcArrow.bottom : rcArrow.top;
ptsArrow[2].x = x;
ptsArrow[2].y = bAscending ? rcArrow.top : rcArrow.bottom;
DrawSortArrow(pDC, ptsArrow, bAscending);
}
void CXTPHeaderCtrlTheme::OnDrawItemText(LPDRAWITEMSTRUCT lpDIS, CXTPHeaderCtrl* pHeaderCtrl)
{
ASSERT_VALID(pHeaderCtrl);
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
LPHDITEM lpHDI = (LPHDITEM)lpDIS->itemData;
// prepare the device context to draw text.
CXTPFontDC fontDC(pDC, pHeaderCtrl->GetFont());
// construct text size.
CRect rcItem(lpDIS->rcItem);
rcItem.DeflateRect(m_sizePadding.cx, 0);
BOOL bSortAsc;
UINT nSortItem = pHeaderCtrl->GetSortedCol(&bSortAsc);
if (nSortItem == lpDIS->itemID)
rcItem.right -= m_sizeArrow.cx + m_iArrowPadding*2;
CRect rcText(rcItem);
CSize sizeText = pDC->GetTextExtent(lpHDI->pszText);
rcText.top = (m_sizePadding.cy > 0) ?
m_sizePadding.cy : (rcItem.Height()-sizeText.cy)/2;
rcText.bottom = rcText.top + sizeText.cy;
if ((lpHDI->fmt & HDF_BITMAP && lpHDI->hbm != NULL) || (lpHDI->fmt & HDF_IMAGE))
{
if (lpHDI->fmt & HDF_BITMAP_ON_RIGHT)
{
CRect rcImage(rcText);
rcImage.left += sizeText.cx + m_sizePadding.cx;
OnDrawItemBitmap(lpDIS, rcImage, pHeaderCtrl);
}
else
{
OnDrawItemBitmap(lpDIS, rcText, pHeaderCtrl);
}
}
// determine justification for text.
switch (lpHDI->fmt & HDF_JUSTIFYMASK)
{
case HDF_LEFT:
rcText.right = rcText.left + sizeText.cx;
break;
case HDF_CENTER:
rcText.left += (rcItem.Width()-sizeText.cx)/2;
rcText.right = rcText.left + sizeText.cx;
break;
case HDF_RIGHT:
rcText.left = rcText.right - sizeText.cx;
break;
}
// size text to fit available display area.
rcText.left = __max(rcText.left, rcItem.left);
rcText.right = __min(rcText.right, rcItem.right);
// check if we are sorting.
if (HasSortArrow() && nSortItem == lpDIS->itemID)
{
lpDIS->rcItem = rcText;
OnDrawItemSortArrow(lpDIS, bSortAsc);
}
if (rcText.Width() > 0)
{
if (lpDIS->itemState == ODS_SELECTED)
rcText.OffsetRect(1, 1);
// draw text.
pDC->DrawText(lpHDI->pszText, &rcText,
DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS);
}
}
void CXTPHeaderCtrlTheme::DrawHeader(CDC* pDC, CXTPHeaderCtrl* pHeaderCtrl)
{
ASSERT_VALID(pHeaderCtrl);
CXTPClientRect rcClient(pHeaderCtrl);
DRAWITEMSTRUCT dis;
dis.CtlType = ODT_BUTTON;
dis.CtlID = 0;
dis.itemID = 0;
dis.itemAction = ODA_DRAWENTIRE;
dis.itemState = 0;
dis.hwndItem = pHeaderCtrl->m_hWnd;
dis.hDC = pDC->m_hDC;
dis.rcItem = rcClient;
dis.itemData = 0;
// draw background.
if (!m_bUseWinThemes || !OnDrawBackgroundWinThemed(&dis))
OnDrawBackground(&dis);
// set text attributes.
CXTPFontDC fontDC(pDC, pHeaderCtrl->GetFont());
pDC->SetBkColor(m_cr3DFace);
pDC->SetTextColor(m_crText);
pDC->SetBkMode(TRANSPARENT);
// Set up the header item order array.
HD_ITEM hdi;
::ZeroMemory(&hdi, sizeof(HD_ITEM));
hdi.fmt = HDF_STRING | HDF_LEFT | HDF_BITMAP;
hdi.mask = HDI_WIDTH | HDI_TEXT | HDI_FORMAT | HDI_ORDER | HDI_BITMAP | HDI_LPARAM;
int cxy = 0;
int iItem = 0;
int iItemCount = pHeaderCtrl->GetItemCount();
int *plItems = new int[iItemCount];
for (iItem = 0; iItem < iItemCount; iItem++)
{
pHeaderCtrl->GetItem(iItem, &hdi);
plItems[hdi.iOrder] = iItem;
}
hdi.fmt = HDF_STRING | HDF_LEFT | HDF_BITMAP;
hdi.mask = HDI_WIDTH | HDI_TEXT | HDI_FORMAT | HDI_BITMAP | HDI_LPARAM;
// get cursor position.
CPoint point;
::GetCursorPos(&point);
pHeaderCtrl->ScreenToClient(&point);
// Draw each header item
for (iItem = 0; iItem < iItemCount; ++iItem)
{
// Get the header item text and format
TCHAR szBuffer[256];
hdi.pszText = szBuffer;
hdi.cchTextMax = 255;
pHeaderCtrl->GetItem(plItems[iItem], &hdi);
// initialize draw item structure.
dis.itemID = plItems[iItem];
dis.itemState = 0;
dis.rcItem = rcClient;
dis.rcItem.left = cxy;
dis.rcItem.right = dis.rcItem.left + hdi.cxy;
dis.itemData = (DWORD_PTR)&hdi;
// if hot tracking is enabled, set the state.
if (GetDrawStyle() & HDR_XTP_HOTTRACKING)
{
if (pHeaderCtrl->HitTest(point) == plItems[iItem])
dis.itemState = ODS_HOTLIGHT;
}
// check if the item is selected
if (pHeaderCtrl->ItemPressed(plItems[iItem]))
dis.itemState = ODS_SELECTED;
// draw the item background.
if (!m_bUseWinThemes || !OnDrawItemBackgroundWinThemed(&dis))
OnDrawItemBackground(&dis);
// draw the item text.
OnDrawItemText(&dis, pHeaderCtrl);
cxy += hdi.cxy;
}
delete [] plItems;
}
BOOL CXTPHeaderCtrlTheme::UseWinXPThemes(CXTPHeaderCtrl* pHeaderCtrl)
{
ASSERT_VALID(pHeaderCtrl);
// if windows xp themes are not allowed, return FALSE.
if ((GetDrawStyle() & HDR_XTP_WINDEF) == 0)
return FALSE;
// if we got this far then we try to load the theme data for
// this control if it is not currently open.
if (!m_themeHeader->ThemeDataOpen())
m_themeHeader->OpenThemeData(pHeaderCtrl->m_hWnd, L"HEADER");
// if our application is not "Theme Ready" meaning that we cannot
// display Windows XP themes, then return FALSE.
#ifndef _XTP_ACTIVEX
if (!m_themeHeader->IsAppThemeReady())
return FALSE;
#endif
// this will return TRUE if we can display visual styles.
return m_themeHeader->ThemeDataOpen();
}
void CXTPHeaderCtrlTheme::SetDrawStyle(DWORD dwDrawStyle, CXTPHeaderCtrl* pHeaderCtrl)
{
m_dwDrawStyle = dwDrawStyle;
m_bUseWinThemes = UseWinXPThemes(pHeaderCtrl) && ((m_dwDrawStyle & HDR_XTP_WINDEF) != 0);
}
DWORD CXTPHeaderCtrlTheme::GetDrawStyle() const
{
return m_dwDrawStyle;
}
BOOL CXTPHeaderCtrlTheme::Layout(LPHDLAYOUT lpHDL, CXTPHeaderCtrl* pHeaderCtrl)
{
ASSERT_VALID(pHeaderCtrl);
return (BOOL)pHeaderCtrl->DefWindowProc(HDM_LAYOUT,
(WPARAM)0, (LPARAM)lpHDL);
}
BOOL CXTPHeaderCtrlTheme::SetBitmap(int iCol, UINT uBitmapID, BOOL bRemove, COLORREF crMask, CXTPHeaderCtrl* pHeaderCtrl)
{
ASSERT_VALID(pHeaderCtrl);
// reset header image list
HD_ITEM hdi;
::ZeroMemory(&hdi, sizeof(HD_ITEM));
hdi.mask = HDI_BITMAP | HDI_FORMAT;
pHeaderCtrl->GetItem(iCol, &hdi);
// free previous GDI resources.
if (hdi.fmt & HDF_BITMAP && hdi.hbm != NULL)
::ImageList_Destroy((HIMAGELIST)hdi.hbm);
hdi.hbm = NULL;
hdi.fmt &= ~HDF_BITMAP;
pHeaderCtrl->SetItem(iCol, &hdi);
pHeaderCtrl->RedrawWindow();
// add new image list
if (!bRemove)
{
HBITMAP hBitmap = (HBITMAP)::LoadImage(AfxGetResourceHandle(),
MAKEINTRESOURCE(uBitmapID), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
if (hBitmap == NULL)
return FALSE;
BITMAP bmpInfo;
ZeroMemory(&bmpInfo, sizeof(BITMAP));
if (::GetObject(hBitmap, sizeof(BITMAP), &bmpInfo) == 0)
return FALSE;
HIMAGELIST hImageList = ::ImageList_Create(bmpInfo.bmWidth,
bmpInfo.bmHeight, ILC_MASK | ILC_COLOR24, 0, 1);
if (hImageList == NULL)
return FALSE;
if (::ImageList_AddMasked(hImageList, hBitmap, crMask) == -1)
{
::ImageList_Destroy(hImageList);
::DeleteObject(hBitmap);
return FALSE;
}
// we are actually storing a handle to the image list and
// not the bitmap so we can draw using the mask.
hdi.hbm = (HBITMAP)hImageList;
hdi.fmt = HDF_BITMAP;
pHeaderCtrl->SetItem(iCol, &hdi);
pHeaderCtrl->RedrawWindow();
::DeleteObject(hBitmap);
return TRUE;
}
return FALSE;
}
void CXTPHeaderCtrlTheme::OnDrawItemBitmap(LPDRAWITEMSTRUCT lpDIS, CRect& rcText, CXTPHeaderCtrl* pHeaderCtrl)
{
ASSERT_VALID(pHeaderCtrl);
HDITEM hdi;
hdi.mask = HDI_BITMAP | HDI_FORMAT | HDI_IMAGE;
pHeaderCtrl->GetItem(lpDIS->itemID, &hdi);
HIMAGELIST hImageList = 0;
int nIndex = -1;
if (hdi.fmt & HDF_BITMAP && hdi.hbm != NULL)
{
hImageList = (HIMAGELIST)hdi.hbm;
nIndex = 0;
}
else if (hdi.fmt & HDF_IMAGE)
{
hImageList = (HIMAGELIST)pHeaderCtrl->SendMessage(HDM_GETIMAGELIST);
nIndex = hdi.iImage;
}
if (nIndex != -1 && (hdi.fmt & HDF_IMAGE) && pHeaderCtrl->GetImageManager())
{
CXTPImageManagerIcon* pIcon = pHeaderCtrl->GetImageManager()->GetImage(nIndex, 0);
if (pIcon)
{
CRect rcItem(lpDIS->rcItem);
CPoint point(rcText.left, (rcItem.Height() - pIcon->GetHeight()) / 2);
rcText.left += pIcon->GetWidth() + m_sizePadding.cx;
XTPImageState imageState = (lpDIS->itemState & ODS_SELECTED) ? xtpImageChecked :
(lpDIS->itemState & ODS_HOTLIGHT) ? xtpImageHot : xtpImageNormal;
if (lpDIS->itemState == ODS_SELECTED)
point.Offset(1, 1);
if (point.x + pIcon->GetWidth() > lpDIS->rcItem.right)
return;
// draw image transparently.
pIcon->Draw(CDC::FromHandle(lpDIS->hDC), point, pIcon->GetIcon(imageState));
return;
}
}
if (hImageList)
{
int cx, cy;
if (::ImageList_GetIconSize(hImageList, &cx, &cy) && (nIndex < ImageList_GetImageCount(hImageList)))
{
CRect rcItem(lpDIS->rcItem);
CPoint point(rcText.left, (rcItem.Height() - cy) / 2);
rcText.left += cx + m_sizePadding.cx;
if (lpDIS->itemState == ODS_SELECTED)
point.Offset(1, 1);
if (point.x + cx > lpDIS->rcItem.right)
return;
// draw image transparently.
::ImageList_Draw(hImageList, nIndex, lpDIS->hDC, point.x, point.y, ILD_TRANSPARENT);
}
}
}
void CXTPHeaderCtrlTheme::CleanUp(CXTPHeaderCtrl* pHeaderCtrl)
{
ASSERT_VALID(pHeaderCtrl);
// free GDI resources
for (int i = 0; i < pHeaderCtrl->GetItemCount(); ++i)
{
HDITEM hdi;
hdi.mask = HDI_FORMAT | HDI_BITMAP;
pHeaderCtrl->GetItem(i, &hdi);
if (hdi.fmt & HDF_BITMAP && hdi.hbm != NULL)
{
::ImageList_Destroy((HIMAGELIST)hdi.hbm);
}
}
}
//=============================================================================
// CXTPHeaderCtrlThemeOfficeXP
//=============================================================================
CXTPHeaderCtrlThemeOfficeXP::CXTPHeaderCtrlThemeOfficeXP()
{
m_nTheme = xtpControlThemeOfficeXP;
m_dwDrawStyle = HDR_XTP_SORTARROW;
}
CXTPHeaderCtrlThemeOfficeXP::~CXTPHeaderCtrlThemeOfficeXP()
{
}
void CXTPHeaderCtrlThemeOfficeXP::OnDrawBackground(LPDRAWITEMSTRUCT lpDIS)
{
CRect rcItem(lpDIS->rcItem);
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
// fill background
pDC->FillSolidRect(&rcItem, m_cr3DFace);
rcItem.right += 2;
// draw 3D borders.
pDC->Draw3dRect(&rcItem, m_cr3DHighLight, m_cr3DShadow);
}
void CXTPHeaderCtrlThemeOfficeXP::OnDrawItemBackground(LPDRAWITEMSTRUCT lpDIS)
{
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
if (lpDIS->itemState == ODS_SELECTED)
{
CXTPPenDC penDC(lpDIS->hDC, m_cr3DShadow);
pDC->MoveTo(lpDIS->rcItem.right-2, 2);
pDC->LineTo(lpDIS->rcItem.right-2, lpDIS->rcItem.bottom-2);
penDC.Color(m_cr3DHighLight);
pDC->MoveTo(lpDIS->rcItem.right-1, 2);
pDC->LineTo(lpDIS->rcItem.right-1, lpDIS->rcItem.bottom-2);
}
else
{
CXTPPenDC penDC(lpDIS->hDC, m_cr3DShadow);
pDC->MoveTo(lpDIS->rcItem.right-2, 2);
pDC->LineTo(lpDIS->rcItem.right-2, lpDIS->rcItem.bottom-2);
penDC.Color(m_cr3DHighLight);
pDC->MoveTo(lpDIS->rcItem.right-1, 2);
pDC->LineTo(lpDIS->rcItem.right-1, lpDIS->rcItem.bottom-2);
}
}
//=============================================================================
// CXTPHeaderCtrlThemeOffice2003
//=============================================================================
CXTPHeaderCtrlThemeOffice2003::CXTPHeaderCtrlThemeOffice2003()
{
m_nTheme = xtpControlThemeOffice2003;
m_dwDrawStyle = HDR_XTP_SORTARROW;
m_sizePadding = CSize(6, 0);
}
CXTPHeaderCtrlThemeOffice2003::~CXTPHeaderCtrlThemeOffice2003()
{
}
void CXTPHeaderCtrlThemeOffice2003::OnDrawBackground(LPDRAWITEMSTRUCT lpDIS)
{
CRect rcItem(lpDIS->rcItem);
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
// fill background
pDC->FillSolidRect(&rcItem, m_cr3DFace);
rcItem.right += 2;
// draw 3D borders.
pDC->Draw3dRect(&rcItem, m_cr3DHighLight, MixColor(m_cr3DFace, m_cr3DShadow, 0.6));
CXTPPenDC penDC(lpDIS->hDC, MixColor(m_cr3DFace, m_cr3DShadow, 0.4));
pDC->MoveTo(rcItem.left, rcItem.bottom-2);
pDC->LineTo(rcItem.right, rcItem.bottom-2);
penDC.Color(MixColor(m_cr3DFace, m_cr3DShadow, 0.25));
pDC->MoveTo(rcItem.left, rcItem.bottom-3);
pDC->LineTo(rcItem.right, rcItem.bottom-3);
}
void CXTPHeaderCtrlThemeOffice2003::OnDrawItemBackground(LPDRAWITEMSTRUCT lpDIS)
{
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
if (lpDIS->itemState == ODS_SELECTED)
{
CXTPPenDC penDC(lpDIS->hDC, m_cr3DShadow);
pDC->MoveTo(lpDIS->rcItem.right-2, 2);
pDC->LineTo(lpDIS->rcItem.right-2, lpDIS->rcItem.bottom-4);
penDC.Color(m_cr3DHighLight);
pDC->MoveTo(lpDIS->rcItem.right-1, 2);
pDC->LineTo(lpDIS->rcItem.right-1, lpDIS->rcItem.bottom-4);
}
else
{
CXTPPenDC penDC(lpDIS->hDC, m_cr3DShadow);
pDC->MoveTo(lpDIS->rcItem.right-2, 2);
pDC->LineTo(lpDIS->rcItem.right-2, lpDIS->rcItem.bottom-4);
penDC.Color(m_cr3DHighLight);
pDC->MoveTo(lpDIS->rcItem.right-1, 2);
pDC->LineTo(lpDIS->rcItem.right-1, lpDIS->rcItem.bottom-4);
}
}
BOOL CXTPHeaderCtrlThemeOffice2003::Layout(LPHDLAYOUT lpHDL, CXTPHeaderCtrl* pHeaderCtrl)
{
ASSERT_VALID(pHeaderCtrl);
LPRECT pRC = lpHDL->prc;
LPWINDOWPOS pWP = lpHDL->pwpos;
CWindowDC dc(NULL);
CXTPFontDC fontDC(&dc, pHeaderCtrl->GetFont());
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
int iHeight = tm.tmHeight + 10;
pWP->hwndInsertAfter = 0;
pWP->x = pRC->left;
pWP->cx = pRC->right - pRC->left;
pWP->cy = iHeight;
pWP->y = pRC->top;
pRC->top += iHeight;
pWP->flags = SWP_NOACTIVATE | SWP_NOZORDER;
return TRUE;
}
//=============================================================================
// CXTPHeaderCtrlThemeExplorer
//=============================================================================
CXTPHeaderCtrlThemeExplorer::CXTPHeaderCtrlThemeExplorer()
{
m_nTheme = xtpControlThemeNativeWinXP;
m_dwDrawStyle = HDR_XTP_WINDEF | HDR_XTP_HOTTRACKING | HDR_XTP_SORTARROW;
m_sizePadding = CSize(6, 0);
m_sizeArrow = CSize(8, 4);
}
CXTPHeaderCtrlThemeExplorer::~CXTPHeaderCtrlThemeExplorer()
{
}
BOOL CXTPHeaderCtrlThemeExplorer::OnDrawItemBackgroundWinThemed(LPDRAWITEMSTRUCT lpDIS)
{
return CXTPHeaderCtrlTheme::OnDrawItemBackgroundWinThemed(lpDIS);
}
BOOL CXTPHeaderCtrlThemeExplorer::Layout(LPHDLAYOUT lpHDL, CXTPHeaderCtrl* pHeaderCtrl)
{
ASSERT_VALID(pHeaderCtrl);
LPRECT pRC = lpHDL->prc;
LPWINDOWPOS pWP = lpHDL->pwpos;
CWindowDC dc(NULL);
CXTPFontDC fontDC(&dc, pHeaderCtrl->GetFont());
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
int iHeight = tm.tmHeight + 6;
pWP->hwndInsertAfter = 0;
pWP->x = pRC->left;
pWP->cx = pRC->right - pRC->left;
pWP->cy = iHeight;
pWP->y = pRC->top;
pRC->top += iHeight;
pWP->flags = SWP_NOACTIVATE | SWP_NOZORDER;
return TRUE;
}
void CXTPHeaderCtrlThemeExplorer::DrawSortArrow(CDC* pDC, LPPOINT ptsArrow, BOOL /*bAscending*/)
{
CXTPPenDC dcPen(pDC->m_hDC, RGB(172, 168, 153));
CXTPBrushDC dcBrush(pDC->m_hDC, RGB(172, 168, 153));
pDC->SetPolyFillMode(WINDING);
pDC->Polygon(ptsArrow, 3);
}
void CXTPHeaderCtrlThemeExplorer::OnDrawBackground(LPDRAWITEMSTRUCT lpDIS)
{
CRect rcItem(lpDIS->rcItem);
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
// fill background
pDC->FillSolidRect(&rcItem, m_cr3DFace);
rcItem.right += 2;
// draw 3D borders.
pDC->Draw3dRect(&rcItem, m_cr3DHighLight, m_cr3DShadow);
}
//=============================================================================
// CXTPHeaderCtrlThemeResource
//=============================================================================
CXTPHeaderCtrlThemeResource::CXTPHeaderCtrlThemeResource()
{
m_nTheme = xtpControlThemeResource;
m_sizeArrow = CSize(8, 4);
}
void CXTPHeaderCtrlThemeResource::RefreshMetrics(CXTPHeaderCtrl* pHeader)
{
CXTPHeaderCtrlThemeOfficeXP::RefreshMetrics(pHeader);
CXTPResourceImages* pImages = XTPResourceImages();
if (pImages)
{
m_crText = pImages->GetImageColor(_T("ReportControl"), _T("HeaderText"), m_crText);
m_cr3DShadow = pImages->GetImageColor(_T("ReportControl"), _T("ColumnSeparator"), m_crText);
m_cr3DDkShadow = pImages->GetImageColor(_T("ReportControl"), _T("ColumnShadow"), m_crText);
m_crgBack.SetStandardValue(
pImages->GetImageColor(_T("ReportControl"), _T("NormalColumnLight"), m_cr3DFace),
pImages->GetImageColor(_T("ReportControl"), _T("NormalColumnDark"), m_cr3DFace));
m_crgBackPressed.SetStandardValue(
pImages->GetImageColor(_T("ReportControl"), _T("PressedColumnLight"), m_cr3DFace),
pImages->GetImageColor(_T("ReportControl"), _T("PressedColumnDark"), m_cr3DFace));
}
else
{
m_crgBack.SetStandardValue(m_cr3DFace, m_cr3DFace);
}
}
void CXTPHeaderCtrlThemeResource::OnDrawBackground(LPDRAWITEMSTRUCT lpDIS)
{
CXTPResourceImages* pImages = XTPResourceImages();
if (pImages)
{
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
CRect rcItem = lpDIS->rcItem;
// fill background
XTPDrawHelpers()->GradientFill(pDC, rcItem, m_crgBack, FALSE);
rcItem.right += 2;
// draw border.
CXTPPenDC penDC(pDC->m_hDC, m_cr3DDkShadow);
pDC->MoveTo(lpDIS->rcItem.left, lpDIS->rcItem.bottom-1);
pDC->LineTo(lpDIS->rcItem.right, lpDIS->rcItem.bottom-1);
}
else
{
CXTPHeaderCtrlThemeOfficeXP::OnDrawBackground(lpDIS);
}
}
void CXTPHeaderCtrlThemeResource::OnDrawItemBackground(LPDRAWITEMSTRUCT lpDIS)
{
CXTPResourceImages* pImages = XTPResourceImages();
if (pImages)
{
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
CRect rcItem = lpDIS->rcItem;
rcItem.left++;
if (lpDIS->itemState == ODS_SELECTED)
{
XTPDrawHelpers()->GradientFill(pDC, &rcItem, m_crgBackPressed, FALSE);
// draw border.
{
CXTPPenDC dcPen(pDC->m_hDC, m_cr3DDkShadow);
pDC->MoveTo(rcItem.left, rcItem.bottom-1);
pDC->LineTo(rcItem.right, rcItem.bottom-1);
}
// draw separator.
{
CXTPPenDC dcPen(pDC->m_hDC, m_cr3DShadow);
pDC->MoveTo(rcItem.right, 2);
pDC->LineTo(rcItem.right, rcItem.bottom-3);
}
}
else
{
// draw separator.
CXTPPenDC dcPen(pDC->m_hDC, m_cr3DShadow);
pDC->MoveTo(rcItem.right, 2);
pDC->LineTo(rcItem.right, rcItem.bottom-3);
}
}
else
{
CXTPHeaderCtrlThemeOfficeXP::OnDrawItemBackground(lpDIS);
}
}
void CXTPHeaderCtrlThemeResource::DrawSortArrow(CDC* pDC, LPPOINT ptsArrow, BOOL bAscending)
{
CXTPResourceImages* pImages = XTPResourceImages();
if (pImages)
{
CXTPPenDC dcPen(pDC->m_hDC, m_cr3DShadow);
CXTPBrushDC dcBrush(pDC->m_hDC, m_cr3DShadow);
pDC->SetPolyFillMode(WINDING);
pDC->Polygon(ptsArrow, 3);
}
else
{
CXTPHeaderCtrlThemeOfficeXP::DrawSortArrow(pDC, ptsArrow, bAscending);
}
}
void CXTPHeaderCtrlThemeResource::OnDrawItemText(LPDRAWITEMSTRUCT lpDIS, CXTPHeaderCtrl* pHeaderCtrl)
{
ASSERT_VALID(pHeaderCtrl);
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
LPHDITEM lpHDI = (LPHDITEM)lpDIS->itemData;
// prepare the device context to draw text.
CXTPFontDC fontDC(pDC, pHeaderCtrl->GetFont());
// construct text size.
CRect rcItem(lpDIS->rcItem);
rcItem.DeflateRect(m_sizePadding.cx, 0);
BOOL bSortAsc;
UINT nSortItem = pHeaderCtrl->GetSortedCol(&bSortAsc);
if (nSortItem == lpDIS->itemID)
rcItem.right -= m_sizeArrow.cx + m_iArrowPadding*2;
CRect rcText(rcItem);
CSize sizeText = pDC->GetTextExtent(lpHDI->pszText);
rcText.top = (m_sizePadding.cy > 0) ?
m_sizePadding.cy : (rcItem.Height()-sizeText.cy)/2;
rcText.bottom = rcText.top + sizeText.cy;
if ((lpHDI->fmt & HDF_BITMAP && lpHDI->hbm != NULL) || (lpHDI->fmt & HDF_IMAGE))
{
if (lpHDI->fmt & HDF_BITMAP_ON_RIGHT)
{
CRect rcImage(rcText);
rcImage.left += sizeText.cx + m_sizePadding.cx;
OnDrawItemBitmap(lpDIS, rcImage, pHeaderCtrl);
}
else
{
OnDrawItemBitmap(lpDIS, rcText, pHeaderCtrl);
}
}
// determine justification for text.
switch (lpHDI->fmt & HDF_JUSTIFYMASK)
{
case HDF_LEFT:
rcText.right = rcText.left + sizeText.cx;
break;
case HDF_CENTER:
rcText.left += (rcItem.Width()-sizeText.cx)/2;
rcText.right = rcText.left + sizeText.cx;
break;
case HDF_RIGHT:
rcText.left = rcText.right - sizeText.cx;
break;
}
// size text to fit available display area.
rcText.left = __max(rcText.left, rcItem.left);
rcText.right = __min(rcText.right, rcItem.right);
// check if we are sorting.
if (HasSortArrow() && nSortItem == lpDIS->itemID)
{
lpDIS->rcItem = rcText;
OnDrawItemSortArrow(lpDIS, bSortAsc);
}
if (rcText.Width() > 0)
{
// draw text.
pDC->DrawText(lpHDI->pszText, &rcText,
DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS);
}
}
void CXTPHeaderCtrlThemeResource::OnDrawItemSortArrow(LPDRAWITEMSTRUCT lpDIS, BOOL bAscending)
{
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
CRect rcItem = lpDIS->rcItem;
CPoint point;
point.x = rcItem.right + m_iArrowPadding;
point.y = (rcItem.top - 1) + (rcItem.Height() - m_sizeArrow.cy) / 2;
if (point.x < rcItem.left)
return;
CRect rcArrow;
rcArrow.left = point.x;
rcArrow.top = point.y;
rcArrow.right = point.x + m_sizeArrow.cx;
rcArrow.bottom = point.y + m_sizeArrow.cy;
int x = point.x + (m_sizeArrow.cx/2);
POINT ptsArrow[3];
ptsArrow[0].x = x-m_sizeArrow.cx/2;
ptsArrow[0].y = bAscending ? rcArrow.bottom : rcArrow.top;
ptsArrow[1].x = x+m_sizeArrow.cx/2;
ptsArrow[1].y = bAscending ? rcArrow.bottom : rcArrow.top;
ptsArrow[2].x = x;
ptsArrow[2].y = bAscending ? rcArrow.top : rcArrow.bottom;
DrawSortArrow(pDC, ptsArrow, bAscending);
}