www.gusucode.com > 一个VC++ GUI测试程序-源码程序 > 一个VC++ GUI测试程序-源码程序/code/ScrollLabel.cpp

    //Download by http://www.NewXing.com
/*
* Copyright (c) 2002, Bcdliang
* All rights reserved.
*
* 文件名称:ScrollLabel.cpp
* 摘    要:类ScrollLabel的实现
*
* 当前版本:1.01
* 作    者:LIANG Zheng
* 完成日期:2002年8月11日
*/

#include "stdafx.h"
#include "ScrollLabel.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

const int SL_DEFAULT_SCROLLSTYLE = CScrollLabel::SL_HSCROLLBOTH;
const int SL_DEFAULT_STEP = 4;
const int SL_DEFAULT_TICK = 200;
const int SL_DEFAULT_TEXTHALIGN = CScrollLabel::SL_TA_LEFT;
const int SL_DEFAULT_TEXTVALIGN = CScrollLabel::SL_TA_TOP;
const COLORREF SL_DEFAULT_TEXTCOLOR = RGB(0, 255, 0);
const COLORREF SL_DEFAULT_BKCOLOR = RGB(0, 0, 0);
const HFONT SL_DEFAULT_FONT = (HFONT)::GetStockObject(DEFAULT_GUI_FONT);

/////////////////////////////////////////////////////////////////////////////
// CScrollLabel

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:CScrollLabel
* 函数介绍:构造函数,初始化除m_InnerRect和m_InnerLabel外的其它数据成员
* 输入参数:无
* 输出参数:无
* 返回值  :无
*/
CScrollLabel::CScrollLabel()
{
	m_uStep                    = SL_DEFAULT_STEP;					//步长:4(1-10)
	m_uTick                    = SL_DEFAULT_TICK;				//速度:200(50-2000)

	m_uScrollStyle             = SL_DEFAULT_SCROLLSTYLE;			// 当前滚动效果
	m_uTextHAlign              = SL_DEFAULT_TEXTHALIGN;		// 当前文字的水平对齐方式
	m_uTextVAlign              = SL_DEFAULT_TEXTVALIGN;			// 当前文字的垂直对齐方式
	m_crBkColor                = SL_DEFAULT_BKCOLOR;		// 背景色
	m_crTextColor              = SL_DEFAULT_TEXTCOLOR;// 前景色
	m_hBrush = ::CreateSolidBrush(m_crBkColor);		// 背景刷子
	m_Font.Attach(SL_DEFAULT_FONT);		// 字体
	m_bLeft = false;                                // m_InnerLabel是否正在向左滚动(used in SL_SCROLLBOTH only)
}

CScrollLabel::~CScrollLabel()
{
	::DeleteObject(m_hBrush);
	m_Font.DeleteObject();
}


BEGIN_MESSAGE_MAP(CScrollLabel, CWnd)
	//{{AFX_MSG_MAP(CScrollLabel)
	ON_WM_TIMER()
	ON_WM_CTLCOLOR_REFLECT()
	ON_WM_CTLCOLOR()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:Initialize
* 函数介绍:初始化m_InnerRect和m_InnerLabel
            m_InnerLabel必须在此初始化,才能显示出来, 在OnCreate和构造函数中初始化均不能显示
* 输入参数:无
* 输出参数:无
* 返回值  :无
*/
void CScrollLabel::Initialize()
{
	// Create the m_InnerLabel
	m_InnerRect = CRect(0, 0, 40, 20);
	BOOL bRet = m_InnerLabel.Create(_T(""), 
		WS_CHILD | WS_VISIBLE | SS_LEFT | SS_LEFTNOWORDWRAP,
		m_InnerRect,
		this);
	ASSERT(bRet);

	// Set text & font
	CString str;
	CWnd::GetWindowText(str);
	this->SetWindowText(str);
	this->SetFont(&m_Font);

	// Clear the parent window
	CWnd::SetWindowText(_T(""));
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:CtlColor
* 函数介绍:响应WM_CTLCOLOR_REFLECT消息,重画自己的背景
* 输入参数:CDC* pDC, UINT nCtlColor
* 输出参数:无
* 返回值  :HBRUSH
*/
HBRUSH CScrollLabel::CtlColor(CDC* pDC, UINT nCtlColor) 
{
	// TODO: Change any attributes of the DC here

	// TODO: Return a different brush if the default is not desired
	return this->m_hBrush;
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:OnCtlColor
* 函数介绍:响应WM_CTLCOLOR消息,重画子窗口
* 输入参数:CDC* pDC, CWnd *pWnd, UINT nCtlColor
* 输出参数:无
* 返回值  :HBRUSH
*/
HBRUSH CScrollLabel::OnCtlColor(CDC* pDC, CWnd *pWnd, UINT nCtlColor) 
{
//	HBRUSH hbr = CWnd::OnCtlColor(pDC, pWnd, nCtlColor);
 	
	// TODO: Change any attributes of the DC here
	pDC->SetBkMode(TRANSPARENT);
	pDC->SetTextColor(this->m_crTextColor);
	pDC->SetBkColor(this->m_crBkColor);
	// TODO: Return a different brush if the default is not desired
//	hbr = (HBRUSH)this->m_bkBrush.GetSafeHandle();
	return this->m_hBrush;
}

void CScrollLabel::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default

	// rect of parent window
	CRect rect;
	this->GetClientRect(&rect);

	switch (m_uScrollStyle)
	{
	case SL_NONE:
		break;
	case SL_HSCROLLLEFT:
		if (m_InnerRect.left < -m_InnerRect.Width())	// appear again
		{
			m_InnerRect.OffsetRect(rect.Width() + m_InnerRect.Width(), 0);
		}
		m_InnerRect.OffsetRect(-(int)m_uStep, 0);
		break;
	case SL_HSCROLLRIGHT:
		if (m_InnerRect.left > rect.Width())	// appear again
		{
			m_InnerRect.OffsetRect(-(rect.Width() + m_InnerRect.Width()), 0);
		}
		m_InnerRect.OffsetRect(m_uStep, 0);
		break;
	case SL_HSCROLLBOTH:
		if (rect.Width() > m_InnerRect.Width())
		{
			if (m_InnerRect.left < 0 || m_InnerRect.left > rect.Width() - m_InnerRect.Width())
			{
//				m_InnerRect.OffsetRect(m_bLeft ? m_uStep : -(int)m_uStep, 0);
				m_bLeft = !m_bLeft;
			}
		}
		else
		{
			if (m_InnerRect.left < rect.Width() - m_InnerRect.Width() || m_InnerRect.left > 0)
			{
//				m_InnerRect.OffsetRect(m_bLeft ? m_uStep : -(int)m_uStep, 0);
				m_bLeft = !m_bLeft;
			}
		}
		m_InnerRect.OffsetRect(m_bLeft ? -(int)m_uStep : m_uStep, 0);
		break;
	case SL_HSCROLLAUTO:
		break;
	default:
		break;
	}
	m_InnerLabel.MoveWindow(&m_InnerRect);
	
	CWnd::OnTimer(nIDEvent);
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:SetWindowText
* 函数介绍:重写父类成员SetWindowText, 设定m_InnerLabel中的字符串
* 输入参数:
            LPCTSTR lpszString, 新字符串
* 输出参数:无
* 返回值  :无
*/
void CScrollLabel::SetWindowText(LPCTSTR lpszString)
{
	m_InnerLabel.SetWindowText(lpszString);

	switch (this->m_uScrollStyle)
	{
	case SL_NONE:
		// Do nothing
		break;
	case SL_HSCROLLLEFT:
	case SL_HSCROLLRIGHT:
	case SL_HSCROLLBOTH:
		// Reset the size of m_InnerRect and horizontally move it to (0, x)
		this->CalculateTextSize();
		m_InnerRect.OffsetRect(-m_InnerRect.left, 0);

		this->m_bLeft = false;
		// Move m_InnerLabel to the rect specified by m_InnerRect
		m_InnerLabel.MoveWindow(&m_InnerRect);
		m_InnerLabel.Invalidate();
		break;
	case SL_HSCROLLAUTO:
		break;
	default:
		break;
	}
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:GetWindowText
* 函数介绍:重写父类成员GetWindowText, 返回m_InnerLabel中的字符串
* 输入参数:无
* 输出参数:
			CString &rString, 返回m_InnerLabel中的字符串
* 返回值  :无
*/
void CScrollLabel::GetWindowText(CString &rString) const
{
	m_InnerLabel.GetWindowText(rString);
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:SetFont
* 函数介绍:设定m_InnerLabel的字体
* 输入参数:
            CFont *f, 新字体
* 输出参数:无
* 返回值  :无
*/
void CScrollLabel::SetFont(CFont *f)
{
	ASSERT_VALID(f);
	LOGFONT lf;
	f->GetLogFont(&lf);
	m_Font.DeleteObject();
	m_Font.CreateFontIndirect(&lf);
	m_InnerLabel.SetFont(&m_Font);
	CRect rect;
	this->GetClientRect(&rect);

	switch (this->m_uScrollStyle)
	{
	case SL_NONE:
		// Reset the size of m_InnerRect and vertically move it
		this->CalculateTextSize();
		m_InnerRect.right = m_InnerRect.left + rect.Width();
		switch (this->m_uTextVAlign)
		{
		case SL_TA_TOP:
			m_InnerRect.OffsetRect(-m_InnerRect.left, 
				-m_InnerRect.top);
			break;
		case SL_TA_VCENTER:
			m_InnerRect.OffsetRect(-m_InnerRect.left, 
				(rect.Height() - m_InnerRect.Height())/2 - m_InnerRect.top);
			break;
		case SL_TA_BOTTOM:
			m_InnerRect.OffsetRect(-m_InnerRect.left, 
				rect.bottom - m_InnerRect.bottom);
			break;
		default:
			break;
		}

		// Move m_InnerLabel to the rect specified by m_InnerRect
		m_InnerLabel.MoveWindow(&m_InnerRect);
		break;
	case SL_HSCROLLLEFT:
	case SL_HSCROLLRIGHT:
	case SL_HSCROLLBOTH:
		// Reset the size of m_InnerRect and vertically move it
		this->CalculateTextSize();
		switch (this->m_uTextVAlign)
		{
		case SL_TA_TOP:
			m_InnerRect.OffsetRect(-m_InnerRect.left, 
				-m_InnerRect.top);
			break;
		case SL_TA_VCENTER:
			m_InnerRect.OffsetRect(-m_InnerRect.left, 
				(rect.Height() - m_InnerRect.Height())/2 - m_InnerRect.top);
			break;
		case SL_TA_BOTTOM:
			m_InnerRect.OffsetRect(-m_InnerRect.left, 
				rect.bottom - m_InnerRect.bottom);
			break;
		default:
			break;
		}

		this->m_bLeft = false;
		// Move m_InnerLabel to the rect specified by m_InnerRect
		m_InnerLabel.MoveWindow(&m_InnerRect);
		break;
	case SL_HSCROLLAUTO:
		break;
	default:
		break;
	}
	m_InnerLabel.Invalidate();
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:GetFont
* 函数介绍:返回当前m_InnerLabel的字体
* 输入参数:无
* 输出参数:无
* 返回值  :当前字体
*/
CFont *CScrollLabel::GetFont()
{
	return &this->m_Font;
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:SetBkColor
* 函数介绍:设定背景色
* 输入参数:
            COLORREF crColor, 新背景色
* 输出参数:无
* 返回值  :无
*/
void CScrollLabel::SetBkColor(COLORREF crColor)
{
	m_crBkColor=crColor;

	// Reset bk brush
	if (m_hBrush)
		::DeleteObject(m_hBrush);
	m_hBrush = ::CreateSolidBrush(m_crBkColor);

	m_InnerLabel.Invalidate();
	this->Invalidate();
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:GetBkColor
* 函数介绍:返回当前底色
* 输入参数:无
* 输出参数:无
* 返回值  :当前底色
*/
COLORREF CScrollLabel::GetBkColor() const
{
	return this->m_crBkColor;
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:SetTextColor
* 函数介绍:设定文字颜色
* 输入参数:
            COLORREF crColor, 新文字颜色
* 输出参数:无
* 返回值  :无
*/
void CScrollLabel::SetTextColor(COLORREF crColor)
{	
	m_crTextColor=crColor;
	m_InnerLabel.Invalidate();
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:GetTextColor
* 函数介绍:返回当前文字颜色
* 输入参数:无
* 输出参数:无
* 返回值  :当前文字颜色
*/
COLORREF CScrollLabel::GetTextColor() const
{
	return this->m_crTextColor;
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:SetStep
* 函数介绍:设置步长
* 输入参数:
            UINT nStep, 新步长
* 输出参数:无
* 返回值  :无
*/
void CScrollLabel::SetStep(UINT uStep)
{
	this->m_uStep = uStep;
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:GetStep
* 函数介绍:返回当前步长
* 输入参数:无
* 输出参数:无
* 返回值  :当前文字步长
*/
UINT CScrollLabel::GetStep(void) const
{
	return this->m_uStep;
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:SetTick
* 函数介绍:设置速度
* 输入参数:
            UINT nTick, 新速度
* 输出参数:无
* 返回值  :无
*/
void CScrollLabel::SetTick(UINT uTick)
{
	this->m_uTick = uTick;
	this->SetTimer((int)this, this->m_uTick, NULL);
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:GetTick
* 函数介绍:返回当前速度
* 输入参数:无
* 输出参数:无
* 返回值  :当前文字速度
*/
UINT CScrollLabel::GetTick(void) const
{
	return this->m_uTick;
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:SetScrollStyle
* 函数介绍:设置Scroll效果
* 输入参数:
            UINT nStyle, 新Scroll效果
* 输出参数:无
* 返回值  :无
*/
void CScrollLabel::SetScrollStyle(UINT nStyle)
{
	ASSERT(nStyle < SL_STYLENUM);
	m_uScrollStyle=nStyle;
	CRect rect;
	this->GetClientRect(&rect);

	switch (this->m_uScrollStyle)
	{
	case SL_NONE:
		// Stop the timer
		this->KillTimer((int)this);

		// Reset the size of m_InnerRect and move it to (0,x)
		m_InnerRect.right = m_InnerRect.left + rect.Width();
		m_InnerRect.OffsetRect(-m_InnerRect.left, 0);

		// Move m_InnerLabel to the rect specified by m_InnerRect
		m_InnerLabel.MoveWindow(&m_InnerRect);

		// Reset text align
		this->SetTextHAlign(this->m_uTextHAlign);

		break;
	case SL_HSCROLLLEFT:
	case SL_HSCROLLRIGHT:
	case SL_HSCROLLBOTH:
		// Set text align to Left&NoWrap
		m_InnerLabel.ModifyStyle(SS_CENTER | SS_RIGHT, SS_LEFT | SS_LEFTNOWORDWRAP);
		
		// Reset the size of m_InnerRect and horizontally move it
		this->CalculateTextSize();
		m_InnerRect.OffsetRect(-m_InnerRect.left, 0);

		m_bLeft = false;
		// Move m_InnerLabel to the rect specified by m_InnerRect
		m_InnerLabel.MoveWindow(&m_InnerRect);

		this->SetTimer((int)this, this->m_uTick, NULL);
		break;
	case SL_HSCROLLAUTO:
		break;
	default:
		break;
	}
	m_InnerLabel.Invalidate();
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:GetScrollStyle
* 函数介绍:返回当前Scroll效果
* 输入参数:无
* 输出参数:无
* 返回值  :当前Scroll效果
*/
UINT CScrollLabel::GetScrollStyle() const
{
	return this->m_uScrollStyle;
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:SetTextHAlign
* 函数介绍:设定水平对齐方式
* 输入参数:
            UINT nTextHAlign, 新水平对齐方式
* 输出参数:无
* 返回值  :无
*/
void CScrollLabel::SetTextHAlign(UINT nTextHAlign)
{
	m_uTextHAlign=nTextHAlign;
	switch (this->m_uTextHAlign)
	{
	case SL_TA_LEFT:		// 左对齐且不换行
		m_InnerLabel.ModifyStyle(SS_CENTER | SS_RIGHT, SS_LEFT | SS_LEFTNOWORDWRAP);
		break;
	case SL_TA_HCENTER:		// 中间对齐且换行
		m_InnerLabel.ModifyStyle(SS_RIGHT | SS_LEFT | SS_LEFTNOWORDWRAP, SS_CENTER);
		break;
	case SL_TA_RIGHT:		// 右对齐且换行
		m_InnerLabel.ModifyStyle(SS_LEFT | SS_CENTER | SS_LEFTNOWORDWRAP, SS_RIGHT);
		break;
	default:
		break;
	}
	m_InnerLabel.Invalidate();
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:GetTextHAlign
* 函数介绍:返回当前水平对齐方式
* 输入参数:无
* 输出参数:无
* 返回值  :当前水平对齐方式
*/
UINT CScrollLabel::GetTextHAlign() const
{
	return this->m_uTextHAlign;
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:SetTextVAlign
* 函数介绍:设定垂直对齐方式
* 输入参数:
            UINT nTextVAlign, 新垂直对齐方式
* 输出参数:无
* 返回值  :无
*/
void CScrollLabel::SetTextVAlign(UINT nTextVAlign)
{
	m_uTextVAlign=nTextVAlign;

	// 将m_InnerLabel移动到(0, x), x的值由垂直对齐方式决定
//	CalculateTextSize();
	CRect rect;
	this->GetClientRect(&rect);
	switch (this->m_uTextVAlign)
	{
	case SL_TA_TOP:
		m_InnerRect.OffsetRect(-m_InnerRect.left, 
			-m_InnerRect.top);
		break;
	case SL_TA_VCENTER:
		m_InnerRect.OffsetRect(-m_InnerRect.left, 
			(rect.Height() - m_InnerRect.Height())/2 - m_InnerRect.top);
		break;
	case SL_TA_BOTTOM:
		m_InnerRect.OffsetRect(-m_InnerRect.left, 
			rect.bottom - m_InnerRect.bottom);
		break;
	default:
		break;
	}
	this->m_bLeft = false;
	m_InnerLabel.MoveWindow(&m_InnerRect);
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:GetTextVAlign
* 函数介绍:返回当前垂直对齐方式
* 输入参数:无
* 输出参数:无
* 返回值  :当前垂直对齐方式
*/
UINT CScrollLabel::GetTextVAlign() const
{
	return this->m_uTextVAlign;
}

////////////////////////////////////////////////////////////////////////
/*
* 函数名称:CalculateTextSize
* 函数介绍:计算m_InnerLabel中的字符串的大小,根据结果修改m_InnerRect的大小,
            但不改变m_InnerRect左上角的位置
* 输入参数:无
* 输出参数:无
* 返回值  :无
*/
void CScrollLabel::CalculateTextSize()
{
	CString str;
	m_InnerLabel.GetWindowText(str);
	CDC *pDC = this->GetDC();
	CFont *oldfont = pDC->SelectObject(&this->m_Font);
	CSize size = pDC->GetTextExtent(str);
	pDC->SelectObject(oldfont);
	m_InnerRect.right = m_InnerRect.left + size.cx;
	m_InnerRect.bottom = m_InnerRect.top + size.cy;
}


////////////////////////////////////////////////////////////////////////
/*
* 函数名称:Default
* 函数介绍:将文字的各种属性(除文字外)设置为默认值
* 输入参数:无
* 输出参数:无
* 返回值  :无
*/
void CScrollLabel::Default()
{
	CFont f;
	f.Attach(SL_DEFAULT_FONT);
	this->SetFont(&f);
	f.DeleteObject();
	this->SetBkColor(SL_DEFAULT_BKCOLOR);
	this->SetTextColor(SL_DEFAULT_TEXTCOLOR);
	this->SetStep(SL_DEFAULT_STEP);
	this->SetTick(SL_DEFAULT_TICK);
	this->SetTextHAlign(SL_DEFAULT_TEXTHALIGN);
	this->SetTextVAlign(SL_DEFAULT_TEXTVALIGN);
	this->SetScrollStyle(SL_DEFAULT_SCROLLSTYLE);
}