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.

756 lines
18 KiB

  1. //----------------------------------------------------------
  2. //
  3. // BUGBUG: make sure this stuff really works with the DWORD
  4. // ranges
  5. //
  6. //----------------------------------------------------------
  7. #include "ctlspriv.h"
  8. #include "tracki.h"
  9. #ifndef _WIN32
  10. #include "muldiv32.h"
  11. #else
  12. #define MulDiv32 MulDiv
  13. #endif
  14. #define THUMBSLOP 2
  15. #define TICKHEIGHT 2
  16. #define ABS(X) (X >= 0) ? X : -X
  17. #define BOUND(x,low,high) max(min(x, high),low)
  18. #define LONG2POINT(l, pt) ((pt).x = (SHORT)LOWORD(l), (pt).y = (SHORT)HIWORD(l))
  19. TCHAR aszTrackbarClassName[] = TRACKBAR_CLASS;
  20. LPARAM FAR CALLBACK _loadds TrackBarWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  21. //
  22. // convert a logical scroll-bar position to a physical pixel position
  23. //
  24. static int NEAR PASCAL TBLogToPhys(PTrackBar tb, DWORD dwPos)
  25. {
  26. if (tb->lLogMax == tb->lLogMin)
  27. return tb->rc.left;
  28. return (UINT)MulDiv32(dwPos - tb->lLogMin, tb->iSizePhys - 1,
  29. tb->lLogMax - tb->lLogMin) + tb->rc.left;
  30. }
  31. static LONG NEAR PASCAL TBPhysToLog(PTrackBar tb, int iPos)
  32. {
  33. if (tb->iSizePhys <= 1)
  34. return tb->lLogMin;
  35. if (iPos <= tb->rc.left)
  36. return tb->lLogMin;
  37. if (iPos >= tb->rc.right)
  38. return tb->lLogMax;
  39. return MulDiv32(iPos - tb->rc.left, tb->lLogMax - tb->lLogMin,
  40. tb->iSizePhys - 1) + tb->lLogMin;
  41. }
  42. /*
  43. Initialize the trackbar code.
  44. */
  45. BOOL FAR PASCAL InitTrackBar(HINSTANCE hInstance)
  46. {
  47. WNDCLASS wc;
  48. if (!GetClassInfo(hInstance, aszTrackbarClassName, &wc)) {
  49. // See if we must register a window class
  50. wc.lpszClassName = aszTrackbarClassName;
  51. wc.lpfnWndProc = TrackBarWndProc;
  52. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  53. wc.hIcon = NULL;
  54. wc.lpszMenuName = NULL;
  55. wc.hbrBackground = (HBRUSH)(NULL);
  56. wc.hInstance = hInstance;
  57. wc.style = CS_GLOBALCLASS | CS_DBLCLKS;
  58. wc.cbClsExtra = 0;
  59. wc.cbWndExtra = EXTRA_TB_BYTES;
  60. if (!RegisterClass(&wc))
  61. return FALSE;
  62. }
  63. return TRUE;
  64. }
  65. static void NEAR PASCAL PatRect(HDC hdc,int x,int y,int dx,int dy)
  66. {
  67. RECT rc;
  68. rc.left = x;
  69. rc.top = y;
  70. rc.right = x + dx;
  71. rc.bottom = y + dy;
  72. ExtTextOut(hdc,0,0,ETO_OPAQUE,&rc,NULL,0,NULL);
  73. }
  74. static void NEAR PASCAL DrawTic(PTrackBar tb, int x, int yTic)
  75. {
  76. SetBkColor(tb->hdc, GetSysColor(COLOR_BTNTEXT));
  77. PatRect(tb->hdc,(x),yTic,1,TICKHEIGHT);
  78. SetBkColor(tb->hdc, GetSysColor(COLOR_BTNHIGHLIGHT));
  79. PatRect(tb->hdc,(x)+1,yTic,1,TICKHEIGHT);
  80. }
  81. /* DrawTics() */
  82. /* There is always a tick at the beginning and end of the bar, but you can */
  83. /* add some more of your own with a TBM_SETTIC message. This draws them. */
  84. /* They are kept in an array whose handle is a window word. The first */
  85. /* element is the number of extra ticks, and then the positions. */
  86. static void NEAR PASCAL DrawTics(PTrackBar tb)
  87. {
  88. PDWORD pTics;
  89. int iPos;
  90. int yTic;
  91. int i;
  92. yTic = tb->rc.bottom + THUMBSLOP + 1;
  93. // !!! Not for MCIWnd
  94. // DrawTic(tb, tb->rc.left, yTic); // first
  95. // DrawTic(tb, tb->rc.right-1, yTic); // last
  96. // those inbetween
  97. pTics = tb->pTics;
  98. if (pTics) {
  99. for (i = 0; i < tb->nTics; ++i) {
  100. iPos = TBLogToPhys(tb,pTics[i]);
  101. DrawTic(tb, iPos, yTic);
  102. }
  103. }
  104. // draw the selection range (triangles)
  105. if ((tb->Flags & TBF_SELECTION) &&
  106. (tb->lSelStart <= tb->lSelEnd) && (tb->lSelEnd >= tb->lLogMin)) {
  107. SetBkColor(tb->hdc, GetSysColor(COLOR_BTNTEXT));
  108. iPos = TBLogToPhys(tb,tb->lSelStart);
  109. for (i=0; i < TICKHEIGHT; i++)
  110. PatRect(tb->hdc,iPos-i,yTic+i,1,TICKHEIGHT-i);
  111. iPos = TBLogToPhys(tb,tb->lSelEnd);
  112. for (i=0; i < TICKHEIGHT; i++)
  113. PatRect(tb->hdc,iPos+i,yTic+i,1,TICKHEIGHT-i);
  114. }
  115. // !!! Not for MCIWnd
  116. // line across the bottom
  117. // SetBkColor(tb->hdc, GetSysColor(COLOR_BTNTEXT));
  118. // PatRect(tb->hdc, tb->rc.left, yTic+TICKHEIGHT,tb->iSizePhys,1);
  119. //
  120. // SetBkColor(tb->hdc, GetSysColor(COLOR_BTNHIGHLIGHT));
  121. // PatRect(tb->hdc, tb->rc.left, yTic+TICKHEIGHT+1,tb->iSizePhys,1);
  122. }
  123. /* This draws the track bar itself */
  124. static void NEAR PASCAL DrawChannel(PTrackBar tb)
  125. {
  126. HBRUSH hbrTemp;
  127. // draw the frame around the window
  128. SetBkColor(tb->hdc, GetSysColor(COLOR_WINDOWFRAME));
  129. PatRect(tb->hdc, tb->rc.left, tb->rc.top, tb->iSizePhys, 1);
  130. PatRect(tb->hdc, tb->rc.left, tb->rc.bottom-2, tb->iSizePhys, 1);
  131. PatRect(tb->hdc, tb->rc.left, tb->rc.top, 1, tb->rc.bottom-tb->rc.top-1);
  132. PatRect(tb->hdc, tb->rc.right-1, tb->rc.top, 1, tb->rc.bottom-tb->rc.top-1);
  133. SetBkColor(tb->hdc, GetSysColor(COLOR_BTNHIGHLIGHT));
  134. PatRect(tb->hdc, tb->rc.left, tb->rc.bottom-1, tb->iSizePhys, 1);
  135. SetBkColor(tb->hdc, GetSysColor(COLOR_BTNSHADOW));
  136. PatRect(tb->hdc, tb->rc.left+1, tb->rc.top + 1, tb->iSizePhys-2,1);
  137. // draw the background in dither gray
  138. hbrTemp = SelectObject(tb->hdc, hbrDither);
  139. if (hbrTemp) {
  140. PatBlt(tb->hdc, tb->rc.left+1, tb->rc.top + 2,
  141. tb->iSizePhys-2, tb->rc.bottom-tb->rc.top-4, PATCOPY);
  142. SelectObject(tb->hdc, hbrTemp);
  143. }
  144. // now highlight the selection range
  145. if ((tb->Flags & TBF_SELECTION) &&
  146. (tb->lSelStart <= tb->lSelEnd) && (tb->lSelEnd > tb->lLogMin)) {
  147. int iStart, iEnd;
  148. iStart = TBLogToPhys(tb,tb->lSelStart);
  149. iEnd = TBLogToPhys(tb,tb->lSelEnd);
  150. SetBkColor(tb->hdc, GetSysColor(COLOR_BTNTEXT));
  151. PatRect(tb->hdc, iStart,tb->rc.top+1,1,tb->rc.bottom-tb->rc.top-2);
  152. PatRect(tb->hdc, iEnd, tb->rc.top+1,1,tb->rc.bottom-tb->rc.top-2);
  153. if (iStart + 2 <= iEnd) {
  154. SetBkColor(tb->hdc, GetSysColor(COLOR_BTNHIGHLIGHT));
  155. PatRect(tb->hdc, iStart+1, tb->rc.top+1, iEnd-iStart-1, tb->rc.bottom-tb->rc.top-3);
  156. }
  157. }
  158. }
  159. static void NEAR PASCAL MoveThumb(PTrackBar tb, LONG lPos)
  160. {
  161. InvalidateRect(tb->hwnd, &tb->Thumb, TRUE);
  162. tb->lLogPos = BOUND(lPos,tb->lLogMin,tb->lLogMax);
  163. tb->Thumb.left = TBLogToPhys(tb, tb->lLogPos) - tb->wThumbWidth/2;
  164. tb->Thumb.right = tb->Thumb.left + tb->wThumbWidth;
  165. tb->Thumb.top = tb->rc.top - THUMBSLOP;
  166. tb->Thumb.bottom = tb->rc.bottom + THUMBSLOP;
  167. InvalidateRect(tb->hwnd, &tb->Thumb, TRUE);
  168. UpdateWindow(tb->hwnd);
  169. }
  170. static void NEAR PASCAL DrawThumb(PTrackBar tb)
  171. {
  172. HBITMAP hbmT;
  173. HDC hdcT;
  174. int x;
  175. hdcT = CreateCompatibleDC(tb->hdc);
  176. if( (tb->Cmd == TB_THUMBTRACK) || !IsWindowEnabled(tb->hwnd) )
  177. x = tb->wThumbWidth;
  178. else
  179. x = 0;
  180. hbmT = SelectObject(hdcT, hbmThumb);
  181. if (hbmT) {
  182. BitBlt(tb->hdc,tb->Thumb.left, tb->rc.top-THUMBSLOP,
  183. tb->wThumbWidth, tb->wThumbHeight, hdcT, x + 2*tb->wThumbWidth, 0, SRCAND);
  184. BitBlt(tb->hdc,tb->Thumb.left, tb->rc.top-THUMBSLOP,
  185. tb->wThumbWidth, tb->wThumbHeight, hdcT, x, 0, SRCPAINT);
  186. }
  187. SelectObject(hdcT, hbmT);
  188. DeleteDC(hdcT);
  189. }
  190. /* SetTBCaretPos() */
  191. /* Make the caret flash in the middle of the thumb when it has the focus */
  192. static void NEAR PASCAL SetTBCaretPos(PTrackBar tb)
  193. {
  194. // We only get the caret if we have the focus.
  195. if (tb->hwnd == GetFocus())
  196. SetCaretPos(tb->Thumb.left + tb->wThumbWidth / 2,
  197. tb->Thumb.top + THUMBSLOP);
  198. }
  199. static void NEAR PASCAL DoAutoTics(PTrackBar tb)
  200. {
  201. LONG NEAR *pl;
  202. LONG l;
  203. if (!(GetWindowLong(tb->hwnd, GWL_STYLE) & TBS_AUTOTICKS))
  204. return;
  205. tb->nTics = (int)(tb->lLogMax - tb->lLogMin - 1);
  206. // If our length is zero, we'll blow!
  207. if (tb->nTics <= 0) {
  208. tb ->nTics = 0;
  209. return;
  210. }
  211. if (tb->pTics)
  212. LocalFree((HANDLE)tb->pTics);
  213. tb->pTics = (DWORD NEAR *)LocalAlloc(LPTR, sizeof(DWORD) * tb->nTics);
  214. if (!tb->pTics) {
  215. tb->nTics = 0;
  216. return;
  217. }
  218. for (pl = (LONG NEAR *)tb->pTics, l = tb->lLogMin + 1; l < tb->lLogMax; l++)
  219. *pl++ = l;
  220. }
  221. LPARAM FAR CALLBACK _loadds TrackBarWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  222. {
  223. PTrackBar tb;
  224. PAINTSTRUCT ps;
  225. BITMAP bm;
  226. HANDLE h;
  227. HDC hdc;
  228. HBRUSH hbr;
  229. RECT rc;
  230. tb = TrackBarLock(hwnd);
  231. switch (message) {
  232. case WM_CREATE:
  233. if (!CreateDitherBrush(FALSE))
  234. return -1;
  235. // Get us our window structure.
  236. TrackBarCreate(hwnd);
  237. tb = TrackBarLock(hwnd);
  238. tb->hwnd = hwnd;
  239. tb->Cmd = (UINT)-1;
  240. /* load the 2 thumb bitmaps (pressed and released) */
  241. CreateThumb(FALSE);
  242. GetObject(hbmThumb, sizeof(bm), &bm);
  243. // bitmap has up and down thumb and up&down masks
  244. tb->wThumbWidth = (UINT)(bm.bmWidth/4);
  245. tb->wThumbHeight = (UINT)bm.bmHeight;
  246. // all lLog fields are zero inited by
  247. // the LocalAlloc();
  248. // fall through to WM_SIZE
  249. case WM_SIZE:
  250. GetClientRect(hwnd, &tb->rc);
  251. tb->rc.bottom = tb->rc.top + tb->wThumbHeight - THUMBSLOP;
  252. tb->rc.top += THUMBSLOP;
  253. tb->rc.left += tb->wThumbWidth/2;
  254. tb->rc.right -= tb->wThumbWidth/2;
  255. // Figure out how much room we have to move the thumb in
  256. //!!! -2
  257. tb->iSizePhys = tb->rc.right - tb->rc.left;
  258. // Elevator isn't there if there's no room.
  259. if (tb->iSizePhys == 0) {
  260. // Lost our thumb.
  261. tb->Flags |= TBF_NOTHUMB;
  262. tb->iSizePhys = 1;
  263. } else {
  264. // Ah. We have a thumb.
  265. tb->Flags &= ~TBF_NOTHUMB;
  266. }
  267. InvalidateRect(hwnd, NULL, TRUE);
  268. MoveThumb(tb, tb->lLogPos);
  269. break;
  270. case WM_DESTROY:
  271. TrackBarDestroy(hwnd);
  272. FreeDitherBrush();
  273. DestroyThumb();
  274. break;
  275. case WM_SETFOCUS:
  276. // We gots the focus. We need a caret.
  277. CreateCaret(hwnd, (HBITMAP)1,
  278. 3, tb->wThumbHeight - 2 * THUMBSLOP);
  279. SetTBCaretPos(tb);
  280. ShowCaret(hwnd);
  281. break;
  282. case WM_KILLFOCUS:
  283. DestroyCaret();
  284. break;
  285. case WM_ERASEBKGND:
  286. hdc = (HDC) wParam;
  287. #ifdef _WIN32
  288. hbr = (HBRUSH)(UINT)SendMessage(GetParent(hwnd),
  289. WM_CTLCOLORSTATIC, (WPARAM) hdc, (LPARAM)hwnd);
  290. #else
  291. hbr = (HBRUSH)(UINT)SendMessage(GetParent(hwnd),
  292. WM_CTLCOLOR, (WPARAM) hdc,
  293. MAKELONG(hwnd, CTLCOLOR_STATIC);
  294. #endif
  295. if (hbr) {
  296. GetClientRect(hwnd, &rc);
  297. FillRect(hdc, &rc, hbr);
  298. return(FALSE);
  299. }
  300. return(TRUE);
  301. break;
  302. case WM_ENABLE:
  303. InvalidateRect(hwnd, NULL, FALSE);
  304. break;
  305. case WM_PAINT:
  306. if (wParam == 0)
  307. tb->hdc = BeginPaint(hwnd, &ps);
  308. else
  309. tb->hdc = (HDC)wParam;
  310. // Update the dither brush if necessary.
  311. CheckSysColors();
  312. DrawTics(tb);
  313. DrawThumb(tb);
  314. ExcludeClipRect(tb->hdc, tb->Thumb.left, tb->Thumb.top,
  315. tb->Thumb.right, tb->Thumb.bottom);
  316. DrawChannel(tb);
  317. SetTBCaretPos(tb);
  318. if (wParam == 0)
  319. EndPaint(hwnd, &ps);
  320. tb->hdc = NULL;
  321. break;
  322. case WM_GETDLGCODE:
  323. return DLGC_WANTARROWS;
  324. break;
  325. case WM_LBUTTONDOWN:
  326. /* Give ourselves focus */
  327. // !!! MCIWnd wants to keep focus
  328. // SetFocus(hwnd);
  329. TBTrackInit(tb, lParam);
  330. break;
  331. case WM_LBUTTONUP:
  332. // We're through doing whatever we were doing with the
  333. // button down.
  334. TBTrackEnd(tb, lParam);
  335. break;
  336. case WM_TIMER:
  337. // The only way we get a timer message is if we're
  338. // autotracking.
  339. lParam = GetMessagePos();
  340. ScreenToClient(tb->hwnd, (LPPOINT)&lParam);
  341. // fall through to WM_MOUSEMOVE
  342. case WM_MOUSEMOVE:
  343. // We only care that the mouse is moving if we're
  344. // tracking the bloody thing.
  345. if (tb->Cmd != (UINT)-1) {
  346. if (GetCapture() != tb->hwnd) {
  347. TBTrackEnd(tb, lParam);
  348. return 0L;
  349. }
  350. TBTrack(tb, lParam);
  351. }
  352. return 0L;
  353. case WM_KEYUP:
  354. // If key was any of the keyboard accelerators, send end
  355. // track message when user up clicks on keyboard
  356. switch (wParam) {
  357. case VK_HOME:
  358. case VK_END:
  359. case VK_PRIOR:
  360. case VK_NEXT:
  361. case VK_LEFT:
  362. case VK_UP:
  363. case VK_RIGHT:
  364. case VK_DOWN:
  365. DoTrack(tb, TB_ENDTRACK, 0);
  366. break;
  367. default:
  368. break;
  369. }
  370. break;
  371. case WM_KEYDOWN:
  372. switch (wParam) {
  373. case VK_HOME:
  374. wParam = TB_TOP;
  375. goto KeyTrack;
  376. case VK_END:
  377. wParam = TB_BOTTOM;
  378. goto KeyTrack;
  379. case VK_PRIOR:
  380. wParam = TB_PAGEUP;
  381. goto KeyTrack;
  382. case VK_NEXT:
  383. wParam = TB_PAGEDOWN;
  384. goto KeyTrack;
  385. case VK_LEFT:
  386. case VK_UP:
  387. wParam = TB_LINEUP;
  388. goto KeyTrack;
  389. case VK_RIGHT:
  390. case VK_DOWN:
  391. wParam = TB_LINEDOWN;
  392. KeyTrack:
  393. DoTrack(tb, wParam, 0);
  394. break;
  395. default:
  396. break;
  397. }
  398. break;
  399. case TBM_GETPOS:
  400. return tb->lLogPos;
  401. case TBM_GETSELSTART:
  402. return tb->lSelStart;
  403. case TBM_GETSELEND:
  404. return tb->lSelEnd;
  405. case TBM_GETRANGEMIN:
  406. return tb->lLogMin;
  407. case TBM_GETRANGEMAX:
  408. return tb->lLogMax;
  409. case TBM_GETPTICS:
  410. return (LONG)(LPVOID)tb->pTics;
  411. case TBM_CLEARSEL:
  412. tb->Flags &= ~TBF_SELECTION;
  413. tb->lSelStart = -1;
  414. tb->lSelEnd = -1;
  415. goto RedrawTB;
  416. case TBM_CLEARTICS:
  417. if (tb->pTics)
  418. LocalFree((HLOCAL)tb->pTics);
  419. tb->nTics = 0;
  420. tb->pTics = NULL;
  421. goto RedrawTB;
  422. case TBM_GETTIC:
  423. if (tb->pTics == NULL || (int)wParam >= tb->nTics)
  424. return -1L;
  425. return tb->pTics[wParam];
  426. case TBM_GETTICPOS:
  427. if (tb->pTics == NULL || (int)wParam >= tb->nTics)
  428. return -1L;
  429. return TBLogToPhys(tb,tb->pTics[wParam]);
  430. case TBM_GETNUMTICS:
  431. return tb->nTics;
  432. case TBM_SETTIC:
  433. /* not a valid position */
  434. if (lParam < 0)
  435. break;
  436. if (tb->pTics)
  437. h = LocalReAlloc((HLOCAL)tb->pTics,
  438. sizeof(DWORD) * (UINT)(tb->nTics + 1),
  439. LMEM_MOVEABLE | LMEM_ZEROINIT);
  440. else
  441. h = LocalAlloc(LPTR, sizeof(DWORD));
  442. if (h)
  443. tb->pTics = (PDWORD)h;
  444. else
  445. return (LONG)FALSE;
  446. tb->pTics[tb->nTics++] = (DWORD)lParam;
  447. InvalidateRect(hwnd, NULL, TRUE);
  448. return (LONG)TRUE;
  449. break;
  450. case TBM_SETPOS:
  451. /* Only redraw if it will physically move */
  452. if (wParam && TBLogToPhys(tb, lParam) !=
  453. TBLogToPhys(tb, tb->lLogPos))
  454. MoveThumb(tb, lParam);
  455. else
  456. tb->lLogPos = BOUND(lParam,tb->lLogMin,tb->lLogMax);
  457. break;
  458. case TBM_SETSEL:
  459. tb->Flags |= TBF_SELECTION;
  460. tb->lSelStart = LOWORD(lParam);
  461. tb->lSelEnd = HIWORD(lParam);
  462. if (tb->lSelEnd < tb->lSelStart)
  463. tb->lSelEnd = tb->lSelStart;
  464. goto RedrawTB;
  465. case TBM_SETSELSTART:
  466. tb->Flags |= TBF_SELECTION;
  467. tb->lSelStart = lParam;
  468. if (tb->lSelEnd < tb->lSelStart || tb->lSelEnd == -1)
  469. tb->lSelEnd = tb->lSelStart;
  470. goto RedrawTB;
  471. case TBM_SETSELEND:
  472. tb->Flags |= TBF_SELECTION;
  473. tb->lSelEnd = lParam;
  474. if (tb->lSelStart > tb->lSelEnd || tb->lSelStart == -1)
  475. tb->lSelStart = tb->lSelEnd;
  476. goto RedrawTB;
  477. case TBM_SETRANGE:
  478. tb->lLogMin = LOWORD(lParam);
  479. tb->lLogMax = HIWORD(lParam);
  480. DoAutoTics(tb);
  481. goto RedrawTB;
  482. case TBM_SETRANGEMIN:
  483. tb->lLogMin = (DWORD)lParam;
  484. goto RedrawTB;
  485. case TBM_SETRANGEMAX:
  486. tb->lLogMax = (DWORD)lParam;
  487. RedrawTB:
  488. tb->lLogPos = BOUND(tb->lLogPos, tb->lLogMin,tb->lLogMax);
  489. /* Only redraw if flag says so */
  490. if (wParam) {
  491. InvalidateRect(hwnd, NULL, TRUE);
  492. MoveThumb(tb, tb->lLogPos);
  493. }
  494. break;
  495. }
  496. return DefWindowProc(hwnd, message, wParam, lParam);
  497. }
  498. /* DoTrack() */
  499. static void NEAR PASCAL DoTrack(PTrackBar tb, int cmd, DWORD dwPos)
  500. {
  501. // note: we only send back a WORD worth of the position.
  502. #ifdef _WIN32
  503. SendMessage(GetParent(tb->hwnd), WM_HSCROLL,
  504. MAKELONG(cmd, LOWORD(dwPos)), (LPARAM)tb->hwnd);
  505. #else
  506. SendMessage(GetParent(tb->hwnd), WM_HSCROLL, cmd,
  507. MAKELONG(LOWORD(dwPos), tb->hwnd));
  508. #endif
  509. }
  510. /* WTrackType() */
  511. static WORD NEAR PASCAL WTrackType(PTrackBar tb, LONG lParam)
  512. {
  513. POINT pt;
  514. #ifdef _WIN32
  515. LONG2POINT(lParam, pt);
  516. #else
  517. pt = MAKEPOINT(lParam);
  518. #endif
  519. if (tb->Flags & TBF_NOTHUMB) // If no thumb, just leave.
  520. return 0;
  521. if (PtInRect(&tb->Thumb, pt))
  522. return TB_THUMBTRACK;
  523. if (!PtInRect(&tb->rc, pt))
  524. return 0;
  525. if (pt.x >= tb->Thumb.left)
  526. return TB_PAGEDOWN;
  527. else
  528. return TB_PAGEUP;
  529. }
  530. /* TBTrackInit() */
  531. static void NEAR PASCAL TBTrackInit(PTrackBar tb, LONG lParam)
  532. {
  533. UINT wCmd;
  534. if (tb->Flags & TBF_NOTHUMB) // No thumb: just leave.
  535. return;
  536. wCmd = WTrackType(tb, lParam);
  537. if (!wCmd)
  538. return;
  539. HideCaret(tb->hwnd);
  540. SetCapture(tb->hwnd);
  541. tb->Cmd = wCmd;
  542. tb->dwDragPos = (DWORD)-1;
  543. // Set up for auto-track (if needed).
  544. if (wCmd != TB_THUMBTRACK) {
  545. // Set our timer up
  546. tb->Timer = (UINT)SetTimer(tb->hwnd, TIMER_ID, REPEATTIME, NULL);
  547. }
  548. TBTrack(tb, lParam);
  549. }
  550. /* EndTrack() */
  551. static void near PASCAL TBTrackEnd(PTrackBar tb, long lParam)
  552. {
  553. lParam = lParam; // Just reference this variable
  554. // If we lose mouse capture we need to call this
  555. // if (GetCapture() != tb->hwnd)
  556. // return;
  557. // Let the mouse go.
  558. ReleaseCapture();
  559. // Decide how we're ending this thing.
  560. if (tb->Cmd == TB_THUMBTRACK)
  561. DoTrack(tb, TB_THUMBPOSITION, tb->dwDragPos);
  562. if (tb->Timer)
  563. KillTimer(tb->hwnd, TIMER_ID);
  564. tb->Timer = 0;
  565. // Always send TB_ENDTRACK message.
  566. DoTrack(tb, TB_ENDTRACK, 0);
  567. // Give the caret back.
  568. ShowCaret(tb->hwnd);
  569. // Nothing going on.
  570. tb->Cmd = (UINT)-1;
  571. MoveThumb(tb, tb->lLogPos);
  572. }
  573. static void NEAR PASCAL TBTrack(PTrackBar tb, LONG lParam)
  574. {
  575. DWORD dwPos;
  576. // See if we're tracking the thumb
  577. if (tb->Cmd == TB_THUMBTRACK) {
  578. dwPos = TBPhysToLog(tb, LOWORD(lParam));
  579. // Tentative position changed -- notify the guy.
  580. if (dwPos != tb->dwDragPos) {
  581. tb->dwDragPos = dwPos;
  582. MoveThumb(tb, dwPos);
  583. DoTrack(tb, TB_THUMBTRACK, dwPos);
  584. }
  585. }
  586. else {
  587. if (tb->Cmd != WTrackType(tb, lParam))
  588. return;
  589. DoTrack(tb, tb->Cmd, 0);
  590. }
  591. }