www.gusucode.com > VC++静态颜色自绘文字滚动-源码程序 > VC++静态颜色自绘文字滚动-源码程序/code/ColorStatic.cpp

    //Download by http://www.NewXing.com
// ColorStatic.cpp : implementation file
//

#include "stdafx.h"
#include "ColorStatic.h"

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

/////////////////////////////////////////////////////////////////////////////
// CColorStatic

CColorStatic::CColorStatic()
{
	// Init our vars.
	m_clBackColor=::GetSysColor(COLOR_BTNFACE);
	m_clTextColor=::GetSysColor(COLOR_WINDOWTEXT);
	m_nTextXPos=3;
	m_nTextYPos=3;
	m_nScrollXPos=m_nTextXPos;
	m_nScrollYPos=m_nTextYPos;
	m_nStep=5;
	m_bIsSingleLine=true;
	m_bUseRoll=false;
	m_bUseSysFont=true;
	m_bHCentered=false;
	m_bVCentered=false;
	m_bTextInfoGotten=false;
	m_bRollPosSetted=false;
	m_bRollTimerKilled=false;
	m_bBkTransparent=false;
	m_bDCStored=false;
	m_nRollDirection=ROLL_LEFT;
}

CColorStatic::~CColorStatic()
{
}


BEGIN_MESSAGE_MAP(CColorStatic, CStatic)
	//{{AFX_MSG_MAP(CColorStatic)
	ON_WM_ERASEBKGND()
	ON_WM_PAINT()
	ON_WM_TIMER()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CColorStatic message handlers

///////////////////////////////////////////////////////////
//  Name: OnEraseBkgnd(CDC* pDC)
///////////////////////////////////////////////////////////
//  Function: Draw the background and the text.
//
///////////////////////////////////////////////////////////
BOOL CColorStatic::OnEraseBkgnd(CDC* pDC) 
{
	// TODO: Add your message handler code here and/or call default
	CRect   clientRect;
	CRgn	clipRgn;
	GetClientRect(&clientRect);
	if(!m_bDCStored)
	{
		CBitmap   bitmap;
		m_StoreDC.CreateCompatibleDC(pDC);
		bitmap.CreateCompatibleBitmap(pDC,clientRect.Width(),clientRect.Height());
		m_StoreDC.SelectObject(&bitmap);
		m_StoreDC.BitBlt(0,0,clientRect.Width(),clientRect.Height(),pDC,0,0,SRCCOPY);
		m_bDCStored=true;
	}
	// Get our client rect and fill it with bk-color
	GetClientRect(&clientRect);

	if(m_bBkTransparent)
	{
		pDC->BitBlt(0,0,clientRect.Width(),clientRect.Height(),&m_StoreDC,0,0,SRCCOPY);
	}
	else
	{
		pDC->FillRect(&clientRect,&CBrush(m_clBackColor));
	}
	pDC->SetBkMode(TRANSPARENT);
	pDC->SetTextColor(m_clTextColor);

	// Get and Set our font.
	CFont *pCurrentFont;
	if(m_bUseSysFont)
	{
		// Get the dialog's font.
	    pCurrentFont= GetFont(); 
	}
	else
	{
		// Use our member font.
		pCurrentFont=&m_font;
	}
    CFont *pOldFont = pDC->SelectObject(pCurrentFont);

	// Set clip rgn.
	clipRgn.CreateRectRgnIndirect(&clientRect);
	pDC->SelectClipRgn(&clipRgn);
	// Draw the Text.
	if(m_sText)
	{
		// judge if the text is a single line.
		m_bIsSingleLine=(m_sText.Find("\n")>=0)?false:true;

		if(m_bIsSingleLine)
		{
			if(!m_bTextInfoGotten)
			{
				// We'll get the text width and height to roll it.
				CSize  size=pDC->GetTextExtent(m_sText);
				m_nTextWidth=size.cx ;
				m_nTextHeight=size.cy ;
				// We have gotten the text info.
				m_bTextInfoGotten=true;
			}
			if(m_bHCentered)
			{
				// H Center our text.
				m_nTextXPos=(clientRect.Width()-m_nTextWidth)/2;
			}
			if(m_bVCentered)
			{
				// V center our text.
				m_nTextYPos=(clientRect.Height()-m_nTextHeight)/2;
			}
			if(!m_bRollPosSetted)
			{
				// Set our start roll pos.
				m_nScrollXPos=m_nTextXPos;
				m_nScrollYPos=m_nTextYPos;
				m_bRollPosSetted=true;
			}
			// Draw a single-line text.
			pDC->TextOut(m_bUseRoll?m_nScrollXPos:m_nTextXPos,m_bUseRoll?m_nScrollYPos:m_nTextYPos,m_sText);
		}
		else
		{
			// Draw multi-line text.
			CString  sShow,sOthers;
			sOthers=m_sText;
			int width;  // every line's width
			int nPos=0;  // new line's pos (in text)
			int x=m_bUseRoll?m_nScrollXPos:m_nTextXPos;
			int y=m_bUseRoll?m_nScrollYPos:m_nTextYPos;
	
			if(!m_bTextInfoGotten)
			{
				m_nTextWidth=m_nTextHeight=0;
				// Get the line-height.
				TEXTMETRIC	tm;
				pDC->GetTextMetrics(&tm);
				m_nLineHeight=tm.tmHeight+tm.tmExternalLeading;
			}

			while(!sOthers.IsEmpty())
			{
				nPos=sOthers.Find("\n");
				if(nPos>=0)
				{
					// trim left to get the line to show.
					sShow=sOthers.Left(nPos);
					// trim right.
					sOthers=sOthers.Right(sOthers.GetLength()-nPos-1);
					pDC->TextOut(x,y,sShow);
					y+=m_nLineHeight;
					// We'll get the multi-line text max width and height.
					if(m_bUseRoll && !m_bTextInfoGotten)
					{
						// Get the text info.
						CSize size=pDC->GetTextExtent(sShow);
						width=size.cx;
						if(width>m_nTextWidth)
							m_nTextWidth=width;
						m_nTextHeight+=m_nLineHeight;
					}
				}
				else
				{
					// There is no more line,so just show it.
					sShow=sOthers;
					sOthers.Empty();
					pDC->TextOut(x,y,sShow);
					if(m_bUseRoll && !m_bTextInfoGotten)
					{
						CSize size=pDC->GetTextExtent(sShow);
						width=size.cx;
						if(width>m_nTextWidth)
							m_nTextWidth=width;
						m_nTextHeight+=m_nLineHeight;
						m_bTextInfoGotten=true;
					}
				}
			}
		}
		pDC->SelectObject(pOldFont);
	}
	
	return TRUE;
}

///////////////////////////////////////////////////////////
//  Name:		SetTextColor()
///////////////////////////////////////////////////////////
//  Function:	Change the color of the text.
//  Parm:		COLORREF clTextColor
///////////////////////////////////////////////////////////
//  Remark:     Call this if you want to change the text color.
///////////////////////////////////////////////////////////
void CColorStatic::SetTextColor(COLORREF clTextColor)
{
	m_clTextColor=clTextColor;
	Invalidate();
}

///////////////////////////////////////////////////////////
//  Name:		SetBkColor()
///////////////////////////////////////////////////////////
//  Function:	Change the color of the background.
//  Parm:		COLORREF clBkColor
///////////////////////////////////////////////////////////
//  Remark:     Call this if you want to change the back color.
///////////////////////////////////////////////////////////
void CColorStatic::SetBkColor(COLORREF clBkColor)
{
	m_clBackColor=clBkColor;
	Invalidate();
}

///////////////////////////////////////////////////////////
//  We do not want the default effect,
// so we judt do nothing in function OnPaint()
///////////////////////////////////////////////////////////
void CColorStatic::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	
	// TODO: Add your message handler code here
	
	// Do not call CStatic::OnPaint() for painting messages
}


///////////////////////////////////////////////////////////
//  Name: PreSubclassWindow()
///////////////////////////////////////////////////////////
//  Function: Get the static's text.
///////////////////////////////////////////////////////////
//  Remark: Because we don't use the SetWindowText() call,
//    in stead we use SetText() call to change the text,
//    so we must get the text here,not in OnEraseBkgnd().
///////////////////////////////////////////////////////////
void CColorStatic::PreSubclassWindow() 
{
	// TODO: Add your specialized code here and/or call the base class
	GetWindowText(m_sText);

	CStatic::PreSubclassWindow();
}

///////////////////////////////////////////////////////////
//  Name:       SetText()
///////////////////////////////////////////////////////////
//  Function:   Change the text of the ststic.
//  Parm:       CString sText
///////////////////////////////////////////////////////////
//  Remark:  Use this but not SetWindowText() if you need to
//    change the text.
//    **If we use the SetWindowText() call,there will be
//    some dreadful effect.So I wrote this function.
///////////////////////////////////////////////////////////

void CColorStatic::SetText(CString sText)
{
	if(m_sText!=sText)
	{
		m_sText=sText;
		m_bTextInfoGotten=false;
		m_bRollPosSetted=false;
		Invalidate();
	}
}
///////////////////////////////////////////////////////////
//  Name:		BeginRoll()
///////////////////////////////////////////////////////////
//  Function:	Set the vars and set a timer.
//  Parm1:		int nStep  default:5
//		- the move step of the rolling text.Increase this 
//      if you want the text rolling faster.
//  Parm2:		int nTimer default:100
//      - the time interval of the rolling text.Decrease it
//      if you want the text rolling faster.
///////////////////////////////////////////////////////////
void CColorStatic::BeginRoll(int nStep,int nTimer)
{
	m_nStep=nStep;
	m_bUseRoll=true;
	m_bRollPosSetted=false;
	SetTimer(ID_ROLLTIMER,nTimer,NULL);
}

///////////////////////////////////////////////////////////
//  Name:		SetRollDirection()
///////////////////////////////////////////////////////////
//  Function:	Set the rolling direction.
//  Parm:		int direction.value:
//
//					ROLL_LEFT		0
//					ROLL_RIGHT		1
//					ROLL_UP 		2
//					ROLL_DOWN		3
///////////////////////////////////////////////////////////
//  Remark:     Use this before BeginRoll()
///////////////////////////////////////////////////////////
void CColorStatic::SetRollDirection(int direction)
{
	m_nRollDirection=direction;
}

///////////////////////////////////////////////////////////
// Name:         StopRoll()
///////////////////////////////////////////////////////////
// Function:     kill the timer.
// Parm:
///////////////////////////////////////////////////////////
void CColorStatic::StopRoll()
{
	m_bUseRoll=false;
	KillTimer(ID_ROLLTIMER);
	Invalidate();
	m_bRollTimerKilled=true;
}

///////////////////////////////////////////////////////////
// Name:         OnTimer(UINT nIDEvent)
///////////////////////////////////////////////////////////
// Function:     Change the output text (if it is set to 
//          show current time) or caculate the output position
//          (if it is set to roll).
// Parm:
///////////////////////////////////////////////////////////
void CColorStatic::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	if(nIDEvent==ID_ROLLTIMER)
	{
		if(!m_bTextInfoGotten)
			return;
		CRect  clientRect;
		GetClientRect(&clientRect);

		switch(m_nRollDirection)
		{
			case ROLL_LEFT:
			{
				if(m_nScrollXPos<=clientRect.left-m_nTextWidth)
				{
					m_nScrollXPos=clientRect.right;
				}
				else
				{
					m_nScrollXPos-=m_nStep;
				}
				break;
			}
			case ROLL_RIGHT:
			{
				if(m_nScrollXPos>=clientRect.right)
				{
					m_nScrollXPos=clientRect.left-m_nTextWidth;
				}
				else
				{
					m_nScrollXPos+=m_nStep;
				}
				break;
			}
			case ROLL_UP:
			{
				if(m_nScrollYPos<=clientRect.top-m_nTextHeight)
				{
					m_nScrollYPos=clientRect.bottom;
				}
				else
				{
					m_nScrollYPos-=m_nStep;
				}
				break;
			}
			case ROLL_DOWN:
			{
				if(m_nScrollYPos>=clientRect.bottom)
				{
					m_nScrollYPos=clientRect.top-m_nTextHeight;
				}
				else
				{
					m_nScrollYPos+=m_nStep;
				}
				break;
			}
		}
	}
	else if(nIDEvent==ID_CLOCKTIMER)
	{
		CTime	time=CTime::GetCurrentTime ();
		CString  scurTime;
		scurTime=time.Format ("%H:%M:%S");
		SetText(scurTime);
	}
	Invalidate();
	CStatic::OnTimer(nIDEvent);
}

///////////////////////////////////////////////////////////
// Name:         HCenterText()
///////////////////////////////////////////////////////////
// Function:     H center our text.
// Parm:
///////////////////////////////////////////////////////////
void CColorStatic::HCenterText()
{
	m_bHCentered=true;
	Invalidate();
}

///////////////////////////////////////////////////////////
// Name:         VCenterText()
///////////////////////////////////////////////////////////
// Function:     V center our text.
// Parm:
///////////////////////////////////////////////////////////
void CColorStatic::VCenterText()
{
	m_bVCentered=true;
	Invalidate();
}


///////////////////////////////////////////////////////////
// Name:         SetTextXPos()
///////////////////////////////////////////////////////////
// Function:     Set the output text's x position.
// Parm:
///////////////////////////////////////////////////////////
// Remark:       Use this to change the x pos.
///////////////////////////////////////////////////////////
void CColorStatic::SetTextXPos(int x)
{
	m_nScrollXPos=m_nTextXPos=x;
}

///////////////////////////////////////////////////////////
// Name:         SetTextYPos(int y)
///////////////////////////////////////////////////////////
// Function:     
// Parm:
///////////////////////////////////////////////////////////
void CColorStatic::SetTextYPos(int y)
{
	m_nScrollYPos=m_nTextYPos=y;
}

///////////////////////////////////////////////////////////
// Name:         SetTextFont()
///////////////////////////////////////////////////////////
// Function:     Set the output font of the text.
// Parm:	     LOGFONT *lf
///////////////////////////////////////////////////////////
void CColorStatic::SetTextFont(LOGFONT *lf)
{
	m_font.CreateFontIndirect(lf);
	m_bUseSysFont=false;
	Invalidate();
}

///////////////////////////////////////////////////////////
// Name:        SetTextHeight()
///////////////////////////////////////////////////////////
// Function:    Set the height of the output text.
// Parm:        int height
///////////////////////////////////////////////////////////
//  Remark:      Call this if you only want to change the
//            the height of the text.
//               If you call SetTextFont(LOGFONT *lf),
//            make sure don't call this.
///////////////////////////////////////////////////////////
void CColorStatic::SetTextHeight(int height)
{
	LOGFONT  lf;
	CFont *pDlgFont=GetFont();
	pDlgFont->GetLogFont(&lf);
	lf.lfHeight =height;
	lf.lfWidth =0;
	m_font.CreateFontIndirect(&lf);

	m_bUseSysFont=false;
	m_bTextInfoGotten=false;
	Invalidate();
}

///////////////////////////////////////////////////////////
// Name:        SetClock()
///////////////////////////////////////////////////////////
// Function:    Set the static to show time or date.
// Parm:		bool bTime, value
//              - true    show time
//              - false   show date
///////////////////////////////////////////////////////////
void CColorStatic::SetClock(bool bTime)
{
	if(bTime)
	{
		SetTimer(ID_CLOCKTIMER,500,NULL);
		HCenterText();
		VCenterText();
	}
	else
	{
		CString  scurTime;
		CTime	time=CTime::GetCurrentTime ();
		scurTime=time.Format ("%Y-%m-%d");
		SetText(scurTime);
		HCenterText();
		VCenterText();
	}
}

///////////////////////////////////////////////////////////
// Name:       
///////////////////////////////////////////////////////////
// Function:     
// Parm:
///////////////////////////////////////////////////////////
void CColorStatic::OnDestroy() 
{
	CStatic::OnDestroy();

	// TODO: Add your message handler code here
	if(!m_bRollTimerKilled)
		KillTimer(ID_ROLLTIMER);

	KillTimer(ID_CLOCKTIMER);
}

void CColorStatic::SetBkTransparent(bool btranparent)
{
	m_bBkTransparent=btranparent;
	Invalidate();
}