CreditsCtrl.cpp
上传用户:dengkfang
上传日期:2008-12-30
资源大小:5233k
文件大小:38k
源码类别:

CA认证

开发平台:

Visual C++

  1. // CreditsCtrl.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "CreditsCtrl.h"
  5. #include <afxtempl.h>
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #undef THIS_FILE
  9. static char THIS_FILE[] = __FILE__;
  10. #endif
  11. #define CCREDITCTRL_TIMER1 100
  12. // use transparent BitBlts if supported? ( UNTESTED!! )
  13. //#define CCREDITCTRL_USE_TRANSPARENT_BITBLT
  14. // stuff that _should_ have been defined in some header :-/
  15. #ifndef C1_TRANSPARENT
  16.     #define C1_TRANSPARENT 0x0001
  17. #endif 
  18. #ifndef CAPS1
  19.     #define CAPS1 94
  20. #endif 
  21. #ifndef NEWTRANSPARENT
  22.     #define NEWTRANSPARENT 3
  23. #endif
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CCreditsCtrl
  26. LPCTSTR CCreditsCtrl::m_lpszClassName = NULL;
  27. CCreditsCtrl::CCreditsCtrl()
  28. {
  29. m_nTimerSpeed = 40;
  30. m_nCurBitmapOffset = 0;
  31. m_crInternalTransparentColor = RGB(255,0,255);
  32. m_pBackgroundPaint = CCreditsCtrl::DrawBackground;
  33. m_dwBackgroundPaintLParam = GetSysColor(COLOR_BTNFACE);//(DWORD)m_crBackgroundColor;
  34. m_hLinkCursor = NULL;
  35. m_hDefaultCursor = NULL;
  36. m_bCanScroll = TRUE;
  37. m_bIsScrolling = FALSE;
  38. }
  39. CCreditsCtrl::~CCreditsCtrl()
  40. {
  41. }
  42. BEGIN_MESSAGE_MAP(CCreditsCtrl, CWnd)
  43. //{{AFX_MSG_MAP(CCreditsCtrl)
  44. ON_WM_PAINT()
  45. ON_WM_TIMER()
  46. ON_WM_SIZE()
  47. ON_WM_MOUSEMOVE()
  48. ON_WM_LBUTTONDOWN()
  49. ON_WM_LBUTTONUP()
  50. //}}AFX_MSG_MAP
  51. END_MESSAGE_MAP()
  52. BOOL CCreditsCtrl::Create(DWORD dwExStyle, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, UINT nDefaultCursorID, UINT nLinkCursorID)
  53. {
  54. m_hDefaultCursor = nDefaultCursorID == 0 ? NULL : AfxGetApp()->LoadCursor(nDefaultCursorID);
  55. if(nLinkCursorID == 0)
  56. SetDefaultLinkCursor();
  57. else
  58. m_hLinkCursor = AfxGetApp()->LoadCursor(nLinkCursorID);
  59. // register window class & create CWnd object
  60. if (m_lpszClassName == NULL)
  61. m_lpszClassName = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW);
  62. BOOL bResult = CreateEx(dwExStyle, m_lpszClassName, _T(""), dwStyle,
  63. rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
  64. pParentWnd->GetSafeHwnd(), (HMENU)nID, NULL );
  65. // start scrolling
  66. if(bResult)
  67. SetTimer(CCREDITCTRL_TIMER1,m_nTimerSpeed*10,NULL);
  68. return bResult;
  69. }
  70. BOOL CCreditsCtrl::Create(DWORD dwExStyle, DWORD dwStyle, UINT nPlaceholderID, CWnd* pParentWnd, UINT nID, UINT nDefaultCursorID, UINT nLinkCursorID)
  71. {
  72. // get rect from placeholder and call create with the found rect
  73. RECT rect;
  74. pParentWnd->GetDlgItem(nPlaceholderID)->GetWindowRect(&rect);
  75. pParentWnd->ScreenToClient(&rect);
  76. return Create(dwExStyle, dwStyle, rect, pParentWnd, nID, nDefaultCursorID, nLinkCursorID);
  77. }
  78. /////////////////////////////////////////////////////////////////////////////
  79. // CCreditsCtrl message handlers
  80. void CCreditsCtrl::OnPaint() 
  81. {
  82. static BOOL bFirstDraw = TRUE;
  83. CPaintDC dc(this); // device context for painting
  84. // init memory DC
  85. CDC memDC;
  86. memDC.CreateCompatibleDC(&dc);
  87. int nMemDCSave = memDC.SaveDC();
  88. CBitmap memBmp;
  89. memBmp.CreateCompatibleBitmap(&dc,m_rcClient.Width(),m_rcClient.Height());
  90. memDC.SelectObject(&memBmp);
  91. // draw backgorund
  92. if(m_pBackgroundPaint!=NULL)
  93. (*m_pBackgroundPaint)(&memDC,m_rcClient,m_bIsScrolling||bFirstDraw,m_dwBackgroundPaintLParam);
  94. // calculate hot rectagle position and save background at that location
  95. CDC hotBgDC;
  96. CBitmap hotbgBmp,*pOldHBgBmp;
  97. CRect rcHotRect;
  98. if(m_rcHotRect != CRect(0,0,0,0))
  99. {
  100. hotBgDC.CreateCompatibleDC(&memDC);
  101. hotbgBmp.CreateCompatibleBitmap(&memDC,m_rcHotRect.Width(),m_rcHotRect.Height());
  102. pOldHBgBmp = hotBgDC.SelectObject(&hotbgBmp);
  103. if(m_nBitmapHeight <= m_rcClient.bottom)
  104. rcHotRect = m_rcHotRect;
  105. else if(m_nBitmapHeight-m_nCurBitmapOffset+m_rcHotRect.top < m_rcClient.bottom)
  106. rcHotRect.SetRect(m_rcHotRect.left,m_nBitmapHeight-m_nCurBitmapOffset+m_rcHotRect.top,m_rcHotRect.right,m_nBitmapHeight-m_nCurBitmapOffset+m_rcHotRect.bottom);
  107. else
  108. rcHotRect.SetRect(m_rcHotRect.left,m_rcHotRect.top-m_nCurBitmapOffset,m_rcHotRect.right,m_rcHotRect.bottom-m_nCurBitmapOffset);
  109. hotBgDC.BitBlt(0,0,m_rcHotRect.Width(),m_rcHotRect.Height(),&memDC,rcHotRect.left,rcHotRect.top,SRCCOPY);
  110. }
  111. // draw normal bitmap
  112. if(m_nBitmapHeight <= m_rcClient.bottom)
  113. {
  114. CRect rect = m_rcClient;
  115. rect.bottom = m_nBitmapHeight;
  116. DrawTransparentBitmap(&m_bmpNormal,&memDC,m_crInternalTransparentColor,rect,rect);
  117. } else
  118. {
  119. DrawTransparentBitmap(&m_bmpNormal,&memDC,m_crInternalTransparentColor,CRect(0,0,m_rcClient.right,min(m_nBitmapHeight-m_nCurBitmapOffset,m_rcClient.bottom)),CRect(0,m_nCurBitmapOffset,0,0/*the two last values are not taken into account by DrawTransparentBitmap anyway*/));
  120. if(m_nBitmapHeight-m_nCurBitmapOffset < m_rcClient.bottom)
  121. DrawTransparentBitmap(&m_bmpNormal,&memDC,m_crInternalTransparentColor,CRect(0,m_nBitmapHeight-m_nCurBitmapOffset,m_rcClient.right,m_rcClient.bottom),CRect(0,0,0,0/*the two last values are not taken into account by DrawTransparentBitmap anyway*/));
  122. }
  123. // draw hot rect onto generic background
  124. if(m_rcHotRect != CRect(0,0,0,0))
  125. {
  126. memDC.BitBlt(rcHotRect.left,rcHotRect.top,rcHotRect.Width(),rcHotRect.Height(),&hotBgDC,0,0,SRCCOPY);
  127. DrawTransparentBitmap(&m_bmpHot,&memDC,m_crInternalTransparentColor,rcHotRect,m_rcHotRect);
  128. hotBgDC.SelectObject(pOldHBgBmp);
  129. }
  130. // copy memory DC to screen
  131. dc.BitBlt(0,0,m_rcClient.Width(),m_rcClient.Height(),&memDC,0,0,SRCCOPY);
  132. memDC.RestoreDC(nMemDCSave);
  133. if(bFirstDraw)
  134. bFirstDraw = FALSE;
  135. }
  136. CString CCreditsCtrl::SetDataString(LPCTSTR lpszNewString)
  137. {
  138. CString sOldString = m_sData;
  139. m_sData = lpszNewString;
  140. if(IsWindow(m_hWnd))
  141. Initialize();
  142. return sOldString;
  143. }
  144. CString CCreditsCtrl::SetDataString(UINT nStringResourceID)
  145. {
  146. CString sOldString = m_sData;
  147. m_sData.LoadString(nStringResourceID);
  148. if(IsWindow(m_hWnd))
  149. Initialize();
  150. return sOldString;
  151. }
  152. CString CCreditsCtrl::FormatDataString(LPCTSTR lpszFormat, ...)
  153. {
  154. ASSERT(AfxIsValidString(lpszFormat));
  155. CString sOldString = m_sData; // store old string
  156. // let CString do the formatting
  157. va_list argList;
  158. va_start(argList, lpszFormat);
  159. m_sData.FormatV(lpszFormat, argList);
  160. va_end(argList);
  161. if(IsWindow(m_hWnd)) // Initialize bitmaps if we have already been Create()d
  162. Initialize();
  163. return sOldString;
  164. }
  165. CString CCreditsCtrl::FormatDataString(UINT nFormatID, ...)
  166. {
  167. CString strFormat;
  168. VERIFY(strFormat.LoadString(nFormatID) != 0); // load resource string
  169. CString sOldString = m_sData; // store old string
  170. // let CString do the formatting
  171. va_list argList;
  172. va_start(argList, nFormatID);
  173. m_sData.FormatV(strFormat, argList);
  174. va_end(argList);
  175. if(IsWindow(m_hWnd)) // Initialize bitmaps if we have already been Create()d
  176. Initialize();
  177. return sOldString;
  178. }
  179. CString CCreditsCtrl::GetDataString()
  180. {
  181. return m_sData;
  182. }
  183. void CCreditsCtrl::SetDefaultLinkCursor()
  184. {
  185. // following code is taken from Chris Maunders hyperlink control (http://www.codeproject.com) - tnx
  186. if (m_hLinkCursor == NULL) // No cursor handle - load our own
  187. {
  188.         // Get the windows directory
  189. CString strWndDir;
  190. GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH), MAX_PATH);
  191. strWndDir.ReleaseBuffer();
  192. strWndDir += _T("\winhlp32.exe");
  193. // This retrieves cursor #106 from winhlp32.exe, which is a hand pointer
  194. HMODULE hModule = LoadLibrary(strWndDir);
  195. if (hModule) {
  196. HCURSOR hHandCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106));
  197. if (hHandCursor)
  198. m_hLinkCursor = CopyCursor(hHandCursor);
  199. }
  200. FreeLibrary(hModule);
  201. }
  202. }
  203. void CCreditsCtrl::OnTimer(UINT nIDEvent) 
  204. {
  205. if(nIDEvent == CCREDITCTRL_TIMER1)
  206. {
  207. if(IsWindowVisible())
  208. {
  209. // increment bitmap offset
  210. if(++m_nCurBitmapOffset > m_nBitmapHeight)
  211. m_nCurBitmapOffset = 1;
  212. // update cursor
  213. CPoint point,pt;
  214. GetCursorPos(&point);
  215. pt = point;
  216. ScreenToClient(&point);
  217. if(m_rcClient.PtInRect(point) && WindowFromPoint(pt)==this)
  218. {
  219. CRect rect;
  220. int n;
  221. if((n = HitTest(point)) != -1)
  222. {
  223. rect = m_HotRects[n];
  224. SetCursor(m_hLinkCursor);
  225. }
  226. else
  227. {
  228. rect = CRect(0,0,0,0);
  229. SetCursor(m_hDefaultCursor);
  230. }
  231. if(rect != m_rcHotRect)
  232. m_rcHotRect = rect;
  233. }
  234. // update window
  235. Invalidate(FALSE);
  236. UpdateWindow();
  237. // set timer
  238. SetTimer(CCREDITCTRL_TIMER1,m_nTimerSpeed,NULL);
  239. }
  240. } else
  241. CWnd::OnTimer(nIDEvent);
  242. }
  243. void CCreditsCtrl::OnSize(UINT nType, int cx, int cy) 
  244. {
  245. CWnd::OnSize(nType, cx, cy);
  246. if(IsWindow(m_hWnd))
  247. GetClientRect(m_rcClient);
  248. Initialize();
  249. }
  250. void CCreditsCtrl::TransparentBlt(CDC *pSrcDC, CDC* pDestDC,COLORREF crTrans,const CRect& rcDest,const CRect& rcSrc)
  251. {
  252. int SaveDestDC = pDestDC->SaveDC();
  253. int SaveSrcDC = pSrcDC->SaveDC();
  254. #ifdef CCREDITCTRL_USE_TRANSPARENT_BITBLT // use transparent BitBlts if supported?
  255. // Only attempt this if device supports functionality. ( untested!! )
  256. if(pDestDC->GetDeviceCaps(CAPS1) & C1_TRANSPARENT)
  257. {
  258. // Special transparency background mode
  259. pDestDC->SetBkMode(NEWTRANSPARENT);
  260. pDestDC->SetBkColor(crTrans);
  261. // Actual blt is a simple source copy; transparency is automatic.
  262. pDestDC->BitBlt(rcDest.left, rcDest.top, rcDest.Width(), rcDest.Height(), pSrcDC, rcSrc.left, rcSrc.top, SRCCOPY);
  263. } else // if driver doesn't support transparent BitBlts, do it the hard way
  264. {
  265. #endif
  266. // initialize memory DC and monochrome mask DC
  267. CDC tmpDC, maskDC;
  268. CBitmap bmpTmp, bmpMask;
  269. int SaveTmpDC, SaveMaskDC;
  270. tmpDC.CreateCompatibleDC(pDestDC);
  271. maskDC.CreateCompatibleDC(pDestDC);
  272. SaveTmpDC = tmpDC.SaveDC();
  273. SaveMaskDC = maskDC.SaveDC();
  274. bmpTmp.CreateCompatibleBitmap(pDestDC,rcDest.Width(),rcDest.Height());
  275. bmpMask.CreateBitmap(rcDest.Width(),rcDest.Height(),1,1,NULL);
  276. tmpDC.SelectObject(&bmpTmp);
  277. maskDC.SelectObject(&bmpMask);
  278. // copy existing data from destination dc to memory dc
  279. tmpDC.BitBlt(0,0,rcDest.Width(),rcDest.Height(),pDestDC,rcDest.left,rcDest.top,SRCCOPY);
  280. // create mask
  281. pSrcDC->SetBkColor(crTrans);
  282. maskDC.BitBlt(0,0,rcDest.Width(),rcDest.Height(),pSrcDC,rcSrc.left,rcSrc.top,SRCCOPY);
  283. // do some BitBlt magic
  284. tmpDC.SetBkColor(RGB(255,255,255));
  285. tmpDC.SetTextColor(RGB(0,0,0));
  286. tmpDC.BitBlt(0,0,rcDest.Width(),rcDest.Height(),pSrcDC,rcSrc.left,rcSrc.top,SRCINVERT);
  287. tmpDC.BitBlt(0,0,rcDest.Width(),rcDest.Height(),&maskDC,0,0,SRCAND);
  288. tmpDC.BitBlt(0,0,rcDest.Width(),rcDest.Height(),pSrcDC,rcSrc.left,rcSrc.top,SRCINVERT);
  289. // copy what we have in our memory DC to the destination DC
  290. pDestDC->BitBlt(rcDest.left,rcDest.top,rcDest.Width(),rcDest.Height(),&tmpDC,0,0,SRCCOPY);
  291. // clean up
  292. tmpDC.RestoreDC(SaveTmpDC);
  293. maskDC.RestoreDC(SaveMaskDC);
  294. #ifdef CCREDITCTRL_USE_TRANSPARENT_BITBLT
  295. }
  296. #endif
  297. pDestDC->RestoreDC(SaveDestDC);
  298. pSrcDC->RestoreDC(SaveSrcDC);
  299. }
  300. void CCreditsCtrl::DrawTransparentBitmap(CBitmap *pBitmap, CDC* pDC,COLORREF crTrans,const CRect& rcDest,const CRect& rcSrc)
  301. {
  302. int SaveImageDC;
  303. // initialize image DC
  304. CDC imageDC;
  305. imageDC.CreateCompatibleDC(pDC);
  306. SaveImageDC = imageDC.SaveDC();
  307. imageDC.SelectObject(pBitmap);
  308. TransparentBlt(&imageDC,pDC,crTrans,rcDest,rcSrc);
  309. // clean up
  310. imageDC.RestoreDC(SaveImageDC);
  311. }
  312. void CCreditsCtrl::Initialize()
  313. {
  314. //// [Initialize] ///////////////////////////////////////
  315. //                                                     //
  316. //  Create bitmaps and calc hot regions from m_sData   //
  317. //                                                     //
  318. /////////////////////////////////////////////////////////
  319. int nMaxHeight = 5000;
  320. // initialize normal and hot DCs
  321. CDC *pDC = GetDC();
  322. CDC normalDC, hotDC;
  323. normalDC.CreateCompatibleDC(pDC);
  324. hotDC.CreateCompatibleDC(pDC);
  325. int nSaveDCNormal = normalDC.SaveDC();
  326. int nSaveDCHot = hotDC.SaveDC();
  327. // initialize bitmaps
  328. if(m_bmpNormal.m_hObject)
  329. m_bmpNormal.DeleteObject();
  330. m_bmpNormal.CreateCompatibleBitmap(pDC,m_rcClient.Width(),nMaxHeight);
  331. if(m_bmpHot.m_hObject)
  332. m_bmpHot.DeleteObject();
  333. m_bmpHot.CreateCompatibleBitmap(pDC,m_rcClient.Width(),nMaxHeight);
  334. // select bitmaps into DCs
  335. normalDC.SelectObject(&m_bmpNormal);
  336. hotDC.SelectObject(&m_bmpHot);
  337. // fill with transparent color
  338. normalDC.FillSolidRect(0,0,m_rcClient.right,nMaxHeight,m_crInternalTransparentColor);
  339. hotDC.FillSolidRect(0,0,m_rcClient.right,nMaxHeight,m_crInternalTransparentColor);
  340. CString sData = m_sData;
  341. // substitute line break tags with newline characters
  342. // sData.Remove('n');
  343. // sData.Replace("<br>","n");
  344. // sData.Replace("<p>","nn");
  345. // make sure we get the last line displayed
  346. sData += 'n';
  347. // variables used for parsing
  348. CList<font_attribs,font_attribs&> font_attribs_tree;
  349. font_attribs fa;
  350. fa.bBold = FALSE;
  351. fa.bItalic = FALSE;
  352. fa.bUnderline = FALSE;
  353. fa.bStrikeout = FALSE;
  354. fa.crBkColor = CLR_NONE;
  355. fa.crColor = RGB(0,0,0);
  356. fa.nSize = 12;
  357. strcpy(fa.szName,"Arial");
  358. font_attribs_tree.AddTail(fa); // default font
  359. CList<general_attribs,general_attribs&> general_attribs_tree;
  360. general_attribs ga;
  361. ga.nAlign = 1;
  362. ga.nVAlign = 1;
  363. ga.nMaxWidth = m_rcClient.Width();
  364. ga.nMaxHeight = nMaxHeight;
  365. general_attribs_tree.AddTail(ga); // default alignment
  366. font_attribs link;
  367. BOOL bInsideTag = FALSE;
  368. CString sCurTagName;
  369. CString sCurElement;
  370. CString sCurOption;
  371. int nCurHPos = 0;
  372. int nCurVPos = 0;
  373. int nCurLineHeight = 0;
  374. CArray<line_rect,line_rect&> arcLineRects; // list containg information about the elements in the current line. used for vertical alignment of these element at line break.
  375. BOOL bIsLineEmpty = TRUE;
  376. BOOL bIsOption = FALSE;
  377. TCHAR cTmp;
  378. COLORREF crHrColor;
  379. int nHrWidth;
  380. int nHrSize;
  381. int nHrAlign;
  382. CString sCurLink;
  383. COLORREF crBitmap;
  384. int nBitmapBorder;
  385. CString sBitmap;
  386. CDC lineDC;
  387. lineDC.CreateCompatibleDC(&normalDC);
  388. CBitmap lineBmp;
  389. lineBmp.CreateCompatibleBitmap(&normalDC,ga.nMaxWidth,ga.nMaxHeight);
  390. CBitmap *pOldBmp = lineDC.SelectObject(&lineBmp);
  391. CDC hover_lineDC;
  392. hover_lineDC.CreateCompatibleDC(&hotDC);
  393. CBitmap hover_lineBmp;
  394. hover_lineBmp.CreateCompatibleBitmap(&hotDC,ga.nMaxWidth,ga.nMaxHeight);
  395. CBitmap *pOldHoverBmp = hover_lineDC.SelectObject(&hover_lineBmp);
  396. // main parsing loop... processing character by character
  397. //  (don't even _try_ to understand what's going on here :)
  398. for(int i = 0; i < sData.GetLength() && i >= 0; i++)
  399. {
  400. if(!bInsideTag)
  401. {
  402. if(sData[i] == '<')
  403. {
  404. if(sCurElement != "")
  405. {
  406. Parse_AppendText(&lineDC,&hover_lineDC,&nCurHPos,&nCurVPos,&nCurLineHeight,&arcLineRects,&general_attribs_tree.GetTail(),&font_attribs_tree.GetTail(),sCurElement, sCurLink, link);
  407. bIsLineEmpty = FALSE;
  408. }
  409. sCurTagName = "";
  410. sCurElement = "";
  411. bInsideTag = TRUE;
  412. continue;
  413. }
  414. if(sData[i] == 'n') // line break
  415. {
  416. if(bIsLineEmpty) // if line is empty add the height of a space with the current font
  417. {
  418. fa = font_attribs_tree.GetTail();
  419. CFont font;
  420. font.CreateFont(-fa.nSize,0,0,0,fa.bBold?FW_BOLD:0,fa.bItalic,fa.bUnderline,fa.bStrikeout,0,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,PROOF_QUALITY,DEFAULT_PITCH|FF_DONTCARE,&fa.szName[0]);
  421. CFont *pOldFont = lineDC.SelectObject(&font);
  422. CRect rect(0,0,ga.nMaxWidth,ga.nMaxHeight);
  423. lineDC.DrawText(" ",rect,DT_CALCRECT);
  424. lineDC.SelectObject(pOldFont);
  425. nCurVPos += rect.Height();
  426. } else
  427. {
  428. if(sCurElement != "")
  429. Parse_AppendText(&lineDC,&hover_lineDC,&nCurHPos,&nCurVPos,&nCurLineHeight,&arcLineRects,&general_attribs_tree.GetTail(),&font_attribs_tree.GetTail(),sCurElement,sCurLink,link);
  430. Parse_VAlignLine(&normalDC,&hotDC,&lineDC,&hover_lineDC,nCurHPos,nCurVPos,nCurLineHeight,&arcLineRects,&general_attribs_tree.GetTail());
  431. nCurVPos += nCurLineHeight;
  432. bIsLineEmpty = TRUE;
  433. }
  434. arcLineRects.RemoveAll();
  435. nCurLineHeight = 0;
  436. nCurHPos = 0;
  437. sCurElement = "";
  438. continue;
  439. }
  440. sCurElement += sData[i];
  441. bIsLineEmpty = FALSE;
  442. } else
  443. {
  444. if(sData[i] == '>')
  445. {
  446. if(sCurTagName == "font") // <font face="s" size="n" style="[-b|b][-i|i][-u|u][-s|s]" color="n,n,n" background="n,n,n">
  447. {
  448. font_attribs_tree.AddTail(fa);
  449. general_attribs_tree.AddTail(ga);
  450. } else if(sCurTagName == "" && sCurElement == "/font") // closing font tag.. revove the last attributes from the lists
  451. {
  452. if(font_attribs_tree.GetCount() > 1)
  453. font_attribs_tree.RemoveTail();
  454. if(general_attribs_tree.GetCount() > 1)
  455. general_attribs_tree.RemoveTail();
  456. } else if(sCurTagName == "" && sCurElement == "hr") // no parameters specified for the hr tag.. use the defaults
  457. {
  458. crHrColor = GetSysColor(COLOR_BTNSHADOW); // default color
  459. nHrWidth = ga.nMaxWidth-100; // default width
  460. nHrSize = 2; // default height
  461. nHrAlign = 1; // center by default
  462. sCurTagName = "hr";
  463. }
  464. if(sCurTagName == "hr") // wrap line is needed and draw rect
  465. {
  466. if(!bIsLineEmpty)
  467. {
  468. Parse_VAlignLine(&normalDC,&hotDC,&lineDC,&hover_lineDC,nCurHPos,nCurVPos,nCurLineHeight,&arcLineRects,&general_attribs_tree.GetTail());
  469. nCurVPos += nCurLineHeight;
  470. bIsLineEmpty = TRUE;
  471. }
  472. arcLineRects.RemoveAll();
  473. nCurLineHeight = 0;
  474. nCurHPos = 0;
  475. CRect rect;
  476. rect.left = nHrAlign == 0 ? 0 : (nHrAlign == 2 ? ga.nMaxWidth-nHrWidth : ga.nMaxWidth/2-nHrWidth/2);
  477. rect.right = rect.left + nHrWidth;
  478. rect.top = nCurVPos + 2;
  479. rect.bottom = rect.top + nHrSize;
  480. normalDC.FillSolidRect(rect,crHrColor);
  481. nCurVPos += 4+nHrSize;
  482. } else if(sCurTagName == "" && sCurElement== "/a" && sCurLink != "") // if we have an ending link tag AND valid link action and link region...
  483. sCurLink = "";
  484. else if(sCurTagName == "img" && sBitmap != "")
  485. {
  486. if(sBitmap[0]=='#') // only resource bitmaps allowed at this time
  487. {
  488. CBitmap bmp;
  489. bmp.LoadBitmap(atoi(sBitmap.Mid(1)));
  490. Parse_AppendBitmap(&lineDC,&hover_lineDC,&nCurHPos,&nCurVPos,&nCurLineHeight,&arcLineRects,&general_attribs_tree.GetTail(),&bmp, crBitmap, nBitmapBorder, sCurLink, link);
  491. bIsLineEmpty = FALSE;
  492. }
  493. crBitmap = CLR_NONE;
  494. nBitmapBorder = 0;
  495. sBitmap = "";
  496. } else if(sCurTagName == "br" || (sCurTagName == "" && sCurElement== "br")) // just substitute with newline character
  497. {
  498. sData.SetAt(i,'n');
  499. i--;
  500. } else if(sCurTagName == "p" || (sCurTagName == "" && sCurElement== "p")) // just substitute with 2 newline characters
  501. {
  502. sData.SetAt(i,'n');
  503. sData.SetAt(i-1,'n');
  504. i-= 2;
  505. }
  506. sCurElement = "";
  507. bInsideTag = FALSE;
  508. continue;
  509. }
  510. if(sData[i] == ' ' && !bIsOption)
  511. {
  512. if(sCurElement != "")
  513. {
  514. if(sCurTagName == "")
  515. {
  516. sCurTagName = sCurElement;
  517. sCurTagName.MakeLower();
  518. if(sCurTagName == "font") // store latest font attributes. these are the ones that are modified by the font tags parameters
  519. {
  520. fa = font_attribs_tree.GetTail();
  521. ga = general_attribs_tree.GetTail();
  522. } else if(sCurTagName == "hr") // set default hr options...
  523. {
  524. crHrColor = GetSysColor(COLOR_BTNSHADOW);
  525. nHrWidth = ga.nMaxWidth-10;
  526. nHrSize = 2;
  527. nHrAlign = 1;
  528. } else if(sCurTagName == "a") // init link hot attributes
  529. {
  530. link = font_attribs_tree.GetTail();
  531. link.crColor = 0xeeffffff;
  532. link.crBkColor = 0xeeffffff;
  533. link.bBold = -10;
  534. link.bItalic = -10;
  535. link.bUnderline = -10;
  536. link.bStrikeout = -10;
  537. link.nSize = 0;
  538. link.szName[0] = '';
  539. } else if(sCurTagName == "img")
  540. {
  541. nBitmapBorder = 2;
  542. crBitmap = CLR_NONE;
  543. sBitmap = "";
  544. }
  545. } else
  546. {
  547. sCurOption = sCurTagName;
  548. sCurOption.MakeLower();
  549. }
  550. }
  551. sCurElement = "";
  552. continue;
  553. }
  554. if(sData[i] == '"' || sData[i] == ''') // this happens when we have a new parameter value to parse
  555. {
  556. if(bIsOption && sData[i]==cTmp) // "sData[i]==cTmp" : closing (double)quote has to match opening quote
  557. {
  558. if(sCurTagName == "font") // parse font tag paramaters
  559. {
  560. if(sCurOption == "size") // font size
  561. {
  562. int nSize = atoi(sCurElement);
  563. if(nSize > 0 && nSize < 2000) // let's be reasonable
  564. fa.nSize = nSize;
  565. } else if(sCurOption == "face") // font face
  566. {
  567. strcpy(fa.szName,sCurElement.Left(MAX_PATH-1));
  568. } else if(sCurOption == "style") // font style (bold (b) ,italic (i) ,underline (u) ,strikeout (s) )
  569. {
  570. if(sCurElement.Find("-b")!=-1 || sCurElement.Find("-B")!=-1)
  571. fa.bBold = FALSE;
  572. else if(sCurElement.FindOneOf("bB")!=-1)
  573. fa.bBold = TRUE;
  574. if(sCurElement.Find("-i")!=-1 || sCurElement.Find("-I")!=-1)
  575. fa.bItalic = FALSE;
  576. else if(sCurElement.FindOneOf("iI")!=-1)
  577. fa.bItalic = TRUE;
  578. if(sCurElement.Find("-u")!=-1 || sCurElement.Find("-U")!=-1)
  579. fa.bUnderline = FALSE;
  580. else if(sCurElement.FindOneOf("uU")!=-1)
  581. fa.bUnderline = TRUE;
  582. if(sCurElement.Find("-s")!=-1 || sCurElement.Find("-S")!=-1)
  583. fa.bStrikeout = FALSE;
  584. else if(sCurElement.FindOneOf("sS")!=-1)
  585. fa.bStrikeout = TRUE;
  586. } else if(sCurOption == "color") // font color
  587. StringToColor(sCurElement,fa.crColor);
  588. else if(sCurOption == "background") // font background-color
  589. StringToColor(sCurElement,fa.crBkColor);
  590. else if(sCurOption == "align") // horisontal font alignment. here we change the "general_attribs"
  591. { // only the latest open font tag with this parameter takes effect at a line break!!
  592. sCurElement.MakeLower();
  593. if(sCurElement == "left")
  594. ga.nAlign = 0;
  595. else if(sCurElement == "center")
  596. ga.nAlign = 1;
  597. else if(sCurElement == "right")
  598. ga.nAlign = 2;
  599. } else if(sCurOption == "valign") // vertical font alignment. here we change the "general_attribs"
  600. {
  601. sCurElement.MakeLower();
  602. if(sCurElement == "top")
  603. ga.nVAlign = 0;
  604. else if(sCurElement == "middle")
  605. ga.nVAlign = 1;
  606. else if(sCurElement == "bottom")
  607. ga.nVAlign = 2;
  608. }
  609. } else if(sCurTagName == "a")
  610. {
  611. if(sCurOption == "href") // what to do
  612. sCurLink = sCurElement;
  613. else if(sCurOption == "size") // font size
  614. {
  615. int nSize = atoi(sCurElement);
  616. if(nSize > 0 && nSize < 2000) // let's be reasonable
  617. link.nSize = nSize;
  618. } else if(sCurOption == "face") // font face
  619. {
  620. strcpy(link.szName,sCurElement.Left(MAX_PATH-1));
  621. } else if(sCurOption == "style") // font style (bold (b) ,italic (i) ,underline (u) ,strikeout (s) )
  622. {
  623. if(sCurElement.Find("-b")!=-1 || sCurElement.Find("-B")!=-1)
  624. link.bBold = FALSE;
  625. else if(sCurElement.FindOneOf("bB")!=-1)
  626. link.bBold = TRUE;
  627. if(sCurElement.Find("-i")!=-1 || sCurElement.Find("-I")!=-1)
  628. link.bItalic = FALSE;
  629. else if(sCurElement.FindOneOf("iI")!=-1)
  630. link.bItalic = TRUE;
  631. if(sCurElement.Find("-u")!=-1 || sCurElement.Find("-U")!=-1)
  632. link.bUnderline = FALSE;
  633. else if(sCurElement.FindOneOf("uU")!=-1)
  634. link.bUnderline = TRUE;
  635. if(sCurElement.Find("-s")!=-1 || sCurElement.Find("-S")!=-1)
  636. link.bStrikeout = FALSE;
  637. else if(sCurElement.FindOneOf("sS")!=-1)
  638. link.bStrikeout = TRUE;
  639. } else if(sCurOption == "color") // font color
  640. StringToColor(sCurElement,link.crColor);
  641. else if(sCurOption == "background") // font background-color
  642. StringToColor(sCurElement,link.crBkColor);
  643. } else if(sCurTagName == "img") // image tag: <img src="#resourceID">
  644. {
  645. // TODO: alow usage of filenames in <img> tag
  646. if(sCurOption == "src" && sCurElement != "")
  647. sBitmap = sCurElement;
  648. if(sCurOption == "color")
  649. StringToColor(sCurElement,crBitmap);
  650. if(sCurOption == "border" && sCurElement != "")
  651. nBitmapBorder = atoi(sCurElement);
  652. } else if(sCurTagName == "hr") // horisontal ruler
  653. {
  654. if(sCurElement != "")
  655. {
  656. if(sCurOption == "color") // color
  657. StringToColor(sCurElement,crHrColor);
  658. else if(sCurOption == "width") // width
  659. nHrWidth = atoi(sCurElement);
  660. else if(sCurOption == "size") // height
  661. nHrSize = atoi(sCurElement);
  662. else if(sCurOption == "align") // horz alignment
  663. {
  664. sCurElement.MakeLower();
  665. if(sCurElement=="left")
  666. nHrAlign = 0;
  667. else if(sCurElement=="right")
  668. nHrAlign = 2;
  669. else
  670. nHrAlign = 1;
  671. }
  672. }
  673. } else if((sCurTagName == "vspace") && (sCurOption == "size")) // vertical space
  674. {
  675. if(!bIsLineEmpty) // insert linebreak only is line isn't empty
  676. {
  677. Parse_VAlignLine(&normalDC,&hotDC,&lineDC,&hover_lineDC,nCurHPos,nCurVPos,nCurLineHeight,&arcLineRects,&general_attribs_tree.GetTail());
  678. nCurVPos += nCurLineHeight;
  679. bIsLineEmpty = TRUE;
  680. }
  681. arcLineRects.RemoveAll();
  682. nCurLineHeight = 0;
  683. nCurHPos = 0;
  684. nCurVPos += atoi(sCurElement); // add "size" parameters value to vertical offset
  685. } else if((sCurTagName == "hspace") && (sCurOption == "size")) // horisontal space
  686. nCurHPos += atoi(sCurElement); // add "size" parameters value to horisontal offset
  687. sCurElement = "";
  688. bIsOption = FALSE;
  689. } else if(sData[i-1] == '=') // parameter is beginning
  690. {
  691. sCurOption = sCurElement;
  692. sCurOption = sCurOption.Left(sCurOption.GetLength()-1); // remove trailing "=";
  693. sCurOption.MakeLower();
  694. sCurOption.TrimRight();
  695. sCurElement = "";
  696. cTmp = sData[i];
  697. bIsOption = TRUE;
  698. }
  699. continue;
  700. }
  701. sCurElement += sData[i]; // append non-formatting-significant character to curent element
  702. }
  703. }
  704. lineDC.SelectObject(pOldBmp);
  705. hover_lineDC.SelectObject(pOldHoverBmp);
  706. //... finished parsing
  707. m_nBitmapHeight = nCurVPos;
  708. // clean up
  709. normalDC.RestoreDC(nSaveDCNormal);
  710. hotDC.RestoreDC(nSaveDCHot);
  711. }
  712. void CCreditsCtrl::DrawBackground(CDC *pDC, RECT rect, BOOL bAnimate, DWORD lParam)
  713. {
  714. pDC->FillSolidRect(&rect,(COLORREF)lParam);
  715. }
  716. void CCreditsCtrl::SetDefaultBkColor(COLORREF crColor)
  717. {
  718. m_dwBackgroundPaintLParam = (DWORD)crColor; // default background color
  719. }
  720. void CCreditsCtrl::Parse_AppendText(CDC *pDC, CDC *pHoverDC, int *pnCurHPos, int *pnCurVPos, int *pnCurHeight, CArray<line_rect,line_rect&>* parcLineRects, general_attribs *pga, font_attribs *pfa, CString sText, CString sCurLink, font_attribs link)
  721. {
  722. CRect rect(0,0,pga->nMaxWidth,pga->nMaxHeight);
  723. CDC dc,hoverDC;
  724. CBitmap hoverBmp,bmp,*pOldHBmp;
  725. dc.CreateCompatibleDC(pDC);
  726. CFont font,hover_font,*pOldHFont;
  727. font.CreateFont(-pfa->nSize,0,0,0,pfa->bBold?FW_BOLD:0,pfa->bItalic,pfa->bUnderline,pfa->bStrikeout,0,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,PROOF_QUALITY,DEFAULT_PITCH|FF_DONTCARE,pfa->szName);
  728. CFont *pOldFont = dc.SelectObject(&font);
  729. dc.SetTextColor(pfa->crColor == CLR_NONE ? m_crInternalTransparentColor : pfa->crColor);
  730. dc.SetBkColor(pfa->crBkColor == CLR_NONE ? m_crInternalTransparentColor : pfa->crBkColor);
  731. dc.SetBkMode(OPAQUE);
  732. dc.DrawText(sText,rect,DT_CALCRECT|DT_SINGLELINE);
  733. if(sCurLink != "")
  734. {
  735. if(link.bBold == -10) link.bBold = pfa->bBold;
  736. if(link.bItalic == -10) link.bItalic = pfa->bItalic;
  737. if(link.bUnderline == -10) link.bUnderline = pfa->bUnderline;
  738. if(link.bStrikeout == -10) link.bStrikeout = pfa->bStrikeout;
  739. if(link.crColor == 0xeeffffff) link.crColor = pfa->crColor;
  740. if(link.crBkColor == 0xeeffffff) link.crBkColor = pfa->crBkColor;
  741. if(link.nSize == 0) link.nSize = pfa->nSize;
  742. if(link.szName[0] == '') strcpy(link.szName,pfa->szName);
  743. CRect rect2(0,0,pga->nMaxWidth,pga->nMaxHeight);
  744. hoverDC.CreateCompatibleDC(pDC);
  745. hover_font.CreateFont(-link.nSize,0,0,0,link.bBold?FW_BOLD:0,link.bItalic,link.bUnderline,link.bStrikeout,0,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,PROOF_QUALITY,DEFAULT_PITCH|FF_DONTCARE,link.szName);
  746. pOldHFont = hoverDC.SelectObject(&hover_font);
  747. hoverDC.DrawText(sText,rect2,DT_CALCRECT|DT_SINGLELINE);
  748. if(rect.Width() < rect2.Width())
  749. rect = rect2;
  750. hoverBmp.CreateCompatibleBitmap(pDC,rect.right,rect.bottom);
  751. pOldHBmp = hoverDC.SelectObject(&hoverBmp);
  752. hoverDC.FillSolidRect(rect,m_crInternalTransparentColor);
  753. hoverDC.SetTextColor(link.crColor == CLR_NONE ? m_crInternalTransparentColor : link.crColor);
  754. hoverDC.SetBkColor(link.crBkColor == CLR_NONE ? m_crInternalTransparentColor : link.crBkColor);
  755. hoverDC.SetBkMode(OPAQUE);
  756. hoverDC.DrawText(sText,rect,DT_SINGLELINE);
  757. }
  758. bmp.CreateCompatibleBitmap(pDC,rect.right,rect.bottom);
  759. CBitmap *pOldBmp = dc.SelectObject(&bmp);
  760. dc.FillSolidRect(rect,m_crInternalTransparentColor);
  761. dc.SetBkColor(pfa->crBkColor == CLR_NONE ? m_crInternalTransparentColor : pfa->crBkColor);
  762. dc.DrawText(sText,rect,DT_SINGLELINE);
  763. if(sCurLink != "")
  764. {
  765. Parse_AppendElement(pDC,pHoverDC,pnCurHPos,pnCurVPos,pnCurHeight,parcLineRects,pga,rect.Width(),rect.Height(),&dc,&hoverDC,sCurLink);
  766. hoverDC.SelectObject(pOldHBmp);
  767. hoverDC.SelectObject(pOldHFont);
  768. }
  769. else
  770. Parse_AppendElement(pDC,pHoverDC,pnCurHPos,pnCurVPos,pnCurHeight,parcLineRects,pga,rect.Width(),rect.Height(),&dc,&dc,sCurLink);
  771. // clean up
  772. dc.SelectObject(pOldBmp);
  773. dc.SelectObject(pOldFont);
  774. }
  775. void CCreditsCtrl::Parse_AppendBitmap(CDC *pDC, CDC *pHoverDC, int *pnCurHPos, int *pnCurVPos, int *pnCurHeight, CArray<line_rect,line_rect&>* parcLineRects, general_attribs *pga, CBitmap *pBitmap, COLORREF crBorder, int nBorder, CString sCurLink, font_attribs link)
  776. {
  777. BITMAP bm;
  778. pBitmap->GetBitmap(&bm);
  779. CDC bmpDC;
  780. bmpDC.CreateCompatibleDC(pDC);
  781. CBitmap *pOldBmp1 = bmpDC.SelectObject(pBitmap);
  782. CDC dc;
  783. dc.CreateCompatibleDC(pDC);
  784. CBitmap bmp;
  785. bmp.CreateCompatibleBitmap(pDC,bm.bmWidth+nBorder*2,bm.bmHeight+nBorder*2);
  786. CBitmap *pOldBmp2 = dc.SelectObject(&bmp);
  787. dc.FillSolidRect(0,0,bm.bmWidth+nBorder*2,bm.bmHeight+nBorder*2,crBorder==CLR_NONE?m_crInternalTransparentColor:crBorder);
  788. dc.BitBlt(nBorder,nBorder,bm.bmWidth,bm.bmHeight,&bmpDC,0,0,SRCCOPY);
  789. if(sCurLink == "")
  790. Parse_AppendElement(pDC,pHoverDC,pnCurHPos,pnCurVPos,pnCurHeight,parcLineRects,pga,bm.bmWidth+nBorder*2,bm.bmHeight+nBorder*2,&dc,&dc,sCurLink);
  791. else
  792. {
  793. CDC hoverDC;
  794. hoverDC.CreateCompatibleDC(pDC);
  795. CBitmap bmp;
  796. bmp.CreateCompatibleBitmap(pDC,bm.bmWidth+nBorder*2,bm.bmHeight+nBorder*2);
  797. CBitmap *pOldBmp = hoverDC.SelectObject(&bmp);
  798. hoverDC.FillSolidRect(0,0,bm.bmWidth+nBorder*2,bm.bmHeight+nBorder*2,link.crColor==CLR_NONE?m_crInternalTransparentColor:link.crColor==0xeeffffff?crBorder:link.crColor);
  799. hoverDC.BitBlt(nBorder,nBorder,bm.bmWidth,bm.bmHeight,&bmpDC,0,0,SRCCOPY);
  800. Parse_AppendElement(pDC,pHoverDC,pnCurHPos,pnCurVPos,pnCurHeight,parcLineRects,pga,bm.bmWidth+nBorder*2,bm.bmHeight+nBorder*2,&dc,&hoverDC,sCurLink);
  801. hoverDC.SelectObject(pOldBmp);
  802. }
  803. // clean up
  804. dc.SelectObject(pOldBmp2);
  805. bmpDC.SelectObject(pOldBmp1);
  806. }
  807. void CCreditsCtrl::Parse_AppendElement(CDC *pDC, CDC *pHoverDC, int *pnCurHPos, int *pnCurVPos, int *pnCurHeight, CArray<line_rect,line_rect&>* parcLineRects, general_attribs *pga, int nElementWidth, int nElementHeight, CDC *pElementDC, CDC *pHoverElementDC, CString sCurLink)
  808. {
  809. if(*pnCurHeight < nElementHeight)
  810. *pnCurHeight = nElementHeight;
  811. CRect rect;
  812. rect.left = *pnCurHPos;
  813. rect.top = 0;
  814. rect.right = rect.left+nElementWidth;
  815. rect.bottom = nElementHeight;
  816. line_rect lr;
  817. lr.rcRect = rect;
  818. lr.nVAlign = pga->nVAlign;
  819. lr.sLink = sCurLink;
  820. parcLineRects->Add(lr);
  821. pDC->BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),pElementDC,0,0,SRCCOPY);
  822. pHoverDC->BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),pHoverElementDC,0,0,SRCCOPY);
  823. *pnCurHPos += nElementWidth;
  824. }
  825. void CCreditsCtrl::Parse_VAlignLine(CDC *pDestDC, CDC *pHoverDestDC, CDC *pLineDC, CDC *pHoverLineDC, int nCurHPos, int nCurVPos, int nCurHeight, CArray<line_rect,line_rect&>* parcLineRects, general_attribs *pga)
  826. {
  827. {
  828. CArray<line_rect,line_rect&> LinkElements;
  829. CRect rect;
  830. CDC memDC;
  831. memDC.CreateCompatibleDC(pDestDC);
  832. CBitmap memBmp;
  833. memBmp.CreateCompatibleBitmap(pDestDC,nCurHPos,nCurHeight);
  834. CBitmap *pOldBmp = memDC.SelectObject(&memBmp);
  835. memDC.FillSolidRect(0,0,nCurHPos,nCurHeight,m_crInternalTransparentColor);
  836. for(int i = 0; i < parcLineRects->GetSize(); i++)
  837. {
  838. rect.left = (*parcLineRects)[i].rcRect.left;
  839. // calculate elements vertical position
  840. if((*parcLineRects)[i].nVAlign == 0) // top align
  841. rect.top = 0;
  842. else if((*parcLineRects)[i].nVAlign == 1) // middle align
  843. rect.top = nCurHeight/2-(*parcLineRects)[i].rcRect.bottom/2;
  844. else // bottom align
  845. rect.top = nCurHeight - (*parcLineRects)[i].rcRect.bottom;
  846. rect.bottom = rect.top + (*parcLineRects)[i].rcRect.bottom;
  847. // don't touch horz alignment
  848. rect.left = (*parcLineRects)[i].rcRect.left;
  849. rect.right = (*parcLineRects)[i].rcRect.right;
  850. // draw element
  851. memDC.BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),pLineDC,(*parcLineRects)[i].rcRect.left,(*parcLineRects)[i].rcRect.top,SRCCOPY);
  852. // add link to list(if necessary)
  853. if((*parcLineRects)[i].sLink != "")
  854. {
  855. line_rect lr;
  856. lr.sLink = (*parcLineRects)[i].sLink;
  857. lr.rcRect = rect;
  858. LinkElements.Add(lr);
  859. }
  860. }
  861. rect.top = nCurVPos;
  862. rect.bottom = rect.top + nCurHeight;
  863. if(pga->nAlign == 0) // left align
  864. rect.left = 0;
  865. else if(pga->nAlign == 1) // center align
  866. rect.left = pga->nMaxWidth/2 - nCurHPos/2;
  867. else // right align
  868. rect.left = pga->nMaxWidth - nCurHPos;
  869. rect.right = rect.left + nCurHPos;
  870. TransparentBlt(&memDC,pDestDC,m_crInternalTransparentColor,rect,CRect(0,0,rect.Width(),rect.Height()));
  871. memDC.SelectObject(pOldBmp);
  872. // calculate horisontal offset of links in list and add them to global list
  873. for(i = 0; i < LinkElements.GetSize(); i++)
  874. {
  875. CRect rc = LinkElements[i].rcRect;
  876. rc.OffsetRect(rect.left,nCurVPos);
  877. m_HotRects.Add(rc);
  878. m_HotRectActions.Add(LinkElements[i].sLink);
  879. }
  880. }
  881. // do the same, but this time for the hover CD
  882. {
  883. CRect rect;
  884. CDC memDC;
  885. memDC.CreateCompatibleDC(pHoverDestDC);
  886. CBitmap memBmp;
  887. memBmp.CreateCompatibleBitmap(pHoverDestDC,nCurHPos,nCurHeight);
  888. CBitmap *pOldBmp = memDC.SelectObject(&memBmp);
  889. memDC.FillSolidRect(0,0,nCurHPos,nCurHeight,m_crInternalTransparentColor);
  890. for(int i = 0; i < parcLineRects->GetSize(); i++)
  891. {
  892. rect.left = (*parcLineRects)[i].rcRect.left;
  893. // calculate elements vertical position
  894. if((*parcLineRects)[i].nVAlign == 0) // top align
  895. rect.top = 0;
  896. else if((*parcLineRects)[i].nVAlign == 1) // middle align
  897. rect.top = nCurHeight/2-(*parcLineRects)[i].rcRect.bottom/2;
  898. else // bottom align
  899. rect.top = nCurHeight - (*parcLineRects)[i].rcRect.bottom;
  900. rect.bottom = rect.top + (*parcLineRects)[i].rcRect.bottom;
  901. // don't touch horz alignment
  902. rect.left = (*parcLineRects)[i].rcRect.left;
  903. rect.right = (*parcLineRects)[i].rcRect.right;
  904. // draw element
  905. memDC.BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),pHoverLineDC,(*parcLineRects)[i].rcRect.left,(*parcLineRects)[i].rcRect.top,SRCCOPY);
  906. }
  907. rect.top = nCurVPos;
  908. rect.bottom = rect.top + nCurHeight;
  909. if(pga->nAlign == 0) // left align
  910. rect.left = 0;
  911. else if(pga->nAlign == 1) // center align
  912. rect.left = pga->nMaxWidth/2 - nCurHPos/2;
  913. else // right align
  914. rect.left = pga->nMaxWidth - nCurHPos;
  915. rect.right = rect.left + nCurHPos;
  916. TransparentBlt(&memDC,pHoverDestDC,m_crInternalTransparentColor,rect,CRect(0,0,rect.Width(),rect.Height()));
  917. memDC.SelectObject(pOldBmp);
  918. }
  919. }
  920. BOOL CCreditsCtrl::StringToColor(CString string, COLORREF &cr)
  921. {
  922. int i,r,g,b;
  923. if(string=="")
  924. return FALSE;
  925. else if((string=="none")||(string=="transparant"))
  926. cr = CLR_NONE;
  927. else if((i = string.Find(','))==-1)
  928. return FALSE;
  929. else
  930. {
  931. r = atoi(string.Left(i));
  932. string.Delete(0,i+1);
  933. if((i = string.Find(','))==-1)
  934. return FALSE;
  935. else
  936. {
  937. g = atoi(string.Left(i));
  938. string.Delete(0,i+1);
  939. b = atoi(string);
  940. cr = RGB(r,g,b);
  941. }
  942. }
  943. return TRUE;
  944. }
  945. void CCreditsCtrl::OnMouseMove(UINT nFlags, CPoint point) 
  946. {
  947. if(m_bIsScrolling)
  948. {
  949. m_nCurBitmapOffset = m_nScrollStart-point.y;
  950. m_nCurBitmapOffset %= m_nBitmapHeight;
  951. if(m_nCurBitmapOffset < 0)
  952. m_nCurBitmapOffset = m_nCurBitmapOffset+m_nBitmapHeight;
  953. Invalidate(FALSE);
  954. UpdateWindow();
  955. return;
  956. }
  957. if(GetCapture()==this)
  958. ReleaseCapture();
  959. else
  960. SetCapture();
  961. if(m_rcClient.PtInRect(point))
  962. {
  963. int n;
  964. CRect rect;
  965. if((n = HitTest(point)) != -1)
  966. {
  967. rect = m_HotRects[n];
  968. SetCursor(m_hLinkCursor);
  969. }
  970. else
  971. {
  972. rect = CRect(0,0,0,0);
  973. SetCursor(m_hDefaultCursor);
  974. }
  975. if(rect != m_rcHotRect)
  976. {
  977. m_rcHotRect = rect;
  978. // Invalidate(FALSE);
  979. // UpdateWindow();
  980. }
  981. }
  982. }
  983. void CCreditsCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
  984. {
  985. int n = HitTest(point);
  986. if(n != -1)
  987. {
  988. m_rcHotRect = CRect(0,0,0,0); // will be update next timer tick
  989. CString s = m_HotRectActions[n];
  990. if(s[0] == '#')
  991. {
  992. int i = s.Find('#',1);
  993. CString arg = i==-1?"":s.Mid(1,i-1);
  994. s = s.Mid(i==-1?1:i+1);
  995. void(*func)(LPCTSTR) = (void(*)(LPCTSTR))atol(s);
  996. if(func)
  997. (*func)(i==-1?NULL:(LPCTSTR)arg);
  998. } else
  999. ShellExecute(NULL,NULL,s,NULL,NULL,SW_SHOW);
  1000. } else if(m_bCanScroll && (m_nBitmapHeight > m_rcClient.bottom))
  1001. {
  1002. KillTimer(CCREDITCTRL_TIMER1);
  1003. m_bIsScrolling = TRUE;
  1004. m_nScrollStart = point.y + m_nCurBitmapOffset;
  1005. Invalidate();
  1006. UpdateWindow();
  1007. SetCapture();
  1008. }
  1009. }
  1010. void CCreditsCtrl::OnLButtonUp(UINT nFlags, CPoint point) 
  1011. {
  1012. if(m_bIsScrolling)
  1013. {
  1014. ReleaseCapture();
  1015. m_bIsScrolling = FALSE;
  1016. OnTimer(CCREDITCTRL_TIMER1);
  1017. }
  1018. }
  1019. int CCreditsCtrl::HitTest(CPoint pt)
  1020. {
  1021. if(m_nBitmapHeight <= m_rcClient.bottom)
  1022. {
  1023. for(int i = 0; i < m_HotRects.GetSize(); i++)
  1024. {
  1025. if(m_HotRects[i].PtInRect(pt))
  1026. return i;
  1027. }
  1028. return -1;
  1029. }
  1030. pt.y += m_nCurBitmapOffset;
  1031. CPoint pt0 = pt;
  1032. if(pt0.y > m_nBitmapHeight-m_nCurBitmapOffset)
  1033. pt0.y -= m_nBitmapHeight;
  1034. for(int i = 0; i < m_HotRects.GetSize(); i++)
  1035. {
  1036. if(m_HotRects[i].PtInRect(pt) || m_HotRects[i].PtInRect(pt0))
  1037. return i;
  1038. }
  1039. return -1;
  1040. }