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.

392 lines
9.8 KiB

  1. /*****************************************************************************
  2. *
  3. * Component: sndvol32.exe
  4. * File: vu.c
  5. * Purpose: peak meter custom control
  6. *
  7. * Copyright (c) 1985-1998 Microsoft Corporation
  8. *
  9. *****************************************************************************/
  10. /*
  11. * VUMeter Control
  12. *
  13. * */
  14. #include <windows.h>
  15. #include <windowsx.h>
  16. #include "vu.h"
  17. const TCHAR gszVUClass[] = VUMETER_CLASS;
  18. LRESULT FAR PASCAL VUMeterProc(HWND hwnd, UINT wMessage, WPARAM wParam, LPARAM lParam);
  19. #define GETVUINST(x) (VUINST *)GetWindowLongPtr(x, 0)
  20. #define SETVUINST(x,y) SetWindowLongPtr(x, 0, (LONG_PTR)y)
  21. typedef struct tag_VUINST {
  22. CREATESTRUCT cs;
  23. DWORD dwLevel; // current value
  24. DWORD dwMax; // value max
  25. DWORD dwMin; // value min
  26. DWORD dwBreak; // last break
  27. DWORD dwStyle; // dbl extra style bits ???
  28. DWORD cBreaks; // no. of breaks
  29. DWORD cRGB; // no. of RGBQUADs
  30. DWORD dwHeight;
  31. DWORD dwWidth;
  32. HBITMAP hColor; // bitmap cache of full display
  33. HBITMAP hBackground; // bitmap cache of background
  34. RGBQUAD *aRGB; // array of RGBQUADs describing colors
  35. } VUINST, *PVUINST, FAR *LPVUINST;
  36. const RGBQUAD gaRGBDefault[] = {
  37. { 0, 127, 0, 0}, // dark green
  38. { 0, 127, 0, 0}, // dark green
  39. { 0, 255, 0, 0}, // light green
  40. { 0, 255, 255, 0}, // yellow
  41. { 0, 0, 255, 0} // red
  42. };
  43. BOOL InitVUControl(HINSTANCE hInst)
  44. {
  45. WNDCLASS wc;
  46. wc.lpszClassName = (LPTSTR)gszVUClass;
  47. wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  48. wc.lpszMenuName = (LPTSTR)NULL;
  49. wc.style = CS_HREDRAW|CS_VREDRAW|CS_GLOBALCLASS;
  50. wc.lpfnWndProc = (WNDPROC) VUMeterProc;
  51. wc.hInstance = hInst;
  52. wc.hIcon = NULL;
  53. wc.cbWndExtra = sizeof(VUINST *);
  54. wc.cbClsExtra = 0;
  55. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1 );
  56. /* register meter window class */
  57. if(!RegisterClass(&wc))
  58. {
  59. return FALSE;
  60. }
  61. return (TRUE);
  62. }
  63. DWORD vu_CalcBreaks(
  64. PVUINST pvi)
  65. {
  66. DWORD cBreaks;
  67. if (pvi->dwMax - pvi->dwMin > 0)
  68. {
  69. cBreaks = ((pvi->dwLevel - pvi->dwMin) * pvi->cBreaks)
  70. / (pvi->dwMax - pvi->dwMin);
  71. if (!cBreaks && pvi->dwLevel > pvi->dwMin)
  72. cBreaks++;
  73. }
  74. else
  75. cBreaks = 0;
  76. if (cBreaks > pvi->cBreaks)
  77. cBreaks = pvi->cBreaks;
  78. return cBreaks;
  79. }
  80. BOOL vu_OnCreate(
  81. HWND hwnd,
  82. LPCREATESTRUCT lpCreateStruct)
  83. {
  84. PVUINST pvi;
  85. //
  86. // alloc an instance data structure
  87. pvi = LocalAlloc(LPTR, sizeof(VUINST));
  88. if (!pvi)
  89. return FALSE;
  90. SETVUINST(hwnd, pvi);
  91. pvi->cBreaks = 10;
  92. pvi->cRGB = sizeof(gaRGBDefault)/sizeof(RGBQUAD);
  93. pvi->aRGB = (RGBQUAD *)gaRGBDefault;
  94. pvi->dwMin = 0;
  95. pvi->dwMax = 0;
  96. pvi->dwLevel = 0;
  97. pvi->dwBreak = 0;
  98. pvi->hColor = NULL;
  99. pvi->hBackground = NULL;
  100. return TRUE;
  101. }
  102. void vu_ResetControl(
  103. PVUINST pvi)
  104. {
  105. if (pvi->hColor)
  106. {
  107. DeleteObject(pvi->hColor);
  108. pvi->hColor = NULL;
  109. }
  110. if (pvi->hBackground)
  111. {
  112. DeleteObject(pvi->hBackground);
  113. pvi->hBackground = NULL;
  114. }
  115. }
  116. void vu_OnDestroy(
  117. HWND hwnd)
  118. {
  119. PVUINST pvi = GETVUINST(hwnd);
  120. if (pvi)
  121. {
  122. vu_ResetControl(pvi);
  123. LocalFree((HLOCAL)pvi);
  124. SETVUINST(hwnd,0);
  125. }
  126. }
  127. void vu_OnPaint(
  128. HWND hwnd)
  129. {
  130. PVUINST pvi = GETVUINST(hwnd);
  131. RECT rc, rcB;
  132. PAINTSTRUCT ps;
  133. int i;
  134. int iSize;
  135. DWORD cBreaks;
  136. if (!GetUpdateRect(hwnd, &rc, FALSE))
  137. return;
  138. BeginPaint(hwnd, &ps);
  139. GetClientRect(hwnd, &rc);
  140. //
  141. // Create the foreground bitmap if not already cached
  142. //
  143. if (pvi->hColor == NULL)
  144. {
  145. HDC hdc;
  146. HBITMAP hbmp, hold;
  147. HBRUSH hbr;
  148. RECT rcp;
  149. rcp.left = 0;
  150. rcp.right = rc.right - rc.left - 4;
  151. rcp.top = 0;
  152. rcp.bottom = rc.bottom - rc.top - 4 ;
  153. hdc = CreateCompatibleDC(ps.hdc);
  154. hbmp = CreateCompatibleBitmap(ps.hdc, rcp.right, rcp.bottom);
  155. hold = SelectObject(hdc, hbmp);
  156. //
  157. // background
  158. //
  159. hbr = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  160. FillRect(hdc, &rcp, hbr);
  161. if (hbr) DeleteObject(hbr);
  162. //
  163. // each block will be iSize tall
  164. //
  165. iSize = (rcp.bottom - 1) / pvi->cBreaks;
  166. //
  167. // color blocks
  168. //
  169. for (i = 0; i < (int)pvi->cBreaks; i++)
  170. {
  171. int iColor = i / (pvi->cBreaks/pvi->cRGB);
  172. if (iColor >= (int)pvi->cRGB - 1)
  173. iColor = (int)pvi->cRGB - 1;
  174. hbr = CreateSolidBrush(RGB(pvi->aRGB[iColor].rgbRed
  175. ,pvi->aRGB[iColor].rgbGreen
  176. ,pvi->aRGB[iColor].rgbBlue));
  177. rcB.left = 0;
  178. rcB.right = rcp.right;
  179. rcB.top = rcp.bottom - (i+1)*iSize;
  180. // rcB.bottom = rcp.bottom - i*iSize;
  181. rcB.bottom = rcB.top + iSize - 1;
  182. FillRect(hdc, &rcB, hbr);
  183. DeleteObject(hbr);
  184. }
  185. pvi->hColor = SelectObject(hdc, hold);
  186. DeleteDC(hdc);
  187. }
  188. //
  189. // Paint it
  190. //
  191. {
  192. HDC hdc, hdcColor;
  193. HBITMAP holdColor, hbmp, hold;
  194. RECT rcC = rc;
  195. HBRUSH hbr;
  196. //
  197. // always show something if we exceed the minimum
  198. cBreaks = vu_CalcBreaks(pvi);
  199. rcC.left = 0;
  200. rcC.right = rc.right - rc.left - 4;
  201. rcC.top = 0;
  202. rcC.bottom = rc.bottom - rc.top - 4;
  203. // each block will be iSize+1 tall
  204. iSize = (rcC.bottom - 1) / pvi->cBreaks ;
  205. // paint the uncolor area
  206. hdc = CreateCompatibleDC(ps.hdc);
  207. hbmp = CreateCompatibleBitmap(ps.hdc, rcC.right, rcC.bottom);
  208. hold = SelectObject(hdc, hbmp);
  209. hbr = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  210. FillRect(hdc, &rcC, hbr);
  211. if (hbr)
  212. DeleteObject(hbr);
  213. if (cBreaks > 0)
  214. {
  215. // paint the color area
  216. hdcColor = CreateCompatibleDC(ps.hdc);
  217. if (hdcColor)
  218. holdColor = SelectObject(hdcColor, pvi->hColor);
  219. BitBlt(hdc
  220. , 0
  221. , rcC.bottom - (iSize * cBreaks)
  222. , rcC.right
  223. , iSize * cBreaks
  224. , hdcColor
  225. , 0
  226. , rcC.bottom - (iSize * cBreaks)
  227. , SRCCOPY);
  228. SelectObject(hdcColor, holdColor);
  229. DeleteDC(hdcColor);
  230. }
  231. //
  232. // finally, blt into the real dc
  233. BitBlt(ps.hdc
  234. , 2
  235. , 2
  236. , rcC.right
  237. , rcC.bottom
  238. , hdc
  239. , 0
  240. , 0
  241. , SRCCOPY);
  242. SelectObject(hdc, hold);
  243. if (hbmp) DeleteObject(hbmp);
  244. DeleteDC(hdc);
  245. }
  246. DrawEdge(ps.hdc, &rc, BDR_SUNKENOUTER, BF_RECT);
  247. EndPaint(hwnd, &ps);
  248. }
  249. void vu_OnSysColorChange(
  250. HWND hwnd)
  251. {
  252. PVUINST pvi = GETVUINST(hwnd);
  253. vu_ResetControl(pvi);
  254. }
  255. void vu_OnPaletteChanged(
  256. HWND hwnd,
  257. HWND hwndPaletteChange)
  258. {
  259. PVUINST pvi = GETVUINST(hwnd);
  260. vu_ResetControl(pvi);
  261. }
  262. void vu_OnSize(
  263. HWND hwnd,
  264. UINT state,
  265. int cx,
  266. int cy)
  267. {
  268. PVUINST pvi = GETVUINST(hwnd);
  269. pvi->dwWidth = cx;
  270. pvi->dwHeight = cy;
  271. vu_ResetControl(pvi);
  272. }
  273. void vu_OnEnable(
  274. HWND hwnd,
  275. BOOL fEnable)
  276. {
  277. PVUINST pvi = GETVUINST(hwnd);
  278. }
  279. void vu_OnPrivateMessage(
  280. HWND hwnd,
  281. UINT wMessage,
  282. WPARAM wParam,
  283. LPARAM lParam)
  284. {
  285. PVUINST pvi = GETVUINST(hwnd);
  286. switch (wMessage)
  287. {
  288. case VU_SETRANGEMIN:
  289. // OutputDebugString(TEXT ("SetRangeMin\r\n"));
  290. pvi->dwMin = (DWORD)lParam;
  291. break;
  292. case VU_SETRANGEMAX:
  293. // OutputDebugString(TEXT ("SetRangeMax\r\n"));
  294. pvi->dwMax = (DWORD)lParam;
  295. break;
  296. case VU_SETPOS:
  297. pvi->dwLevel = (DWORD)lParam;
  298. // {TCHAR foo[256];
  299. // wsprintf(foo, TEXT ("v:%lx\r\n"),lParam);
  300. // OutputDebugString(foo);
  301. // }
  302. if (pvi->dwBreak != vu_CalcBreaks(pvi))
  303. {
  304. pvi->dwBreak = vu_CalcBreaks(pvi);
  305. InvalidateRect(hwnd, NULL, TRUE);
  306. }
  307. else if (wParam)
  308. InvalidateRect(hwnd, NULL, TRUE);
  309. break;
  310. }
  311. }
  312. LRESULT FAR PASCAL
  313. VUMeterProc(
  314. HWND hwnd,
  315. UINT wMessage,
  316. WPARAM wParam,
  317. LPARAM lParam)
  318. {
  319. switch (wMessage)
  320. {
  321. HANDLE_MSG(hwnd, WM_CREATE, vu_OnCreate);
  322. HANDLE_MSG(hwnd, WM_DESTROY, vu_OnDestroy);
  323. HANDLE_MSG(hwnd, WM_PAINT, vu_OnPaint);
  324. HANDLE_MSG(hwnd, WM_SYSCOLORCHANGE, vu_OnSysColorChange);
  325. HANDLE_MSG(hwnd, WM_PALETTECHANGED, vu_OnPaletteChanged);
  326. HANDLE_MSG(hwnd, WM_SIZE, vu_OnSize);
  327. HANDLE_MSG(hwnd, WM_ENABLE, vu_OnEnable);
  328. // HANDLE_MSG(hwnd, WM_TIMER, vu_OnTimer);
  329. case VU_SETRANGEMIN:
  330. case VU_SETRANGEMAX:
  331. case VU_SETPOS:
  332. vu_OnPrivateMessage(hwnd, wMessage, wParam, lParam);
  333. return 0;
  334. case WM_ERASEBKGND:
  335. return TRUE;
  336. default:
  337. break;
  338. }
  339. return DefWindowProc (hwnd, wMessage, wParam, lParam) ;
  340. }