www.pudn.com > HReportTest.rar > HFlatHeaderCtrl.cpp
// HFlatHeaderCtrl.cpp : implementation file
//
#include "stdafx.h"
#include "HFlatHeaderCtrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CHFlatHeaderCtrl
#define XTWM_INITIAL_UPDATE WM_USER+1024
static const COLORREF clr3DFace = ::GetSysColor( COLOR_3DFACE );
static const COLORREF clr3DShadow = ::GetSysColor( COLOR_3DSHADOW );
static const COLORREF clr3DHilight = ::GetSysColor( COLOR_3DHILIGHT );
/*
static const COLORREF clr3DDkShadow = ::GetSysColor( COLOR_3DDKSHADOW );
static const COLORREF clrBtnText = ::GetSysColor( COLOR_BTNTEXT );
static const COLORREF clrGrayText = ::GetSysColor( COLOR_GRAYTEXT );
static const COLORREF clrHighlight = ::GetSysColor( COLOR_HIGHLIGHT );
static const COLORREF clrHighlightText = ::GetSysColor( COLOR_HIGHLIGHTTEXT );
static const COLORREF clrMenu = ::GetSysColor( COLOR_MENU );
static const COLORREF clrMenuText = ::GetSysColor( COLOR_MENUTEXT );
static const COLORREF clrWindow = ::GetSysColor( COLOR_WINDOW );
static const COLORREF clrWindowFrame = ::GetSysColor( COLOR_WINDOWFRAME );
static const COLORREF clrWindowText = ::GetSysColor( COLOR_WINDOWTEXT );
static const COLORREF clrActiveCaption = ::GetSysColor( COLOR_ACTIVECAPTION );
*/
CHFlatHeaderCtrl::CHFlatHeaderCtrl()
{
m_bLBtnDown = FALSE;
m_bAscending = -1;
m_bSortArrow = FALSE;
m_nSortedCol = -1;
m_nOffset = 6;
m_bInitControl = TRUE;
}
CHFlatHeaderCtrl::~CHFlatHeaderCtrl()
{
}
IMPLEMENT_DYNAMIC(CHFlatHeaderCtrl, CHeaderCtrl)
BEGIN_MESSAGE_MAP(CHFlatHeaderCtrl, CHeaderCtrl)
//{{AFX_MSG_MAP(CHFlatHeaderCtrl)
ON_WM_PAINT()
ON_WM_CREATE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_ERASEBKGND()
ON_WM_WINDOWPOSCHANGED()
//}}AFX_MSG_MAP
ON_MESSAGE(XTWM_INITIAL_UPDATE, OnInitControl)
END_MESSAGE_MAP()
void CHFlatHeaderCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
ASSERT(lpDrawItemStruct != NULL);
// define some temporary variables.
CDC* pDC = CDC::FromHandle( lpDrawItemStruct->hDC );
CRect rcItem = lpDrawItemStruct->rcItem;
CRect rcIcon = lpDrawItemStruct->rcItem;
int nState = lpDrawItemStruct->itemState;
int nItemID = lpDrawItemStruct->itemID;
CWnd* pParentWnd = GetParent();
BOOL bNoSortHeader = ((pParentWnd->GetStyle() & LVS_NOSORTHEADER) == LVS_NOSORTHEADER);
int nSavedDC = pDC->SaveDC();
// Paint the background.
pDC->FillSolidRect(rcItem, clr3DFace);
pDC->SetBkMode(TRANSPARENT);
// Set clipping region to limit drawing within column
CRgn rgn;
rgn.CreateRectRgnIndirect( &rcItem );
pDC->SelectObject( &rgn );
rgn.DeleteObject();
// Get the column text and format
TCHAR buf[256];
HD_ITEM hditem;
hditem.mask = HDI_TEXT | HDI_FORMAT;
hditem.pszText = buf;
hditem.cchTextMax = 255;
GetItem( nItemID, &hditem );
// Determine format for drawing column label
UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP
| DT_VCENTER | DT_END_ELLIPSIS ;
if( hditem.fmt & HDF_CENTER)
{
uFormat |= DT_CENTER;
}
else if( hditem.fmt & HDF_RIGHT)
{
uFormat |= DT_RIGHT;
}
else
{
uFormat |= DT_LEFT;
}
// Adjust the rect if the mouse button is pressed on it
if (nState == ODS_SELECTED && !bNoSortHeader)
{
rcItem.left++;
rcItem.top += 2;
rcItem.right++;
}
// Adjust the rect further if Sort arrow is to be displayed
if (nItemID == m_nSortedCol && m_bSortArrow) {
rcItem.right -= 3 * m_nOffset;
}
rcItem.left += m_nOffset;
rcItem.right -= m_nOffset;
// Draw column label
if( rcItem.left < rcItem.right )
{
pDC->SelectObject(GetFont());
pDC->DrawText(buf,-1,rcItem, uFormat);
}
// Draw the Sort arrow
if(( nItemID == m_nSortedCol ) && m_bSortArrow && !bNoSortHeader)
{
// Set up pens to use for drawing the triangle
CPen penLite(PS_SOLID, 1, clr3DHilight);
CPen penShad(PS_SOLID, 1, clr3DShadow);
pDC->SelectObject(&penLite);
if (m_bAscending)
{
// Draw triangle pointing upwards
pDC->MoveTo( rcIcon.right - 2*m_nOffset, m_nOffset-1);
pDC->LineTo( rcIcon.right - 3*m_nOffset/2, rcIcon.bottom - m_nOffset );
pDC->LineTo( rcIcon.right - 5*m_nOffset/2-2, rcIcon.bottom - m_nOffset );
pDC->MoveTo( rcIcon.right - 5*m_nOffset/2-1, rcIcon.bottom - m_nOffset-1 );
pDC->SelectObject( &penShad );
pDC->LineTo( rcIcon.right - 2*m_nOffset, m_nOffset-2);
}
else
{
// Draw triangle pointing downwords
pDC->MoveTo( rcIcon.right - 3*m_nOffset/2, m_nOffset-1);
pDC->LineTo( rcIcon.right - 2*m_nOffset-1, rcIcon.bottom - m_nOffset + 1 );
pDC->MoveTo( rcIcon.right - 2*m_nOffset-1, rcIcon.bottom - m_nOffset );
pDC->SelectObject( &penShad );
pDC->LineTo( rcIcon.right - 5*m_nOffset/2-1, m_nOffset -1 );
pDC->LineTo( rcIcon.right - 3*m_nOffset/2, m_nOffset -1);
}
}
pDC->RestoreDC(nSavedDC);
}
void CHFlatHeaderCtrl::DrawBorders(CDC* pDC, CRect& rect)
{
int nSavedDC = pDC->SaveDC();
// Draw flat style border around entire header.
CRect rc(rect);
rc.InflateRect(0,0,1,0);
pDC->Draw3dRect(rc, clr3DHilight, clr3DShadow);
// Cover up thick 3D border.
rc.DeflateRect(1,1,0,1);
pDC->Draw3dRect(rc, clr3DFace, clr3DFace);
// Create the pens for further cover-up.
CPen penLite(PS_SOLID, 1, clr3DHilight);
CPen penShad(PS_SOLID, 1, clr3DShadow);
CPen penFace(PS_SOLID, 1, clr3DFace);
pDC->SelectObject( &penLite );
// Set up the header item struct.
HD_ITEM hdi;
memset (&hdi, 0, sizeof(HD_ITEM));
hdi.fmt = HDF_STRING | HDF_LEFT | HDF_OWNERDRAW;
hdi.mask = HDI_WIDTH | HDI_TEXT | HDI_FORMAT | HDI_ORDER;
int cx = 0;
long j = GetItemCount();
long i = 0;
long * ItemOrders = new long[j];
for( i=0; iSelectObject(&penShad);
pDC->MoveTo(cx, 2);
pDC->LineTo(cx, rc.bottom-1);
pDC->SelectObject(&penLite);
pDC->MoveTo(cx+1, 2);
pDC->LineTo(cx+1, rc.bottom-1);
pDC->SelectObject(&penFace);
pDC->MoveTo(cx-1, 2);
pDC->LineTo(cx-1, rc.bottom-1);
pDC->SelectObject(&penFace);
pDC->MoveTo(cx-2, 2);
pDC->LineTo(cx-2, rc.bottom-1);
}
delete [] ItemOrders;
if (m_bLBtnDown == FALSE)
{
pDC->SelectObject(&penShad);
pDC->MoveTo(rect.right-1, rect.top);
pDC->LineTo(rect.right-1, rect.bottom);
}
// Cleanup.
pDC->RestoreDC(nSavedDC);
}
LRESULT CHFlatHeaderCtrl::OnInitControl(WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(wParam);
UNREFERENCED_PARAMETER(lParam);
if (m_bInitControl)
{
m_bInitControl = FALSE;
CWnd* pParentWnd = GetParent();
ASSERT_VALID(pParentWnd);
pParentWnd->ModifyStyle(0, WS_CLIPCHILDREN);
}
return 0;
}
void CHFlatHeaderCtrl::PreSubclassWindow()
{
CHeaderCtrl::PreSubclassWindow();
PostMessage(XTWM_INITIAL_UPDATE);
}
int CHFlatHeaderCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CHeaderCtrl::OnCreate(lpCreateStruct) == -1)
return -1;
SendMessage(XTWM_INITIAL_UPDATE);
return 0;
}
void CHFlatHeaderCtrl::OnPaint()
{
// background is already filled in gray
CPaintDC dc(this);
// Get the client rect.
CRect rectClient;
GetClientRect(&rectClient);
// Paint to a memory device context to help
// eliminate screen flicker.
CHMemDC memDC(&dc, rectClient);
// and let the window do its default painting...
CWnd::DefWindowProc( WM_PAINT, (WPARAM)memDC.m_hDC, 0 );
// draw the flat borders.
DrawBorders(&memDC, rectClient);
}
BOOL CHFlatHeaderCtrl::OnEraseBkgnd(CDC* pDC)
{
UNUSED_ALWAYS(pDC);
return FALSE;
}
void CHFlatHeaderCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
m_bLBtnDown = TRUE;
CHeaderCtrl::OnLButtonDown(nFlags, point);
}
void CHFlatHeaderCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
m_bLBtnDown = FALSE;
CHeaderCtrl::OnLButtonUp(nFlags, point);
}
void CHFlatHeaderCtrl::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)
{
CHeaderCtrl::OnWindowPosChanged(lpwndpos);
Invalidate();
}
int CHFlatHeaderCtrl::HitTest( CPoint pt ) const
{
for (int iItem = 0; iItem < GetItemCount(); ++iItem)
{
CRect r;
Header_GetItemRect(m_hWnd, iItem, &r);
if (r.PtInRect(pt))
return iItem;
}
return -1;
}
void CHFlatHeaderCtrl::SendNotify(int iIndex)
{
CWnd* pParentWnd = GetParent();
if (pParentWnd && (
pParentWnd->IsKindOf(RUNTIME_CLASS(CListCtrl)) ||
pParentWnd->IsKindOf(RUNTIME_CLASS(CListView))))
{
CWnd* pOwnerWnd = pParentWnd->GetOwner();
if (pOwnerWnd)
{
TCHAR lpBuffer[256];
HDITEM hdi;
hdi.mask = HDI_TEXT|HDI_BITMAP|HDI_FORMAT|HDI_IMAGE|HDI_LPARAM|HDI_ORDER|HDI_WIDTH;
hdi.pszText = lpBuffer;
hdi.cchTextMax = 256;
GetItem(iIndex, &hdi);
NMHEADER nmh;
nmh.hdr.hwndFrom = m_hWnd;
nmh.hdr.idFrom = GetDlgCtrlID();
nmh.hdr.code = HDN_ITEMCLICK;
nmh.iItem = iIndex;
nmh.iButton = 1;
nmh.pitem = &hdi;
// send message to the parent's owner window.
pOwnerWnd->SendMessage(WM_NOTIFY,
(WPARAM)(int)nmh.hdr.idFrom, (LPARAM)(NMHEADER*)&nmh);
// then forward to the descendants.
pOwnerWnd->SendMessageToDescendants(WM_NOTIFY,
(WPARAM)(int)nmh.hdr.idFrom, (LPARAM)(NMHEADER*)&nmh);
}
}
}
int CHFlatHeaderCtrl::SetSortImage(int nCol, BOOL bAsc)
{
int nPrevCol = m_nSortedCol;
m_nSortedCol = nCol;
m_bAscending = bAsc;
// Change the item to ownder drawn
HD_ITEM hditem;
hditem.mask = HDI_BITMAP | HDI_FORMAT;
GetItem( nCol, &hditem );
if (hditem.hbm == NULL)
{
hditem.fmt |= HDF_OWNERDRAW;
SetItem( nCol, &hditem );
Invalidate();
}
return nPrevCol;
}