// XTHeaderCtrlTheme.cpp: implementation of the CXTHeaderCtrlTheme class. // // This file is a part of the XTREME CONTROLS MFC class library. // (c)1998-2008 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 "Resource.h" #include "Common/XTPWinThemeWrapper.h" #include "Common/XTPColorManager.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPImageManager.h" #include "XTVC50Helpers.h" #include "XTHeaderCtrl.h" #include "XTThemeManager.h" #include "XTHeaderCtrlTheme.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #define new DEBUG_NEW #endif IMPLEMENT_THEME_FACTORY(CXTHeaderCtrlTheme) //============================================================================= // CXTHeaderCtrlTheme //============================================================================= CXTHeaderCtrlTheme::CXTHeaderCtrlTheme() : m_sizePadding(6, 0) , m_sizeArrow(8, 7) , m_dwDrawStyle(0) , m_iArrowPadding(10) , m_bUseWinThemes(false) { m_dwDrawStyle = XTTHEME_WINXPTHEMES | XTTHEME_HOTTRACKING | XTTHEME_SORTARROW; } CXTHeaderCtrlTheme::~CXTHeaderCtrlTheme() { } void CXTHeaderCtrlTheme::RefreshMetrics() { CXTThemeManagerStyle ::RefreshMetrics(); 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_themeWrapper.OpenThemeData(0, L"HEADER"); } void CXTHeaderCtrlTheme::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 CXTHeaderCtrlTheme::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 CXTHeaderCtrlTheme::OnDrawBackgroundWinThemed(LPDRAWITEMSTRUCT lpDIS) { if ((GetDrawStyle() & XTTHEME_HOTTRACKING) == 0) return FALSE; if (m_themeWrapper.DrawThemeBackground(lpDIS->hDC, 0, HIS_NORMAL, &lpDIS->rcItem, NULL) != S_OK) { TRACE0("Error drawing background using WinTheme API.\n"); return FALSE; } return TRUE; } BOOL CXTHeaderCtrlTheme::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_themeWrapper.DrawThemeBackground(lpDIS->hDC, HP_HEADERITEM, iState, &lpDIS->rcItem, NULL) != S_OK) { TRACE0("Error drawing background using WinTheme API.\n"); return FALSE; } return TRUE; } void CXTHeaderCtrlTheme::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 CXTHeaderCtrlTheme::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 CXTHeaderCtrlTheme::OnDrawItemText(LPDRAWITEMSTRUCT lpDIS, CXTHeaderCtrl* 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 CXTHeaderCtrlTheme::DrawHeader(CDC* pDC, CXTHeaderCtrl* 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() & XTTHEME_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 CXTHeaderCtrlTheme::UseWinXPThemes(CXTHeaderCtrl* pHeaderCtrl) { ASSERT_VALID(pHeaderCtrl); // if windows xp themes are not allowed, return FALSE. if ((GetDrawStyle() & XTTHEME_WINXPTHEMES) == 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_themeWrapper.ThemeDataOpen()) m_themeWrapper.OpenThemeData(pHeaderCtrl->m_hWnd, L"HEADER"); // if our application is not "Theme Ready" meaning that we cannot // display Windows XP themes, then return FALSE. if (!m_themeWrapper.IsAppThemeReady()) return FALSE; // this will return TRUE if we can display visual styles. return m_themeWrapper.ThemeDataOpen(); } void CXTHeaderCtrlTheme::SetDrawStyle(DWORD dwDrawStyle, CXTHeaderCtrl* pHeaderCtrl) { m_dwDrawStyle = dwDrawStyle; m_bUseWinThemes = UseWinXPThemes(pHeaderCtrl) && ((m_dwDrawStyle & XTTHEME_WINXPTHEMES) != 0); } DWORD CXTHeaderCtrlTheme::GetDrawStyle() const { return m_dwDrawStyle; } BOOL CXTHeaderCtrlTheme::Layout(LPHDLAYOUT lpHDL, CXTHeaderCtrl* pHeaderCtrl) { ASSERT_VALID(pHeaderCtrl); return (BOOL)pHeaderCtrl->DefWindowProc(HDM_LAYOUT, (WPARAM)0, (LPARAM)lpHDL); } BOOL CXTHeaderCtrlTheme::SetBitmap(int iCol, UINT uBitmapID, BOOL bRemove, COLORREF crMask, CXTHeaderCtrl* 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 CXTHeaderCtrlTheme::OnDrawItemBitmap(LPDRAWITEMSTRUCT lpDIS, CRect& rcText, CXTHeaderCtrl* 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 CXTHeaderCtrlTheme::CleanUp(CXTHeaderCtrl* 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); } } } //============================================================================= // CXTHeaderCtrlThemeOfficeXP //============================================================================= CXTHeaderCtrlThemeOfficeXP::CXTHeaderCtrlThemeOfficeXP() { m_dwDrawStyle = XTTHEME_SORTARROW; } CXTHeaderCtrlThemeOfficeXP::~CXTHeaderCtrlThemeOfficeXP() { } void CXTHeaderCtrlThemeOfficeXP::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 CXTHeaderCtrlThemeOfficeXP::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); } } //============================================================================= // CXTHeaderCtrlThemeOffice2003 //============================================================================= CXTHeaderCtrlThemeOffice2003::CXTHeaderCtrlThemeOffice2003() { m_dwDrawStyle = XTTHEME_SORTARROW; m_sizePadding = CSize(6, 0); } CXTHeaderCtrlThemeOffice2003::~CXTHeaderCtrlThemeOffice2003() { } void CXTHeaderCtrlThemeOffice2003::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 CXTHeaderCtrlThemeOffice2003::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 CXTHeaderCtrlThemeOffice2003::Layout(LPHDLAYOUT lpHDL, CXTHeaderCtrl* 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; } //============================================================================= // CXTHeaderCtrlThemeExplorer //============================================================================= CXTHeaderCtrlThemeExplorer::CXTHeaderCtrlThemeExplorer() { m_dwDrawStyle = XTTHEME_WINXPTHEMES | XTTHEME_HOTTRACKING | XTTHEME_SORTARROW; m_sizePadding = CSize(6, 0); m_sizeArrow = CSize(8, 4); } CXTHeaderCtrlThemeExplorer::~CXTHeaderCtrlThemeExplorer() { } BOOL CXTHeaderCtrlThemeExplorer::OnDrawItemBackgroundWinThemed(LPDRAWITEMSTRUCT lpDIS) { return CXTHeaderCtrlTheme::OnDrawItemBackgroundWinThemed(lpDIS); } BOOL CXTHeaderCtrlThemeExplorer::Layout(LPHDLAYOUT lpHDL, CXTHeaderCtrl* 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 CXTHeaderCtrlThemeExplorer::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 CXTHeaderCtrlThemeExplorer::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); }