www.pudn.com > CListCtrlfjs.rar > SortHeaderCtrl.cpp


#include "stdafx.h" 
#include "SortHeaderCtrl.h" 
#include "Resource.h" 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
static const CString strOfficeFontName	= _T("Tahoma"); 
static const CString strDefaultFontName = _T("MS Sans Serif"); 
static const CString strVertFontName	= _T("Arial"); 
static const CString strMarlettFontName	= _T("Marlett"); 
 
static int CALLBACK FontFamalyProcFonts (const LOGFONT FAR* lplf, 
									const TEXTMETRIC FAR* /*lptm*/, 
									ULONG /*ulFontType*/, 
									LPARAM /*lParam*/) 
{ 
	ASSERT (lplf != NULL); 
 
	CString strFont = lplf->lfFaceName; 
	return strFont.CollateNoCase (strOfficeFontName) == 0 ? 0 : 1; 
} 
 
CSortHeaderCtrl::CSortHeaderCtrl() 
{ 
	m_bIsMousePressed = FALSE; 
	m_bMultipleSort = FALSE; 
	m_bAscending = TRUE; 
	m_nHighlightedItem = -1; 
    m_nNoTrack=0; 
 
	clrBtnFace = ::GetSysColor(COLOR_BTNFACE); 
	clrBtnShadow = ::GetSysColor(COLOR_BTNSHADOW); 
	clrBtnHilite = ::GetSysColor(COLOR_BTNHIGHLIGHT); 
	clrBtnDkShadow = ::GetSysColor(COLOR_3DDKSHADOW); 
	clrBtnLight = ::GetSysColor(COLOR_3DLIGHT); 
	clrWindowFrame = ::GetSysColor(COLOR_WINDOWFRAME); 
 
	clrBtnText = ::GetSysColor(COLOR_BTNTEXT); 
	brBtnFace.Detach (); 
	brBtnFace.CreateSysColorBrush (COLOR_BTNFACE); 
 
	//------------------ 
	// Initialize fonts: 
	//------------------ 
	NONCLIENTMETRICS info; 
	info.cbSize = sizeof(info); 
 
	::SystemParametersInfo (SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0); 
 
	LOGFONT lf; 
	memset (&lf, 0, sizeof (LOGFONT)); 
 
	CWindowDC dc (NULL); 
	lf.lfCharSet = (BYTE) GetTextCharsetInfo (dc.GetSafeHdc (), NULL, 0); 
 
	lf.lfHeight = info.lfMenuFont.lfHeight; 
	lf.lfWeight = info.lfMenuFont.lfWeight;	 
	lf.lfItalic = info.lfMenuFont.lfItalic; 
 
	_tcscpy (lf.lfFaceName, info.lfMenuFont.lfFaceName); 
 
	BOOL fUseSystemFont = (info.lfMenuFont.lfCharSet > SYMBOL_CHARSET); 
	if (!fUseSystemFont) 
	{ 
		if (::EnumFontFamilies (dc.GetSafeHdc (), NULL, FontFamalyProcFonts, 0) == 0) 
			_tcscpy (lf.lfFaceName, strOfficeFontName); 
		else	_tcscpy (lf.lfFaceName, strDefaultFontName); 
	} 
 
	fontRegular.CreateFontIndirect (&lf); 
} 
 
CSortHeaderCtrl::~CSortHeaderCtrl() 
{ 
 
} 
 
 
BEGIN_MESSAGE_MAP(CSortHeaderCtrl, CHeaderCtrl) 
	//{{AFX_MSG_MAP(CSortHeaderCtrl) 
	ON_WM_ERASEBKGND() 
	ON_WM_PAINT() 
	ON_WM_LBUTTONDOWN() 
	ON_WM_LBUTTONUP() 
	ON_WM_MOUSEMOVE() 
	ON_WM_CANCELMODE() 
	ON_WM_SETCURSOR() 
	//}}AFX_MSG_MAP 
	ON_MESSAGE(HDM_LAYOUT, OnLayout) 
	ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave) 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CSortHeaderCtrl message handlers 
 
void CSortHeaderCtrl::OnDrawItem (CDC* pDC, int iItem, CRect rect, BOOL bIsPressed, BOOL bIsHighlighted) 
{ 
	ASSERT_VALID (this); 
	ASSERT_VALID (pDC); 
  
 	const int nTextMargin = 5; 
	//------------- 
	// Draw border: 
	//------------- 
	if (bIsPressed) 
	{ 
		pDC->Draw3dRect (rect,clrBtnShadow,clrBtnShadow); 
		rect.left++;	rect.top++; 
	}else	pDC->Draw3dRect (rect,clrBtnHilite,clrBtnShadow); 
 
	if (iItem < 0)		return; 
 
	int nSortVal = 0; 
	if (m_mapColumnsStatus.Lookup (iItem, nSortVal) &&	nSortVal != 0) 
	{ 
		//----------------- 
		// Draw sort arrow: 
		//----------------- 
		CRect rectArrow = rect; 
		rectArrow.left = rectArrow.right - rectArrow.Height (); 
		rect.right = rectArrow.left+1; 
		m_bAscending = nSortVal > 0; 
		OnDrawSortArrow (pDC, rectArrow); 
	} 
 
	HD_ITEM hdItem; 
	memset (&hdItem, 0, sizeof (hdItem)); 
	hdItem.mask = HDI_FORMAT | HDI_BITMAP | HDI_TEXT | HDI_IMAGE; 
 
	TCHAR szText [256]; 
	hdItem.pszText = szText; 
	hdItem.cchTextMax = 255; 
 
	if (!GetItem (iItem, &hdItem))	return; 
 
	CBitmap bmp; 
	bmp.LoadBitmap(IDB_BACK); 
	BITMAP  bmpInfo; 
	bmp.GetBitmap(&bmpInfo); 
	CDC dcMem; 
	dcMem.CreateCompatibleDC(pDC); 
	CBitmap *pOldBitmap=dcMem.SelectObject(&bmp); 
	pDC->StretchBlt(rect.left,rect.top,rect.Width()-1,rect.Height(),&dcMem,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY); 
	dcMem.SelectObject(pOldBitmap); 
 
	//----------------------- 
	// Draw bitmap and image: 
	//----------------------- 
	if ((hdItem.fmt & HDF_IMAGE) && hdItem.iImage >= 0)  
	{ 
		//--------------------------------------- 
		// The column has a image from imagelist: 
		//--------------------------------------- 
		CImageList* pImageList = GetImageList (); 
		if (pImageList != NULL) 
		{			 
			int cx = 0; 
			int cy = 0; 
 
			VERIFY (::ImageList_GetIconSize (*pImageList, &cx, &cy)); 
 
			CPoint pt = rect.TopLeft (); 
			pt.x ++; 
			pt.y = (rect.top + rect.bottom - cy) / 2; 
 
			VERIFY (pImageList->Draw (pDC, hdItem.iImage, pt, ILD_NORMAL)); 
			rect.left += cx; 
		} 
	} 
 
	if ((hdItem.fmt & (HDF_BITMAP | HDF_BITMAP_ON_RIGHT)) && hdItem.hbm != NULL) 
	{ 
		CBitmap* pBmp = CBitmap::FromHandle (hdItem.hbm); 
		ASSERT_VALID (pBmp); 
 
		BITMAP bmp; 
		pBmp->GetBitmap (&bmp); 
 
		CRect rectBitmap = rect; 
		if (hdItem.fmt & HDF_BITMAP_ON_RIGHT) 
		{ 
			rectBitmap.right--; 
			rect.right = rectBitmap.left = rectBitmap.right - bmp.bmWidth; 
		}else 
		{ 
			rectBitmap.left++; 
			rect.left = rectBitmap.right = rectBitmap.left + bmp.bmWidth; 
		} 
 
		rectBitmap.top += max (0, (rectBitmap.Height () - bmp.bmHeight) / 2); 
		rectBitmap.bottom = rectBitmap.top + bmp.bmHeight; 
 
		pDC->DrawState (rectBitmap.TopLeft (), rectBitmap.Size (), pBmp, DSS_NORMAL); 
	} 
 
	//----------- 
	// Draw text: 
	//----------- 
	if (hdItem.fmt & HDF_STRING) 
	{ 
		CRect rectLabel = rect; 
		rectLabel.DeflateRect (nTextMargin, 0); 
 
		CString strLabel = hdItem.pszText; 
 
		UINT uiTextFlags = DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX; 
		if (hdItem.fmt & HDF_CENTER)		uiTextFlags |= DT_CENTER; 
		else if (hdItem.fmt & HDF_RIGHT)	uiTextFlags |= DT_RIGHT; 
	    pDC->SetTextColor(RGB(255,255,255)); 
		pDC->DrawText (strLabel, rectLabel, uiTextFlags); 
	} 
} 
//*************************************************************************************** 
void CSortHeaderCtrl::SetSortColumn (int iColumn, BOOL bAscending, BOOL bAdd) 
{ 
	ASSERT_VALID (this); 
 
	if (iColumn < 0) 
	{ 
		m_mapColumnsStatus.RemoveAll (); 
		return; 
	} 
 
	if (bAdd) 
	{ 
		if (!m_bMultipleSort) 
		{ 
			ASSERT (FALSE); 
			bAdd = FALSE; 
		} 
	} 
 
	if (!bAdd) 
	{ 
		m_mapColumnsStatus.RemoveAll (); 
	} 
 
	m_mapColumnsStatus.SetAt (iColumn, bAscending ? 1 : -1); 
	RedrawWindow (); 
} 
//*************************************************************************************** 
void CSortHeaderCtrl::RemoveSortColumn (int iColumn) 
{ 
	ASSERT_VALID (this); 
	m_mapColumnsStatus.RemoveKey (iColumn); 
	RedrawWindow (); 
} 
//*************************************************************************************** 
BOOL CSortHeaderCtrl::OnEraseBkgnd(CDC* /*pDC*/) 
{ 
	return TRUE; 
} 
//*************************************************************************************** 
void CSortHeaderCtrl::OnPaint()  
{ 
	CPaintDC dc(this); // device context for painting 
	 
	CRect rectClip; 
	dc.GetClipBox (rectClip); 
 
	CRect rectClient; 
	GetClientRect (rectClient); 
 
	CDC*		pDC = &dc; 
	BOOL		bMemDC = FALSE; 
	CDC			dcMem; 
	CBitmap		bmp; 
	CBitmap*	pOldBmp = NULL; 
 
	if (dcMem.CreateCompatibleDC (&dc) &&bmp.CreateCompatibleBitmap (&dc, rectClient.Width (),rectClient.Height ())) 
	{ 
		//------------------------------------------------------------- 
		// Off-screen DC successfully created. Better paint to it then! 
		//------------------------------------------------------------- 
		bMemDC = TRUE; 
		pOldBmp = dcMem.SelectObject (&bmp); 
		pDC = &dcMem; 
	} 
 
	OnFillBackground (pDC); 
 
	CFont* pOldFont = (CFont*) pDC->SelectObject (&fontRegular); 
	ASSERT_VALID (pOldFont); 
 
	pDC->SetTextColor (clrBtnText); 
	pDC->SetBkMode (TRANSPARENT); 
 
	CRect rect; 
	GetClientRect(rect); 
 
	CRect rectItem; 
	int nCount = GetItemCount (); 
 
	for (int i = 0; i < nCount; i++) 
	{ 
		//------------------ 
		// Is item pressed? 
		//------------------ 
		CPoint ptCursor; 
		::GetCursorPos (&ptCursor); 
		ScreenToClient (&ptCursor); 
 
		HDHITTESTINFO hdHitTestInfo; 
		hdHitTestInfo.pt = ptCursor; 
 
		int iHit = SendMessage (HDM_HITTEST, 0, (LPARAM) &hdHitTestInfo); 
 
		BOOL bIsHighlighted = iHit == i && (hdHitTestInfo.flags & HHT_ONHEADER); 
		BOOL bIsPressed = m_bIsMousePressed && bIsHighlighted; 
 
		GetItemRect (i, rectItem); 
 
		CRgn rgnClip; 
		rgnClip.CreateRectRgnIndirect (&rectItem); 
		pDC->SelectClipRgn (&rgnClip); 
 
		//----------- 
		// Draw item: 
		//----------- 
		OnDrawItem (pDC, i, rectItem, bIsPressed, m_nHighlightedItem == i); 
 
		pDC->SelectClipRgn (NULL); 
	} 
 
	//-------------------- 
	// Draw "tail border": 
	//-------------------- 
	if (nCount == 0) 
	{ 
		rectItem = rect; 
		rectItem.right++; 
	} 
	else 
	{ 
		rectItem.left = rectItem.right; 
		rectItem.right = rect.right + 1; 
	} 
 
	OnDrawItem (pDC, -1, rectItem, FALSE, FALSE); 
 
	pDC->SelectObject (pOldFont); 
 
	if (bMemDC) 
	{ 
		//-------------------------------------- 
		// Copy the results to the on-screen DC: 
		//--------------------------------------  
		dc.BitBlt (rectClip.left, rectClip.top, rectClip.Width(), rectClip.Height(), 
					   &dcMem, rectClip.left, rectClip.top, SRCCOPY); 
 
		dcMem.SelectObject(pOldBmp); 
	} 
} 
//*************************************************************************************** 
void CSortHeaderCtrl::OnFillBackground (CDC* pDC) 
{ 
	ASSERT_VALID (this); 
	ASSERT_VALID (pDC); 
 
	CRect rectClient; 
	GetClientRect (rectClient); 
     
	pDC->FillRect (rectClient, &brBtnFace); 
} 
//*************************************************************************************** 
void CSortHeaderCtrl::OnLButtonDown(UINT nFlags, CPoint point)  
{ 
	m_bIsMousePressed = TRUE; 
	CHeaderCtrl::OnLButtonDown(nFlags, point); 
} 
//*************************************************************************************** 
void CSortHeaderCtrl::OnLButtonUp(UINT nFlags, CPoint point)  
{ 
	m_bIsMousePressed = FALSE; 
	CHeaderCtrl::OnLButtonUp(nFlags, point); 
} 
//*************************************************************************************** 
void CSortHeaderCtrl::OnDrawSortArrow (CDC* pDC, CRect rectArrow) 
{ 
	ASSERT_VALID (pDC); 
	ASSERT_VALID (this); 
 
	CPen penLight (1, PS_SOLID,clrBtnHilite); 
	CPen penDark (1, PS_SOLID,clrBtnDkShadow); 
 
	CPen* pPenOld = pDC->SelectObject (&penLight); 
	ASSERT_VALID (pPenOld); 
	CBitmap bmp; 
	if (!m_bAscending)		bmp.LoadBitmap(IDB_SORT1); 
	else					bmp.LoadBitmap(IDB_SORT2); 
 
	BITMAP  bmpInfo; 
	bmp.GetBitmap(&bmpInfo); 
	CDC dcMem; 
	dcMem.CreateCompatibleDC(pDC); 
	CBitmap *pOldBitmap=dcMem.SelectObject(&bmp); 
	pDC->StretchBlt(rectArrow.left-1,rectArrow.top,rectArrow.Width(),rectArrow.Height(),&dcMem,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY); 
	dcMem.SelectObject(pOldBitmap); 
 
	pDC->SelectObject (pPenOld); 
} 
//********************************************************************************* 
void CSortHeaderCtrl::EnableMultipleSort (BOOL bEnable) 
{ 
	ASSERT_VALID (this); 
 
	if (m_bMultipleSort == bEnable)		return; 
	 
	m_bMultipleSort = bEnable; 
 
	if (!m_bMultipleSort) 
	{ 
		m_mapColumnsStatus.RemoveAll (); 
		if (GetSafeHwnd () != NULL)		RedrawWindow (); 
	} 
} 
//********************************************************************************* 
int CSortHeaderCtrl::GetSortColumn () const 
{ 
	ASSERT_VALID (this); 
 
	if (m_bMultipleSort) 
	{ 
		TRACE0("Call CSortHeaderCtrl::GetColumnState for muliple sort\n"); 
		ASSERT (FALSE); 
		return -1; 
	} 
 
	int nCount = GetItemCount (); 
	for (int i = 0; i < nCount; i++) 
	{ 
		int nSortVal = 0; 
		if (m_mapColumnsStatus.Lookup (i, nSortVal) &&	nSortVal != 0) 
		{ 
			return i; 
		} 
	} 
 
	return -1; 
} 
//********************************************************************************* 
BOOL CSortHeaderCtrl::IsAscending () const 
{ 
	ASSERT_VALID (this); 
 
	if (m_bMultipleSort) 
	{ 
		TRACE0("Call CBCGHeaderCtrl::GetColumnState for muliple sort\n"); 
		ASSERT (FALSE); 
		return -1; 
	} 
 
	int nCount = GetItemCount (); 
	for (int i = 0; i < nCount; i++) 
	{ 
		int nSortVal = 0; 
		if (m_mapColumnsStatus.Lookup (i, nSortVal) && 
			nSortVal != 0) 
		{ 
			return nSortVal > 0; 
		} 
	} 
 
	return i; 
} 
//********************************************************************************* 
int CSortHeaderCtrl::GetColumnState (int iColumn) const 
{ 
	int nSortVal = 0; 
	m_mapColumnsStatus.Lookup (iColumn, nSortVal); 
 
	return nSortVal; 
} 
//********************************************************************************** 
void CSortHeaderCtrl::OnMouseMove(UINT nFlags, CPoint point)  
{ 
 
		HDHITTESTINFO hdHitTestInfo; 
		hdHitTestInfo.pt = point; 
 
		int nPrevHighlightedItem = m_nHighlightedItem; 
		m_nHighlightedItem = SendMessage (HDM_HITTEST, 0, (LPARAM) &hdHitTestInfo); 
		m_nMouseInItem=hdHitTestInfo.iItem; 
	if ((nFlags & MK_LBUTTON) == 0) 
	{ 
 
		if ((hdHitTestInfo.flags & HHT_ONHEADER) == 0) 
		{ 
	 
			m_nHighlightedItem = -1; 
		} 
		if (nPrevHighlightedItem != m_nHighlightedItem) 
		{ 
			RedrawWindow (); 
		} 
	} 
	 
	CHeaderCtrl::OnMouseMove(nFlags, point); 
} 
//***************************************************************************************** 
LRESULT CSortHeaderCtrl::OnMouseLeave(WPARAM,LPARAM) 
{ 
	if (m_nHighlightedItem >= 0) 
	{ 
		m_nHighlightedItem = -1; 
		RedrawWindow (); 
	} 
 
	return 0; 
} 
//***************************************************************************************** 
void CSortHeaderCtrl::OnCancelMode()  
{ 
	CHeaderCtrl::OnCancelMode(); 
	 
	if (m_nHighlightedItem >= 0) 
	{ 
		m_nHighlightedItem = -1; 
		RedrawWindow (); 
	} 
} 
 
LRESULT CSortHeaderCtrl::OnLayout(WPARAM, LPARAM lParam) 
{ 
	LPHDLAYOUT lphdlayout = (LPHDLAYOUT)lParam; 
 
	if (m_bStaticBorder) 
		lphdlayout->prc->right += GetSystemMetrics(SM_CXBORDER)*2; 
 
	return CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam); 
} 
 
 
 
void CSortHeaderCtrl::Serialize( CArchive& ar ) 
{ 
	if( ar.IsStoring() ) 
	{ 
		const int iItemCount = GetItemCount(); 
		if( iItemCount != -1 ) 
		{ 
			ar << iItemCount; 
 
			HD_ITEM hdItem = { 0 }; 
			hdItem.mask = HDI_WIDTH; 
 
			for( int i = 0; i < iItemCount; i++ ) 
			{ 
				VERIFY( GetItem( i, &hdItem ) ); 
				ar << hdItem.cxy; 
			} 
		} 
	} 
	else 
	{ 
		int iItemCount; 
		ar >> iItemCount; 
		 
		if( GetItemCount() != iItemCount ) 
			TRACE0( _T("Different number of columns in registry.") ); 
		else 
		{ 
			HD_ITEM hdItem = { 0 }; 
			hdItem.mask = HDI_WIDTH; 
 
			for( int i = 0; i < iItemCount; i++ ) 
			{ 
				ar >> hdItem.cxy; 
				VERIFY( SetItem( i, &hdItem ) ); 
			} 
		} 
	} 
} 
void CSortHeaderCtrl::SetSortArrow( const int iSortColumn, const BOOL bSortAscending ) 
{ 
	SetSortColumn (iSortColumn,bSortAscending); 
 
} 
 
BOOL CSortHeaderCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT msg) 
{ 
 
	 
	return m_nMouseInItemhDC ) ); 
 
	// save the device context. 
	const int iSavedDC = dc.SaveDC(); 
 
	// get the column rect. 
	CRect rc( lpDrawItemStruct->rcItem ); 
 
	// set the clipping region to limit drawing within the column. 
	CRgn rgn; 
	VERIFY( rgn.CreateRectRgnIndirect( &rc ) ); 
	(void)dc.SelectObject( &rgn ); 
	VERIFY( rgn.DeleteObject() ); 
 
	// draw the background, 
//	CBrush brush(RGB(100,100,10)); 
//	CBrush brush( GetSysColor( COLOR_3DFACE ) ); 
//	dc.FillRect( rc, &brush ); 
	if(m_bOK) 
		dc.StretchBlt(rc.left,rc.top,rc.right,rc.bottom,&m_dcBack,0,0,17,17,SRCCOPY); 
 
	// get the column text and format. 
	TCHAR szText[ 256 ]; 
	HD_ITEM hditem; 
 
	hditem.mask = HDI_TEXT | HDI_FORMAT; 
	hditem.pszText = szText; 
	hditem.cchTextMax = 255; 
 
	VERIFY( GetItem( lpDrawItemStruct->itemID, &hditem ) ); 
 
	// determine the format for drawing the 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( lpDrawItemStruct->itemState == ODS_SELECTED ) 
	{ 
		rc.left++; 
		rc.top += 2; 
		rc.right++; 
	} 
 
	CRect rcIcon( lpDrawItemStruct->rcItem ); 
	const int iOffset = ( rcIcon.bottom - rcIcon.top ) / 4; 
 
	// adjust the rect further if the sort arrow is to be displayed. 
	if( lpDrawItemStruct->itemID == (UINT)m_iSortColumn ) 
		rc.right -= 3 * iOffset; 
 
	rc.left += iOffset; 
	rc.right -= iOffset; 
 
	// draw the column label. 
	if( rc.left < rc.right ) 
	{ 
		dc.SetBkMode(TRANSPARENT); 
		dc.SetTextColor(RGB(10,10,55)); 
		(void)dc.DrawText( szText, -1, rc, uFormat ); 
	} 
	// draw the sort arrow. 
	if( lpDrawItemStruct->itemID == (UINT)m_iSortColumn ) 
	{ 
		// set up the pens to use for drawing the arrow. 
		if(m_bOK) 
		{ 
 
			if( m_bSortAscending ) 
			{ 
				dc.BitBlt(rcIcon.right - 3 * iOffset,0,17,17,&m_dcAsc,0,0,SRCCOPY); 
			} 
			else 
			{ 
				dc.BitBlt(rcIcon.right - 3 * iOffset,0,17,17,&m_dcDec,0,0,SRCCOPY); 
			} 
 
		} 
		else 
		{ 
			CPen penLight( PS_SOLID, 1, GetSysColor( COLOR_3DHILIGHT ) ); 
			CPen penShadow( PS_SOLID, 1, GetSysColor( COLOR_3DSHADOW ) ); 
			CPen* pOldPen = dc.SelectObject( &penLight ); 
 
			if( m_bSortAscending ) 
			{ 
				// draw the arrow pointing upwards. 
				dc.MoveTo( rcIcon.right - 2 * iOffset, iOffset); 
				dc.LineTo( rcIcon.right - iOffset, rcIcon.bottom - iOffset - 1 ); 
				dc.LineTo( rcIcon.right - 3 * iOffset - 2, rcIcon.bottom - iOffset - 1 ); 
				(void)dc.SelectObject( &penShadow ); 
				dc.MoveTo( rcIcon.right - 3 * iOffset - 1, rcIcon.bottom - iOffset - 1 ); 
				dc.LineTo( rcIcon.right - 2 * iOffset, iOffset - 1);		 
			} 
			else 
			{ 
				// draw the arrow pointing downwards. 
				dc.MoveTo( rcIcon.right - iOffset - 1, iOffset ); 
				dc.LineTo( rcIcon.right - 2 * iOffset - 1, rcIcon.bottom - iOffset ); 
				(void)dc.SelectObject( &penShadow ); 
				dc.MoveTo( rcIcon.right - 2 * iOffset - 2, rcIcon.bottom - iOffset ); 
				dc.LineTo( rcIcon.right - 3 * iOffset - 1, iOffset ); 
				dc.LineTo( rcIcon.right - iOffset - 1, iOffset );		 
			} 
 
			// restore the pen. 
			(void)dc.SelectObject( pOldPen ); 
		} 
	} 
 
	// restore the previous device context. 
	VERIFY( dc.RestoreDC( iSavedDC ) ); 
 
	// detach the device context before returning. 
	(void)dc.Detach(); 
} 
 
 
void CSortHeaderCtrl::Serialize( CArchive& ar ) 
{ 
	if( ar.IsStoring() ) 
	{ 
		const int iItemCount = GetItemCount(); 
		if( iItemCount != -1 ) 
		{ 
			ar << iItemCount; 
 
			HD_ITEM hdItem = { 0 }; 
			hdItem.mask = HDI_WIDTH; 
 
			for( int i = 0; i < iItemCount; i++ ) 
			{ 
				VERIFY( GetItem( i, &hdItem ) ); 
				ar << hdItem.cxy; 
			} 
		} 
	} 
	else 
	{ 
		int iItemCount; 
		ar >> iItemCount; 
		 
		if( GetItemCount() != iItemCount ) 
			TRACE0( _T("Different number of columns in registry.") ); 
		else 
		{ 
			HD_ITEM hdItem = { 0 }; 
			hdItem.mask = HDI_WIDTH; 
 
			for( int i = 0; i < iItemCount; i++ ) 
			{ 
				ar >> hdItem.cxy; 
				VERIFY( SetItem( i, &hdItem ) ); 
			} 
		} 
	} 
} 
 
void CSortHeaderCtrl::SetImage(UINT back, UINT asc, UINT dec) 
{ 
 
	m_bOK=TRUE; 
	CBitmap bmBack,bmAsc,bmDec; 
	bmBack.LoadBitmap(back); 
	bmAsc.LoadBitmap(asc); 
	bmDec.LoadBitmap(dec); 
	m_dcBack.CreateCompatibleDC(GetDC()); 
	m_dcAsc.CreateCompatibleDC(GetDC()); 
	m_dcDec.CreateCompatibleDC(GetDC()); 
	m_dcBack.SelectObject(&bmBack); 
	m_dcAsc.SelectObject(&bmAsc); 
	m_dcDec.SelectObject(&bmDec); 
 
} 
*/