CTextWnd轻松实现文字的滚动

//========================================================================
//TITLE:
// CTextWnd轻松实现文字的滚动
//AUTHOR:
// norains
//DATE:
// Wednesday 27-February-2008
//Environment:
// VS2005 + SDK-WINCE5.0-MIPSII
// EVC 4.0 + SDK-WINCE5.0-MIPSII
//========================================================================

本文是我另一篇《文字滚动的技术实现》的实例补充,因为在该文已经详细解释技术实现的原理,所以本文的重点仅仅是如何调用CTextWnd实现文字的滚动。

首先我们来通览一遍CTextWnd的完整源代码:


/ /
// TextWnd.h:interfacefortheCTextWndclass.
//
// Version:
// 0.1.4
//
// Date:
// 2008.02.27
//
// Description:
// Thebasewindowversion:
// CWndBase-0.1.8
// CMemDC-0.1.0
// CStrStore-1.0.0
/ /

#pragma once
#include
" wndbase.h "
#include
" StrStore.h "
#include
" MemDC.h "

// ----------------------------------------------------------
// Enumvaluetype
enum DirectionValue
{
DRT_NULL,
DRT_LEFT,
DRT_RIGHT,
DRT_UP,
DRT_DOWN
};
// ----------------------------------------------------------
class CTextWnd:
public CWndBase
{

public :
virtual ~ CTextWnd( void );
CTextWnd(
void );

virtual BOOLCreate(HINSTANCEhInst,HWNDhWndParent, const TCHAR * pcszWndClass, const TCHAR * pcszWndName,BOOLbMsgThrdInside = FALSE);

BOOLMove(
const RECT * prcWnd);
BOOLSetText(
const TCHAR * pcszText);
BOOLSetTxtPath(
const TCHAR * pcszPath);
BOOLPlay(
void );
BOOLPause(
void );
BOOLStop(
void );
void SetDirection(DirectionValuedtValue);
void SetInterval(DWORDdwInterval);
void SetMovePixel( int iPixel);
void SetTxtColor(COLORREFcrColor);
void SetTxtPointSize( int iPointSize);
void SetTxtWeight( int iWeight);
void SetBkColor(COLORREFcrColor);
BOOLSwitchNext(
void );
BOOLSwitchPrevious(
void );


private :
static BOOLCheckFile( const TCHAR * pszFileName);
BOOLReadCurTxt(
void );
void OnPaint(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam);
void OnWindowPosChanged(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam);
BOOLResetTxtInfoRect(
void );
BOOLInitDCTxtInfo(
void );
BOOLFindFile(
const TCHAR * pszPath,CStrStore * pStore,BOOL( * pCheckFunc)( const TCHAR * pcszPath));

private :
// Callbackfunction
virtual LRESULTWndProc(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam);
virtual void DrawBackground(HDChdc);

private :
CStrStorem_FileStore;
int m_iIndexCurTxt;
TCHAR
* m_pszTxtInfo;
int m_iWndWidth;
int m_iWndHeight;
int m_iTxtInfoX;
int m_iTxtInfoY;
int m_iTxtInfoWidth;
int m_iTxtInfoHeight;
int m_iMovePixel;
int m_iTxtInfoPointSize;
COLORREFm_crTxtInfoColor;
COLORREFm_crBkColor;
int m_iTxtInfoWeight;
CMemDCm_DCTxtInfo;
BOOLm_bInited;



private :
// ThevaluetypeisfortheTimerThread,meaningtheaction
enum TimeoutAction
{
TA_NULL,
TA_MOVE,
TA_EXIT,
TA_STOP
};
HANDLEm_hEventTimer;
TimeoutActionm_taCurAction;
DWORDm_dwInterval;
DirectionValuem_dtValue;
static DWORDTimerThread(PVOIDpArg);

};

/
//TextWnd.cpp

#include "stdafx.h"
#include "TextWnd.h"


//----------------------------------------------------------------------
//Macro define
#define DEFAULT_BKGND_COLORRGB(128,128,128)

//For the text move
#define DEFAULT_INTERVAL100 //500ms
#define DEFAULT_MOVE_PIXEL1 //pixel

//The text information
#define DEFAULT_TEXT_COLORRGB(255,255,255)
#define DEFAULT_TEXT_POINTSIZE 0
#define DEFAULT_TEXT_WEIGHT0
//----------------------------------------------------------------------


//----------------------------------------------------------------------
//Description:
//Construction
//-----------------------------------------------------------------------
CTextWnd::CTextWnd(void):
m_iIndexCurTxt(0),
m_pszTxtInfo(NULL),
m_taCurAction(TA_NULL),
m_dwInterval(DEFAULT_INTERVAL),
m_hEventTimer(CreateEvent(NULL,FALSE,FALSE,NULL)),
m_dtValue(DRT_NULL),
m_iWndWidth(0),
m_iWndHeight(0),
m_iTxtInfoX(0),
m_iTxtInfoY(0),
m_iTxtInfoWidth(0),
m_iTxtInfoHeight(0),
m_iMovePixel(DEFAULT_MOVE_PIXEL),
m_iTxtInfoPointSize(DEFAULT_TEXT_POINTSIZE),
m_crTxtInfoColor(DEFAULT_TEXT_COLOR),
m_iTxtInfoWeight(DEFAULT_TEXT_WEIGHT),
m_bInited(FALSE),
m_crBkColor(DEFAULT_BKGND_COLOR)
{

//Create the timer thread to move the text
HANDLE hdThrd = CreateThread(NULL,NULL,TimerThread,this,NULL,NULL);
CloseHandle(hdThrd);
}

//----------------------------------------------------------------------
//Description:
//Destruction
//----------------------------------------------------------------------
CTextWnd::~CTextWnd(void)
{
if(m_hEventTimer != NULL)
{
CloseHandle(m_hEventTimer);
m_hEventTimer = NULL;
}

if(m_DCTxtInfo.IsOK() == TRUE)
{
m_DCTxtInfo.Delete();
}
}


//----------------------------------------------------------------------
//Description:
//Move the window
//----------------------------------------------------------------------
BOOL CTextWnd::Move(const RECT * prcWnd)
{
return MoveWindow(GetWindow(),
prcWnd->left,
prcWnd->top,
prcWnd->right - prcWnd->left,
prcWnd->bottom - prcWnd->top,
FALSE);
}

//----------------------------------------------------------------------
//Description:
//Set the text information.
//It would take effect in next calling Play().
//----------------------------------------------------------------------
BOOL CTextWnd::SetText(const TCHAR * pcszText)
{
if(m_pszTxtInfo != NULL)
{
delete [] m_pszTxtInfo;
m_pszTxtInfo = NULL;
}

m_pszTxtInfo = new TCHAR[_tcslen(pcszText) + 1];
_tcscpy(m_pszTxtInfo,pcszText);


//Set the flag to reinitialize the memory DC
m_bInited = FALSE;

return TRUE;
}


//----------------------------------------------------------------------
//Description:
//Set the text file path
//----------------------------------------------------------------------
BOOL CTextWnd::SetTxtPath(const TCHAR * pcszPath)
{

if(pcszPath == NULL)
{
return FALSE;
}

m_FileStore.DeleteAllData();

WIN32_FIND_DATA fd = {0};
HANDLE hFind = FindFirstFile(pcszPath,&fd);
if(hFind == INVALID_HANDLE_VALUE)
{
return FALSE;
}

if(fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
{
FindFile(pcszPath,&m_FileStore,CheckFile);
}
else
{
m_FileStore.Add(pcszPath);
}

FindClose(hFind);

//Open the first text file
m_iIndexCurTxt = 0;
ReadCurTxt();

return TRUE;
}


//----------------------------------------------------------------------
//Description:
//Play the text. If first using, it would be very slow bacause must initialize the memory DC.
//It would be quickly next time when the setting has not changed since first using
//----------------------------------------------------------------------
BOOL CTextWnd::Play(void)
{
if(m_DCTxtInfo.IsOK() == FALSE || m_bInited == FALSE)
{
//Create the memory DC for text information
InitDCTxtInfo();

m_bInited = TRUE;
}

m_taCurAction = TA_MOVE;
SetEvent(m_hEventTimer);

return TRUE;
}


//----------------------------------------------------------------------
//Description:
//Pause the text
//----------------------------------------------------------------------
BOOL CTextWnd::Pause(void)
{
m_taCurAction = TA_NULL;
SetEvent(m_hEventTimer);

return TRUE;
}


//----------------------------------------------------------------------
//Description:
//Check the file
//----------------------------------------------------------------------
BOOL CTextWnd::CheckFile(const TCHAR * pszFileName)
{
TCHAR szSuffix[MAX_PATH] = {0};

int iLen = _tcslen(pszFileName);
if(iLen == 0)
{
return FALSE;
}

int iPos = iLen - 1;
while(iPos >= 0)
{
if(pszFileName[iPos] == '.')
{
break;
}

iPos --;
}

if(iPos < 0)
{
return FALSE;
}

_tcscpy(szSuffix, pszFileName + iPos);
_tcslwr(szSuffix);

if(_tcscmp(szSuffix,TEXT(".txt")) == 0)
{
return TRUE;
}

return FALSE;
}


//----------------------------------------------------------------------
//Description:
//Read the text information base on the current index
//----------------------------------------------------------------------
BOOL CTextWnd::ReadCurTxt(void)
{
if(m_iIndexCurTxt >= m_FileStore.GetAmount() || m_iIndexCurTxt < 0 || m_FileStore.GetAmount() == 0)
{
return FALSE;
}

if(m_pszTxtInfo != NULL)
{
delete [] m_pszTxtInfo;
m_pszTxtInfo = NULL;
}

TCHAR szFile[MAX_PATH] = {0};
if(m_FileStore.GetData(m_iIndexCurTxt,szFile,MAX_PATH) == TRUE)
{
HANDLE hFile = CreateFile(szFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);

DWORD dwSize = GetFileSize(hFile,NULL);
BYTE *pReadBuf = (BYTE*)malloc(dwSize);
DWORD dwRead = 0;
ReadFile(hFile,pReadBuf,dwSize,&dwRead,NULL);
#ifdef UNICODE
if(dwSize >= 2 && pReadBuf[0] == 0xFF && pReadBuf[1] == 0xFE)
{
//It must be the UNICODE file
DWORD dwNum = (dwSize - 2) / sizeof(TCHAR) + 1; //Must be end with '/0', so add 1
m_pszTxtInfo = new TCHAR[dwNum];
memset(m_pszTxtInfo,0,sizeof(TCHAR) * dwNum);
if(m_pszTxtInfo != NULL)
{
_tcscpy(m_pszTxtInfo,reinterpret_cast<TCHAR *>(pReadBuf + 2));
}

}
else
{
//It must be the ASCII file
DWORD dwNum = MultiByteToWideChar (CP_ACP, 0, reinterpret_cast<char *>(pReadBuf), -1, NULL, 0);
m_pszTxtInfo = new TCHAR[dwNum];
memset(m_pszTxtInfo,0,sizeof(TCHAR) * dwNum);
if(m_pszTxtInfo != NULL)
{
// Convert string from ASCII to Unicode.
MultiByteToWideChar (CP_ACP, 0, reinterpret_cast<char *>(pReadBuf), -1, m_pszTxtInfo, dwNum);
}
}


#else
#error "There is not the completed code here when the UNICODE macor is not defined. :-("
#endif

free(pReadBuf);

CloseHandle(hFile);
}


return TRUE;
}

//----------------------------------------------------------------------
//Description:
// Actual WndProc
//
//----------------------------------------------------------------------
LRESULT CTextWnd::WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
switch(wMsg)
{
case WM_PAINT:
OnPaint(hWnd,wMsg,wParam,lParam);
return 0;
case WM_ERASEBKGND:
return 0;
case WM_WINDOWPOSCHANGED:
OnWindowPosChanged(hWnd,wMsg,wParam,lParam);
break;
}

return CWndBase::WndProc(hWnd,wMsg,wParam,lParam);
}


//----------------------------------------------------------------------
//Description:
// On message WM_PAINT
//
//----------------------------------------------------------------------
void CTextWnd::OnPaint(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{


PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd,&ps);

//Create the memory DC
CMemDC memDC;
SIZE size = {m_iWndWidth,m_iWndHeight};
memDC.Create(hdc,&size);

DrawBackground(memDC.GetDC());

//Draw the text
if(m_DCTxtInfo.IsOK() == TRUE)
{
TransparentBlt(memDC.GetDC(),
m_iTxtInfoX,
m_iTxtInfoY,
m_iTxtInfoWidth,
m_iTxtInfoHeight,
m_DCTxtInfo.GetDC(),
0,
0,
m_DCTxtInfo.GetWidth(),
m_DCTxtInfo.GetHeight(),
m_crBkColor);
}

//Draw the device context
BitBlt(hdc,0,0,m_iWndWidth,m_iWndHeight,memDC.GetDC(),0,0,SRCCOPY);

//Delete the memory DC
memDC.Delete();

EndPaint(hWnd,&ps);
}

//----------------------------------------------------------------------
//Description:
// The timer thread
//
//----------------------------------------------------------------------
DWORD CTextWnd::TimerThread(PVOID pArg)
{
CTextWnd *pObject = (CTextWnd *)pArg;

while(TRUE)
{
if(WaitForSingleObject(pObject->m_hEventTimer,pObject->m_dwInterval) == WAIT_TIMEOUT)
{
if(pObject->m_taCurAction == TA_MOVE)
{
switch(pObject->m_dtValue)
{
case DRT_NULL:
{
//Do nothing
break;
}
case DRT_LEFT:
{
pObject->m_iTxtInfoX -= pObject->m_iMovePixel;
if(pObject->m_iTxtInfoX + pObject->m_iTxtInfoWidth <= 0)
{
pObject->m_iTxtInfoX = pObject->m_iWndWidth;
}
break;
}
case DRT_RIGHT:
{
pObject->m_iTxtInfoX += pObject->m_iMovePixel;
if(pObject->m_iTxtInfoX >= pObject->m_iWndWidth)
{
pObject->m_iTxtInfoX = - pObject->m_iTxtInfoWidth;
}
break;
}
case DRT_UP:
{
pObject->m_iTxtInfoY -= pObject->m_iMovePixel;
if(pObject->m_iTxtInfoY + pObject->m_iTxtInfoHeight <= 0)
{
pObject->m_iTxtInfoY = pObject->m_iWndHeight;
}
break;
}
case DRT_DOWN:
{
pObject->m_iTxtInfoY += pObject->m_iMovePixel;
if(pObject->m_iTxtInfoY >= pObject->m_iWndHeight)
{
pObject->m_iTxtInfoY = -pObject->m_iTxtInfoWidth;
}
break;
}
}

//Redraw the text information
InvalidateRect(pObject->GetWindow(),NULL,FALSE);

}
else if(pObject->m_taCurAction == TA_EXIT)
{
break;
}
else if(pObject->m_taCurAction == TA_STOP)
{
switch(pObject->m_dtValue)
{
case DRT_NULL:
{
//Do nothing
break;
}
case DRT_LEFT:
{
pObject->m_iTxtInfoX = pObject->m_iWndWidth;
break;
}
case DRT_RIGHT:
{
pObject->m_iTxtInfoX = - pObject->m_iTxtInfoWidth;
break;
}
case DRT_UP:
{
pObject->m_iTxtInfoY = pObject->m_iWndHeight;
break;
}
case DRT_DOWN:
{
pObject->m_iTxtInfoY = -pObject->m_iTxtInfoWidth;
break;
}
}

pObject->m_taCurAction = TA_NULL;
InvalidateRect(pObject->GetWindow(),NULL,FALSE);
}
}
}

return 0;
}

//----------------------------------------------------------------------
//Description:
// Set the direction for the text information displayed
//
//----------------------------------------------------------------------
void CTextWnd::SetDirection(DirectionValue dtValue)
{
if(m_dtValue == dtValue)
{
//Do nothing
return;
}

m_dtValue = dtValue;

}
//----------------------------------------------------------------------
//Description:
// Set the interval for text moving
//
//----------------------------------------------------------------------
void CTextWnd::SetInterval(DWORD dwInterval)
{
m_dwInterval = dwInterval;
}


//----------------------------------------------------------------------
//Description:
//Create the window
//
//Parameters:
//You should see the explanation of the parameters in CWndBase
//
//----------------------------------------------------------------------
BOOL CTextWnd::Create(HINSTANCE hInst, HWND hWndParent, const TCHAR *pcszWndClass, const TCHAR *pcszWndName,BOOL bMsgThrdInside)
{
if(CWndBase::Create(hInst,hWndParent,pcszWndClass,pcszWndName,bMsgThrdInside) == FALSE)
{
return FALSE;
}

//Get the window area
RECT rcWnd = {0};
GetWindowRect(GetWindow(),&rcWnd);
m_iWndWidth = rcWnd.right - rcWnd.left;
m_iWndHeight = rcWnd.bottom - rcWnd.top;

return TRUE;
}

//----------------------------------------------------------------------
//Description:
//On message WM_WINDOWPOSCHANGED
//
//----------------------------------------------------------------------
void CTextWnd::OnWindowPosChanged(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
//Get the window area
WINDOWPOS wp = *((WINDOWPOS *) lParam);

if(m_iWndWidth != wp.cx || m_iWndHeight != wp.cy)
{
m_iWndWidth = wp.cx;
m_iWndHeight = wp.cy;

//Set the flag to reinitialize the memory DC
m_bInited = FALSE;

}

}


//----------------------------------------------------------------------
//Description:
//Caculate the text informat rectangle.
//
//----------------------------------------------------------------------
BOOL CTextWnd::ResetTxtInfoRect(void)
{
HWND hWnd = GetWindow();
if(hWnd == NULL || m_pszTxtInfo == NULL)
{
return FALSE;
}



HDC hdc = GetDC(hWnd);

//Set the font to caculate
LOGFONT lf = {0};
HFONT hFontNew, hFontOld;
lf.lfQuality = CLEARTYPE_QUALITY;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfHeight = -1 * (m_iTxtInfoPointSize * GetDeviceCaps(hdc,LOGPIXELSY) / 72);
lf.lfWeight = m_iTxtInfoWeight;

//Create the new font
hFontNew = CreateFontIndirect(&lf);
hFontOld = (HFONT) SelectObject(hdc, hFontNew);

//Get the size of the string
SIZE size = {0};
GetTextExtentPoint(hdc,m_pszTxtInfo,_tcslen(m_pszTxtInfo),&size);

//Restore the font
SelectObject(hdc, hFontOld);
DeleteObject(hFontNew);

ReleaseDC(hWnd,hdc);

if(m_dtValue == DRT_NULL)
{
m_iTxtInfoWidth = m_iWndWidth;
m_iTxtInfoHeight = m_iWndHeight;
}
else if(m_dtValue == DRT_LEFT || m_dtValue == DRT_RIGHT)
{
m_iTxtInfoWidth = size.cx;
m_iTxtInfoHeight = size.cy;
}
else if(m_dtValue == DRT_UP || m_dtValue == DRT_DOWN)
{
//Get the amount of the "/n"
TCHAR *pFind = m_pszTxtInfo;
int iCountLine = 1;
while(TRUE)
{
pFind = _tcsstr(pFind,TEXT("/n"));

if(pFind != NULL)
{
pFind += 1;
iCountLine ++;
}
else
{
break;
}
}

m_iTxtInfoWidth = m_iWndWidth;
m_iTxtInfoHeight = size.cy * iCountLine;

}

//The begin position of X and Y
switch(m_dtValue)
{
case DRT_NULL:
m_iTxtInfoX = (m_iWndWidth - m_iTxtInfoWidth) / 2;
m_iTxtInfoY = (m_iWndHeight - m_iTxtInfoHeight) / 2;
break;
case DRT_LEFT:
m_iTxtInfoX = m_iWndWidth;
m_iTxtInfoY = (m_iWndHeight - m_iTxtInfoHeight) / 2;
break;
case DRT_RIGHT:
m_iTxtInfoX = -m_iTxtInfoWidth;
m_iTxtInfoY = (m_iWndHeight - m_iTxtInfoHeight) / 2;
break;
case DRT_UP:
m_iTxtInfoX = (m_iWndWidth - m_iTxtInfoWidth) / 2;
m_iTxtInfoY = m_iWndHeight;
break;
case DRT_DOWN:
m_iTxtInfoX = (m_iWndWidth - m_iTxtInfoWidth) / 2;
m_iTxtInfoY = -m_iTxtInfoHeight;
break;
}

return TRUE;
}

//----------------------------------------------------------------------
//Description:
//Draw the background
//
//----------------------------------------------------------------------
void CTextWnd::DrawBackground(HDC hdc)
{

//Create the pen
HPEN hPen = CreatePen(PS_SOLID,1,m_crBkColor);
HPEN hOldPen = NULL;
hOldPen = (HPEN)SelectObject(hdc,hPen);

//the rect color
HBRUSH hBrush = CreateSolidBrush(m_crBkColor);
HGDIOBJ hOldBrush = SelectObject(hdc,hBrush);

//Draw
Rectangle(hdc,0,0,m_iWndWidth + 1, m_iWndHeight + 1);

//Realse the resource
SelectObject(hdc,hOldBrush);
DeleteObject(hBrush);
SelectObject(hdc,hOldPen);
DeleteObject(hPen);


}

//----------------------------------------------------------------------
//Description:
//Initialize the memory DC for storing the current text information
//
//----------------------------------------------------------------------
BOOL CTextWnd::InitDCTxtInfo(void)
{
if(ResetTxtInfoRect() == FALSE)
{
return FALSE;
}

HDC hdc = GetDC(GetWindow());

//If existing the memory DC, delete it.
m_DCTxtInfo.Delete();

//Create the memory DC
SIZE size = {m_iTxtInfoWidth,m_iTxtInfoHeight};
m_DCTxtInfo.Create(hdc,&size);

//Draw the background with the transparent color
HPEN hPen = CreatePen(PS_SOLID,1,m_crBkColor);
HPEN hOldPen = NULL;
hOldPen = (HPEN)SelectObject(m_DCTxtInfo.GetDC(),hPen);
//the rect color
HBRUSH hBrush = CreateSolidBrush(m_crBkColor);
HGDIOBJ hOldBrush = SelectObject(m_DCTxtInfo.GetDC(),hBrush);
//Draw
Rectangle(m_DCTxtInfo.GetDC(),0,0,m_iTxtInfoWidth + 1, m_iTxtInfoHeight + 1);
//Realse the resource
SelectObject(m_DCTxtInfo.GetDC(),hOldBrush);
DeleteObject(hBrush);
SelectObject(m_DCTxtInfo.GetDC(),hOldPen);
DeleteObject(hPen);

//Set the background mode
::SetBkMode(m_DCTxtInfo.GetDC(),TRANSPARENT);

//Draw the text
RECT rcDraw = {0, 0, m_iTxtInfoWidth, m_iTxtInfoHeight};
UINT uFormat = 0;
switch(m_dtValue)
{
case DRT_NULL:
uFormat = DT_LEFT | DT_TOP | DT_WORDBREAK;
break;
case DRT_LEFT:
uFormat = DT_VCENTER | DT_SINGLELINE | DT_LEFT;
break;
case DRT_RIGHT:
uFormat = DT_VCENTER | DT_SINGLELINE | DT_RIGHT;
break;
case DRT_UP:
case DRT_DOWN:
uFormat = DT_CENTER | DT_WORDBREAK;
break;
}

//Set the text color
COLORREF crOldTextColor = ::SetTextColor(m_DCTxtInfo.GetDC(),m_crTxtInfoColor);

//Set the font to caculate
LOGFONT lf = {0};
HFONT hFontNew, hFontOld;
lf.lfQuality = CLEARTYPE_QUALITY;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfHeight = -1 * (m_iTxtInfoPointSize * GetDeviceCaps(m_DCTxtInfo.GetDC(),LOGPIXELSY) / 72);
lf.lfWeight = m_iTxtInfoWeight;

//Create the new font
hFontNew = CreateFontIndirect(&lf);
hFontOld = (HFONT) SelectObject(m_DCTxtInfo.GetDC(), hFontNew);

if(m_dtValue == DRT_RIGHT)
{
//Reverse the string
int iLen = _tcslen(m_pszTxtInfo);
TCHAR *pszReverse = new TCHAR[iLen + 1];
for(int i = 0; i < iLen; i ++)
{
pszReverse[i] = m_pszTxtInfo[iLen - i - 1];
}
pszReverse[iLen] = '/0';

DrawText(m_DCTxtInfo.GetDC(),pszReverse,-1,&rcDraw,uFormat);

delete []pszReverse;
}
else
{
DrawText(m_DCTxtInfo.GetDC(),m_pszTxtInfo,-1,&rcDraw,uFormat);
}

//Restore the font
SelectObject(m_DCTxtInfo.GetDC(), hFontOld);
DeleteObject(hFontNew);

//Restore the color
::SetTextColor(m_DCTxtInfo.GetDC(),crOldTextColor);

ReleaseDC(GetWindow(),hdc);

return TRUE;

}

//----------------------------------------------------------------------
//Description:
//Set the move distance once, base on pixel.
//
//----------------------------------------------------------------------
void CTextWnd::SetMovePixel(int iPixel)
{
m_iMovePixel = iPixel;
}


//----------------------------------------------------------------------
//Description:
//Set the text color. Don't set the same color with the background.
//It would take effect in next calling Play().
//
//----------------------------------------------------------------------
void CTextWnd::SetTxtColor(COLORREF crColor)
{
m_crTxtInfoColor = crColor;

//Set the flag to reinitialize the memory DC
m_bInited = FALSE;

}

//----------------------------------------------------------------------
//Description:
//Set the text point size.
//It would take effect in next calling Play().
//
//----------------------------------------------------------------------
void CTextWnd::SetTxtPointSize(int iPointSize)
{
m_iTxtInfoPointSize = iPointSize;

//Set the flag to reinitialize the memory DC
m_bInited = FALSE;
}

//----------------------------------------------------------------------
//Description:
//Set the text weight. See LOGFONT for a list of value.
//It would take effect in next calling Play().
//
//----------------------------------------------------------------------
void CTextWnd::SetTxtWeight(int iWeight)
{
m_iTxtInfoWeight = iWeight;

//Set the flag to reinitialize the memory DC
m_bInited = FALSE;
}

//----------------------------------------------------------------------
//Description:
//Set the color for the background of window
//
//----------------------------------------------------------------------
void CTextWnd::SetBkColor(COLORREF crColor)
{
m_crBkColor = crColor;
}

//----------------------------------------------------------------------
//Description:
//Switch to next image
//----------------------------------------------------------------------
BOOL CTextWnd::SwitchNext(void)
{
if(m_FileStore.GetAmount() == 0)
{
return FALSE;
}

m_iIndexCurTxt ++;
if(m_iIndexCurTxt >= m_FileStore.GetAmount())
{
m_iIndexCurTxt = 0;
}


ReadCurTxt();

return TRUE;
}

//----------------------------------------------------------------------
//Description:
//Switch to previous image
//----------------------------------------------------------------------
BOOL CTextWnd::SwitchPrevious(void)
{
if(m_FileStore.GetAmount() == 0)
{
return FALSE;
}

m_iIndexCurTxt --;
if(m_iIndexCurTxt < 0 )
{
m_iIndexCurTxt = m_FileStore.GetAmount() - 1;
}


ReadCurTxt();

return TRUE;
}


//---------------------------------------------------------------------
//Description:
//Find the file in the specified directory
//
//Parameters:
//pszPath : [in] The path to find file
//pStore : [in] The buffer for storing the file path
//pCheckFunc : [in] Pointer to the function for checking the file
//---------------------------------------------------------------------
BOOL CTextWnd::FindFile(const TCHAR *pszPath,CStrStore *pStore,BOOL (*pCheckFunc)(const TCHAR *pcszPath))
{
if(_tcslen(pszPath) >= MAX_PATH || pszPath == NULL || pStore == NULL || pCheckFunc == NULL)
{
return FALSE;
}


TCHAR szFindDir[MAX_PATH] = {0};
_tcscpy(szFindDir,pszPath);
//the last 4 elememts must be like as "/*.*"
ULONG ulLen = _tcslen(szFindDir);
if(ulLen != 0 && szFindDir[ulLen - 1]=='//')
{
_tcscat(szFindDir,TEXT("*.*"));
}
else
{
_tcscat(szFindDir,TEXT("//*.*"));
}


WIN32_FIND_DATA fd;
HANDLE hFind;
hFind=FindFirstFile(szFindDir,&fd);
if(hFind != INVALID_HANDLE_VALUE)
{
do{
if(fd.dwFileAttributes==FILE_ATTRIBUTE_DIRECTORY)
{
//it must be directory
TCHAR szNextDir[MAX_PATH] = {0};
_tcscpy(szNextDir,pszPath);
ULONG ulLenNext = _tcslen(pszPath);
if(ulLenNext != 0 && szNextDir[ulLenNext - 1] != '//')
{
_tcscat(szNextDir,TEXT("//"));
}
_tcscat(szNextDir,fd.cFileName);
FindFile(szNextDir,pStore,pCheckFunc);
}
else
{
//it is file

if((*pCheckFunc)(fd.cFileName) == TRUE)
{
TCHAR szPathFile[MAX_PATH] = {0};
_tcscpy(szPathFile,pszPath);
ULONG ulLenFile = _tcslen(szPathFile);
if(ulLenFile != 0 && szPathFile[ulLenFile - 1] != '//')
{
_tcscat(szPathFile,TEXT("//"));
}
_tcscat(szPathFile,fd.cFileName);
pStore->Add(szPathFile);
}

}
}while(FindNextFile(hFind,&fd));
}
FindClose(hFind);

return TRUE;
}

//---------------------------------------------------------------------
//Description:
//Stop playing
//
//---------------------------------------------------------------------
BOOL CTextWnd::Stop(void)
{
m_taCurAction = TA_STOP;
SetEvent(m_hEventTimer);

return TRUE;
}


在CTextWnd中还用到了三个类,分别是CMemDC、CWndBase和CStrStore,其作用依次是创建内存DC、父类窗口和存储文件路径。

CWndBase的相关信息可参考这边文章: http://blog.csdn.net/norains/archive/2007/11/10/1878218.aspx

CMemDC和CStrStore的代码比较简单,没有什么难点需要描述的,其代码分别如下:


CMemDC:

/ /
// MemDC.h:interfacefortheCCommonclass.
//
// Version:
// 0.1.0
// Date:
// 2008.02.20
/ /

#pragma once

class CMemDC
{
public :
CMemDC(
void );
~ CMemDC( void );

BOOLCreate(HDChdc,
const SIZE * pSize);
BOOLDelete(
void );
HDCGetDC(
void );
LONGGetWidth(
void );
LONGGetHeight(
void );
BOOLIsOK(
void );


private :
HDCm_hdcMem;
HBITMAPm_hBitmap;
HGDIOBJm_hOldSel;
SIZEm_Size;


};


/ /
// MemDC.cpp
//
/ /
#include " stdafx.h "
#include
" MemDC.h "

// ----------------------------------------------------------------------
// Description:
// Construction
// -----------------------------------------------------------------------
CMemDC::CMemDC( void ):
m_hdcMem(NULL),
m_hBitmap(NULL),
m_hOldSel(NULL)
{
memset(
& m_Size, 0 , sizeof (m_Size));
}

// ----------------------------------------------------------------------
// Description:
// Destruction
// -----------------------------------------------------------------------
CMemDC:: ~ CMemDC( void )
{
}


// ----------------------------------------------------------------------
// Description:
// CreatethememoryDC.Aftersucceedincallingthefunction,youshould
// callDelete()toreleaseresource.
//
// Parameters:
// hdc:[in]Handletoanexistingdevicecontext.
// pSize:[in]ThesizeofthememoryDCtocreate.
// IfNULL,thefunctionusesthescreensize.
// -----------------------------------------------------------------------
BOOLCMemDC::Create(HDChdc, const SIZE * pSize)
{
BOOLbResult
= FALSE;

if (hdc == NULL || m_hdcMem != NULL)
{
goto EXIT;
}

if (pSize != NULL)
{
m_Size
= * pSize;
}
else
{
m_Size.cx
= GetSystemMetrics(SM_CXSCREEN);
m_Size.cy
= GetSystemMetrics(SM_CYSCREEN);
}

// CreateaDCthatmatchesthedevice
m_hdcMem = CreateCompatibleDC(hdc);
if (m_hdcMem == NULL)
{
goto EXIT;
}

m_hBitmap
= CreateCompatibleBitmap(hdc,m_Size.cx,m_Size.cy);
if (m_hBitmap == NULL)
{
goto EXIT;
}

// Selectthebitmapintotothecompatibledevicecontext
m_hOldSel = SelectObject(m_hdcMem,m_hBitmap);

bResult
= TRUE;

EXIT:
if (bResult == FALSE)
{
DeleteObject(m_hBitmap);
m_hBitmap
= NULL;

DeleteDC(m_hdcMem);
m_hdcMem
= NULL;
}

return bResult;
}



// ----------------------------------------------------------------------
// Description:
// DeletethememoryDC
//
// -----------------------------------------------------------------------
BOOLCMemDC::Delete( void )
{
if (m_hdcMem == NULL || m_hOldSel == NULL || m_hBitmap == NULL)
{
return FALSE;
}

// RestoreoriginalbitmapselectionanddestroythememoryDC
SelectObject(m_hdcMem,m_hOldSel);
DeleteObject(m_hBitmap);
DeleteDC(m_hdcMem);

m_hdcMem
= NULL;
m_hOldSel
= NULL;
m_hBitmap
= NULL;

memset(
& m_Size, 0 , sizeof (m_Size));

return TRUE;
}


// ----------------------------------------------------------------------
// Description:
// GetthehandleofthememoryDC.YouCOULDN'TreleasetheDCbywindowapifuntionReleaseDC()!
// Instead,youshouldcallCMemDC::Delete().
// Nullincdicatesfailed
//
// -----------------------------------------------------------------------
HDCCMemDC::GetDC( void )
{
return m_hdcMem;
}

// ----------------------------------------------------------------------
// Description:
// GetthewidthofthememoryDC
//
// -----------------------------------------------------------------------
LONGCMemDC::GetWidth( void )
{
return m_Size.cx;
}

// ----------------------------------------------------------------------
// Description:
// GettheheightofthememoryDC
//
// -----------------------------------------------------------------------
LONGCMemDC::GetHeight( void )
{
return m_Size.cy;
}

// ----------------------------------------------------------------------
// Description:
// CheckthememoryDC.
//
// Parameters:
// NULL
//
// ReturnValues:
// TRUE-ready.
// FALSE-Notready.
//
// -----------------------------------------------------------------------
BOOLCMemDC::IsOK( void )
{
return (m_hdcMem != NULL);
}

CStrStore:
/ /
// StrStore.h:interfacefortheCStrStoreclass.
//
// Version:
// 1.0.0
// Date:
// 2008.02.26
/ /

#pragma once



// -----------------------------------------------------------------------
class CStrStore
{
public :
int GetDataLength( int iIndex);
int FindData( const TCHAR * pcszFind);
BOOLGetData(
int iIndex,TCHAR * pszOut, int iSize);
int GetAmount();
void DeleteAllData();
BOOLAdd(
const TCHAR * pszIn);
CStrStore();
virtual ~ CStrStore();
protected :

typedef
struct _StoreData
{
TCHAR
* pszString;
_StoreData
* pNextData;
}STOREDATA,
* PSTOREDATA;
PSTOREDATAm_pFirstData;
PSTOREDATAm_pEndData;

int m_iAmount;

};


/ /
// StrStore.cpp:implementationoftheCStrStoreclass.
//
/ /

#include
" stdafx.h "
#include
" StrStore.h "

/ /
// Construction/Destruction
/ /

CStrStore::CStrStore()
{
m_pFirstData
= NULL;
m_pEndData
= NULL;
m_iAmount
= 0 ;
}

CStrStore::
~ CStrStore()
{
DeleteAllData();
}


// ----------------------------------------------------------------------
// Description:
// AddtheTCHARstring
// ----------------------------------------------------------------------
BOOLCStrStore::Add( const TCHAR * pszIn)
{
PSTOREDATApNewData
= new STOREDATA();

if (pNewData == NULL)
{
return FALSE;
}

int iLen = _tcslen(pszIn);
pNewData
-> pszString = new TCHAR[iLen + 1 ];
if (pNewData -> pszString == NULL)
{
deletepNewData;
return FALSE;
}
_tcscpy(pNewData
-> pszString,pszIn);


pNewData
-> pNextData = NULL;

if (m_pFirstData == NULL)
{
m_pFirstData
= pNewData;
}
else
{
m_pEndData
-> pNextData = pNewData;
}

m_pEndData
= pNewData;

m_iAmount
++ ;

return TRUE;
}


// ----------------------------------------------------------------------
// Description:
// Deleteallthestoreddata
// ----------------------------------------------------------------------
void CStrStore::DeleteAllData()
{
if (m_pFirstData == NULL)
{
return ;
}

PSTOREDATApDeleteData
= m_pFirstData;

while (m_pFirstData -> pNextData != NULL)
{
m_pFirstData
= m_pFirstData -> pNextData;

delete[]pDeleteData
-> pszString;
deletepDeleteData;

pDeleteData
= m_pFirstData;
}

// Deletethelastone
deletepDeleteData;

m_pFirstData
= NULL;
m_pEndData
= NULL;

m_iAmount
= 0 ;
}


// ----------------------------------------------------------------------
// Description:
// Gettheamount
// ----------------------------------------------------------------------
int CStrStore::GetAmount()
{
return m_iAmount;
}


// ----------------------------------------------------------------------
// Description:
// Getthedatabaseontheindex.Andthebeginindexis0.
// ----------------------------------------------------------------------
BOOLCStrStore::GetData( int iIndex,TCHAR * pszOut, int iSize)
{
if (iIndex < 0 || iIndex >= m_iAmount || pszOut == NULL)
{
return FALSE;
}

int iCount = 0 ;
PSTOREDATApData
= m_pFirstData;

while (iCount != iIndex)
{
pData
= pData -> pNextData;
iCount
++ ;
}

int iLen = _tcslen(pData -> pszString);

if (iSize < iLen + 1 )
{
return FALSE;
}

_tcscpy(pszOut,pData
-> pszString);


return TRUE;
}


// ----------------------------------------------------------------------
// Description:
// Findthestringdataandreturntheindexinthestorage.
//
// Parameters:
// pcszFind:[in]Thestringtofind
//
// ReturnValues:
// -1:failed
// others:succeed.
// ----------------------------------------------------------------------
int CStrStore::FindData( const TCHAR * pcszFind)
{
int iIndexFind = 0 ;


PSTOREDATApData
= m_pFirstData;

while (iIndexFind < m_iAmount)
{
if (_tcscmp(pData -> pszString,pcszFind) == 0 )
{
break ;
}

pData
= pData -> pNextData;
iIndexFind
++ ;
}

if (iIndexFind >= m_iAmount)
{
// Failedinfindingthestring
iIndexFind = - 1 ;
}

return iIndexFind;
}


// ----------------------------------------------------------------------
// Description:
// Getthelengthofthestringdatabaseontheindex.Andthebeginindexis0.
//
// Parameters:
// iIndex:[in]Theindexinthestoreddata,andit'sbaseon0.
//
// ReturnValues:
// -1:failed
// others:succeed.
// ----------------------------------------------------------------------
int CStrStore::GetDataLength( int iIndex)
{
if (iIndex < 0 || iIndex >= m_iAmount)
{
return - 1 ;
}

int iCount = 0 ;
PSTOREDATApData
= m_pFirstData;

while (iCount != iIndex)
{
pData
= pData -> pNextData;
iCount
++ ;
}

return _tcslen(pData -> pszString);

}


既然前戏已经过完,那么我们开始来干正活吧。 :-)

如果我们想创建一个窗口,该窗口的文字有下往上滚动,则代码可以如此:
int WINAPIWinMain(HINSTANCEhInstance,
HINSTANCEhPrevInstance,
LPTSTRlpCmdLine,
int nCmdShow)
{
// TODO:Placecodehere.

CTextWndtxtWnd;
txtWnd.Create(hInstance,NULL,TEXT(
" TextWnd " ),TEXT( " TextWnd " ));
txtWnd.SetDirection(DRT_UP);
txtWnd.SetText(TEXT(
" 向上滚动第二行信息 " ));
txtWnd.Play();
txtWnd.ShowWindow(TRUE);

MSGmsg;
while (GetMessage( & msg,NULL, 0 , 0 ))
{
TranslateMessage(
& msg);
DispatchMessage(
& msg);
}

return 0 ;
}



一个滚动窗口就出来了,是不是很简单?

最后,我们来看看CTextWnd一些常用的函数:


1.Create(HINSTANCE hInst, HWND hWndParent, const TCHAR *pcszWndClass, const TCHAR *pcszWndName,BOOL bMsgThrdInside = FALSE)
在使用之前都必须创建一个窗口。

2.SetText(const TCHAR * pcszText)
设置显示的文本

3.SetDirection(DirectionValue dtValue)
设置文字的滚动方向,取值有五种:DRT_NULL,DRT_LEFT,DRT_RIGHT,DRT_UP,DRT_DOWN,其含义和字面意义一致。

4.SetInterval(DWORD dwInterval)
设置移动的时间间隔,默认为100ms

5.SetMovePixel(int iPixel)
设置每次移动的像素,默认为1

6.SetTxtPath(const TCHAR * pcszPath)
设置读取的文件名或文件夹。如果所给的路径为文件夹,则该函数默认将读取第一个文件,但可以通过调用SwitchNext和SwitchPrevious切换不同的文件。

7.Play(void)
开始播放。

这里还有个函数需要留意的,CTextWnd会调用DrawBackground进行背景的绘制。因为在实际使用中,往往需要实现透明的效果或是绘制其它的背景画面,这时候只要创建一个派生自CTextWnd的类,然后重载DrawBackground函数即可。

该文的例子可在此下载:http://download.csdn.net/source/362836

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值