Leaked source code of windows server 2003
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.

1414 lines
37 KiB

  1. /////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1997 Active Voice Corporation. All Rights Reserved.
  4. //
  5. // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
  6. //
  7. // Other brand and product names used herein are trademarks of their respective owners.
  8. //
  9. // The entire program and user interface including the structure, sequence, selection,
  10. // and arrangement of the dialog, the exclusively "yes" and "no" choices represented
  11. // by "1" and "2," and each dialog message are protected by copyrights registered in
  12. // the United States and by international treaties.
  13. //
  14. // Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
  15. // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
  16. //
  17. // Active Voice Corporation
  18. // Seattle, Washington
  19. // USA
  20. //
  21. /////////////////////////////////////////////////////////////////////////////////////////
  22. ////
  23. // tmeter.c - TrackMeter custom control
  24. ////
  25. #include "tmeter.h"
  26. #include "resource.h"
  27. #include <commctrl.h>
  28. #include <custcntl.h>
  29. #include "trace.h"
  30. #include "mem.h"
  31. ////
  32. // public
  33. ////
  34. BOOL WINAPI DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved);
  35. UINT DLLEXPORT CALLBACK CustomControlInfoA(LPCCINFOA acci);
  36. BOOL DLLEXPORT CALLBACK TrackMeter_Style(HWND hWndParent, LPCCSTYLEA pccs);
  37. INT DLLEXPORT CALLBACK TrackMeter_SizeToText(
  38. DWORD flStyle, DWORD flExtStyle, HFONT hFont, LPSTR pszText);
  39. LRESULT DLLEXPORT CALLBACK TrackMeter_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  40. ////
  41. // private
  42. ////
  43. static HINSTANCE g_hInstLib;
  44. #define GWL_USER 0
  45. #define TRACKMETER_DESCRIPTION "TrackBar with level meter"
  46. #define TRACKMETER_DEFAULTTEXT "[===||=======]"
  47. // control styles
  48. //
  49. #define SS_HORIZONTAL 0x0001
  50. #define SS_VERTICAL 0x0002
  51. CCSTYLEFLAGA aTrackMeterStyleFlags[] =
  52. {
  53. { TMS_HORZ, 0, "TMS_HORZ" },
  54. { TMS_VERT, 0, "TMS_VERT" },
  55. { TMS_NOTHUMB, 0, "TMS_NOTHUMB" }
  56. };
  57. // number of extra bytes for control window
  58. //
  59. #define TRACKMETER_EXTRABYTES (1*sizeof(DWORD_PTR))
  60. // tmeter control struct
  61. //
  62. typedef struct TMETER
  63. {
  64. HWND hwnd;
  65. HWND hwndParent;
  66. HDC hdcCompat;
  67. HBITMAP hbmpSave;
  68. HBITMAP hbmpCompat;
  69. long lPosition;
  70. long lMinimum;
  71. long lMaximum;
  72. long lLevel;
  73. long lLineSize;
  74. long lPageSize;
  75. BOOL fHasFocus;
  76. BOOL fIsEnabled;
  77. BOOL fIsThumbPressed;
  78. DWORD dwFlags;
  79. RECT rcCtrl;
  80. RECT rcTrack;
  81. RECT rcMeter;
  82. RECT rcLevel;
  83. POINT aptThumb[5];
  84. COLORREF acr[TMCR_MAX];
  85. } TMETER, FAR *LPTMETER;
  86. // helper functions
  87. //
  88. static BOOL TrackMeter_OnNCCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct);
  89. static void TrackMeter_OnNCDestroy(LPTMETER lptm);
  90. static BOOL TrackMeter_OnCreate(LPTMETER lptm, CREATESTRUCT FAR* lpCreateStruct);
  91. static void TrackMeter_OnDestroy(LPTMETER lptm);
  92. static void TrackMeter_OnSize(LPTMETER lptm, UINT state, int cx, int cy);
  93. static BOOL TrackMeter_OnEraseBkgnd(LPTMETER lptm, HDC hdc);
  94. static void TrackMeter_OnPaint(LPTMETER lptm);
  95. static int TrackMeter_Draw(LPTMETER lptm, HDC hdc);
  96. static void TrackMeter_OnCommand(LPTMETER lptm, int id, HWND hwndCtl, UINT codeNotify);
  97. static void TrackMeter_OnSetFocus(LPTMETER lptm, HWND hwndOldFocus);
  98. static void TrackMeter_OnKillFocus(LPTMETER lptm, HWND hwndNewFocus);
  99. static void TrackMeter_OnEnable(LPTMETER lptm, BOOL fEnable);
  100. static UINT TrackMeter_OnGetDlgCode(LPTMETER lptm, LPMSG lpmsg);
  101. static void TrackMeter_OnKey(LPTMETER lptm, UINT vk, BOOL fDown, int cRepeat, UINT flags);
  102. static void TrackMeter_OnLButtonDown(LPTMETER lptm, BOOL fDoubleClick, int x, int y, UINT keyFlags);
  103. static void TrackMeter_OnLButtonUp(LPTMETER lptm, int x, int y, UINT keyFlags);
  104. static void TrackMeter_OnRButtonDown(LPTMETER lptm, BOOL fDoubleClick, int x, int y, UINT keyFlags);
  105. static void TrackMeter_OnRButtonUp(LPTMETER lptm, int x, int y, UINT keyFlags);
  106. static void TrackMeter_OnMouseMove(LPTMETER lptm, int x, int y, UINT keyFlags);
  107. static void TrackMeter_OnCaptureChanged(LPTMETER lptm, HWND hwndNewCapture);
  108. static void TrackMeter_NotifyParent(LPTMETER lptm, UINT code, UINT nPos);
  109. static LONG TrackMeter_OnTMMGetPos(LPTMETER lptm);
  110. static void TrackMeter_OnTMMSetPos(LPTMETER lptm, LONG lPosition, BOOL fRedraw);
  111. static LONG TrackMeter_OnTMMGetLevel(LPTMETER lptm);
  112. static void TrackMeter_OnTMMSetLevel(LPTMETER lptm, LONG lLevel, BOOL fRedraw);
  113. static LONG TrackMeter_OnTMMGetRangeMin(LPTMETER lptm);
  114. static void TrackMeter_OnTMMSetRangeMin(LPTMETER lptm, LONG lMinimum, BOOL fRedraw);
  115. static LONG TrackMeter_OnTMMGetRangeMax(LPTMETER lptm);
  116. static void TrackMeter_OnTMMSetRangeMax(LPTMETER lptm, LONG lMaximum, BOOL fRedraw);
  117. static void TrackMeter_OnTMMSetRange(LPTMETER lptm, LONG lMinimum, LONG lMaximum, BOOL fRedraw);
  118. static COLORREF TrackMeter_OnTMMGetColor(LPTMETER lptm, UINT elem);
  119. static void TrackMeter_OnTMMSetColor(LPTMETER lptm, COLORREF cr, UINT elem, BOOL fRedraw);
  120. #define TrackMeter_DefProc(hwnd, msg, wParam, lParam) \
  121. DefWindowProc(hwnd, msg, wParam, lParam)
  122. static int TrackMeter_Recalc(LPTMETER lptm, DWORD dwFlags);
  123. #define TMR_TRACK 0x00000001
  124. #define TMR_METER 0x00000002
  125. #define TMR_LEVEL 0x00000004
  126. #define TMR_THUMB 0x00000008
  127. #define TMR_COLORS 0x00000010
  128. #define TMR_PAGESIZE 0x00000020
  129. #define TMR_ALL (TMR_TRACK | TMR_METER | TMR_LEVEL | TMR_THUMB | TMR_COLORS | TMR_PAGESIZE)
  130. static int TrackMeter_PositionToX(LPTMETER lptm, long lPosition);
  131. static long TrackMeter_XToPosition(LPTMETER lptm, int xPosition);
  132. static BOOL TrackMeter_PtInThumb(LPTMETER lptm, int x, int y);
  133. // for some reason this is not in windowsx.h
  134. //
  135. #ifndef HANDLE_WM_CAPTURECHANGED
  136. /* void Cls_OnCaptureChanged(HWND hwnd, HWND hwndNewCapture) */
  137. #define HANDLE_WM_CAPTURECHANGED(hwnd, wParam, lParam, fn) \
  138. ((fn)((hwnd), (HWND)(wParam)), 0L)
  139. #define FORWARD_WM_CAPTURECHANEGED(hwnd, hwndNewCapture, fn) \
  140. (void)(fn)((hwnd), WM_CAPTURECHANGED, (WPARAM)(HWND)(hwndNewCapture), 0L)
  141. #endif
  142. ////
  143. // public
  144. ////
  145. BOOL WINAPI DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved)
  146. {
  147. BOOL fSuccess = TRUE;
  148. switch (fdwReason)
  149. {
  150. case DLL_PROCESS_ATTACH:
  151. {
  152. WNDCLASS wc;
  153. g_hInstLib = hModule;
  154. wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_GLOBALCLASS;
  155. wc.lpfnWndProc = TrackMeter_WndProc;
  156. wc.cbClsExtra = 0;
  157. wc.cbWndExtra = TRACKMETER_EXTRABYTES;
  158. wc.hInstance = hModule;
  159. wc.hIcon = NULL;
  160. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  161. wc.hbrBackground = NULL;
  162. wc.lpszMenuName = (LPTSTR) NULL;
  163. wc.lpszClassName = (LPTSTR) TRACKMETER_CLASS;
  164. if (!RegisterClass (&wc))
  165. {
  166. fSuccess = TraceFALSE(NULL);
  167. return FALSE;
  168. }
  169. }
  170. break;
  171. case DLL_THREAD_ATTACH:
  172. break;
  173. case DLL_THREAD_DETACH:
  174. break;
  175. case DLL_PROCESS_DETACH:
  176. if (!UnregisterClass ((LPTSTR) TRACKMETER_CLASS, hModule))
  177. fSuccess = TraceFALSE(NULL);
  178. break;
  179. default:
  180. break;
  181. }
  182. return fSuccess;
  183. }
  184. // CustomControlInfoA
  185. // <lpacci> (i/o) pointer to array of CCINFOA structs
  186. // returns number of controls supported by this DLL
  187. // NOTE: see CUSTCNTL.H for more info
  188. //
  189. UINT DLLEXPORT CALLBACK CustomControlInfoA(LPCCINFOA acci)
  190. {
  191. UINT uControls = 1;
  192. if (acci != NULL)
  193. {
  194. // calculate width and height of dialog units (in pixels)
  195. //
  196. DWORD dw = GetDialogBaseUnits();
  197. WORD cxBaseUnits = LOWORD(dw);
  198. WORD cyBaseUnits = HIWORD(dw);
  199. // fill in a CCINFOA struct for each supported control
  200. //
  201. strncpy(acci[0].szClass, TRACKMETER_CLASS_A,
  202. sizeof(acci[0].szClass));
  203. acci[0].flOptions = CCF_NOTEXT;
  204. strncpy(acci[0].szDesc, TRACKMETER_DESCRIPTION,
  205. sizeof(acci[0].szDesc));
  206. acci[0].cxDefault = (120 * 4) / max(1, cxBaseUnits);
  207. acci[0].cyDefault = (18 * 8) / max(1, cyBaseUnits);
  208. acci[0].flStyleDefault = WS_CHILD | WS_VISIBLE | SS_HORIZONTAL;
  209. acci[0].flExtStyleDefault = 0;
  210. acci[0].flCtrlTypeMask = 0;
  211. strncpy(acci[0].szTextDefault, TRACKMETER_DEFAULTTEXT,
  212. sizeof(acci[0].szTextDefault));
  213. acci[0].cStyleFlags = (sizeof(aTrackMeterStyleFlags) / sizeof(aTrackMeterStyleFlags[0]));
  214. acci[0].aStyleFlags = aTrackMeterStyleFlags;
  215. acci[0].lpfnStyle = TrackMeter_Style;
  216. acci[0].lpfnSizeToText = TrackMeter_SizeToText;
  217. acci[0].dwReserved1 = 0;
  218. acci[0].dwReserved2 = 0;
  219. }
  220. // return the number of controls that the DLL supports
  221. //
  222. return uControls;
  223. }
  224. // TrackMeter_Style - do modal dialog for custom control style
  225. // <hwndParent> (i) parent window (dialog editor)
  226. // <pccs> (i/o) pointer to CCSTYLE struct
  227. // returns TRUE if success, otherwise FALSE
  228. //
  229. BOOL DLLEXPORT CALLBACK TrackMeter_Style(HWND hWndParent, LPCCSTYLEA pccs)
  230. {
  231. BOOL fSuccess = TRUE;
  232. #if 0
  233. if (DialogBox(g_hInstLib, MAKEINTRESOURCE(IDD_TMETERSTYLE),
  234. hWndParent, TrackMeter_DlgProc) == -1)
  235. fSuccess = TraceFALSE(NULL);
  236. #else
  237. fSuccess = TraceFALSE(NULL);
  238. #endif
  239. return fSuccess;
  240. }
  241. // TrackMeter_SizeToText
  242. // <flStyle> (i) control style
  243. // <flExtStyle> (i) control extended style
  244. // <hFont> (i) handle of font used to draw text
  245. // <pszText> (i) control text
  246. // returns control width (pixels) needed to accomodate text, -1 if error
  247. //
  248. INT DLLEXPORT CALLBACK TrackMeter_SizeToText(
  249. DWORD flStyle, DWORD flExtStyle, HFONT hFont, LPSTR pszText)
  250. {
  251. // this control has no text to resize, so do nothing
  252. //
  253. return -1;
  254. }
  255. LRESULT DLLEXPORT CALLBACK TrackMeter_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  256. {
  257. BOOL fSuccess = TRUE;
  258. LPTMETER lptm = (LPTMETER) GetWindowLongPtr(hwnd, GWL_USER);
  259. #if 0
  260. TracePrintf_1(NULL, 1,
  261. TEXT("msg 0x%X\n"),
  262. (unsigned int) msg);
  263. #endif
  264. switch (msg)
  265. {
  266. HANDLE_MSG(hwnd, WM_NCCREATE, TrackMeter_OnNCCreate);
  267. HANDLE_MSG(lptm, WM_NCDESTROY, TrackMeter_OnNCDestroy);
  268. HANDLE_MSG(lptm, WM_CREATE, TrackMeter_OnCreate);
  269. HANDLE_MSG(lptm, WM_DESTROY, TrackMeter_OnDestroy);
  270. HANDLE_MSG(lptm, WM_SIZE, TrackMeter_OnSize);
  271. HANDLE_MSG(lptm, WM_ERASEBKGND, TrackMeter_OnEraseBkgnd);
  272. HANDLE_MSG(lptm, WM_PAINT, TrackMeter_OnPaint);
  273. HANDLE_MSG(lptm, WM_COMMAND, TrackMeter_OnCommand);
  274. HANDLE_MSG(lptm, WM_SETFOCUS, TrackMeter_OnSetFocus);
  275. HANDLE_MSG(lptm, WM_KILLFOCUS, TrackMeter_OnKillFocus);
  276. HANDLE_MSG(lptm, WM_ENABLE, TrackMeter_OnEnable);
  277. HANDLE_MSG(lptm, WM_GETDLGCODE, TrackMeter_OnGetDlgCode);
  278. HANDLE_MSG(lptm, WM_KEYDOWN, TrackMeter_OnKey);
  279. HANDLE_MSG(lptm, WM_KEYUP, TrackMeter_OnKey);
  280. HANDLE_MSG(lptm, WM_LBUTTONDOWN, TrackMeter_OnLButtonDown);
  281. HANDLE_MSG(lptm, WM_LBUTTONUP, TrackMeter_OnLButtonUp);
  282. // HANDLE_MSG(lptm, WM_RBUTTONDOWN, TrackMeter_OnRButtonDown);
  283. // HANDLE_MSG(lptm, WM_RBUTTONUP, TrackMeter_OnRButtonUp);
  284. HANDLE_MSG(lptm, WM_MOUSEMOVE, TrackMeter_OnMouseMove);
  285. HANDLE_MSG(lptm, WM_CAPTURECHANGED, TrackMeter_OnCaptureChanged);
  286. HANDLE_MSG(lptm, TMM_GETPOS, TrackMeter_OnTMMGetPos);
  287. HANDLE_MSG(lptm, TMM_SETPOS, TrackMeter_OnTMMSetPos);
  288. HANDLE_MSG(lptm, TMM_GETRANGEMIN, TrackMeter_OnTMMGetRangeMin);
  289. HANDLE_MSG(lptm, TMM_SETRANGEMIN, TrackMeter_OnTMMSetRangeMin);
  290. HANDLE_MSG(lptm, TMM_GETRANGEMAX, TrackMeter_OnTMMGetRangeMax);
  291. HANDLE_MSG(lptm, TMM_SETRANGEMAX, TrackMeter_OnTMMSetRangeMax);
  292. HANDLE_MSG(lptm, TMM_SETRANGE, TrackMeter_OnTMMSetRange);
  293. HANDLE_MSG(lptm, TMM_GETLEVEL, TrackMeter_OnTMMGetLevel);
  294. HANDLE_MSG(lptm, TMM_SETLEVEL, TrackMeter_OnTMMSetLevel);
  295. HANDLE_MSG(lptm, TMM_GETCOLOR, TrackMeter_OnTMMGetColor);
  296. HANDLE_MSG(lptm, TMM_SETCOLOR, TrackMeter_OnTMMSetColor);
  297. default:
  298. return TrackMeter_DefProc(hwnd, msg, wParam, lParam);
  299. }
  300. return (LRESULT) TRUE;
  301. }
  302. ////
  303. // helper functions
  304. ////
  305. static BOOL TrackMeter_OnNCCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
  306. {
  307. BOOL fSuccess = TRUE;
  308. LPTMETER lptm;
  309. // create control struct and associate it with window
  310. //
  311. if ((lptm = (LPTMETER) GetWindowLongPtr(hwnd, GWL_USER)) == NULL &&
  312. (lptm = (LPTMETER) MemAlloc(NULL, sizeof(TMETER), 0)) == NULL)
  313. {
  314. fSuccess = TraceFALSE(NULL);
  315. return FALSE;
  316. }
  317. else
  318. {
  319. lptm->hwnd = hwnd;
  320. SetWindowLongPtr(hwnd, GWL_USER, (LONG_PTR) lptm);
  321. }
  322. return FORWARD_WM_NCCREATE(hwnd, lpCreateStruct, DefWindowProc);
  323. }
  324. static void TrackMeter_OnNCDestroy(LPTMETER lptm)
  325. {
  326. BOOL fSuccess = TRUE;
  327. // destroy control struct and disassociate it from window
  328. //
  329. if (lptm != NULL)
  330. {
  331. HWND hwnd = lptm->hwnd;
  332. SetWindowLongPtr(hwnd, GWL_USER, (LPARAM) NULL);
  333. if ((lptm = MemFree(NULL, lptm)) != NULL)
  334. fSuccess = TraceFALSE(NULL);
  335. FORWARD_WM_NCDESTROY(hwnd, DefWindowProc);
  336. }
  337. }
  338. static BOOL TrackMeter_OnCreate(LPTMETER lptm, CREATESTRUCT FAR* lpCreateStruct)
  339. {
  340. BOOL fSuccess = TRUE;
  341. HWND hwnd = lptm->hwnd;
  342. LPVOID lpParam = (LPVOID) lpCreateStruct->lpCreateParams;
  343. HDC hdc = NULL;
  344. if ((hdc = GetDC(hwnd)) == NULL)
  345. fSuccess = TraceFALSE(NULL);
  346. else if ((lptm->hdcCompat = CreateCompatibleDC(hdc)) == NULL)
  347. fSuccess = TraceFALSE(NULL);
  348. else
  349. {
  350. lptm->hwndParent = lpCreateStruct->hwndParent;
  351. lptm->hdcCompat = lptm->hdcCompat; // recalc during WM_CREATE
  352. lptm->hbmpSave = NULL;
  353. lptm->hbmpCompat = NULL;
  354. lptm->lPosition = 0;
  355. lptm->lMinimum = 0;
  356. lptm->lMaximum = 100;
  357. lptm->lLevel = 0;
  358. lptm->lLineSize = 1;
  359. lptm->lPageSize = lptm->lPageSize; // recalc later
  360. lptm->fHasFocus = FALSE;
  361. lptm->fIsEnabled = TRUE;
  362. lptm->fIsThumbPressed = FALSE;
  363. lptm->dwFlags = 0;
  364. TrackMeter_Recalc(lptm, TMR_ALL);
  365. }
  366. if (hdc != NULL)
  367. ReleaseDC(hwnd, hdc);
  368. return fSuccess ? 1 : -1;
  369. }
  370. static void TrackMeter_OnDestroy(LPTMETER lptm)
  371. {
  372. BOOL fSuccess = TRUE;
  373. SelectObject(lptm->hdcCompat, lptm->hbmpSave);
  374. if (lptm->hbmpCompat != NULL && !DeleteObject(lptm->hbmpCompat))
  375. fSuccess = TraceFALSE(NULL);
  376. else
  377. lptm->hbmpCompat = NULL;
  378. if (lptm->hdcCompat != NULL && !DeleteDC(lptm->hdcCompat))
  379. fSuccess = TraceFALSE(NULL);
  380. else
  381. lptm->hdcCompat = NULL;
  382. }
  383. static void TrackMeter_OnSize(LPTMETER lptm, UINT state, int cx, int cy)
  384. {
  385. BOOL fSuccess = TRUE;
  386. HWND hwnd = lptm->hwnd;
  387. TracePrintf_3(NULL, 6,
  388. TEXT("WM_SIZE, state=%u, cx=%d, cy=%d\n"),
  389. (unsigned) state,
  390. (int) cx,
  391. (int) cy);
  392. switch (state)
  393. {
  394. case SIZE_RESTORED:
  395. case SIZE_MAXIMIZED:
  396. {
  397. HDC hdc = NULL;
  398. HBITMAP hbmpTemp = NULL;
  399. if ((hdc = GetDC(hwnd)) == NULL)
  400. fSuccess = TraceFALSE(NULL);
  401. else if (TrackMeter_Recalc(lptm, TMR_TRACK | TMR_METER | TMR_LEVEL | TMR_THUMB) != 0)
  402. fSuccess = TraceFALSE(NULL);
  403. else if ((hbmpTemp = CreateCompatibleBitmap(hdc, cx, cy)) == NULL)
  404. fSuccess = TraceFALSE(NULL);
  405. else
  406. {
  407. lptm->hbmpSave = SelectObject(lptm->hdcCompat, hbmpTemp);
  408. if (lptm->hbmpCompat != NULL && !DeleteObject(lptm->hbmpCompat))
  409. fSuccess = TraceFALSE(NULL);
  410. else
  411. lptm->hbmpCompat = hbmpTemp;
  412. }
  413. if (hdc != NULL)
  414. ReleaseDC(hwnd, hdc);
  415. InvalidateRect(hwnd, NULL, FALSE);
  416. }
  417. break;
  418. default:
  419. break;
  420. }
  421. }
  422. static BOOL TrackMeter_OnEraseBkgnd(LPTMETER lptm, HDC hdc)
  423. {
  424. BOOL fSuccess = TRUE;
  425. // we do nothing
  426. //
  427. return fSuccess;
  428. }
  429. static void TrackMeter_OnPaint(LPTMETER lptm)
  430. {
  431. BOOL fSuccess = TRUE;
  432. PAINTSTRUCT ps;
  433. BOOL fBitBlt = TRUE;
  434. HDC hdc;
  435. //
  436. // We have tot ake care for EndPaint
  437. //
  438. if (!BeginPaint(lptm->hwnd, &ps))
  439. {
  440. fSuccess = TraceFALSE(NULL);
  441. }
  442. else
  443. {
  444. if ((hdc = (fBitBlt ? lptm->hdcCompat : ps.hdc)) == NULL)
  445. {
  446. EndPaint( lptm->hwnd, &ps);
  447. fSuccess = TraceFALSE(NULL);
  448. }
  449. else if (TrackMeter_Draw(lptm, hdc))
  450. {
  451. EndPaint( lptm->hwnd, &ps);
  452. fSuccess = TraceFALSE(NULL);
  453. }
  454. else if (!EndPaint(lptm->hwnd, &ps))
  455. fSuccess = TraceFALSE(NULL);
  456. else if (fBitBlt && !BitBlt(ps.hdc, ps.rcPaint.left, ps.rcPaint.top,
  457. ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top,
  458. lptm->hdcCompat, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY))
  459. {
  460. fSuccess = TraceFALSE(NULL);
  461. }
  462. }
  463. }
  464. static int TrackMeter_Draw(LPTMETER lptm, HDC hdc)
  465. {
  466. BOOL fSuccess = TRUE;
  467. HPEN hpenOld = GetCurrentObject(hdc, OBJ_PEN);
  468. HBRUSH hbrushOld = GetCurrentObject(hdc, OBJ_BRUSH);
  469. LONG_PTR LPStyle = GetWindowLongPtr(lptm->hwnd, GWL_STYLE);
  470. BOOL fDrawThumb = !(LPStyle & TMS_NOTHUMB);
  471. // draw background of control
  472. //
  473. if (1)
  474. {
  475. HBRUSH hbrushCtrlBackground;
  476. if ((hbrushCtrlBackground = CreateSolidBrush(lptm->acr[TMCR_CTRLBACKGROUND])) == NULL)
  477. fSuccess = TraceFALSE(NULL);
  478. else
  479. {
  480. if (!FillRect(hdc, &lptm->rcCtrl, hbrushCtrlBackground))
  481. fSuccess = TraceFALSE(NULL);
  482. if (!DeleteObject(hbrushCtrlBackground))
  483. fSuccess = TraceFALSE(NULL);
  484. }
  485. }
  486. // draw background of track
  487. //
  488. if (1)
  489. {
  490. HBRUSH hbrushTrackBackground;
  491. if ((hbrushTrackBackground = CreateSolidBrush(lptm->acr[TMCR_TRACKBACKGROUND])) == NULL)
  492. fSuccess = TraceFALSE(NULL);
  493. else
  494. {
  495. if (!FillRect(hdc, &lptm->rcTrack, hbrushTrackBackground))
  496. fSuccess = TraceFALSE(NULL);
  497. if (!DeleteObject(hbrushTrackBackground))
  498. fSuccess = TraceFALSE(NULL);
  499. }
  500. }
  501. // draw track light
  502. //
  503. if (1)
  504. {
  505. HPEN hpenTrackLight;
  506. if ((hpenTrackLight = CreatePen(PS_SOLID, 1, lptm->acr[TMCR_TRACKLIGHT])) == NULL)
  507. fSuccess = TraceFALSE(NULL);
  508. else
  509. {
  510. SelectObject(hdc, hpenTrackLight);
  511. MoveToEx(hdc, lptm->rcTrack.right, lptm->rcTrack.top, NULL);
  512. LineTo(hdc, lptm->rcTrack.right, lptm->rcTrack.bottom + 1);
  513. MoveToEx(hdc, lptm->rcTrack.right, lptm->rcTrack.bottom, NULL);
  514. LineTo(hdc, lptm->rcTrack.left - 1, lptm->rcTrack.bottom);
  515. if (!DeleteObject(hpenTrackLight))
  516. fSuccess = TraceFALSE(NULL);
  517. }
  518. }
  519. // draw track shadow
  520. //
  521. if (1)
  522. {
  523. HPEN hpenTrackShadow;
  524. if ((hpenTrackShadow = CreatePen(PS_SOLID, 1,
  525. lptm->fIsEnabled ? lptm->acr[TMCR_TRACKSHADOW] :
  526. lptm->acr[TMCR_CTRLBACKGROUND])) == NULL)
  527. fSuccess = TraceFALSE(NULL);
  528. else
  529. {
  530. SelectObject(hdc, hpenTrackShadow);
  531. MoveToEx(hdc, lptm->rcTrack.left, lptm->rcTrack.top, NULL);
  532. LineTo(hdc, lptm->rcTrack.right, lptm->rcTrack.top);
  533. MoveToEx(hdc, lptm->rcTrack.left, lptm->rcTrack.top, NULL);
  534. LineTo(hdc, lptm->rcTrack.left, lptm->rcTrack.bottom);
  535. if (!DeleteObject(hpenTrackShadow))
  536. fSuccess = TraceFALSE(NULL);
  537. }
  538. }
  539. // draw track dark shadow
  540. //
  541. if (1)
  542. {
  543. HPEN hpenTrackDkShadow;
  544. if ((hpenTrackDkShadow = CreatePen(PS_SOLID, 1,
  545. lptm->fIsEnabled ? lptm->acr[TMCR_TRACKDKSHADOW] :
  546. lptm->acr[TMCR_TRACKSHADOW])) == NULL)
  547. fSuccess = TraceFALSE(NULL);
  548. else
  549. {
  550. SelectObject(hdc, hpenTrackDkShadow);
  551. MoveToEx(hdc, lptm->rcTrack.left + 1, lptm->rcTrack.top + 1, NULL);
  552. LineTo(hdc, lptm->rcTrack.right - 1, lptm->rcTrack.top + 1);
  553. MoveToEx(hdc, lptm->rcTrack.left + 1, lptm->rcTrack.top + 1, NULL);
  554. LineTo(hdc, lptm->rcTrack.left + 1, lptm->rcTrack.bottom - 1);
  555. if (!DeleteObject(hpenTrackDkShadow))
  556. fSuccess = TraceFALSE(NULL);
  557. }
  558. }
  559. // fill track up to current level
  560. //
  561. if (lptm->fIsEnabled && lptm->lLevel > lptm->lMinimum)
  562. {
  563. HBRUSH hbrushLevel;
  564. if ((hbrushLevel = CreateSolidBrush(lptm->acr[TMCR_LEVEL])) == NULL)
  565. fSuccess = TraceFALSE(NULL);
  566. else
  567. {
  568. FillRect(hdc, &lptm->rcLevel, hbrushLevel);
  569. if (!DeleteObject(hbrushLevel))
  570. fSuccess = TraceFALSE(NULL);
  571. }
  572. }
  573. // fill thumb region
  574. //
  575. if (fDrawThumb)
  576. {
  577. HRGN hrgnThumb;
  578. if ((hrgnThumb = CreatePolygonRgn(lptm->aptThumb,
  579. (sizeof(lptm->aptThumb)/sizeof(lptm->aptThumb[0])), WINDING)) == NULL)
  580. fSuccess = TraceFALSE(NULL);
  581. else
  582. {
  583. HBRUSH hbrushThumbFace;
  584. if ((hbrushThumbFace = CreateSolidBrush(lptm->acr[lptm->fIsThumbPressed ?
  585. TMCR_THUMBFACEPRESSED : TMCR_THUMBFACE])) == NULL)
  586. fSuccess = TraceFALSE(NULL);
  587. else
  588. {
  589. if (!FillRgn(hdc, hrgnThumb, hbrushThumbFace))
  590. fSuccess = TraceFALSE(NULL);
  591. if (!DeleteObject(hbrushThumbFace))
  592. fSuccess = TraceFALSE(NULL);
  593. }
  594. if (!DeleteObject(hrgnThumb))
  595. fSuccess = TraceFALSE(NULL);
  596. }
  597. }
  598. // draw thumb light
  599. //
  600. if (fDrawThumb)
  601. {
  602. HPEN hpenThumbLight;
  603. if ((hpenThumbLight = CreatePen(PS_SOLID, 1,
  604. lptm->fIsEnabled ? lptm->acr[TMCR_THUMBLIGHT] :
  605. lptm->acr[TMCR_THUMBSHADOW])) == NULL)
  606. fSuccess = TraceFALSE(NULL);
  607. else
  608. {
  609. SelectObject(hdc, hpenThumbLight);
  610. MoveToEx(hdc, lptm->aptThumb[0].x, lptm->aptThumb[0].y, NULL);
  611. LineTo(hdc, lptm->aptThumb[1].x - 1, lptm->aptThumb[1].y + 1);
  612. MoveToEx(hdc, lptm->aptThumb[1].x, lptm->aptThumb[1].y, NULL);
  613. LineTo(hdc, lptm->aptThumb[2].x, lptm->aptThumb[2].y);
  614. if (!DeleteObject(hpenThumbLight))
  615. fSuccess = TraceFALSE(NULL);
  616. }
  617. }
  618. // draw thumb dark shadow
  619. //
  620. if (fDrawThumb)
  621. {
  622. HPEN hpenThumbDkShadow;
  623. if ((hpenThumbDkShadow = CreatePen(PS_SOLID, 1,
  624. lptm->fIsEnabled ? lptm->acr[TMCR_THUMBDKSHADOW] :
  625. lptm->acr[TMCR_THUMBLIGHT])) == NULL)
  626. fSuccess = TraceFALSE(NULL);
  627. else
  628. {
  629. SelectObject(hdc, hpenThumbDkShadow);
  630. MoveToEx(hdc, lptm->aptThumb[2].x, lptm->aptThumb[2].y, NULL);
  631. LineTo(hdc, lptm->aptThumb[3].x + 1, lptm->aptThumb[3].y);
  632. MoveToEx(hdc, lptm->aptThumb[3].x, lptm->aptThumb[3].y, NULL);
  633. LineTo(hdc, lptm->aptThumb[4].x, lptm->aptThumb[4].y - 1);
  634. MoveToEx(hdc, lptm->aptThumb[4].x, lptm->aptThumb[4].y, NULL);
  635. LineTo(hdc, lptm->aptThumb[0].x, lptm->aptThumb[0].y);
  636. if (!DeleteObject(hpenThumbDkShadow))
  637. fSuccess = TraceFALSE(NULL);
  638. }
  639. }
  640. // draw focus border, if necessary
  641. //
  642. if (lptm->fHasFocus)
  643. {
  644. COLORREF crBkColorOld = SetBkColor(hdc, lptm->acr[TMCR_FOCUSBACKGROUND]);
  645. if (!DrawFocusRect(hdc, &lptm->rcCtrl))
  646. fSuccess = TraceFALSE(NULL);
  647. SetBkColor(hdc, crBkColorOld);
  648. }
  649. // cleanup
  650. //
  651. if (hpenOld != NULL)
  652. SelectObject(hdc, hpenOld);
  653. if (hbrushOld != NULL)
  654. SelectObject(hdc, hbrushOld);
  655. return fSuccess ? 0 : -1;
  656. }
  657. static void TrackMeter_OnCommand(LPTMETER lptm, int id, HWND hwndCtl, UINT codeNotify)
  658. {
  659. }
  660. static void TrackMeter_OnSetFocus(LPTMETER lptm, HWND hwndOldFocus)
  661. {
  662. BOOL fSuccess = TRUE;
  663. TracePrintf_0(NULL, 6,
  664. TEXT("WM_SETFOCUS\n"));
  665. lptm->fHasFocus = TRUE;
  666. if (!InvalidateRect(lptm->hwnd, NULL, TRUE))
  667. fSuccess = TraceFALSE(NULL);
  668. }
  669. static void TrackMeter_OnKillFocus(LPTMETER lptm, HWND hwndNewFocus)
  670. {
  671. BOOL fSuccess = TRUE;
  672. TracePrintf_0(NULL, 6,
  673. TEXT("WM_KILLFOCUS\n"));
  674. lptm->fHasFocus = FALSE;
  675. if (!InvalidateRect(lptm->hwnd, NULL, TRUE))
  676. fSuccess = TraceFALSE(NULL);
  677. }
  678. static void TrackMeter_OnEnable(LPTMETER lptm, BOOL fEnable)
  679. {
  680. BOOL fSuccess = TRUE;
  681. TracePrintf_1(NULL, 6,
  682. TEXT("WM_ENABLE, fEnable=%d\n"),
  683. (int) fEnable);
  684. lptm->fIsEnabled = fEnable;
  685. if (!InvalidateRect(lptm->hwnd, NULL, TRUE))
  686. fSuccess = TraceFALSE(NULL);
  687. }
  688. static UINT TrackMeter_OnGetDlgCode(LPTMETER lptm, LPMSG lpmsg)
  689. {
  690. return DLGC_WANTARROWS;
  691. }
  692. static void TrackMeter_OnKey(LPTMETER lptm, UINT vk, BOOL fDown, int cRepeat, UINT flags)
  693. {
  694. UINT code = 0;
  695. UINT nPos = 0;
  696. LONG lPosition;
  697. switch (vk)
  698. {
  699. case VK_UP:
  700. case VK_RIGHT:
  701. lPosition = lptm->lPosition + lptm->lLineSize;
  702. code = TB_LINEDOWN;
  703. break;
  704. case VK_DOWN:
  705. case VK_LEFT:
  706. lPosition = lptm->lPosition - lptm->lLineSize;
  707. code = TB_LINEUP;
  708. break;
  709. case VK_NEXT:
  710. lPosition = lptm->lPosition + lptm->lPageSize;
  711. code = TB_PAGEDOWN;
  712. break;
  713. case VK_PRIOR:
  714. lPosition = lptm->lPosition - lptm->lPageSize;
  715. code = TB_PAGEUP;
  716. break;
  717. case VK_HOME:
  718. lPosition = lptm->lMinimum;
  719. code = TB_TOP;
  720. break;
  721. case VK_END:
  722. lPosition = lptm->lMaximum;
  723. code = TB_BOTTOM;
  724. break;
  725. default:
  726. return;
  727. }
  728. // Adjust position of thumb
  729. if (fDown)
  730. {
  731. // we change the current position for WM_KEYDOWN only
  732. TrackMeter_OnTMMSetPos(lptm, lPosition, TRUE);
  733. TrackMeter_NotifyParent(lptm, code, 0);
  734. }
  735. TrackMeter_NotifyParent(lptm, TB_ENDTRACK, 0);
  736. }
  737. static void TrackMeter_OnLButtonDown(LPTMETER lptm, BOOL fDoubleClick, int x, int y, UINT keyFlags)
  738. {
  739. SetFocus(lptm->hwnd);
  740. SetCapture(lptm->hwnd);
  741. TracePrintf_3(NULL, 6,
  742. TEXT("WM_LBUTTONDOWN, fDoubleClick=%d, x=%d, y=%d\n"),
  743. (int) fDoubleClick,
  744. (int) x,
  745. (int) y);
  746. if (TrackMeter_PtInThumb(lptm, x, y))
  747. {
  748. lptm->fIsThumbPressed = TRUE;
  749. TrackMeter_OnMouseMove(lptm, x, y, 0);
  750. }
  751. else if (x < lptm->aptThumb[0].x)
  752. TrackMeter_OnKey(lptm, VK_PRIOR, TRUE, 1, 0);
  753. else if (x > lptm->aptThumb[0].x)
  754. TrackMeter_OnKey(lptm, VK_NEXT, TRUE, 1, 0);
  755. }
  756. static void TrackMeter_OnLButtonUp(LPTMETER lptm, int x, int y, UINT keyFlags)
  757. {
  758. TracePrintf_2(NULL, 6,
  759. TEXT("WM_LBUTTONUP, x=%d, y=%d\n"),
  760. (int) x,
  761. (int) y);
  762. ReleaseCapture();
  763. if (lptm->fIsThumbPressed)
  764. {
  765. LONG lPosition = TrackMeter_XToPosition(lptm, x);
  766. lptm->fIsThumbPressed = FALSE;
  767. TrackMeter_OnTMMSetPos(lptm, lptm->lPosition, TRUE); // just redraw
  768. if (lPosition >= lptm->lMinimum && lPosition <= lptm->lMaximum)
  769. TrackMeter_NotifyParent(lptm, TB_THUMBPOSITION, lptm->lPosition);
  770. }
  771. TrackMeter_NotifyParent(lptm, TB_ENDTRACK, 0);
  772. }
  773. static void TrackMeter_OnRButtonDown(LPTMETER lptm, BOOL fDoubleClick, int x, int y, UINT keyFlags)
  774. {
  775. SetFocus(lptm->hwnd);
  776. SetCapture(lptm->hwnd);
  777. TracePrintf_3(NULL, 6,
  778. TEXT("WM_RBUTTONDOWN, fDoubleClick=%d, x=%d, y=%d\n"),
  779. (int) fDoubleClick,
  780. (int) x,
  781. (int) y);
  782. if (TrackMeter_PtInThumb(lptm, x, y))
  783. {
  784. LONG lPosition = TrackMeter_XToPosition(lptm, x);
  785. lptm->fIsThumbPressed = TRUE;
  786. TrackMeter_OnTMMSetPos(lptm, lPosition, TRUE);
  787. TrackMeter_OnMouseMove(lptm, lptm->aptThumb[0].x, y, 0);
  788. TrackMeter_NotifyParent(lptm, TB_THUMBPOSITION, lptm->lPosition);
  789. }
  790. }
  791. static void TrackMeter_OnRButtonUp(LPTMETER lptm, int x, int y, UINT keyFlags)
  792. {
  793. TracePrintf_2(NULL, 6,
  794. TEXT("WM_RBUTTONUP, x=%d, y=%d\n"),
  795. (int) x,
  796. (int) y);
  797. ReleaseCapture();
  798. if ( lptm->fIsThumbPressed )
  799. TrackMeter_NotifyParent(lptm, TB_ENDTRACK, 0);
  800. }
  801. static void TrackMeter_OnMouseMove(LPTMETER lptm, int x, int y, UINT keyFlags)
  802. {
  803. if (lptm->fIsThumbPressed)
  804. {
  805. LONG lPosition = TrackMeter_XToPosition(lptm, x);
  806. TracePrintf_2(NULL, 6,
  807. TEXT("WM_MOUSEMOVE, x=%d, y=%d\n"),
  808. (int) x,
  809. (int) y);
  810. if (lPosition != lptm->lPosition)
  811. {
  812. TrackMeter_OnTMMSetPos(lptm, lPosition, TRUE);
  813. TrackMeter_NotifyParent(lptm, TB_THUMBTRACK, lptm->lPosition);
  814. }
  815. }
  816. }
  817. static void TrackMeter_OnCaptureChanged(LPTMETER lptm, HWND hwndNewCapture)
  818. {
  819. TracePrintf_0(NULL, 6,
  820. TEXT("WM_CAPTURECHANGED\n"));
  821. }
  822. static void TrackMeter_NotifyParent(LPTMETER lptm, UINT code, UINT nPos)
  823. {
  824. if (TraceGetLevel(NULL) >= 6)
  825. {
  826. LPTSTR lpszCode;
  827. switch (code)
  828. {
  829. case TB_LINEUP:
  830. lpszCode = TEXT("LB_LINEUP");
  831. break;
  832. case TB_LINEDOWN:
  833. lpszCode = TEXT("LB_LINEDOWN");
  834. break;
  835. case TB_PAGEUP:
  836. lpszCode = TEXT("LB_PAGEUP");
  837. break;
  838. case TB_PAGEDOWN:
  839. lpszCode = TEXT("LB_PAGEDOWN");
  840. break;
  841. case TB_TOP:
  842. lpszCode = TEXT("LB_TOP");
  843. break;
  844. case TB_BOTTOM:
  845. lpszCode = TEXT("LB_BOTTOM");
  846. break;
  847. case TB_ENDTRACK:
  848. lpszCode = TEXT("LB_ENDTRACK");
  849. break;
  850. case TB_THUMBTRACK:
  851. lpszCode = TEXT("LB_THUMBTRACK");
  852. break;
  853. case TB_THUMBPOSITION:
  854. lpszCode = TEXT("LB_THUMBPOSITION");
  855. break;
  856. default:
  857. lpszCode = TEXT("***unknown***");
  858. break;
  859. }
  860. TracePrintf_4(NULL, 6,
  861. TEXT("WM_HSCROLL, %s, code=%u, nPos=%u, lPosition=%ld\n"),
  862. (LPTSTR) lpszCode,
  863. (unsigned) code,
  864. (unsigned) nPos,
  865. (long) lptm->lPosition);
  866. }
  867. if (1) // $FIXUP - check for horizontal style here
  868. {
  869. FORWARD_WM_HSCROLL(lptm->hwndParent,
  870. lptm->hwnd, code, nPos, SendMessage);
  871. }
  872. else
  873. {
  874. FORWARD_WM_VSCROLL(lptm->hwndParent,
  875. lptm->hwnd, code, nPos, SendMessage);
  876. }
  877. }
  878. static LONG TrackMeter_OnTMMGetPos(LPTMETER lptm)
  879. {
  880. BOOL fSuccess = TRUE;
  881. LONG lPosition = 0;
  882. if (lptm == NULL)
  883. fSuccess = TraceFALSE(NULL);
  884. else
  885. lPosition = lptm->lPosition;
  886. return lPosition;
  887. }
  888. static void TrackMeter_OnTMMSetPos(LPTMETER lptm, LONG lPosition, BOOL fRedraw)
  889. {
  890. BOOL fSuccess = TRUE;
  891. if (lptm == NULL)
  892. fSuccess = TraceFALSE(NULL);
  893. else
  894. {
  895. lptm->lPosition = max(lptm->lMinimum,
  896. min(lPosition, lptm->lMaximum));
  897. if (TrackMeter_Recalc(lptm, TMR_THUMB) != 0)
  898. fSuccess = TraceFALSE(NULL);
  899. if (fRedraw && !InvalidateRect(lptm->hwnd, NULL, TRUE))
  900. fSuccess = TraceFALSE(NULL);
  901. }
  902. }
  903. static LONG TrackMeter_OnTMMGetRangeMin(LPTMETER lptm)
  904. {
  905. BOOL fSuccess = TRUE;
  906. LONG lMinimum = 0;
  907. if (lptm == NULL)
  908. fSuccess = TraceFALSE(NULL);
  909. else
  910. lMinimum = lptm->lMinimum;
  911. return lMinimum;
  912. }
  913. static void TrackMeter_OnTMMSetRangeMin(LPTMETER lptm, LONG lMinimum, BOOL fRedraw)
  914. {
  915. BOOL fSuccess = TRUE;
  916. if (lptm == NULL)
  917. fSuccess = TraceFALSE(NULL);
  918. else
  919. {
  920. lptm->lMinimum = lMinimum;
  921. // adjust position and level if necessary
  922. //
  923. TrackMeter_OnTMMSetPos(lptm, lptm->lPosition, FALSE);
  924. TrackMeter_OnTMMSetLevel(lptm, lptm->lLevel, FALSE);
  925. if (TrackMeter_Recalc(lptm, TMR_PAGESIZE) != 0)
  926. fSuccess = TraceFALSE(NULL);
  927. if (fRedraw && !InvalidateRect(lptm->hwnd, NULL, TRUE))
  928. fSuccess = TraceFALSE(NULL);
  929. }
  930. }
  931. static LONG TrackMeter_OnTMMGetRangeMax(LPTMETER lptm)
  932. {
  933. BOOL fSuccess = TRUE;
  934. LONG lMaximum = 0;
  935. if (lptm == NULL)
  936. fSuccess = TraceFALSE(NULL);
  937. else
  938. lMaximum = lptm->lMaximum;
  939. return lMaximum;
  940. }
  941. static void TrackMeter_OnTMMSetRangeMax(LPTMETER lptm, LONG lMaximum, BOOL fRedraw)
  942. {
  943. BOOL fSuccess = TRUE;
  944. if (lptm == NULL)
  945. fSuccess = TraceFALSE(NULL);
  946. else
  947. {
  948. lptm->lMaximum = lMaximum;
  949. // adjust position and level if necessary
  950. //
  951. TrackMeter_OnTMMSetPos(lptm, lptm->lPosition, FALSE);
  952. TrackMeter_OnTMMSetLevel(lptm, lptm->lLevel, FALSE);
  953. if (TrackMeter_Recalc(lptm, TMR_PAGESIZE) != 0)
  954. fSuccess = TraceFALSE(NULL);
  955. if (fRedraw && !InvalidateRect(lptm->hwnd, NULL, TRUE))
  956. fSuccess = TraceFALSE(NULL);
  957. }
  958. }
  959. static void TrackMeter_OnTMMSetRange(LPTMETER lptm, LONG lMinimum, LONG lMaximum, BOOL fRedraw)
  960. {
  961. TrackMeter_OnTMMSetRangeMin(lptm, lMinimum, FALSE);
  962. TrackMeter_OnTMMSetRangeMax(lptm, lMaximum, fRedraw);
  963. }
  964. static LONG TrackMeter_OnTMMGetLevel(LPTMETER lptm)
  965. {
  966. BOOL fSuccess = TRUE;
  967. LONG lLevel = 0;
  968. if (lptm == NULL)
  969. fSuccess = TraceFALSE(NULL);
  970. else
  971. lLevel = lptm->lLevel;
  972. return lLevel;
  973. }
  974. static void TrackMeter_OnTMMSetLevel(LPTMETER lptm, LONG lLevel, BOOL fRedraw)
  975. {
  976. BOOL fSuccess = TRUE;
  977. if (lptm == NULL)
  978. fSuccess = TraceFALSE(NULL);
  979. else
  980. {
  981. lptm->lLevel = max(lptm->lMinimum,
  982. min(lLevel, lptm->lMaximum));
  983. if (TrackMeter_Recalc(lptm, TMR_LEVEL) != 0)
  984. fSuccess = TraceFALSE(NULL);
  985. if (fRedraw && !InvalidateRect(lptm->hwnd, NULL, TRUE))
  986. fSuccess = TraceFALSE(NULL);
  987. }
  988. }
  989. static COLORREF TrackMeter_OnTMMGetColor(LPTMETER lptm, UINT elem)
  990. {
  991. BOOL fSuccess = TRUE;
  992. COLORREF cr = RGB(0, 0, 0);
  993. if (lptm == NULL)
  994. fSuccess = TraceFALSE(NULL);
  995. else
  996. cr = lptm->acr[elem];
  997. return cr;
  998. }
  999. static void TrackMeter_OnTMMSetColor(LPTMETER lptm, COLORREF cr, UINT elem, BOOL fRedraw)
  1000. {
  1001. BOOL fSuccess = TRUE;
  1002. if (lptm == NULL)
  1003. fSuccess = TraceFALSE(NULL);
  1004. else
  1005. {
  1006. lptm->acr[elem] = cr;
  1007. if (fRedraw && !InvalidateRect(lptm->hwnd, NULL, TRUE))
  1008. fSuccess = TraceFALSE(NULL);
  1009. }
  1010. }
  1011. static int TrackMeter_Recalc(LPTMETER lptm, DWORD dwFlags)
  1012. {
  1013. BOOL fSuccess = TRUE;
  1014. if (!GetClientRect(lptm->hwnd, &lptm->rcCtrl))
  1015. fSuccess = TraceFALSE(NULL);
  1016. else
  1017. {
  1018. int cxCtrl = lptm->rcCtrl.right - lptm->rcCtrl.left;
  1019. int cyCtrl = lptm->rcCtrl.bottom - lptm->rcCtrl.top;
  1020. int cxBorder = 2;
  1021. int cyBorder = 2;
  1022. int cxThumb = ((cyCtrl - cyBorder - cyBorder) / 2) * 2 - 1;
  1023. int cyThumb = cxThumb - 2;
  1024. int cyTrackTopBorder = 2;
  1025. int cxTrackLeftBorder = 2;
  1026. int cxTrackRightBorder = 2;
  1027. int cyTrackBottomBorder = 1;
  1028. int xTrack = cxThumb / 2 - cxTrackLeftBorder + cxBorder;
  1029. int yTrack = cyBorder;
  1030. int cxTrack = cxCtrl - xTrack - xTrack;
  1031. int cyTrack = (cyCtrl - cyBorder - cyBorder) / 2 + 1;
  1032. int xMeter = xTrack + cxTrackLeftBorder;
  1033. int yMeter = yTrack + cyTrackTopBorder;
  1034. int cxMeter = cxTrack - cxTrackLeftBorder - cxTrackRightBorder;
  1035. int cyMeter = cyTrack - cyTrackTopBorder - cyTrackBottomBorder;
  1036. if (dwFlags & TMR_TRACK)
  1037. {
  1038. lptm->rcTrack.left = xTrack;
  1039. lptm->rcTrack.top = yTrack;
  1040. lptm->rcTrack.right = xTrack + cxTrack - 1;
  1041. lptm->rcTrack.bottom = yTrack + cyTrack - 1;
  1042. }
  1043. if (dwFlags & TMR_METER)
  1044. {
  1045. lptm->rcMeter.left = xMeter;
  1046. lptm->rcMeter.top = yMeter;
  1047. lptm->rcMeter.right = xMeter + cxMeter - 1;
  1048. lptm->rcMeter.bottom = yMeter + cyMeter;
  1049. }
  1050. if (dwFlags & TMR_LEVEL)
  1051. {
  1052. lptm->rcLevel.left = xMeter;
  1053. lptm->rcLevel.top = yMeter;
  1054. lptm->rcLevel.right = TrackMeter_PositionToX(lptm, lptm->lLevel) + 1;
  1055. lptm->rcLevel.bottom = yMeter + cyMeter;
  1056. }
  1057. if (dwFlags & TMR_THUMB)
  1058. {
  1059. lptm->aptThumb[0].x = TrackMeter_PositionToX(lptm, lptm->lPosition);
  1060. lptm->aptThumb[0].y = cyCtrl - cyBorder - cyThumb;
  1061. lptm->aptThumb[1].x = lptm->aptThumb[0].x - (cxThumb / 2);
  1062. lptm->aptThumb[1].y = lptm->aptThumb[0].y + (cyThumb / 2) + 1;
  1063. lptm->aptThumb[2].x = lptm->aptThumb[1].x;
  1064. lptm->aptThumb[2].y = lptm->aptThumb[0].y + cyThumb - 1;
  1065. lptm->aptThumb[3].x = lptm->aptThumb[2].x + cxThumb - 1;
  1066. lptm->aptThumb[3].y = lptm->aptThumb[2].y;
  1067. lptm->aptThumb[4].x = lptm->aptThumb[3].x;
  1068. lptm->aptThumb[4].y = lptm->aptThumb[1].y;
  1069. }
  1070. if (dwFlags & TMR_COLORS)
  1071. {
  1072. COLORREF crWindow = GetSysColor(COLOR_WINDOW);
  1073. COLORREF cr3DFace = GetSysColor(COLOR_3DFACE);
  1074. COLORREF cr3DLight = GetSysColor(COLOR_3DLIGHT);
  1075. COLORREF cr3DHilight = GetSysColor(COLOR_3DHILIGHT);
  1076. COLORREF cr3DShadow = GetSysColor(COLOR_3DSHADOW);
  1077. COLORREF cr3DDkShadow = GetSysColor(COLOR_3DDKSHADOW);
  1078. COLORREF crGreen = RGB(0, 128, 0);
  1079. // try to make cr3DLight distinctive
  1080. //
  1081. if (cr3DLight == cr3DFace || cr3DLight == cr3DHilight)
  1082. {
  1083. HDC hdc = NULL;
  1084. int nColors;
  1085. if ((hdc = GetDC(NULL)) == NULL)
  1086. fSuccess = TraceFALSE(NULL);
  1087. // make sure screen device has more than 8 bits per pixel
  1088. //
  1089. else if ((nColors = GetDeviceCaps(hdc, NUMCOLORS)) == -1)
  1090. {
  1091. cr3DLight = RGB((GetRValue(cr3DFace) + GetRValue(cr3DHilight)) / 2,
  1092. (GetGValue(cr3DFace) + GetGValue(cr3DHilight)) / 2,
  1093. (GetBValue(cr3DFace) + GetBValue(cr3DHilight)) / 2);
  1094. }
  1095. else
  1096. {
  1097. cr3DLight = cr3DHilight;
  1098. }
  1099. if (hdc != NULL && !ReleaseDC(NULL, hdc))
  1100. fSuccess = TraceFALSE(NULL);
  1101. }
  1102. lptm->acr[TMCR_CTRLBACKGROUND] = cr3DFace;
  1103. lptm->acr[TMCR_FOCUSBACKGROUND] = crWindow;
  1104. lptm->acr[TMCR_TRACKBACKGROUND] = cr3DLight;
  1105. lptm->acr[TMCR_TRACKLIGHT] = cr3DHilight;
  1106. lptm->acr[TMCR_TRACKSHADOW] = cr3DShadow;
  1107. lptm->acr[TMCR_TRACKDKSHADOW] = cr3DDkShadow;
  1108. lptm->acr[TMCR_THUMBFACE] = cr3DFace;
  1109. lptm->acr[TMCR_THUMBFACEPRESSED] = cr3DLight;
  1110. lptm->acr[TMCR_THUMBLIGHT] = cr3DHilight;
  1111. lptm->acr[TMCR_THUMBSHADOW] = cr3DShadow;
  1112. lptm->acr[TMCR_THUMBDKSHADOW] = cr3DDkShadow;
  1113. lptm->acr[TMCR_LEVEL] = crGreen;
  1114. }
  1115. if (dwFlags & TMR_PAGESIZE)
  1116. {
  1117. lptm->lPageSize = max(1, (lptm->lMaximum - lptm->lMinimum) / 5);
  1118. }
  1119. }
  1120. return fSuccess ? 0 : -1;
  1121. }
  1122. // given lPosition between lptm->lMinimum and lptm->lMaximum,
  1123. // return x coordinate between lptm->rcMeter.left and lptm->rcMeter.right
  1124. //
  1125. static int TrackMeter_PositionToX(LPTMETER lptm, long lPosition)
  1126. {
  1127. long lPos = max(lptm->lMinimum, min(lPosition, lptm->lMaximum));
  1128. long lPct = ((1000 * (lPos - lptm->lMinimum) /
  1129. max(1, lptm->lMaximum - lptm->lMinimum)) + 5) / 10;
  1130. int cxMeter = lptm->rcMeter.right - lptm->rcMeter.left + 1;
  1131. long cxPosition = ((10 * max(0, min(100, lPct)) * cxMeter / 100) + 5) / 10;
  1132. int xPosition = max(lptm->rcMeter.left, lptm->rcMeter.left + min(cxPosition, cxMeter) - 1);
  1133. return xPosition;
  1134. }
  1135. // given x coordinate between lptm->rcMeter.left and lptm->rcMeter.right,
  1136. // return lPosition between lptm->lMinimum and lptm->lMaximum
  1137. //
  1138. static long TrackMeter_XToPosition(LPTMETER lptm, int xPosition)
  1139. {
  1140. int x = max(lptm->rcMeter.left, min(xPosition, lptm->rcMeter.right));
  1141. long lPct = ((1000 * (x - lptm->rcMeter.left) /
  1142. max(1, lptm->rcMeter.right - lptm->rcMeter.left)) + 5) / 10;
  1143. long lRange = lptm->lMaximum - lptm->lMinimum + 1;
  1144. long cxPosition = ((10 * max(0, min(100, lPct)) * lRange / 100) + 5) / 10;
  1145. long lPosition = max(lptm->lMinimum, lptm->lMinimum + min(cxPosition, lRange) - 1);
  1146. return lPosition;
  1147. }
  1148. static BOOL TrackMeter_PtInThumb(LPTMETER lptm, int x, int y)
  1149. {
  1150. BOOL fSuccess = TRUE;
  1151. BOOL fInThumb = FALSE;
  1152. HRGN hrgnThumb;
  1153. if ((hrgnThumb = CreatePolygonRgn(lptm->aptThumb,
  1154. (sizeof(lptm->aptThumb) / sizeof(lptm->aptThumb[0])), WINDING)) == NULL)
  1155. fSuccess = TraceFALSE(NULL);
  1156. else
  1157. {
  1158. if (PtInRegion(hrgnThumb, x, y))
  1159. fInThumb = TRUE;
  1160. if (!DeleteObject(hrgnThumb))
  1161. fSuccess = TraceFALSE(NULL);
  1162. }
  1163. return fInThumb;
  1164. }