带箭头的listbox

#include "stdafx.h"
#include "FinancialListBox.h"
#include <bkres/bkres.h>
#define		SCROLL_BTN_HEIGHT		20
#define		SCROLL_BTN_WIDTH		134
#define		SCROLL_BTN_ARROW_WIDTH		34
#define		SCROLL_BTN_SPACE_WIDTH		(SCROLL_BTN_WIDTH - SCROLL_BTN_ARROW_WIDTH)/2
#define		IDB_TYPELIST_SCROLL_UP		5011
#define		IDB_TYPELIST_SCROLL_DOWN    5012
#define SC_NORMAL					0 // Normal scroll
#define SC_MOUSEOVER				1 // mouse over
#define SC_PRESSED					2 // The scroll is pressed
#define SC_DISABLED					3 // The scroll is disabled

#define SC_UP 2 //Up scroll
#define SC_DOWN 3 //Down Scroll

CFinancialListBox::CFinancialListBox(void)
{
	m_ClickCB = NULL;

	// 内部使用的标志变量
	m_bNoPaintItem = FALSE;
	m_bTrackFlag = FALSE;
	m_bMouseInScrollUp = FALSE;
	m_bMouseInScrollDown = FALSE;
	m_bNcTrackFlag = FALSE;
	m_bScroll = FALSE;
	m_MaxHeight = 0;
	m_nScrollTopestIndex = -1;
	m_nSelectID = -1;
	m_bNoScrollBtn = TRUE;
	//m_bNoBorder = FALSE;
	m_bSetFocusOnMouseMove = TRUE;

	m_fntNormal.Attach( BkFontPool::GetFont( BKF_DEFAULTFONT ) );
	m_fntSelected.Attach( BkFontPool::GetFont( TRUE, FALSE, FALSE, 0 ) );

	m_SelectBgColor = COL_TYPE_LIST_BG_SELECTED;
	m_NormalBgColor = COL_TYPE_LIST_BG_NORMAL;
	m_SelectTextColor = RGB( 0xFF, 0xFF, 0xFF );
	m_MouseInBgColor = COL_TYPE_LIST_BG_MOUSE_IN;
}

CFinancialListBox::~CFinancialListBox(void)
{
	m_fntSelected.Detach();
	m_fntNormal.Detach();
}

void CFinancialListBox::SetSelectBgColor(const COLORREF _SelectBgColor)
{
	m_SelectBgColor = _SelectBgColor;
}

void CFinancialListBox::SetNormalBgColor(const COLORREF _NormalBgColor)
{
	m_NormalBgColor = _NormalBgColor;
}

void CFinancialListBox::SetSelectTextColor(const COLORREF _SelectTextColor)
{
	m_SelectTextColor = _SelectTextColor;
}

void CFinancialListBox::SetMouseInBgColor(const COLORREF _MouseInBgColor)
{
	m_MouseInBgColor = _MouseInBgColor;
}

void CFinancialListBox::ShowScrollBtn(BOOL bShow /*= TRUE*/)
{
	m_bNoScrollBtn = bShow;
}

//void CFinancialListBox::SetNoBorder(BOOL bNoBorder  /*= TRUE*/)
//{
//	m_bNoBorder = bNoBorder ;
//}

void CFinancialListBox::OnSetFocus(HWND hWnd) 
{
	GetParent().GetParent().SetFocus();
	return;
}

LRESULT	CFinancialListBox::OnCtlColor(HDC hDc, HWND hWnd)
{
	if (hWnd==m_hWnd)
	{
		CDCHandle	dchan;
		dchan.Attach(hDc);

		SetMsgHandled(TRUE);

		if (m_hBGBrush.m_hBrush==NULL)
			m_hBGBrush.CreateSolidBrush(COL_TYPE_LIST_BG_NORMAL);

		//DrawBorder();

		dchan.Detach();
		return (LRESULT)m_hBGBrush.m_hBrush;
	}
	SetMsgHandled(FALSE);
	return NULL;
}

void CFinancialListBox::SetFocusOnMouseMove( BOOL bSetFocus )
{
	m_bSetFocusOnMouseMove = bSetFocus;
}

void CFinancialListBox::SetNumber( int nIndex,  int n )
{
	CListBoxItemData * p = GetItemDataX( nIndex );

	p->nNumber = n;

	CRect rt;
	if ( GetItemRect( nIndex, &rt ) )
	{
		InvalidateRect( &rt );
	}
}

void CFinancialListBox::SetCallBack( IListBoxClickCallback * pCallBack )
{
	m_ClickCB = pCallBack;
}

void	CFinancialListBox::SetListID( int nListId )
{
	m_nListId = nListId;
}

HRESULT	CFinancialListBox::OnLButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bMsgHandled )
{
	POINT	pts;
	pts.x		= GET_X_LPARAM(lParam);
	pts.y		= GET_Y_LPARAM(lParam);

	for ( int i=0; i<this->GetCount(); i++ )
	{
		CRect r;
		GetItemRect( i, r );
		if (PtInRect(&r, pts))
		{
			m_nSelectID = i;
			SetCurSel(m_nSelectID);
			Invalidate(FALSE);
			break;
		}
	}

	return S_OK;
}
void CFinancialListBox::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	if ( m_ClickCB != NULL )
	{
		m_ClickCB->OnDbClick( m_nListId );
	}
}
HRESULT	CFinancialListBox::OnLButtonUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bMsgHandled )
{
	POINT	pts;
	BOOL	bOutSide;

	pts.x		= GET_X_LPARAM(lParam);
	pts.y		= GET_Y_LPARAM(lParam);

	INT nIndex;
	if ( m_nSelectID != -1 )
	{
		nIndex = m_nSelectID;
		CListBox::ItemFromPoint(pts,bOutSide);
	}
	else
	{
		nIndex = CListBox::ItemFromPoint(pts,bOutSide);
	}

	if ( !bOutSide && nIndex >= 0 && nIndex < 0xffff )
	{
		CListBoxItemData*	pData = (CListBoxItemData*)GetItemDataX(nIndex);
		if ( m_ClickCB != NULL )
		{
			m_ClickCB->OnClick( m_nListId, pData );
		}		
	}

	bMsgHandled = FALSE;
	return	S_OK;
}

HRESULT	CFinancialListBox::OnMouseWheel( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bMsgHandled )
{
	bMsgHandled = TRUE;

	// 首先刷新一下鼠标悬停区域的颜色
	if ( m_ItemRect.top != MOUSE_IN_ITEM_MAGIC_NUMBER )
	{
		m_ItemRect.bottom = m_ItemRect.top = MOUSE_IN_ITEM_MAGIC_NUMBER;
		InvalidateRect( m_LastRect );
		m_LastRect = m_ItemRect;
	}

	if ( wParam & 0x10000000 )
	{
		// rotated backward
		SendMessage( WM_VSCROLL, SB_LINEDOWN );
	}
	else
	{
		// rotated forward
		SendMessage( WM_VSCROLL, SB_LINEUP );
	}

	DrawScrolls( SC_UP, SC_NORMAL );
	DrawScrolls( SC_DOWN, SC_NORMAL );

	return S_OK;
}

HRESULT	CFinancialListBox::OnMouseLeave( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bMsgHandled )
{
	m_bTrackFlag = FALSE;

	m_ItemRect.bottom = m_ItemRect.top = MOUSE_IN_ITEM_MAGIC_NUMBER;
	InvalidateRect( m_LastRect );
	m_LastRect = m_ItemRect;

	return S_OK;
}

void CFinancialListBox::OnTimer(UINT_PTR nIDEvent)
{
	//Gets the state of the left button to see if it is pressed
	short result=GetKeyState(VK_LBUTTON);

	if (nIDEvent==1){ //Up timer

		//If it returns negative then it is pressed
		if ( result >= 0 ) 
		{ //No longer pressed

			KillTimer(1); 
			DrawScrolls( SC_UP, SC_MOUSEOVER ); 
		}
		else
		{
			SendMessage(WM_VSCROLL,MAKEWPARAM(SB_LINEUP,0),0); 
			DrawScrolls(SC_UP, SC_PRESSED);
			DrawScrolls(SC_DOWN, SC_NORMAL);
		}

	}
	else 
	{ //Down timer

		if ( result >= 0 ) 
		{
			KillTimer(2);  
			DrawScrolls(SC_DOWN,SC_MOUSEOVER); 
		} 
		else
		{
			SendMessage(WM_VSCROLL,MAKEWPARAM(SB_LINEDOWN,0),0);
			DrawScrolls( SC_UP, SC_NORMAL );
			DrawScrolls( SC_DOWN, SC_PRESSED );
		}

	}
}

// 再试一下, 或者这个的消息映射方式也应该改成 Message_Handler 
LRESULT CFinancialListBox::OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam)		
{
	NCCALCSIZE_PARAMS * lpncsp = ( NCCALCSIZE_PARAMS * ) lParam;

	int		nClientHight = lpncsp->rgrc[0].bottom - lpncsp->rgrc[0].top;
	int		nAllItemHight = 0;
	BOOL	bScroll = FALSE;

	for ( int i=0; i<this->GetCount(); i++ )
	{
		nAllItemHight += GetItemHeight( i );
	}

	if ( m_bNoScrollBtn && nAllItemHight + SCROLL_BTN_HEIGHT > nClientHight )
	{
		m_MaxHeight = lpncsp->rgrc[0].bottom - lpncsp->rgrc[0].top - 1;

		lpncsp->rgrc[0].top += SCROLL_BTN_HEIGHT;
		lpncsp->rgrc[0].bottom -= SCROLL_BTN_HEIGHT;
		bScroll = TRUE;
		nClientHight -= SCROLL_BTN_HEIGHT * 2;
	}
	else
	{
		bScroll = FALSE;
		m_MaxHeight = 0;
	}

	// 确定 m_nScrollTopestIndex
	int		nItemHeight = GetItemHeight( 0 );
	int		nDisplayCount;
	if ( nItemHeight > 0 )
	{
		nDisplayCount = nClientHight / nItemHeight;
	}
	else
	{
		nDisplayCount = 0;
	}

	m_nScrollTopestIndex = GetCount() - nDisplayCount;


	m_bScroll = bScroll;

	SendMessage( WM_NCPAINT );		// 修改后必须重绘一次才生效

	// CListBox::OnNcCalcSize(bCalcValidRects, lParam);
	return 0;
}

void CFinancialListBox::CaclTopestIndex(UINT nClientHight)
{
	int		nAllItemHight = 0;
	BOOL	bScroll = FALSE;

	for ( int i=0; i<this->GetCount(); i++ )
	{
		nAllItemHight += GetItemHeight( i );
	}

	if ( m_bNoScrollBtn && nAllItemHight + SCROLL_BTN_HEIGHT > nClientHight )
	{
		nClientHight -= SCROLL_BTN_HEIGHT * 2;
	}
	// 确定 m_nScrollTopestIndex
	int		nItemHeight = GetItemHeight( 0 );
	int		nDisplayCount;
	if ( nItemHeight > 0 )
	{
		nDisplayCount = nClientHight / nItemHeight;
	}
	else
	{
		nDisplayCount = 0;
	}

	m_nScrollTopestIndex = GetCount() - nDisplayCount;
}
LRESULT CFinancialListBox::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{

	LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);

	// 获取List当前的位置, 相对于屏幕左上角
	RECT irect = { 0 };
	GetWindowRect(&irect);

	// 获得当前鼠标位置
	POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };

	if ( lRet == HTNOWHERE )
	{
		if ( pt.x > irect.left && pt.x < irect.right )
		{
			if ( pt.y > irect.top && pt.y < irect.top + SCROLL_BTN_HEIGHT )
			{
				lRet = HTVSCROLL;
			}
			else if ( pt.y > irect.bottom - SCROLL_BTN_HEIGHT && pt.y < irect.bottom )
			{
				lRet = HTHSCROLL;
			}
		}
	}

	return lRet;
}

LRESULT CFinancialListBox::OnNcLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{

	CString str;
	str.Format(_T("123"));
	OutputDebugString(str);

	// 获取List当前的位置, 相对于屏幕左上角
	RECT irect = { 0 };
	GetWindowRect(&irect);

	// 获得当前鼠标位置
	POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };

	if ( pt.x > irect.left && pt.x < irect.right )
	{
		if ( pt.y > irect.top && pt.y < irect.top + SCROLL_BTN_HEIGHT )
		{
			DrawScrolls( SC_UP, SC_PRESSED );
			SendMessage(WM_VSCROLL,MAKEWPARAM(SB_LINEUP,0),0);  
			DrawScrolls( SC_DOWN, SC_NORMAL );

			//DrawBorder();

			SetTimer( 1, 150, NULL );		
		}
		else if ( pt.y > irect.bottom - SCROLL_BTN_HEIGHT && pt.y < irect.bottom )
		{
			DrawScrolls( SC_DOWN, SC_PRESSED );
			SendMessage(WM_VSCROLL,MAKEWPARAM(SB_LINEDOWN,0),0);
			DrawScrolls( SC_UP, SC_NORMAL );

			//DrawBorder();

			SetTimer( 2, 150, NULL );
		}
	}

	return DefWindowProc(uMsg, wParam, lParam);
	//	return 0;
}

LRESULT CFinancialListBox::OnNcMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{

	// 获取List当前的位置, 相对于屏幕左上角
	RECT irect = { 0 };
	GetWindowRect(&irect);

	if ( !m_bNcTrackFlag )
	{
		TRACKMOUSEEVENT tme;
		tme.cbSize = sizeof(tme);
		tme.hwndTrack = this->m_hWnd;
		tme.dwFlags = TME_LEAVE | TME_NONCLIENT;
		tme.dwHoverTime = 0;
		m_bNcTrackFlag = _TrackMouseEvent(&tme);
	}

	// 获得当前鼠标位置
	POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };

	if ( pt.x > irect.left && pt.x < irect.right )
	{
		if ( pt.y > irect.top && pt.y < irect.top + SCROLL_BTN_HEIGHT )
		{
			if ( !m_bMouseInScrollUp )
			{
				DrawScrolls( SC_UP, SC_MOUSEOVER );
				m_bMouseInScrollUp = TRUE;
			}		
		}
		else if ( pt.y > irect.bottom - SCROLL_BTN_HEIGHT && pt.y < irect.bottom )
		{
			if ( !m_bMouseInScrollDown)
			{
				DrawScrolls( SC_DOWN, SC_MOUSEOVER );
				m_bMouseInScrollDown = TRUE;
			}
		}
	}

	return DefWindowProc(uMsg, wParam, lParam);
	// return 0;
}

HRESULT	CFinancialListBox::OnNcMouseLeave( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bMsgHandled )
{
	m_bNcTrackFlag = FALSE;

	if ( m_bMouseInScrollUp )
	{
		DrawScrolls( SC_UP, SC_NORMAL );
		m_bMouseInScrollUp = FALSE;
	}

	if ( m_bMouseInScrollDown )
	{
		DrawScrolls( SC_DOWN, SC_NORMAL );
		m_bMouseInScrollDown = FALSE;
	}

	return	S_OK;
}

HRESULT	CFinancialListBox::OnMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bMsgHandled )
{
	POINT	pts;
	CRect	rcItem;
	CRect	rcOut( -1, -1, -1, -1 );
	BOOL	bOutSide = FALSE;
	BOOL	bOntip=FALSE;
	BOOL	bMove=FALSE;

	if (!m_bTrackFlag)
	{
		TRACKMOUSEEVENT tme;
		tme.cbSize = sizeof(tme);
		tme.hwndTrack = this->m_hWnd;
		tme.dwFlags = TME_LEAVE;
		tme.dwHoverTime = 0;
		m_bTrackFlag = _TrackMouseEvent(&tme);

		if ( m_bSetFocusOnMouseMove )
		{
			//				this->SetFocus();
		}	
	}

	bMsgHandled = FALSE;
	pts.x		= GET_X_LPARAM(lParam);
	pts.y		= GET_Y_LPARAM(lParam);

	int nIndex = -1;
	for ( int i=0; i<this->GetCount(); i++ )
	{
		CRect r;
		GetItemRect( i, r );
		if (PtInRect(&r, pts))
		{
			nIndex = i;
			break;
		}
	}
	if ( nIndex >= 0 && nIndex < 0xffff && GetItemRect(nIndex,&rcItem) )
	{
		if ( m_ItemRect == rcItem )
		{
			return	S_OK;
		}
		else
		{
			m_ItemRect = rcItem;
			InvalidateRect( &rcItem );
		}
	}
	else if (nIndex == -1)
	{
		if ( m_ItemRect == rcOut )
		{
			return	S_OK;
		}
		else
		{
			m_ItemRect = rcOut;
			InvalidateRect( m_LastRect );
		}
	}

	return	S_OK;
}

LRESULT CFinancialListBox::OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	static BOOL before=FALSE;
	if ( !before ) 
	{
		// 指在真正显示这个测栏的时候被呼叫
		SetWindowPos(NULL,0,0,0,0,SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE); 
		before=TRUE;
	}

	//DrawBorder();

	DrawScrolls(SC_UP,SC_NORMAL);
	DrawScrolls(SC_DOWN,SC_NORMAL);

	return 0;
}


void CFinancialListBox::DrawScrolls(UINT WhichOne, UINT State)
{

	if ( !m_bScroll )
	{
		return;
	}

	CRect rect;
	GetClientRect(rect); //Gets the dimensions

	if ( rect.bottom - rect.top > m_MaxHeight )
	{
		return;
	}

	CDC iDC;
	HDC	h = GetDC();

	CDCHandle	han;
	han.Attach( h );
	iDC.CreateCompatibleDC( han );

	int		nCurrentTopIndex = GetTopIndex();

	if ( rect.bottom > 0 )
	{
		if (WhichOne==SC_UP)
		{ 
			//The one to draw is the up one
			//Draws the scroll up
			rect.top = -SCROLL_BTN_HEIGHT;
			rect.bottom = 0;

			HBITMAP hBmpCheck	= BkBmpPool::GetBitmap( IDB_TYPELIST_SCROLL_UP );
			HBITMAP hBmpOld		= iDC.SelectBitmap(hBmpCheck);

			if ( nCurrentTopIndex == 0 )
			{
				State = SC_DISABLED;
			}
			han.StretchBlt( rect.left, rect.top, (rect.Width() - SCROLL_BTN_ARROW_WIDTH)/2 ,rect.Height(), iDC, State * SCROLL_BTN_WIDTH , 0 , SCROLL_BTN_SPACE_WIDTH, SCROLL_BTN_HEIGHT , SRCCOPY );
			han.StretchBlt( rect.left + (rect.Width() - SCROLL_BTN_ARROW_WIDTH)/2, rect.top, SCROLL_BTN_ARROW_WIDTH,rect.Height(), iDC, State * SCROLL_BTN_WIDTH + SCROLL_BTN_SPACE_WIDTH , 0 , SCROLL_BTN_ARROW_WIDTH, SCROLL_BTN_HEIGHT , SRCCOPY );
			han.StretchBlt( rect.left + (rect.Width() - SCROLL_BTN_ARROW_WIDTH)/2 + SCROLL_BTN_ARROW_WIDTH , rect.top, (rect.Width() - SCROLL_BTN_ARROW_WIDTH)/2,rect.Height(), iDC, State * SCROLL_BTN_WIDTH , 0 , SCROLL_BTN_SPACE_WIDTH, SCROLL_BTN_HEIGHT , SRCCOPY );

			iDC.SelectBitmap(hBmpOld);
		}
		else
		{ 
			//Needs to draw down
			rect.top = rect.bottom;
			rect.bottom = rect.bottom + SCROLL_BTN_HEIGHT;

			HBITMAP hBmpCheck	= BkBmpPool::GetBitmap( IDB_TYPELIST_SCROLL_DOWN );
			HBITMAP hBmpOld		= iDC.SelectBitmap(hBmpCheck);
			if ( nCurrentTopIndex == m_nScrollTopestIndex )
			{
				State = SC_DISABLED;
			}
			han.StretchBlt( rect.left, rect.top, (rect.Width() - SCROLL_BTN_ARROW_WIDTH)/2 ,rect.Height(), iDC, State * SCROLL_BTN_WIDTH , 0 , SCROLL_BTN_SPACE_WIDTH, SCROLL_BTN_HEIGHT , SRCCOPY );
			han.StretchBlt( rect.left + (rect.Width() - SCROLL_BTN_ARROW_WIDTH)/2, rect.top, SCROLL_BTN_ARROW_WIDTH,rect.Height(), iDC, State * SCROLL_BTN_WIDTH + SCROLL_BTN_SPACE_WIDTH , 0 , SCROLL_BTN_ARROW_WIDTH, SCROLL_BTN_HEIGHT , SRCCOPY );
			han.StretchBlt( rect.left + (rect.Width() - SCROLL_BTN_ARROW_WIDTH)/2 + SCROLL_BTN_ARROW_WIDTH , rect.top, (rect.Width() - SCROLL_BTN_ARROW_WIDTH)/2,rect.Height(), iDC, State * SCROLL_BTN_WIDTH , 0 , SCROLL_BTN_SPACE_WIDTH, SCROLL_BTN_HEIGHT , SRCCOPY );

			//han.StretchBlt( rect.left, rect.top, rect.Width(),rect.Height(), iDC, State * SCROLL_BTN_WIDTH , 0 , SCROLL_BTN_WIDTH, SCROLL_BTN_HEIGHT , SRCCOPY );
			iDC.SelectBitmap(hBmpOld);

		} 

		HPEN	hPenTmp;
		CPen	pen_border;
		pen_border.CreatePen( PS_SOLID, 1, COL_TYPE_LIST_BORDER_LINE );
		hPenTmp = han.SelectPen( pen_border );

		han.MoveTo( rect.right - 1, rect.top );
		han.LineTo( rect.right - 1, rect.bottom );

		// 恢复
		han.SelectPen( hPenTmp );
	}  

	han.Detach();
	ReleaseDC( h );

	InvalidateRect( &rect );
}

//void CFinancialListBox::DrawBorder()
//{
//	return;
//	CDC iDC;
//	HDC	h = GetDC();
//
//	CDCHandle	han;
//	han.Attach( h );
//	iDC.CreateCompatibleDC( han );
//
//	CRect rect;
//	GetClientRect(rect); //Gets the dimensions
//
//	HPEN	hPenTmp;
//	CPen	pen_border;
//	pen_border.CreatePen( PS_SOLID, 1, COL_TYPE_LIST_BORDER_LINE );
//	hPenTmp = han.SelectPen( pen_border );
//
//	int		nIndex = GetCurSel();
//	CRect	SelRect;
//	int	nret = GetItemRect( nIndex, &SelRect );
//	if ( nret != LB_ERR )
//	{
//		//if ( rect.top < SelRect.top && SelRect.bottom < rect.bottom )
//		//{
//		//	han.MoveTo( rect.right - 1, rect.top );
//		//	han.LineTo( rect.right - 1, SelRect.top );
//
//		//	han.MoveTo( rect.right -1, SelRect.bottom );
//		//	han.LineTo( rect.right - 1, rect.bottom );
//		//}
//		//else if ( SelRect.bottom <= rect.top || SelRect.top >= rect.bottom  )
//		//{
//		//	han.MoveTo( rect.right - 1, rect.top );
//		//	han.LineTo( rect.right - 1, rect.bottom );
//		//}
//		//else if ( SelRect.top <= rect.top && SelRect.bottom > rect.top )
//		//{
//		//	han.MoveTo( rect.right - 1, SelRect.bottom );
//		//	han.LineTo( rect.right - 1, rect.bottom );
//		//}
//		//else if ( SelRect.top < rect.bottom && SelRect.bottom > rect.bottom )
//		//{
//		//	han.MoveTo( rect.right - 1, rect.top );
//		//	han.LineTo( rect.right - 1, SelRect.top );
//		//}
//
//		// 不再画出边线的缺口
//		han.MoveTo( rect.right - 1, rect.top );
//		han.LineTo( rect.right - 1, rect.bottom );
//
//	}
//	else
//	{
//		han.MoveTo( rect.right - 1, rect.top );
//		han.LineTo( rect.right - 1, rect.bottom );
//	}
//
//	// 恢复
//	han.SelectPen( hPenTmp );
//
//	han.Detach();
//	ReleaseDC( h );
//}

void CFinancialListBox::GetCurSelName( CString & strValue )
{
	CListBoxItemData * p = GetItemDataX( m_nSelectID );
	if ( p != NULL )
	{
		strValue = p->strValue;
	}
	else
	{
		strValue = _T( "" );
	}
}

void CFinancialListBox::SetCurSelName( CString strValue, BOOL bOnClick /*= FALSE*/)
{
	for ( int i=0; i<m_arrData.GetSize(); i++ )
	{
		CListBoxItemData * p = GetItemDataX( i );
		if ( p != NULL && p->strValue == strValue )
		{
			m_nSelectID = i;
			SetCurSel( i );
			if (bOnClick)
			{
				m_ClickCB->OnClick(m_nListId, p);
			}
			break;
		}
	}
}

void CFinancialListBox::SetNumberByName( CString strValue, int nNumber )
{
	for ( int i=0; i<m_arrData.GetSize(); i++ )
	{
		CListBoxItemData * p = GetItemDataX( i );
		if ( p != NULL && p->strValue == strValue )
		{
			p->nNumber = nNumber;
			break;
		}
	}
}

int CFinancialListBox::GetNumberByName( CString strValue )
{
	for ( int i=0; i<m_arrData.GetSize(); i++ )
	{
		CListBoxItemData * p = GetItemDataX( i );
		if ( p != NULL && p->strValue == strValue )
		{
			return p->nNumber;
		}
	}

	return 0;		// 没找到
}

void CFinancialListBox::DrawItem ( LPDRAWITEMSTRUCT lpdis )
{
	if ( m_bNoPaintItem )
	{
		return;
	}

	CRect rcWindow;
	GetWindowRect( rcWindow );

	CListBoxItemData * pListData	= GetItemDataX( lpdis->itemID );
	if ( pListData != NULL )
	{
		CDCHandle	dcx;
		CDC			dcTmp;
		HFONT		hFntTmp;
		DWORD		colTxtTmp;
		DWORD		nOldMod;

		dcx.Attach( lpdis->hDC );
		dcTmp.CreateCompatibleDC( dcx );

		nOldMod = dcx.GetBkMode();
		dcx.SetBkMode( TRANSPARENT );

		hFntTmp = dcx.SelectFont( m_fntNormal );
		colTxtTmp = dcx.GetTextColor();

		// 判断当前的item是否被选中
		BOOL	bSelect = FALSE;
		if ( ( lpdis->itemAction | ODA_SELECT )
			&& ( lpdis->itemState & ODS_SELECTED ) )
		{
			bSelect = TRUE;
			m_nSelectID = lpdis->itemID;
			//dcx.SelectFont( m_fntSelected );
		}

		if ( bSelect )
		{
			dcx.FillSolidRect( &( lpdis->rcItem ), m_SelectBgColor );
		}
		else if ( m_ItemRect == lpdis->rcItem )
		{
			dcx.FillSolidRect( &( lpdis->rcItem ), m_MouseInBgColor );
			if ( m_LastRect != m_ItemRect )
			{
				InvalidateRect( m_LastRect );
				m_LastRect = m_ItemRect;
			}
		}
		else
		{
			dcx.FillSolidRect( &( lpdis->rcItem ), m_NormalBgColor );
		}

		if ( bSelect )
		{
			dcx.SetTextColor( m_SelectTextColor );
		}
		else
		{
			// 设置文字颜色
			dcx.SetTextColor( pListData->colName );
		}


		CRect	rcText = lpdis->rcItem;
		rcText.left += pListData->nTextOffset;

		CString		strDisplay;
		if ( pListData->nNumber == -1 )
		{
			strDisplay = pListData->strValue;
		}
		else
		{
			strDisplay.Format( _T("%s(%d)"), pListData->strValue, pListData->nNumber );
		}
		dcx.DrawText( strDisplay, -1, rcText, DT_VCENTER | DT_LEFT | DT_SINGLELINE );

		// 画线
		HPEN	hPenTmp;
		CPen	pen_up;

		pen_up.CreatePen( PS_SOLID, 1, COL_TYPE_LIST_UPPER_LINE );	

		hPenTmp = dcx.SelectPen( pen_up );

		if ( lpdis->itemID != GetTopIndex() && !bSelect )
		{
			dcx.MoveTo( lpdis->rcItem.left + 1, lpdis->rcItem.top );
			dcx.LineTo( lpdis->rcItem.right - 1, lpdis->rcItem.top );
		}

		CPen	pen_down;
		if ( !bSelect )
		{
			pen_down.CreatePen( PS_SOLID, 1, COL_TYPE_LIST_LOWER_LINE );
		}
		else
		{
			pen_down.CreatePen( PS_SOLID, 1, COL_TYPE_LIST_BORDER_LINE );
		}

		dcx.SelectPen( pen_down );


		dcx.MoveTo( lpdis->rcItem.left + 1, lpdis->rcItem.bottom - 1 );

		if ( bSelect )
		{
			dcx.LineTo( lpdis->rcItem.right, lpdis->rcItem.bottom - 1 );
		}
		else
		{
			if ( lpdis->itemID != GetCount() - 1 )
			{
				dcx.LineTo( lpdis->rcItem.right - 1, lpdis->rcItem.bottom - 1 );
			}		
		}


		/*CPen	pen_border;
		pen_border.CreatePen( PS_SOLID, 1, COL_TYPE_LIST_BORDER_LINE );
		dcx.SelectPen( pen_border );

		if ( !bSelect )
		{
			dcx.MoveTo( lpdis->rcItem.right - 1, lpdis->rcItem.top );
			dcx.LineTo( lpdis->rcItem.right - 1, lpdis->rcItem.bottom + 1 );
		}*/


		// 恢复
		dcx.SelectPen( hPenTmp );
		dcx.SetTextColor( colTxtTmp );
		dcx.SelectFont( hFntTmp );
		dcx.SetBkMode( nOldMod );

	}
}

int CFinancialListBox::SetItemDataX(int nIndex, DWORD_PTR dwItemData)
{
	CListBoxItemData*	pItemData=(CListBoxItemData*)dwItemData;
	ATLASSERT(pItemData!=NULL);

	for (int i= 0;i<m_arrData.GetSize();i++)
	{
		if ( m_arrData[i]->nId == pItemData->nId )
		{
			ATLASSERT(FALSE);
			return -1;
		}
	}

	m_arrData.Add(pItemData);
	return SetItemData( nIndex, ( DWORD_PTR ) pItemData->nId );
}

CListBoxItemData*	CFinancialListBox::GetItemDataX(int i)
{
	DWORD	nItemId = (DWORD)GetItemData(i);

	for ( int i=0; i<m_arrData.GetSize(); i++)
	{
		if ( m_arrData[i] != NULL && m_arrData[i]->nId == nItemId)
			return m_arrData[i];
	}
	return NULL;
}

VOID CFinancialListBox::DeleteAllItems()
{
	for ( INT i= 0; i < m_arrData.GetSize(); i++)
	{
		CListBoxItemData*	pData = m_arrData[i];
		if ( pData )
		{
			delete pData;
		}
	}

	m_arrData.RemoveAll();
	CListBox::ResetContent();
}

void CFinancialListBox::RefreshItem(int nIndex)
{
	ATLASSERT(nIndex >= 0 && nIndex < m_arrData.GetSize());
	if (nIndex < 0 || nIndex >= m_arrData.GetSize() || (IsWindow() == FALSE))
	{
		return;
	}

	CRect rcItem;
	GetItemRect(nIndex, &rcItem);
	InvalidateRect(&rcItem, FALSE);
}

BOOL CFinancialListBox::CheckItemExist(CString strText)
{
	for (int i = 0; i < m_arrData.GetSize(); i++)
	{
		CListBoxItemData*	pData = NULL;
		pData = m_arrData[i];
		if ( pData != NULL && pData->strValue == strText)
		{
			return TRUE;
		}
	}

	return FALSE;
}


.h

#ifndef FinancialListBox_H 
#define FinancialListBox_H 

#include "stdafx.h"
#include "FinancialCombox.h"
//
// Type List Box Control
//

class CListBoxItemData
{
public:
	CListBoxItemData( int nOffset, DWORD Id, COLORREF colType, LPCTSTR TypeName, int inumber )
	{
		nTextOffset = nOffset;
		nId			= Id;
		colName = colType;
		strValue = TypeName;
		nNumber		= inumber;
	}

	virtual	~CListBoxItemData()
	{
	
	}

public:
	
	int			nTextOffset;		// 显示文字的偏移
	CString		strValue;		// 分类名
	COLORREF	colName;		// 可以对不同的分类设置颜色
	DWORD		nId;				// 分类的ID
	int			nNumber;			// 数量  -1表示不显示
};

class IListBoxClickCallback
{
public:
	virtual void	OnClick( int nListId, CListBoxItemData * pData) = 0;
	virtual void	OnDbClick( int nListId)
	{
	};
	
};


class CFinancialListBox
	: public CWindowImpl<CFinancialListBox, CListBox>
	, public COwnerDraw<CFinancialListBox>

{
public:
	CFinancialListBox(void);
	~CFinancialListBox(void);
protected:

	CBrush	m_hBGBrush;

	BOOL	m_bSetFocusOnMouseMove;

	CFont		m_fntNormal;
	CFont		m_fntSelected;	// 被点击选中后的字体

	BOOL	m_bNoPaintItem;
	BOOL	m_bTrackFlag;

	BOOL	m_bMouseInScrollUp;
	BOOL	m_bMouseInScrollDown;
	BOOL	m_bNcTrackFlag;

	BOOL    m_bNoScrollBtn;
	//BOOL    m_bNoBorder;
	BOOL	m_bScroll;
	int		m_MaxHeight;

	int		m_nScrollTopestIndex;		// 当listbox中的数据滚动到最高点时显示在最上面的行的索引

	CRect	m_ItemRect;
	CRect	m_LastRect;

	IListBoxClickCallback*	m_ClickCB;

	int		m_nListId;					// 创建ListBox时使用的ID, 保存它用于OnClick回调时区分同一个窗体中的不同ListBox
	int		m_nSelectID;

	CSimpleArray<CListBoxItemData*>	m_arrData;

	COLORREF	m_SelectBgColor;
	COLORREF	m_NormalBgColor;
	COLORREF	m_SelectTextColor;
	COLORREF	m_MouseInBgColor;
public:
	BEGIN_MSG_MAP(CFinancialListBox)   
		MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
		MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
		MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
		MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
		MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
		MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint)
		MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest)
		MESSAGE_HANDLER(WM_NCLBUTTONDOWN, OnNcLButtonDown)
		MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnNcLButtonDown)
		MESSAGE_HANDLER(WM_NCMOUSEMOVE, OnNcMouseMove)
		MESSAGE_HANDLER(WM_NCMOUSELEAVE, OnNcMouseLeave)
		MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
		MSG_WM_TIMER(OnTimer)
		MSG_WM_NCCALCSIZE(OnNcCalcSize)
		MSG_OCM_CTLCOLORLISTBOX(OnCtlColor)
		MSG_WM_SETFOCUS(OnSetFocus)
		CHAIN_MSG_MAP_ALT(COwnerDraw<CFinancialListBox>,1)
		DEFAULT_REFLECTION_HANDLER()
	END_MSG_MAP()   

	void SetSelectBgColor(const COLORREF _SelectBgColor);
	void SetNormalBgColor(const COLORREF _NormalBgColor);
	void SetSelectTextColor(const COLORREF _SelectTextColor);
	void SetMouseInBgColor(const COLORREF _MouseInBgColor);
	
	void ShowScrollBtn(BOOL bShow = TRUE);
	//void SetNoBorder(BOOL bNoBorder  = TRUE);
	void OnSetFocus(HWND hWnd); 
	LRESULT	OnCtlColor(HDC hDc, HWND hWnd);
	void SetFocusOnMouseMove( BOOL bSetFocus );
	void SetNumber( int nIndex,  int n );
	void SetCallBack( IListBoxClickCallback * pCallBack );
	void	SetListID( int nListId );
	HRESULT	OnLButtonDown( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bMsgHandled );
	void OnLButtonDblClk(UINT nFlags, CPoint point);
	HRESULT	OnLButtonUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bMsgHandled );
	HRESULT	OnMouseWheel( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bMsgHandled );
	HRESULT	OnMouseLeave( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bMsgHandled );
	void OnTimer(UINT_PTR nIDEvent);
	// 再试一下, 或者这个的消息映射方式也应该改成 Message_Handler 
	LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam);		
	LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/);
	LRESULT OnNcLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/);
	LRESULT OnNcMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/);
	HRESULT	OnNcMouseLeave( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bMsgHandled );
	HRESULT	OnMouseMove( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bMsgHandled );
	LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	void CaclTopestIndex(UINT nClientHight);
	void DrawScrolls(UINT WhichOne, UINT State);
	//void DrawBorder();
	void GetCurSelName( CString & strValue );
	void SetCurSelName( CString strValue, BOOL bOnClick = FALSE);

	void SetNumberByName( CString strValue, int nNumber );
	int GetNumberByName( CString strValue );
	void DrawItem ( LPDRAWITEMSTRUCT lpdis );
	int SetItemDataX(int nIndex, DWORD_PTR dwItemData);
	CListBoxItemData*	GetItemDataX(int i);
	VOID DeleteAllItems();
	void RefreshItem(int nIndex);
	BOOL CheckItemExist(CString strText);
};

#endif /*FinancialListBox_H*/

.cpp




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值