#include "stdafx.h"
#include "SortHeaderCtrl.h"

CSortHeaderCtrl::CSortHeaderCtrl(): m_nSortColumn( -1 ), m_bSortAscending( TRUE )
{
	m_bPressMoused		= FALSE;
	//m_clrColumText		= RGB(255,255,255);
	//m_clr3DHighLight	= RGB(220, 220, 220);	//::GetSysColor(COLOR_3DHIGHLIGHT);
	//m_clr3DShadow		= RGB(35, 35, 35);		//::GetSysColor(COLOR_3DSHADOW);
	//m_clr3DFace			= RGB(128, 128, 128);	//::GetSysColor(COLOR_3DFACE);

	m_clrColumText		= RGB(7,30,129);
	m_clr3DHighLight	= RGB(107, 201, 255);	//::GetSysColor(COLOR_3DHIGHLIGHT);
	m_clr3DShadow		= RGB(37, 121, 176);		//::GetSysColor(COLOR_3DSHADOW);
	m_clr3DFace			= RGB(105, 201, 255);	//::GetSysColor(COLOR_3DFACE);
}

CSortHeaderCtrl::~CSortHeaderCtrl()
{
}

BEGIN_MESSAGE_MAP(CSortHeaderCtrl, CHeaderCtrl)
	ON_WM_PAINT()
	ON_WM_ERASEBKGND()
END_MESSAGE_MAP()

/************************************************************************/
/*  函数：SetSortArrow[10/20/2016 IT];
/*  描述：设置要排序的列以及排序方式（升序或降序）;
/*  参数：;
/*  	[IN] ：;
/*  	[OUT] ：;
/*  	[IN/OUT] ：;
/*  返回：void;
/*  注意：;
/*  示例：;
/*
/*  修改：;
/*  日期：;
/*  内容：;
/************************************************************************/
void CSortHeaderCtrl::SetSortArrow( IN const int nSortColumn, IN const BOOL bSortAscending )
{
	m_nSortColumn = nSortColumn;
	m_bSortAscending = bSortAscending;

	// 设置项自绘风格;
	HD_ITEM hditem;
	hditem.mask = HDI_FORMAT;
	// 获取列信息;
	VERIFY( GetItem( nSortColumn, &hditem ) );
	// 设置自绘风格;
	hditem.fmt |= HDF_OWNERDRAW;
	// 设置列信息;
	VERIFY( SetItem( nSortColumn, &hditem ) );

	// 更新表头以便重绘;
	Invalidate();
}

BOOL CSortHeaderCtrl::OnEraseBkgnd(CDC* pDC)
{
	return TRUE;
}

void CSortHeaderCtrl::OnPaint()
{
	CPaintDC dc(this); // device context for painting

	int nItems = GetItemCount();
	ASSERT(nItems >= 0);
	dc.SetBkColor(m_clr3DFace);
	dc.SetTextColor(m_clrColumText);

	CRect rectClip;
	if (dc.GetClipBox(&rectClip) == ERROR)
		return;
	dc.FillSolidRect(rectClip, m_clr3DFace);

	// 获取当前鼠标位置;
	POINT point;
	GetCursorPos(&point);
	ScreenToClient(&point);

	CRect rectItem;
	for(int i = 0; i < nItems; i++)
	{
		TCHAR szText[256];
		HD_ITEM hditem;

		hditem.mask = HDI_TEXT | HDI_FORMAT | HDI_ORDER;
		hditem.pszText = szText;
		hditem.cchTextMax = 255;
		GetItem( i, &hditem );

		DRAWITEMSTRUCT DrawItemStruct;
		GetItemRect(i, &rectItem);

		DrawItemStruct.CtlType        = ODT_BUTTON;
		DrawItemStruct.hDC            = dc.GetSafeHdc();
		DrawItemStruct.itemAction     = ODA_DRAWENTIRE; 
		DrawItemStruct.hwndItem       = GetSafeHwnd(); 
		DrawItemStruct.rcItem         = rectItem;
		DrawItemStruct.itemID         = i;
		if ( rectItem.PtInRect(point) && m_bPressMoused )
			DrawItemStruct.itemState = ODS_SELECTED;
		DrawItemEx(&DrawItemStruct);
	}
}

/************************************************************************/
/*  函数：DrawItemEx[10/19/2016 IT];
/*  描述：自绘函数;
/*  参数：;
/*  	[IN] ：;
/*  	[OUT] ：;
/*  	[IN/OUT] ：;
/*  返回：void;
/*  注意：;
/*  示例：;
/*
/*  修改：;
/*  日期：;
/*  内容：;
/************************************************************************/
void CSortHeaderCtrl::DrawItemEx( IN LPDRAWITEMSTRUCT lpDrawItemStruct )
{
	// 定义设备上下文;
	CDC dc;	
	// 附加设备上下文句柄;
	VERIFY( dc.Attach( lpDrawItemStruct->hDC ) );

	// 保存设备上下文;
	const int nSavedDC = dc.SaveDC();

	// 获取当前列区域;
	CRect rc( lpDrawItemStruct->rcItem );

	// 实现列单元格3D效果;
	dc.Draw3dRect(rc, m_clr3DHighLight, m_clr3DShadow);
	rc.InflateRect(-1,-1);
	dc.FillSolidRect(rc, m_clr3DFace);
	dc.SetBkMode(TRANSPARENT);

	// 设置文本颜色;
	dc.SetTextColor(m_clrColumText);

	// 恢复原大小;
	rc = lpDrawItemStruct->rcItem;

	// 获取当前的列的项目信息;
	TCHAR szText[ 256 ];
	HD_ITEM hditem;
	hditem.mask = HDI_TEXT | HDI_FORMAT;
	hditem.pszText = szText;
	hditem.cchTextMax = 255;
	VERIFY( GetItem( lpDrawItemStruct->itemID, &hditem ) );

	// 设置列的文本绘制格式;
	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;

	// 如果鼠标在列区域按下，则重新调整列区域;
	if( lpDrawItemStruct->itemState == ODS_SELECTED )
	{
		rc.left++;
		rc.top += 2;
		rc.right++;
		// 释放鼠标按下标志;
		m_bPressMoused = FALSE;
	}

	// 箭头图标区域(rcIcon);
	CRect rcIcon( lpDrawItemStruct->rcItem );
	const int nOffset = ( rcIcon.bottom - rcIcon.top ) / 4;

	// adjust the rect further if the sort arrow is to be displayed.
	if( lpDrawItemStruct->itemID == (UINT)m_nSortColumn )
		rc.right -= 3 * nOffset;

	rc.left += nOffset;
	rc.right -= nOffset;

	// 绘制列文本;
	if( rc.left < rc.right )
		dc.DrawText( szText, -1, rc, uFormat );

	// 绘制排序箭头;
	if( lpDrawItemStruct->itemID == (UINT)m_nSortColumn )
	{
		// 定义绘制箭头的画笔;
		CPen penLight( PS_SOLID, 1, GetSysColor( COLOR_3DHILIGHT ) );
		CPen penShadow( PS_SOLID, 1, GetSysColor( COLOR_3DSHADOW ) );
		CPen* pOldPen = dc.SelectObject( &penLight );

		if( m_bSortAscending )
		{
			// 绘制向上的箭头;
			dc.MoveTo( rcIcon.right - 2 * nOffset, nOffset);
			dc.LineTo( rcIcon.right - nOffset, rcIcon.bottom - nOffset - 1 );
			dc.LineTo( rcIcon.right - 3 * nOffset - 2, rcIcon.bottom - nOffset - 1 );
			dc.SelectObject( &penShadow );
			dc.MoveTo( rcIcon.right - 3 * nOffset - 1, rcIcon.bottom - nOffset - 1 );
			dc.LineTo( rcIcon.right - 2 * nOffset, nOffset - 1);		
		}
		else
		{
			// 绘制向下的箭头;
			dc.MoveTo( rcIcon.right - nOffset - 1, nOffset );
			dc.LineTo( rcIcon.right - 2 * nOffset - 1, rcIcon.bottom - nOffset );
			dc.SelectObject( &penShadow );
			dc.MoveTo( rcIcon.right - 2 * nOffset - 2, rcIcon.bottom - nOffset );
			dc.LineTo( rcIcon.right - 3 * nOffset - 1, nOffset );
			dc.LineTo( rcIcon.right - nOffset - 1, nOffset );		
		}

		// 恢复原来选择的画笔;
		dc.SelectObject( pOldPen );
	}

	// 恢复之前的设备上下文;
	VERIFY( dc.RestoreDC( nSavedDC ) );

	// 返回之前，分离设备上下文句柄;
	dc.Detach();
}

/************************************************************************/
/*  函数：[10/20/2016 IT];
/*  描述：;
/*  参数：;
/*  	[IN] ：;
/*  	[OUT] ：;
/*  	[IN/OUT] ：;
/*  返回：void;
/*  注意：;
/*  示例：;
/*
/*  修改：;
/*  日期：;
/*  内容：;
/************************************************************************/
void CSortHeaderCtrl::Serialize( CArchive& ar )
{
	try
	{
		if( ar.IsStoring() )
		{
			const int nItemCount = GetItemCount();
			if( nItemCount != -1 )
			{
				ar << nItemCount;

				HD_ITEM hdItem = { 0 };
				hdItem.mask = HDI_WIDTH | HDI_ORDER;
				for( int i = 0; i < nItemCount; i++ )
				{
					VERIFY( GetItem( i, &hdItem ) );
					ar << hdItem.cxy;
					ar << hdItem.iOrder;
				}
			}
		}
		else
		{
			int nItemCount;
			ar >> nItemCount;

			if( GetItemCount() != nItemCount )
				TRACE( _T("Different number of columns in registry.") );
			else
			{
				HD_ITEM hdItem = { 0 };
				hdItem.mask = HDI_WIDTH | HDI_ORDER;

				for( int i = 0; i < nItemCount; i++ )
				{
					ar >> hdItem.cxy;
					ar >> hdItem.iOrder;
					VERIFY( SetItem( i, &hdItem ) );
				}
			}
		}
	}
	catch(...)
	{
	}
}

BOOL CSortHeaderCtrl::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 在此添加专用代码和/或调用基类
	if ( pMsg->message == WM_LBUTTONDOWN )
	{
		m_bPressMoused = TRUE;
	}

	return CHeaderCtrl::PreTranslateMessage(pMsg);
}

/************************************************************************/
/*  函数：SetTextFont[3/6/2017 Jeff];
/*  描述：设置文本字体;
/*  参数：;
/*  	[IN] nTextFontSize：字体大小;
/*  	[IN] bBold：是否粗体;
/*  	[IN] bItalic：是否斜体;
/*  	[IN] strTextFontName：字体名称，如楷体;
/*  返回：void;
/*  注意：;
/*  示例：;
/*
/*  修改：;
/*  日期：;
/*  内容：;
/************************************************************************/
void CSortHeaderCtrl::SetListFont(IN CString strFontName, IN int nFontSize, IN BOOL bBold, IN BOOL bItalic)
{
	LOGFONT lf;
	CClientDC dc(this);
	int dpy = GetDeviceCaps(dc, LOGPIXELSY); // Pixel per inch
	lf.lfHeight = -MulDiv(nFontSize, dpy, 72);
	lf.lfWeight = 0;
	lf.lfEscapement = 0;
	lf.lfOrientation = 0;
	if (bBold)
		lf.lfWeight = FW_BLACK;
	else
		lf.lfWeight = FW_NORMAL;
	lf.lfItalic = bItalic;
	lf.lfUnderline = FALSE;
	lf.lfStrikeOut = 0;
	lf.lfCharSet = ANSI_CHARSET;
	lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
	lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
	lf.lfQuality = DEFAULT_QUALITY;
	lf.lfPitchAndFamily = DEFAULT_PITCH | FF_ROMAN;

	_tcscpy_s(lf.lfFaceName, strFontName);

	// 创建字体;
	//m_cfont = GetFont();// 局部变量会导致字体设置失败,必须是全局或成员变量;
	VERIFY(m_cfont.CreateFontIndirect(&lf));
	// 选入字体;
	this->SetFont(&m_cfont);
}