Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

446 lines
10 KiB

// CreditStatic.cpp : implementation file
//
#include "stdafx.h"
#include "CreditSt.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// defined in MAIN.CPP
extern HINSTANCE ghInstance;
#define DISPLAY_TIMER_ID 150 // timer id
/////////////////////////////////////////////////////////////////////////////
// CCreditStatic
CCreditStatic::CCreditStatic()
{
m_Colors[0] = RGB(0,0,255); // Black
m_Colors[1] = RGB(255,0,0); // Red
m_Colors[2] = RGB(0,128,0); // John Deer Green
m_Colors[3] = RGB(0,255,255); // Turquoise
m_Colors[4] = RGB(255,255,255); // White
m_TextHeights[0] = 36;
m_TextHeights[1] = 34;
m_TextHeights[2] = 34;
m_TextHeights[3] = 30;
m_nCurrentFontHeight = m_TextHeights[NORMAL_TEXT_HEIGHT];
m_Escapes[0] = '\t';
m_Escapes[1] = '\n';
m_Escapes[2] = '\r';
m_Escapes[3] = '^';
/*
m_DisplaySpeed[0] = 75;
m_DisplaySpeed[1] = 65;
m_DisplaySpeed[2] = 15;
*/
m_CurrentSpeed = 15; //DISPLAY_FAST;
m_ScrollAmount = -1;
m_ArrIndex = NULL;
m_nCounter = 31;
m_nClip = 0;
m_bFirstTurn = TRUE;
m_Gradient = GRADIENT_RIGHT_DARK;
n_MaxWidth = 0;
TimerOn = 0;
m_szWork = NULL;
}
CCreditStatic::~CCreditStatic()
{
}
BEGIN_MESSAGE_MAP(CCreditStatic, CStatic)
//{{AFX_MSG_MAP(CCreditStatic)
ON_WM_ERASEBKGND()
ON_WM_TIMER()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCreditStatic message handlers
BOOL CCreditStatic::StartScrolling()
{
if(m_pArrCredit->IsEmpty())
return FALSE;
if (m_BmpMain)
{
DeleteObject(m_BmpMain);
m_BmpMain = NULL;
}
::GetClientRect(this->m_hWnd, &m_ScrollRect);
TimerOn = (UINT)SetTimer(DISPLAY_TIMER_ID, m_CurrentSpeed, NULL);
ASSERT(TimerOn != 0);
m_ArrIndex = m_pArrCredit->GetHeadPosition();
// m_nCounter = 1;
// m_nClip = 0;
return TRUE;
}
void CCreditStatic::EndScrolling()
{
KillTimer(DISPLAY_TIMER_ID);
TimerOn = 0;
if (m_BmpMain)
{
DeleteObject(m_BmpMain);
m_BmpMain = NULL;
}
}
void CCreditStatic::SetCredits(LPCTSTR credits,TCHAR delimiter)
{
LPTSTR str,ptr1,ptr2;
ASSERT(credits);
if ((str = _tcsdup(credits)) == NULL)
return;
m_pArrCredit = new (CStringList);
ASSERT (m_pArrCredit);
m_pArrCredit->RemoveAll();
ptr1 = str;
while((ptr2 = _tcschr(ptr1,delimiter)) != NULL)
{
*ptr2 = '\0';
m_pArrCredit->AddTail(ptr1);
ptr1 = ptr2+1;
}
m_pArrCredit->AddTail(ptr1);
free(str);
m_ArrIndex = m_pArrCredit->GetHeadPosition();
// m_nCounter = 1;
// m_nClip = 0;
}
BOOL CCreditStatic::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
// return CStatic::OnEraseBkgnd(pDC);
}
//************************************************************************
// OnTimer
//
// On each of the display timers, scroll the window 1 unit. Each 20
// units, fetch the next array element and load into work string. Call
// Invalidate and UpdateWindow to invoke the OnPaint which will paint
// the contents of the newly updated work string.
//************************************************************************
void CCreditStatic::OnTimer(UINT nIDEvent)
{
BOOL bCheck = FALSE;
if (m_nCounter++ % m_nCurrentFontHeight == 0) // every x timer events, show new line
{
m_nCounter=1;
m_szWork = (LPCTSTR)m_pArrCredit->GetNext(m_ArrIndex);
if(m_bFirstTurn)
bCheck = TRUE;
if (m_ArrIndex == NULL)
{
m_bFirstTurn = FALSE;
m_ArrIndex = m_pArrCredit->GetHeadPosition();
}
m_nClip = 0;
}
HDC hMainDC = this->GetDC()->m_hDC;
RECT rc = m_ScrollRect;
rc.left = ((rc.right-rc.left)-n_MaxWidth)/2;
rc.right = rc.left + n_MaxWidth;
HDC hDC = ::CreateCompatibleDC(hMainDC);
// Don't try to scroll credits you don't have!
if (m_szWork)
MoveCredit(&hMainDC, rc, bCheck);
else
FillGradient(&hMainDC, m_ScrollRect);
::SelectObject(hDC, m_BmpMain);
::BitBlt(hMainDC, 0, 0, m_ScrollRect.right-m_ScrollRect.left, m_ScrollRect.bottom-m_ScrollRect.top, hDC, 0, 0, SRCCOPY);
::ReleaseDC(this->m_hWnd, hMainDC);
::DeleteDC(hDC);
CStatic::OnTimer(nIDEvent);
}
void CCreditStatic::FillGradient(HDC *pDC, RECT& FillRect)
{
float fStep,fRStep,fGStep,fBStep; // How large is each band?
WORD R = GetRValue(m_Colors[BACKGROUND_COLOR]);
WORD G = GetGValue(m_Colors[BACKGROUND_COLOR]);
WORD B = GetBValue(m_Colors[BACKGROUND_COLOR]);
// Determine how large each band should be in order to cover the
// client with 256 bands (one for every color intensity level)
//if(m_Gradient % 2)
//{
fRStep = (float)R / 255.0f;
fGStep = (float)G / 255.0f;
fBStep = (float)B / 255.0f;
/*
}
else
{
fRStep = (float)(255-R) / 255.0f;
fGStep = (float)(255-G) / 255.0f;
fBStep = (float)(255-B) / 255.0f;
}
*/
COLORREF OldCol = ::GetBkColor(*pDC);
RECT rc;
// Start filling bands
fStep = (float)(m_ScrollRect.right-m_ScrollRect.left) / 256.0f;
for (short iOnBand = (short)((256*FillRect.left)/(m_ScrollRect.right-m_ScrollRect.left));
(int)(iOnBand*fStep) < FillRect.right && iOnBand < 256; iOnBand++)
{
::SetRect(&rc,
(int)(iOnBand * fStep),
FillRect.top,
(int)((iOnBand+1) * fStep),
FillRect.bottom+1);
// If we want to enable gradient filling from any direction!
/*
switch(m_Gradient)
{
case GRADIENT_RIGHT_DARK:
col = RGB((int)(R-iOnBand*fRStep),(int)(G-iOnBand*fGStep),(int)(B-iOnBand*fBStep));
break;
case GRADIENT_RIGHT_LIGHT:
col = RGB((int)(R+iOnBand*fRStep),(int)(G+iOnBand*fGStep),(int)(B+iOnBand*fBStep));
break;
case GRADIENT_LEFT_DARK:
col = RGB((int)(iOnBand*fRStep),(int)(iOnBand*fGStep),(int)(iOnBand*fBStep));
break;
case GRADIENT_LEFT_LIGHT:
col = RGB(255-(int)(iOnBand*fRStep),255-(int)(iOnBand*fGStep),255-(int)(iOnBand*fBStep));
break;
default:
return;
}
*/
::SetBkColor(*pDC, RGB((int)(R-iOnBand*fRStep),(int)(G-iOnBand*fGStep),(int)(B-iOnBand*fBStep)));
::ExtTextOut(*pDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
}
::SetBkColor(*pDC, OldCol);
}
void CCreditStatic::MoveCredit(HDC* pDC, RECT& ClientRect, BOOL bCheck)
{
HDC hMemDC = ::CreateCompatibleDC(*pDC);
HBITMAP *pOldMemDCBitmap = NULL;
HFONT *pOldFont = NULL;
RECT r1;
if (m_BmpMain == NULL)
{
m_BmpMain = ::CreateCompatibleBitmap(*pDC, m_ScrollRect.right-m_ScrollRect.left, m_ScrollRect.bottom-m_ScrollRect.top );
pOldMemDCBitmap = (HBITMAP *)::SelectObject(hMemDC, m_BmpMain);
FillGradient(&hMemDC, m_ScrollRect);
} else pOldMemDCBitmap = (HBITMAP *)::SelectObject(hMemDC, m_BmpMain);
if ((ClientRect.right-ClientRect.left) > 0)
{
::ScrollDC(hMemDC, 0, m_ScrollAmount, &m_ScrollRect, &ClientRect, NULL, &r1);
}
else
{
r1 = m_ScrollRect;
r1.top = r1.bottom-abs(m_ScrollAmount);
}
m_nClip = m_nClip + abs(m_ScrollAmount);
//*********************************************************************
// FONT SELECTIlON
short rmcode = 1;
if (lstrlen(m_szWork))
{
BYTE bUnderline, bItalic;
bUnderline = bItalic = FALSE;
COLORREF nTmpColour = m_Colors[TOP_LEVEL_GROUP_COLOR];
TCHAR c = m_szWork[lstrlen(m_szWork)-1];
if(c == m_Escapes[TOP_LEVEL_GROUP])
{
m_nCurrentFontHeight = m_TextHeights[TOP_LEVEL_GROUP_HEIGHT];
}
else if(c == m_Escapes[GROUP_TITLE])
{
m_nCurrentFontHeight = m_TextHeights[GROUP_TITLE_HEIGHT];
nTmpColour = m_Colors[GROUP_TITLE_COLOR];
}
else if(c == m_Escapes[TOP_LEVEL_TITLE])
{
m_nCurrentFontHeight = m_TextHeights[TOP_LEVEL_TITLE_HEIGHT];
nTmpColour = m_Colors[TOP_LEVEL_TITLE_COLOR];
}
// If this were application critical, I'd make an array of fonts a member
// and create all the fonts prior to starting the timer!
HFONT pfntArial = ::CreateFont(m_nCurrentFontHeight, 0, 0, 0,
FW_BOLD, bItalic, bUnderline, 0,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
PROOF_QUALITY,
VARIABLE_PITCH | 0x04 | FF_DONTCARE,
(LPCTSTR)"Arial");
::SetTextColor(hMemDC, nTmpColour);
if (pOldFont != NULL)
::SelectObject(hMemDC, pOldFont);
pOldFont = (HFONT *)::SelectObject(hMemDC, pfntArial);
}
FillGradient(&hMemDC, r1);
::SetBkMode(hMemDC, TRANSPARENT);
if(bCheck)
{
SIZE size;
::GetTextExtentPoint(hMemDC, (LPCTSTR)m_szWork,lstrlen(m_szWork)-rmcode, &size);
if (size.cx > n_MaxWidth)
{
n_MaxWidth = (short)((size.cx > (m_ScrollRect.right-m_ScrollRect.left)) ? (m_ScrollRect.right-m_ScrollRect.left) : size.cx);
ClientRect.left = ((m_ScrollRect.right-m_ScrollRect.left)-n_MaxWidth)/2;
ClientRect.right = ClientRect.left + n_MaxWidth;
}
}
RECT r = ClientRect;
r.top = r.bottom-m_nClip;
DrawText(hMemDC, (LPCTSTR)m_szWork,lstrlen(m_szWork)-rmcode,&r,DT_TOP|DT_CENTER|DT_NOPREFIX | DT_SINGLELINE);
if (pOldFont != NULL)
::SelectObject(hMemDC, pOldFont);
::SelectObject(hMemDC, pOldMemDCBitmap);
::DeleteDC(hMemDC);
}
void CCreditStatic::OnDestroy()
{
CStatic::OnDestroy();
m_pArrCredit->RemoveAll();
if (m_pArrCredit)
delete (m_pArrCredit);
if(TimerOn)
EndScrolling();
}
/* In the event we ever want a few library routines!
void CCreditStatic::SetCredits(UINT nID, TCHAR delimiter)
{
LPTSTR lpCredits = new (TCHAR[255]);
ASSERT (lpCredits);
::LoadString(ghInstance, nID, lpCredits, 255);
SetCredits((LPCTSTR)lpCredits, delimiter);
if (lpCredits)
delete[] (lpCredits);
}
void CCreditStatic::SetSpeed(UINT index, int speed)
{
ASSERT(index <= DISPLAY_FAST);
if(speed)
m_DisplaySpeed[index] = speed;
m_CurrentSpeed = index;
}
void CCreditStatic::SetColor(UINT index, COLORREF col)
{
ASSERT(index <= NORMAL_TEXT_COLOR);
m_Colors[index] = col;
}
void CCreditStatic::SetTextHeight(UINT index, int height)
{
ASSERT(index <= NORMAL_TEXT_HEIGHT);
m_TextHeights[index] = height;
}
void CCreditStatic::SetEscape(UINT index, char escape)
{
ASSERT(index <= DISPLAY_BITMAP);
m_Escapes[index] = escape;
}
void CCreditStatic::SetGradient(UINT value)
{
ASSERT(value <= GRADIENT_LEFT_LIGHT);
m_Gradient = value;
}
void CCreditStatic::SetTransparent(BOOL bTransparent)
{
m_bTransparent = bTransparent;
}
*/