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

  1. // CreditStatic.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "CreditSt.h"
  5. #ifdef _DEBUG
  6. #define new DEBUG_NEW
  7. #undef THIS_FILE
  8. static char THIS_FILE[] = __FILE__;
  9. #endif
  10. // defined in MAIN.CPP
  11. extern HINSTANCE ghInstance;
  12. #define DISPLAY_TIMER_ID 150 // timer id
  13. /////////////////////////////////////////////////////////////////////////////
  14. // CCreditStatic
  15. CCreditStatic::CCreditStatic()
  16. {
  17. m_Colors[0] = RGB(0,0,255); // Black
  18. m_Colors[1] = RGB(255,0,0); // Red
  19. m_Colors[2] = RGB(0,128,0); // John Deer Green
  20. m_Colors[3] = RGB(0,255,255); // Turquoise
  21. m_Colors[4] = RGB(255,255,255); // White
  22. m_TextHeights[0] = 36;
  23. m_TextHeights[1] = 34;
  24. m_TextHeights[2] = 34;
  25. m_TextHeights[3] = 30;
  26. m_nCurrentFontHeight = m_TextHeights[NORMAL_TEXT_HEIGHT];
  27. m_Escapes[0] = '\t';
  28. m_Escapes[1] = '\n';
  29. m_Escapes[2] = '\r';
  30. m_Escapes[3] = '^';
  31. /*
  32. m_DisplaySpeed[0] = 75;
  33. m_DisplaySpeed[1] = 65;
  34. m_DisplaySpeed[2] = 15;
  35. */
  36. m_CurrentSpeed = 15; //DISPLAY_FAST;
  37. m_ScrollAmount = -1;
  38. m_ArrIndex = NULL;
  39. m_nCounter = 31;
  40. m_nClip = 0;
  41. m_bFirstTurn = TRUE;
  42. m_Gradient = GRADIENT_RIGHT_DARK;
  43. n_MaxWidth = 0;
  44. TimerOn = 0;
  45. m_szWork = NULL;
  46. }
  47. CCreditStatic::~CCreditStatic()
  48. {
  49. }
  50. BEGIN_MESSAGE_MAP(CCreditStatic, CStatic)
  51. //{{AFX_MSG_MAP(CCreditStatic)
  52. ON_WM_ERASEBKGND()
  53. ON_WM_TIMER()
  54. ON_WM_DESTROY()
  55. //}}AFX_MSG_MAP
  56. END_MESSAGE_MAP()
  57. /////////////////////////////////////////////////////////////////////////////
  58. // CCreditStatic message handlers
  59. BOOL CCreditStatic::StartScrolling()
  60. {
  61. if(m_pArrCredit->IsEmpty())
  62. return FALSE;
  63. if (m_BmpMain)
  64. {
  65. DeleteObject(m_BmpMain);
  66. m_BmpMain = NULL;
  67. }
  68. ::GetClientRect(this->m_hWnd, &m_ScrollRect);
  69. TimerOn = (UINT)SetTimer(DISPLAY_TIMER_ID, m_CurrentSpeed, NULL);
  70. ASSERT(TimerOn != 0);
  71. m_ArrIndex = m_pArrCredit->GetHeadPosition();
  72. // m_nCounter = 1;
  73. // m_nClip = 0;
  74. return TRUE;
  75. }
  76. void CCreditStatic::EndScrolling()
  77. {
  78. KillTimer(DISPLAY_TIMER_ID);
  79. TimerOn = 0;
  80. if (m_BmpMain)
  81. {
  82. DeleteObject(m_BmpMain);
  83. m_BmpMain = NULL;
  84. }
  85. }
  86. void CCreditStatic::SetCredits(LPCTSTR credits,TCHAR delimiter)
  87. {
  88. LPTSTR str,ptr1,ptr2;
  89. ASSERT(credits);
  90. if ((str = _tcsdup(credits)) == NULL)
  91. return;
  92. m_pArrCredit = new (CStringList);
  93. ASSERT (m_pArrCredit);
  94. m_pArrCredit->RemoveAll();
  95. ptr1 = str;
  96. while((ptr2 = _tcschr(ptr1,delimiter)) != NULL)
  97. {
  98. *ptr2 = '\0';
  99. m_pArrCredit->AddTail(ptr1);
  100. ptr1 = ptr2+1;
  101. }
  102. m_pArrCredit->AddTail(ptr1);
  103. free(str);
  104. m_ArrIndex = m_pArrCredit->GetHeadPosition();
  105. // m_nCounter = 1;
  106. // m_nClip = 0;
  107. }
  108. BOOL CCreditStatic::OnEraseBkgnd(CDC* pDC)
  109. {
  110. return TRUE;
  111. // return CStatic::OnEraseBkgnd(pDC);
  112. }
  113. //************************************************************************
  114. // OnTimer
  115. //
  116. // On each of the display timers, scroll the window 1 unit. Each 20
  117. // units, fetch the next array element and load into work string. Call
  118. // Invalidate and UpdateWindow to invoke the OnPaint which will paint
  119. // the contents of the newly updated work string.
  120. //************************************************************************
  121. void CCreditStatic::OnTimer(UINT nIDEvent)
  122. {
  123. BOOL bCheck = FALSE;
  124. if (m_nCounter++ % m_nCurrentFontHeight == 0) // every x timer events, show new line
  125. {
  126. m_nCounter=1;
  127. m_szWork = (LPCTSTR)m_pArrCredit->GetNext(m_ArrIndex);
  128. if(m_bFirstTurn)
  129. bCheck = TRUE;
  130. if (m_ArrIndex == NULL)
  131. {
  132. m_bFirstTurn = FALSE;
  133. m_ArrIndex = m_pArrCredit->GetHeadPosition();
  134. }
  135. m_nClip = 0;
  136. }
  137. HDC hMainDC = this->GetDC()->m_hDC;
  138. RECT rc = m_ScrollRect;
  139. rc.left = ((rc.right-rc.left)-n_MaxWidth)/2;
  140. rc.right = rc.left + n_MaxWidth;
  141. HDC hDC = ::CreateCompatibleDC(hMainDC);
  142. // Don't try to scroll credits you don't have!
  143. if (m_szWork)
  144. MoveCredit(&hMainDC, rc, bCheck);
  145. else
  146. FillGradient(&hMainDC, m_ScrollRect);
  147. ::SelectObject(hDC, m_BmpMain);
  148. ::BitBlt(hMainDC, 0, 0, m_ScrollRect.right-m_ScrollRect.left, m_ScrollRect.bottom-m_ScrollRect.top, hDC, 0, 0, SRCCOPY);
  149. ::ReleaseDC(this->m_hWnd, hMainDC);
  150. ::DeleteDC(hDC);
  151. CStatic::OnTimer(nIDEvent);
  152. }
  153. void CCreditStatic::FillGradient(HDC *pDC, RECT& FillRect)
  154. {
  155. float fStep,fRStep,fGStep,fBStep; // How large is each band?
  156. WORD R = GetRValue(m_Colors[BACKGROUND_COLOR]);
  157. WORD G = GetGValue(m_Colors[BACKGROUND_COLOR]);
  158. WORD B = GetBValue(m_Colors[BACKGROUND_COLOR]);
  159. // Determine how large each band should be in order to cover the
  160. // client with 256 bands (one for every color intensity level)
  161. //if(m_Gradient % 2)
  162. //{
  163. fRStep = (float)R / 255.0f;
  164. fGStep = (float)G / 255.0f;
  165. fBStep = (float)B / 255.0f;
  166. /*
  167. }
  168. else
  169. {
  170. fRStep = (float)(255-R) / 255.0f;
  171. fGStep = (float)(255-G) / 255.0f;
  172. fBStep = (float)(255-B) / 255.0f;
  173. }
  174. */
  175. COLORREF OldCol = ::GetBkColor(*pDC);
  176. RECT rc;
  177. // Start filling bands
  178. fStep = (float)(m_ScrollRect.right-m_ScrollRect.left) / 256.0f;
  179. for (short iOnBand = (short)((256*FillRect.left)/(m_ScrollRect.right-m_ScrollRect.left));
  180. (int)(iOnBand*fStep) < FillRect.right && iOnBand < 256; iOnBand++)
  181. {
  182. ::SetRect(&rc,
  183. (int)(iOnBand * fStep),
  184. FillRect.top,
  185. (int)((iOnBand+1) * fStep),
  186. FillRect.bottom+1);
  187. // If we want to enable gradient filling from any direction!
  188. /*
  189. switch(m_Gradient)
  190. {
  191. case GRADIENT_RIGHT_DARK:
  192. col = RGB((int)(R-iOnBand*fRStep),(int)(G-iOnBand*fGStep),(int)(B-iOnBand*fBStep));
  193. break;
  194. case GRADIENT_RIGHT_LIGHT:
  195. col = RGB((int)(R+iOnBand*fRStep),(int)(G+iOnBand*fGStep),(int)(B+iOnBand*fBStep));
  196. break;
  197. case GRADIENT_LEFT_DARK:
  198. col = RGB((int)(iOnBand*fRStep),(int)(iOnBand*fGStep),(int)(iOnBand*fBStep));
  199. break;
  200. case GRADIENT_LEFT_LIGHT:
  201. col = RGB(255-(int)(iOnBand*fRStep),255-(int)(iOnBand*fGStep),255-(int)(iOnBand*fBStep));
  202. break;
  203. default:
  204. return;
  205. }
  206. */
  207. ::SetBkColor(*pDC, RGB((int)(R-iOnBand*fRStep),(int)(G-iOnBand*fGStep),(int)(B-iOnBand*fBStep)));
  208. ::ExtTextOut(*pDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
  209. }
  210. ::SetBkColor(*pDC, OldCol);
  211. }
  212. void CCreditStatic::MoveCredit(HDC* pDC, RECT& ClientRect, BOOL bCheck)
  213. {
  214. HDC hMemDC = ::CreateCompatibleDC(*pDC);
  215. HBITMAP *pOldMemDCBitmap = NULL;
  216. HFONT *pOldFont = NULL;
  217. RECT r1;
  218. if (m_BmpMain == NULL)
  219. {
  220. m_BmpMain = ::CreateCompatibleBitmap(*pDC, m_ScrollRect.right-m_ScrollRect.left, m_ScrollRect.bottom-m_ScrollRect.top );
  221. pOldMemDCBitmap = (HBITMAP *)::SelectObject(hMemDC, m_BmpMain);
  222. FillGradient(&hMemDC, m_ScrollRect);
  223. } else pOldMemDCBitmap = (HBITMAP *)::SelectObject(hMemDC, m_BmpMain);
  224. if ((ClientRect.right-ClientRect.left) > 0)
  225. {
  226. ::ScrollDC(hMemDC, 0, m_ScrollAmount, &m_ScrollRect, &ClientRect, NULL, &r1);
  227. }
  228. else
  229. {
  230. r1 = m_ScrollRect;
  231. r1.top = r1.bottom-abs(m_ScrollAmount);
  232. }
  233. m_nClip = m_nClip + abs(m_ScrollAmount);
  234. //*********************************************************************
  235. // FONT SELECTIlON
  236. short rmcode = 1;
  237. if (lstrlen(m_szWork))
  238. {
  239. BYTE bUnderline, bItalic;
  240. bUnderline = bItalic = FALSE;
  241. COLORREF nTmpColour = m_Colors[TOP_LEVEL_GROUP_COLOR];
  242. TCHAR c = m_szWork[lstrlen(m_szWork)-1];
  243. if(c == m_Escapes[TOP_LEVEL_GROUP])
  244. {
  245. m_nCurrentFontHeight = m_TextHeights[TOP_LEVEL_GROUP_HEIGHT];
  246. }
  247. else if(c == m_Escapes[GROUP_TITLE])
  248. {
  249. m_nCurrentFontHeight = m_TextHeights[GROUP_TITLE_HEIGHT];
  250. nTmpColour = m_Colors[GROUP_TITLE_COLOR];
  251. }
  252. else if(c == m_Escapes[TOP_LEVEL_TITLE])
  253. {
  254. m_nCurrentFontHeight = m_TextHeights[TOP_LEVEL_TITLE_HEIGHT];
  255. nTmpColour = m_Colors[TOP_LEVEL_TITLE_COLOR];
  256. }
  257. // If this were application critical, I'd make an array of fonts a member
  258. // and create all the fonts prior to starting the timer!
  259. HFONT pfntArial = ::CreateFont(m_nCurrentFontHeight, 0, 0, 0,
  260. FW_BOLD, bItalic, bUnderline, 0,
  261. ANSI_CHARSET,
  262. OUT_DEFAULT_PRECIS,
  263. CLIP_DEFAULT_PRECIS,
  264. PROOF_QUALITY,
  265. VARIABLE_PITCH | 0x04 | FF_DONTCARE,
  266. (LPCTSTR)"Arial");
  267. ::SetTextColor(hMemDC, nTmpColour);
  268. if (pOldFont != NULL)
  269. ::SelectObject(hMemDC, pOldFont);
  270. pOldFont = (HFONT *)::SelectObject(hMemDC, pfntArial);
  271. }
  272. FillGradient(&hMemDC, r1);
  273. ::SetBkMode(hMemDC, TRANSPARENT);
  274. if(bCheck)
  275. {
  276. SIZE size;
  277. ::GetTextExtentPoint(hMemDC, (LPCTSTR)m_szWork,lstrlen(m_szWork)-rmcode, &size);
  278. if (size.cx > n_MaxWidth)
  279. {
  280. n_MaxWidth = (short)((size.cx > (m_ScrollRect.right-m_ScrollRect.left)) ? (m_ScrollRect.right-m_ScrollRect.left) : size.cx);
  281. ClientRect.left = ((m_ScrollRect.right-m_ScrollRect.left)-n_MaxWidth)/2;
  282. ClientRect.right = ClientRect.left + n_MaxWidth;
  283. }
  284. }
  285. RECT r = ClientRect;
  286. r.top = r.bottom-m_nClip;
  287. DrawText(hMemDC, (LPCTSTR)m_szWork,lstrlen(m_szWork)-rmcode,&r,DT_TOP|DT_CENTER|DT_NOPREFIX | DT_SINGLELINE);
  288. if (pOldFont != NULL)
  289. ::SelectObject(hMemDC, pOldFont);
  290. ::SelectObject(hMemDC, pOldMemDCBitmap);
  291. ::DeleteDC(hMemDC);
  292. }
  293. void CCreditStatic::OnDestroy()
  294. {
  295. CStatic::OnDestroy();
  296. m_pArrCredit->RemoveAll();
  297. if (m_pArrCredit)
  298. delete (m_pArrCredit);
  299. if(TimerOn)
  300. EndScrolling();
  301. }
  302. /* In the event we ever want a few library routines!
  303. void CCreditStatic::SetCredits(UINT nID, TCHAR delimiter)
  304. {
  305. LPTSTR lpCredits = new (TCHAR[255]);
  306. ASSERT (lpCredits);
  307. ::LoadString(ghInstance, nID, lpCredits, 255);
  308. SetCredits((LPCTSTR)lpCredits, delimiter);
  309. if (lpCredits)
  310. delete[] (lpCredits);
  311. }
  312. void CCreditStatic::SetSpeed(UINT index, int speed)
  313. {
  314. ASSERT(index <= DISPLAY_FAST);
  315. if(speed)
  316. m_DisplaySpeed[index] = speed;
  317. m_CurrentSpeed = index;
  318. }
  319. void CCreditStatic::SetColor(UINT index, COLORREF col)
  320. {
  321. ASSERT(index <= NORMAL_TEXT_COLOR);
  322. m_Colors[index] = col;
  323. }
  324. void CCreditStatic::SetTextHeight(UINT index, int height)
  325. {
  326. ASSERT(index <= NORMAL_TEXT_HEIGHT);
  327. m_TextHeights[index] = height;
  328. }
  329. void CCreditStatic::SetEscape(UINT index, char escape)
  330. {
  331. ASSERT(index <= DISPLAY_BITMAP);
  332. m_Escapes[index] = escape;
  333. }
  334. void CCreditStatic::SetGradient(UINT value)
  335. {
  336. ASSERT(value <= GRADIENT_LEFT_LIGHT);
  337. m_Gradient = value;
  338. }
  339. void CCreditStatic::SetTransparent(BOOL bTransparent)
  340. {
  341. m_bTransparent = bTransparent;
  342. }
  343. */