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.

562 lines
12 KiB

  1. // File: Progressbar.cpp
  2. #include "precomp.h"
  3. #include "ProgressBar.h"
  4. #include "GenControls.h"
  5. #define SIGNAL_STATUS_TRANSMIT 0x01 // data is being received/sent
  6. #define SIGNAL_STATUS_JAMMED 0x02 // wave dev failed to open
  7. CProgressBar::CProgressBar()
  8. {
  9. for (int i=0; i<ARRAY_ELEMENTS(m_hbs); ++i)
  10. {
  11. m_hbs[i] = NULL;
  12. }
  13. }
  14. CProgressBar::~CProgressBar()
  15. {
  16. for (int i=0; i<ARRAY_ELEMENTS(m_hbs); ++i)
  17. {
  18. if (NULL != m_hbs[i])
  19. {
  20. DeleteObject(m_hbs[i]);
  21. m_hbs[i] = NULL;
  22. }
  23. }
  24. }
  25. BOOL CProgressBar::Create(
  26. HBITMAP hbFrame, // The outside (static) part of the progress bar
  27. HBITMAP hbBar, // The inside part of the progress bar that jumps around
  28. HWND hWndParent // The parent of the toolbar window
  29. )
  30. {
  31. ASSERT(NULL!=hbFrame && NULL!=hbBar);
  32. SetFrame(hbFrame);
  33. SetBar(hbBar);
  34. if (!CGenWindow::Create(hWndParent, 0, g_szEmpty, 0, 0))
  35. {
  36. return(FALSE);
  37. }
  38. return(TRUE);
  39. }
  40. void CProgressBar::GetDesiredSize(SIZE *ppt)
  41. {
  42. CGenWindow::GetDesiredSize(ppt);
  43. if (NULL == GetFrame())
  44. {
  45. return;
  46. }
  47. SIZE sizeBitmap;
  48. CBitmapButton::GetBitmapSizes(&m_hbs[Frame], &sizeBitmap, 1);
  49. ppt->cx += sizeBitmap.cx;
  50. ppt->cy += sizeBitmap.cy;
  51. }
  52. LRESULT CProgressBar::ProcessMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  53. {
  54. switch (message)
  55. {
  56. HANDLE_MSG(hwnd, WM_PAINT, OnPaint);
  57. }
  58. return(CGenWindow::ProcessMessage(hwnd, message, wParam, lParam));
  59. }
  60. void CProgressBar::OnPaint(HWND hwnd)
  61. {
  62. if (NULL == GetFrame() || NULL == GetBar() || 0 == GetMaxValue())
  63. {
  64. FORWARD_WM_PAINT(hwnd, CGenWindow::ProcessMessage);
  65. return;
  66. }
  67. PAINTSTRUCT ps;
  68. HDC hdc = BeginPaint(hwnd, &ps);
  69. HDC hdcTemp = CreateCompatibleDC(hdc);
  70. if (NULL != hdcTemp)
  71. {
  72. HPALETTE hPal = GetPalette();
  73. HPALETTE hOld = NULL;
  74. if (NULL != hPal)
  75. {
  76. hOld = SelectPalette(hdc, hPal, TRUE);
  77. RealizePalette(hdc);
  78. SelectPalette(hdcTemp, hPal, TRUE);
  79. RealizePalette(hdcTemp);
  80. }
  81. SIZE sizes[NumBitmaps];
  82. CBitmapButton::GetBitmapSizes(m_hbs, sizes, NumBitmaps);
  83. // BUGBUG georgep: This is going to flicker, so I will need to fix that
  84. SelectObject(hdcTemp, GetFrame());
  85. BitBlt(hdc, 0, 0, sizes[Frame].cx, sizes[Frame].cy, hdcTemp, 0, 0, SRCCOPY);
  86. // BUGBUG georgep: We should clean out the "uncovered" area here
  87. UINT cur = GetCurrentValue();
  88. UINT max = GetMaxValue();
  89. if (cur > max)
  90. {
  91. cur = max;
  92. }
  93. SelectObject(hdcTemp, GetBar());
  94. // Center the bitmap, but only display to the current percentage
  95. BitBlt(hdc, (sizes[Frame].cx-sizes[Bar].cx)/2, (sizes[Frame].cy-sizes[Bar].cy)/2,
  96. (sizes[Bar].cx*cur)/max, sizes[Bar].cy, hdcTemp, 0, 0, SRCCOPY);
  97. // This is where we should attempt to alpha blend the inner onto the
  98. // outer for a few pixels in either direction
  99. // Clean up
  100. DeleteDC(hdcTemp);
  101. if (NULL != hPal)
  102. {
  103. SelectPalette(hdc, hOld, TRUE);
  104. }
  105. }
  106. EndPaint(hwnd, &ps);
  107. }
  108. // Change the max value displayed by this progress bar
  109. void CProgressBar::SetMaxValue(UINT maxVal)
  110. {
  111. m_maxVal = maxVal;
  112. InvalidateRect(GetWindow(), NULL, FALSE);
  113. }
  114. // Change the current value displayed by this progress bar
  115. void CProgressBar::SetCurrentValue(UINT curVal)
  116. {
  117. m_curVal = curVal;
  118. InvalidateRect(GetWindow(), NULL, FALSE);
  119. }
  120. static const int DefWidth = 170;
  121. static const int DefHeight = 23;
  122. CProgressTrackbar::CProgressTrackbar() :
  123. m_nValChannel(0)
  124. {
  125. m_desSize.cx = DefWidth;
  126. m_desSize.cy = DefHeight;
  127. }
  128. CProgressTrackbar::~CProgressTrackbar()
  129. {
  130. }
  131. BOOL CProgressTrackbar::Create(
  132. HWND hWndParent, // The parent of the toolbar window
  133. INT_PTR nId, // The ID of the control
  134. IScrollChange *pNotify // Object to notify of changes
  135. )
  136. {
  137. if (!CFillWindow::Create(
  138. hWndParent,
  139. nId,
  140. "NMTrackbar",
  141. 0,
  142. WS_EX_CONTROLPARENT
  143. ))
  144. {
  145. return(FALSE);
  146. }
  147. // Create the Win32 button
  148. CreateWindowEx(0, TRACKBAR_CLASS, g_szEmpty,
  149. TBS_HORZ|TBS_NOTICKS|TBS_BOTH
  150. |WS_CLIPSIBLINGS|WS_TABSTOP|WS_VISIBLE|WS_CHILD,
  151. 0, 0, 10, 10,
  152. GetWindow(), reinterpret_cast<HMENU>(nId), _Module.GetModuleInstance(), NULL);
  153. m_pNotify = pNotify;
  154. if (NULL != m_pNotify)
  155. {
  156. m_pNotify->AddRef();
  157. }
  158. return(TRUE);
  159. }
  160. void CProgressTrackbar::GetDesiredSize(SIZE *ppt)
  161. {
  162. *ppt = m_desSize;
  163. }
  164. void CProgressTrackbar::SetDesiredSize(SIZE *psize)
  165. {
  166. m_desSize = *psize;
  167. OnDesiredSizeChanged();
  168. }
  169. LRESULT CProgressTrackbar::ProcessMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  170. {
  171. switch (message)
  172. {
  173. HANDLE_MSG(hwnd, WM_NOTIFY , OnNotify);
  174. HANDLE_MSG(hwnd, WM_HSCROLL , OnScroll);
  175. HANDLE_MSG(hwnd, WM_VSCROLL , OnScroll);
  176. HANDLE_MSG(hwnd, WM_CTLCOLORSTATIC, OnCtlColor);
  177. HANDLE_MSG(hwnd, WM_NCDESTROY , OnNCDestroy);
  178. }
  179. return(CFillWindow::ProcessMessage(hwnd, message, wParam, lParam));
  180. }
  181. HBRUSH CProgressTrackbar::OnCtlColor(HWND hwnd, HDC hdc, HWND hwndChild, int type)
  182. {
  183. return(GetBackgroundBrush());
  184. }
  185. LRESULT CProgressTrackbar::PaintChannel(LPNMCUSTOMDRAW pCustomDraw)
  186. {
  187. static const int NUM_RECTANGLES_MAX = 16;
  188. static const int NUM_RECTANGLES_MIN = 6;
  189. static const int g_nAudMeterHeight = 7;
  190. static const int BorderWidth = 1;
  191. HDC hdc = pCustomDraw->hdc;
  192. BOOL bGotDC = FALSE;
  193. DWORD dwVolume = m_nValChannel;
  194. bool bTransmitting;
  195. bTransmitting = HIWORD(dwVolume) & SIGNAL_STATUS_TRANSMIT;
  196. dwVolume = LOWORD(dwVolume);
  197. if (!hdc)
  198. {
  199. hdc = GetDC(GetWindow());
  200. bGotDC = TRUE;
  201. }
  202. // rectangle leading is 1
  203. UINT max = GetMaxValue();
  204. if (dwVolume > max)
  205. {
  206. dwVolume = max;
  207. }
  208. RECT rect = pCustomDraw->rc;
  209. int nVuWidth = rect.right - rect.left - 2*BorderWidth;
  210. if (nVuWidth < (NUM_RECTANGLES_MIN*2))
  211. return(0);
  212. // "rect" represents the edges of the meter's outer rectangle
  213. // compute the number of individual rectangles to use
  214. // we do the computation this way so that sizing the rebar band
  215. // makes the size changes consistant
  216. int nRectsTotal;
  217. nRectsTotal = (nVuWidth + (g_nAudMeterHeight - 1)) / g_nAudMeterHeight;
  218. nRectsTotal = min(nRectsTotal, NUM_RECTANGLES_MAX);
  219. nRectsTotal = max(nRectsTotal, NUM_RECTANGLES_MIN);
  220. // nRectangleWidth - width of colored rectangle - no leading
  221. int nRectangleWidth = (nVuWidth/nRectsTotal) - 1;
  222. // nVuWidth - width of entire VU meter including edges
  223. nVuWidth = (nRectangleWidth + 1)*nRectsTotal;
  224. // re-adjust meter size to be an integral number of rects
  225. int nDiff = (rect.right - rect.left) - (nVuWidth + 2*BorderWidth);
  226. // Subtract 1 since there is no border on the last one
  227. rect.right = rect.left + nVuWidth + 2*BorderWidth - 1;
  228. // center vu-meter across whole channel area so that the
  229. // slider's thumb is always covering some portion of the channel
  230. rect.left += (nDiff/2);
  231. rect.right += (nDiff/2);
  232. // the background color may change on us!
  233. COLORREF GreyColor = GetSysColor(COLOR_3DFACE);
  234. static const COLORREF RedColor = RGB(255,0,0);
  235. static const COLORREF YellowColor = RGB(255,255,0);
  236. static const COLORREF GreenColor = RGB(0,255,0);
  237. COLORREF ShadowColor = GetSysColor(COLOR_3DSHADOW);
  238. COLORREF HiLiteColor = GetSysColor(COLOR_3DHIGHLIGHT);
  239. COLORREF LiteColor = GetSysColor(COLOR_3DLIGHT);
  240. COLORREF DkShadowColor = GetSysColor(COLOR_3DDKSHADOW);
  241. HBRUSH hGreyBrush = CreateSolidBrush(GreyColor);
  242. HPEN hShadowPen = CreatePen(PS_SOLID, 0, ShadowColor);
  243. HBRUSH hRedBrush = CreateSolidBrush (RedColor);
  244. HBRUSH hGreenBrush = CreateSolidBrush(GreenColor);
  245. HBRUSH hYellowBrush = CreateSolidBrush(YellowColor);
  246. RECT rectDraw = rect;
  247. // draw the 3D frame border
  248. // HACKHACK georgep: draw outside the rect they gave us
  249. ++rect.bottom;
  250. DrawEdge(hdc, &rect, BDR_RAISEDINNER, BF_RECT);
  251. HPEN hOldPen = reinterpret_cast<HPEN>(SelectObject(hdc, hShadowPen));
  252. // the top and left of the meter has a 2 line border
  253. // the bottom and right of the meter has a 2 line border
  254. rectDraw.top += 1;
  255. rectDraw.left += 1;
  256. rectDraw.right = rectDraw.left + nRectangleWidth;
  257. // how many colored rectangles do we draw ?
  258. int nRects = (dwVolume * nRectsTotal) / max;
  259. // not transmitting - don't show anything
  260. if ((false == bTransmitting))
  261. nRects = 0;
  262. // transmitting or receiving something very quiet -
  263. // light up at least one rectangle
  264. else if ((bTransmitting) && (nRects == 0))
  265. nRects = 1;
  266. HBRUSH hCurrentBrush = hGreenBrush;
  267. POINT ptOld;
  268. MoveToEx(hdc, 0, 0, &ptOld);
  269. for (int nIndex = 0; nIndex < nRectsTotal; nIndex++)
  270. {
  271. // far left fourth of the bar is green
  272. // right fourth of the bar is red
  273. // middle is yellow
  274. if (nIndex > ((nRectsTotal*3)/4))
  275. hCurrentBrush = hRedBrush;
  276. else if (nIndex >= nRectsTotal/2)
  277. hCurrentBrush = hYellowBrush;
  278. if (nIndex >= nRects)
  279. hCurrentBrush = hGreyBrush;
  280. FillRect(hdc, &rectDraw, hCurrentBrush);
  281. if (nIndex != (nRectsTotal-1))
  282. {
  283. MoveToEx(hdc, rectDraw.left + nRectangleWidth, rectDraw.top, NULL);
  284. LineTo(hdc, rectDraw.left + nRectangleWidth, rectDraw.bottom);
  285. }
  286. rectDraw.left += nRectangleWidth + 1; // +1 for the leading
  287. rectDraw.right = rectDraw.left + nRectangleWidth;
  288. }
  289. MoveToEx(hdc, ptOld.x, ptOld.y, NULL);
  290. SelectObject (hdc, hOldPen);
  291. if (bGotDC)
  292. {
  293. ReleaseDC(GetWindow(), hdc);
  294. }
  295. DeleteObject(hGreyBrush);
  296. DeleteObject(hShadowPen);
  297. DeleteObject(hRedBrush);
  298. DeleteObject(hGreenBrush);
  299. DeleteObject(hYellowBrush);
  300. return(CDRF_SKIPDEFAULT);
  301. }
  302. LRESULT CProgressTrackbar::PaintThumb(LPNMCUSTOMDRAW pCustomDraw)
  303. {
  304. return(0);
  305. #if FALSE // {
  306. HBITMAP hbThumb = GetThumb();
  307. ASSERT(NULL != hbThumb);
  308. // Draw in the upper left
  309. HDC hdcDraw = pCustomDraw->hdc;
  310. HDC hdcTemp = CreateCompatibleDC(hdcDraw);
  311. if (NULL != hdcTemp)
  312. {
  313. HPALETTE hPal = GetPalette();
  314. HPALETTE hOld = NULL;
  315. if (NULL != hPal)
  316. {
  317. hOld = SelectPalette(hdcDraw, hPal, TRUE);
  318. RealizePalette(hdcDraw);
  319. SelectPalette(hdcTemp, hPal, TRUE);
  320. RealizePalette(hdcTemp);
  321. }
  322. SIZE sizeBitmap[NumBitmaps];
  323. CBitmapButton::GetBitmapSizes(m_hbs, sizeBitmap, NumBitmaps);
  324. HBITMAP hbThumb = GetThumb();
  325. if (NULL != SelectObject(hdcTemp, hbThumb))
  326. {
  327. RECT rc = pCustomDraw->rc;
  328. StretchBlt(hdcDraw,
  329. rc.left, rc.top,
  330. rc.right-rc.left, rc.bottom-rc.top,
  331. hdcTemp,
  332. 0, 0, sizeBitmap[Thumb].cx, sizeBitmap[Thumb].cy,
  333. SRCCOPY);
  334. // BUGBUG georgep: We should clear any "uncovered" area here
  335. }
  336. DeleteDC(hdcTemp);
  337. if (NULL != hPal)
  338. {
  339. SelectPalette(hdcDraw, hOld, TRUE);
  340. }
  341. }
  342. return(CDRF_SKIPDEFAULT);
  343. #endif // FALSE }
  344. }
  345. LRESULT CProgressTrackbar::OnNotify(HWND hwnd, int id, NMHDR *pHdr)
  346. {
  347. if (NM_CUSTOMDRAW != pHdr->code)
  348. {
  349. return(FORWARD_WM_NOTIFY(hwnd, id, pHdr, CGenWindow::ProcessMessage));
  350. }
  351. LPNMCUSTOMDRAW pCustomDraw = reinterpret_cast<LPNMCUSTOMDRAW>(pHdr);
  352. switch (pCustomDraw->dwDrawStage)
  353. {
  354. case CDDS_PREPAINT:
  355. return(CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT);
  356. break;
  357. case CDDS_ITEMPREPAINT:
  358. switch (pCustomDraw->dwItemSpec)
  359. {
  360. case TBCD_CHANNEL:
  361. return(PaintChannel(pCustomDraw));
  362. case TBCD_THUMB:
  363. return(PaintThumb(pCustomDraw));
  364. }
  365. default:
  366. break;
  367. }
  368. return(FORWARD_WM_NOTIFY(hwnd, id, pHdr, CGenWindow::ProcessMessage));
  369. }
  370. void CProgressTrackbar::OnScroll(HWND hwnd, HWND hwndCtl, UINT code, int pos)
  371. {
  372. if (NULL != m_pNotify)
  373. {
  374. m_pNotify->OnScroll(this, code, pos);
  375. return;
  376. }
  377. // Translate the hwndCtl and let the parent handle the message
  378. FORWARD_WM_HSCROLL(GetParent(hwnd), GetWindow(), code, pos, SendMessage);
  379. }
  380. void CProgressTrackbar::OnNCDestroy(HWND hwnd)
  381. {
  382. if (NULL != m_pNotify)
  383. {
  384. m_pNotify->Release();
  385. m_pNotify = NULL;
  386. }
  387. FORWARD_WM_NCDESTROY(hwnd, CFillWindow::ProcessMessage);
  388. }
  389. // Change the max value displayed by this progress bar
  390. void CProgressTrackbar::SetMaxValue(UINT maxVal)
  391. {
  392. HWND hwnd = GetChild();
  393. ::SendMessage( hwnd,
  394. TBM_SETRANGE,
  395. FALSE,
  396. MAKELONG(0, maxVal));
  397. }
  398. // Return the max value displayed by this progress bar
  399. UINT CProgressTrackbar::GetMaxValue()
  400. {
  401. HWND hwnd = GetChild();
  402. return(static_cast<UINT>(::SendMessage( hwnd,
  403. TBM_GETRANGEMAX,
  404. 0,
  405. 0)));
  406. }
  407. // Change the current value displayed by this progress bar
  408. void CProgressTrackbar::SetTrackValue(UINT curVal)
  409. {
  410. HWND hwnd = GetChild();
  411. ::SendMessage( hwnd,
  412. TBM_SETPOS,
  413. TRUE,
  414. curVal);
  415. }
  416. // Return the current value displayed by this progress bar
  417. UINT CProgressTrackbar::GetTrackValue()
  418. {
  419. HWND hwnd = GetChild();
  420. return(static_cast<UINT>(::SendMessage( hwnd,
  421. TBM_GETPOS,
  422. 0,
  423. 0)));
  424. }
  425. // Change the current value displayed by this progress bar
  426. void CProgressTrackbar::SetProgressValue(UINT curVal)
  427. {
  428. if (curVal != m_nValChannel)
  429. {
  430. m_nValChannel = curVal;
  431. SchedulePaint();
  432. }
  433. }
  434. // Return the current value displayed by this progress bar
  435. UINT CProgressTrackbar::GetProgressValue()
  436. {
  437. return(m_nValChannel);
  438. }