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.

400 lines
9.3 KiB
C++

2 years ago
// XTPSkinObjectHeader.cpp: implementation of the CXTPSkinObjectHeader 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/XTPDrawHelpers.h"
#include "Common/XTPSystemHelpers.h"
#include "XTPSkinObject.h"
#include "XTPSkinObjectFrame.h"
#include "XTPSkinObjectHeader.h"
#include "XTPSkinManager.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CXTPSkinObjectHeader, CXTPSkinObjectFrame)
CXTPSkinObjectHeader::CXTPSkinObjectHeader()
{
m_strClassName = _T("HEADER");
m_bLBtnDown = FALSE;
m_nHotItem = -1;
}
CXTPSkinObjectHeader::~CXTPSkinObjectHeader()
{
}
BEGIN_MESSAGE_MAP(CXTPSkinObjectHeader, CXTPSkinObjectFrame)
//{{AFX_MSG_MAP(CXTPSkinObjectHeader)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_MESSAGE_VOID(WM_MOUSELEAVE, OnMouseLeave)
ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CXTPSkinObjectHeader message handlers
void CXTPSkinObjectHeader::OnLButtonDown(UINT nFlags, CPoint point)
{
UINT uFlags = 0;
if (HitTest(point, &uFlags) != -1 && ((uFlags & HHT_ONHEADER) == HHT_ONHEADER))
{
m_bLBtnDown = TRUE;
}
CXTPSkinObjectFrame::OnLButtonDown(nFlags, point);
}
void CXTPSkinObjectHeader::OnLButtonUp(UINT nFlags, CPoint point)
{
if (m_bLBtnDown)
{
m_bLBtnDown = FALSE;
Invalidate(FALSE);
}
CXTPSkinObjectFrame::OnLButtonUp(nFlags, point);
}
int CXTPSkinObjectHeader::HitTest(CPoint pt, UINT* pFlags /*=NULL*/) const
{
HDHITTESTINFO hti;
hti.pt.x = pt.x;
hti.pt.y = pt.y;
int iItem = (int)::SendMessage(m_hWnd, HDM_HITTEST, 0, (LPARAM)(&hti));
if (pFlags != NULL)
*pFlags = hti.flags;
return iItem;
}
void CXTPSkinObjectHeader::OnMouseMove(UINT nFlags, CPoint point)
{
int nHotItem = HitTest(point);
if (nHotItem != m_nHotItem)
{
m_nHotItem = nHotItem;
Invalidate(FALSE);
if (m_nHotItem != -1)
{
TRACKMOUSEEVENT tme = {sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd, HOVER_DEFAULT};
_TrackMouseEvent(&tme);
}
}
CXTPSkinObjectFrame::OnMouseMove(nFlags, point);
}
void CXTPSkinObjectHeader::OnMouseLeave()
{
OnMouseMove(0, CPoint(-1, -1));
}
#ifndef HDS_FILTERBAR
#define HDS_FILTERBAR 0x0100
#endif
LRESULT CXTPSkinObjectHeader::OnPrintClient(WPARAM wParam, LPARAM lParam)
{
if ((lParam & PRF_CLIENT) == 0)
return Default();
CDC* pDC = CDC::FromHandle((HDC)wParam);
if (pDC) OnDraw(pDC);
return 1;
}
void CXTPSkinObjectHeader::OnPaint()
{
CXTPSkinObjectPaintDC dc(this);
OnDraw(&dc);
}
void CXTPSkinObjectHeader::OnDraw(CDC* pDC)
{
CXTPClientRect rcClient(this);
CRect rcBackground(rcClient);
CXTPBufferDC dc(*pDC, rcClient);
BOOL bFilterBar = (GetStyle() & HDS_FILTERBAR) && XTPSystemVersion()->GetComCtlVersion() >= MAKELONG(80, 5);
CRect rcFilter(0, 0, 0, 0);
dc.FillSolidRect(rcClient, GetColor(COLOR_3DFACE));
if (bFilterBar)
{
INT cyFilter = (rcClient.Height() - 1)/2;
rcFilter = rcClient;
rcClient.bottom = rcClient.top + cyFilter;
rcFilter.top = rcClient.bottom;
DefWindowProc(WM_PAINT, (WPARAM)dc.GetSafeHdc(), 0);
}
CXTPSkinManagerClass* pClass = GetSkinClass();
CXTPFontDC fontDC(&dc, GetFont());
dc.SetTextColor(GetColor(COLOR_BTNTEXT));
dc.SetBkMode(TRANSPARENT);
CHeaderCtrl* pHeaderCtrl = (CHeaderCtrl*)this;
int iItemCount = pHeaderCtrl->GetItemCount();
// Draw each header item
for (int iItem = 0; iItem < iItemCount; ++iItem)
{
int nIndex = Header_OrderToIndex(m_hWnd, iItem);
// initialize draw item structure.
CRect rcItem(0, 0, 0, 0);
Header_GetItemRect(m_hWnd, nIndex, &rcItem);
if ((rcItem.right < rcClient.left) || (rcItem.left > rcClient.right))
continue;
if (bFilterBar)
{
rcItem.bottom = rcFilter.top;
}
int nState = HIS_NORMAL;
if (nIndex == m_nHotItem)
{
nState = m_bLBtnDown ? HIS_PRESSED : HIS_HOT;
}
rcBackground.left = max(rcBackground.left, rcItem.right);
pClass->DrawThemeBackground(&dc, HP_HEADERITEM, nState, &rcItem);
DrawItemEntry(&dc, nIndex, rcItem, nState);
}
if (rcBackground.left < rcBackground.right)
pClass->DrawThemeBackground(&dc, 0, 0, &rcBackground);
}
#ifndef HDM_GETBITMAPMARGIN
#define HDM_GETBITMAPMARGIN (HDM_FIRST + 21)
#endif
#ifndef HDF_SORTUP
#define HDF_SORTUP 0x0400
#define HDF_SORTDOWN 0x0200
#endif
void CXTPSkinObjectHeader::DrawItemEntry(CDC* pDC, int nIndex, CRect rcItem, int nState)
{
CXTPSkinManagerClass* pClass = GetSkinClass();
CHeaderCtrl* pHeaderCtrl = (CHeaderCtrl*)this;
CImageList* pImageList = CImageList::FromHandle((HIMAGELIST)
::SendMessage(pHeaderCtrl->m_hWnd, HDM_GETIMAGELIST, 0, 0L));
// Set up the header item order array.
HD_ITEM hdi;
::ZeroMemory(&hdi, sizeof(HD_ITEM));
hdi.fmt = HDF_STRING | HDF_IMAGE;
hdi.mask = HDI_TEXT | HDI_FORMAT | HDI_IMAGE | HDI_LPARAM;
// Get the header item text and format
CString strCaption;
LPTSTR pszText = strCaption.GetBuffer(256);
pszText[0] = 0;
hdi.pszText = pszText;
hdi.cchTextMax = 255;
BOOL bResult = pHeaderCtrl->GetItem(nIndex, &hdi);
strCaption.ReleaseBuffer();
#ifdef _UNICODE
if (!bResult)
{
char tText[256];
tText[0] = 0;
HD_ITEMA hdia;
::ZeroMemory(&hdia, sizeof(HD_ITEMA));
hdia.fmt = HDF_STRING | HDF_IMAGE;
hdia.mask = HDI_TEXT | HDI_FORMAT | HDI_IMAGE | HDI_LPARAM;
// Get the header item text and format
hdia.pszText = tText;
hdia.cchTextMax = 255;
::SendMessage(pHeaderCtrl->m_hWnd, HDM_GETITEMA, nIndex, (LPARAM)&hdia);
strCaption = tText;
hdi.fmt = hdia.fmt;
hdi.iImage = hdia.iImage;
hdi.lParam = hdia.lParam;
}
#else
bResult;
#endif
if (hdi.fmt & HDF_OWNERDRAW)
{
DRAWITEMSTRUCT dis;
dis.CtlType = ODT_HEADER;
dis.CtlID = (UINT)GetDlgCtrlID();
dis.itemID = nIndex;
dis.itemAction = ODA_DRAWENTIRE;
dis.itemState = (nState == HIS_PRESSED) ? ODS_SELECTED : 0;
dis.hwndItem = m_hWnd;
dis.hDC = pDC->GetSafeHdc();
dis.rcItem = rcItem;
dis.itemData = hdi.lParam;
// Now send it off to my parent...
if (GetParent()->SendMessage(WM_DRAWITEM, dis.CtlID,
(LPARAM)(DRAWITEMSTRUCT*)&dis))
{
return;
}
}
CRect rcText(rcItem);
if (pImageList && (hdi.fmt & HDF_IMAGE) && hdi.iImage >= 0 && hdi.iImage < pImageList->GetImageCount())
{
int iBitmapMargin = (int)SendMessage(HDM_GETBITMAPMARGIN);
if (iBitmapMargin == 0)
iBitmapMargin = GetMetrics()->m_cxEdge * 3;
int cxBitmap = 16, cyBitmap = 16;
ImageList_GetIconSize(pImageList->GetSafeHandle(), &cxBitmap, &cyBitmap);
CPoint pt(rcItem.left + iBitmapMargin, (rcItem.bottom + rcItem.top - cyBitmap) / 2);
if (hdi.fmt & HDF_BITMAP_ON_RIGHT)
{
CSize sz = pDC->GetTextExtent(strCaption);
pt.x += sz.cx + iBitmapMargin + 9;
if (pt.x + cxBitmap > rcItem.right - 3)
pt.x = max(rcItem.left + 6, rcItem.right - 3 - cxBitmap);
if (nState == HIS_PRESSED)
pt.x ++;
pImageList->Draw(pDC, hdi.iImage, pt, ILD_TRANSPARENT);
rcText.right = pt.x + 6;
}
else
{
if (nState == HIS_PRESSED)
pt.x ++;
pImageList->Draw(pDC, hdi.iImage, pt, ILD_TRANSPARENT);
rcText.left += cxBitmap + iBitmapMargin;
}
}
if (((hdi.fmt & HDF_IMAGE) == 0) && ((hdi.fmt & HDF_SORTUP) || (hdi.fmt & HDF_SORTDOWN)))
{
int iBitmapMargin = GetMetrics()->m_cxEdge * 3;
CSize sz = pDC->GetTextExtent(strCaption);
CPoint pt(rcItem.left + iBitmapMargin, (rcItem.bottom + rcItem.top - 2) / 2);
pt.x += sz.cx + iBitmapMargin + 9;
if (pt.x + 9 > rcItem.right - 3)
pt.x = max(rcItem.left + 6, rcItem.right - 3 - 9);
if (hdi.fmt & HDF_SORTUP)
{
XTPDrawHelpers()->Triangle(pDC, CPoint(pt.x - 4, pt.y + 2),
CPoint(pt.x, pt.y - 2), CPoint(pt.x + 4, pt.y + 2), GetColor(COLOR_3DSHADOW));
}
else
{
XTPDrawHelpers()->Triangle(pDC, CPoint(pt.x - 4, pt.y - 2),
CPoint(pt.x, pt.y + 2), CPoint(pt.x + 4, pt.y - 2), GetColor(COLOR_3DSHADOW));
}
rcText.right = pt.x;
}
UINT nFormat = DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX;
// determine justification for text.
switch (hdi.fmt & HDF_JUSTIFYMASK)
{
case HDF_LEFT:
nFormat |= DT_LEFT;
rcText.DeflateRect(9, 0, 6, 0);
break;
case HDF_CENTER:
nFormat |= DT_CENTER;
rcText.DeflateRect(6, 0, 6, 0);
break;
case HDF_RIGHT:
nFormat |= DT_RIGHT;
rcText.DeflateRect(6, 0, 9, 0);
break;
}
if (rcText.Width() > 0)
{
if (nState == HIS_PRESSED)
rcText.OffsetRect(1, 1);
// draw text.
pDC->SetTextColor(GetColor(COLOR_BTNTEXT));
pClass->DrawThemeText(pDC, HP_HEADERITEM, nState, strCaption, nFormat, &rcText);
}
}