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++
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);
|
|
}
|