Prevent crash when nMinRange > nMaxRange.
[wine/hacks.git] / dlls / comctl32 / trackbar.c
blobbeb68898c255b4f89d4631bd38ff0172188158f6
1 /*
2 * Trackbar control
4 * Copyright 1998, 1999 Eric Kohl <ekohl@abo.rhein-zeitung.de>
5 * Copyright 1998,1999 Alex Priem <alexp@sci.kun.nl>
8 * TODO:
9 * - Some messages.
10 * - more display code.
11 * - handle dragging slider better
12 * - better tic handling.
13 * - more notifications.
17 /* known bugs:
19 -TBM_SETRANGEMAX & TBM_SETRANGEMIN should only change the view of the
20 trackbar, not the actual amount of tics in the list.
21 -TBM_GETTIC & TBM_GETTICPOS shouldn't rely on infoPtr->tics being sorted.
22 - Make drawing code exact match of w95 drawing.
27 #include "winbase.h"
28 #include "commctrl.h"
29 #include "trackbar.h"
30 #include "debug.h"
32 DEFAULT_DEBUG_CHANNEL(trackbar)
35 #define TRACKBAR_GetInfoPtr(wndPtr) ((TRACKBAR_INFO *)GetWindowLongA (hwnd,0))
38 /* Used by TRACKBAR_Refresh to find out which parts of the control
39 need to be recalculated */
41 #define TB_THUMBPOSCHANGED 1
42 #define TB_THUMBSIZECHANGED 2
43 #define TB_THUMBCHANGED (TB_THUMBPOSCHANGED | TB_THUMBPOSCHANGED)
44 #define TB_SELECTIONCHANGED 4
46 #define TB_DRAG_MODE 16 /* we're dragging the slider */
47 #define TB_DRAGPOSVALID 32 /* current Position is in dragPos */
48 #define TB_SHOW_TOOLTIP 64 /* tooltip-style enabled and tooltip on */
49 #define TB_REFRESH_TIMER_SET 128 /* is a TRACBKAR_Refresh queued?*/
52 /* helper defines for TRACKBAR_DrawTic */
53 #define TIC_LEFTEDGE 0x20
54 #define TIC_RIGHTEDGE 0x40
55 #define TIC_EDGE (TIC_LEFTEDGE | TIC_RIGHTEDGE)
56 #define TIC_SELECTIONMARKMAX 0x80
57 #define TIC_SELECTIONMARKMIN 0x100
58 #define TIC_SELECTIONMARK (TIC_SELECTIONMARKMAX | TIC_SELECTIONMARKMIN)
60 static BOOL TRACKBAR_SendNotify (HWND hwnd, UINT code);
62 void TRACKBAR_RecalculateTics (TRACKBAR_INFO *infoPtr)
65 int i,tic,nrTics;
67 if (infoPtr->uTicFreq && infoPtr->nRangeMax >= infoPtr->nRangeMin)
68 nrTics=(infoPtr->nRangeMax - infoPtr->nRangeMin)/infoPtr->uTicFreq;
69 else {
70 nrTics=0;
71 COMCTL32_Free (infoPtr->tics);
72 infoPtr->tics=NULL;
73 infoPtr->uNumTics=0;
74 return;
77 if (nrTics!=infoPtr->uNumTics) {
78 infoPtr->tics=COMCTL32_ReAlloc (infoPtr->tics, (nrTics+1)*sizeof (DWORD));
79 infoPtr->uNumTics=nrTics;
81 infoPtr->uNumTics=nrTics;
82 tic=infoPtr->nRangeMin+infoPtr->uTicFreq;
83 for (i=0; i<nrTics; i++,tic+=infoPtr->uTicFreq)
84 infoPtr->tics[i]=tic;
88 /* converts from physical (mouse) position to logical position
89 (in range of trackbar) */
91 static __inline__ INT
92 TRACKBAR_ConvertPlaceToPosition (TRACKBAR_INFO *infoPtr, int place,
93 int vertical)
95 double range,width,pos;
97 range=infoPtr->nRangeMax - infoPtr->nRangeMin;
98 if (vertical) {
99 width=infoPtr->rcChannel.bottom - infoPtr->rcChannel.top;
100 pos=(range*(place - infoPtr->rcChannel.top)) / width;
101 } else {
102 width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
103 pos=(range*(place - infoPtr->rcChannel.left)) / width;
106 TRACE (trackbar,"%.2f\n",pos);
107 return pos;
112 static VOID
113 TRACKBAR_CalcChannel (HWND hwnd, TRACKBAR_INFO *infoPtr)
115 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
116 INT cyChannel;
117 RECT lpRect,*channel = & infoPtr->rcChannel;
119 GetClientRect (hwnd, &lpRect);
121 if (dwStyle & TBS_ENABLESELRANGE)
122 cyChannel = MAX(infoPtr->uThumbLen - 8, 4);
123 else
124 cyChannel = 4;
126 if (dwStyle & TBS_VERT) {
127 channel->top = lpRect.top + 8;
128 channel->bottom = lpRect.bottom - 8;
130 if (dwStyle & TBS_BOTH) {
131 channel->left = (lpRect.right - cyChannel) / 2;
132 channel->right = (lpRect.right + cyChannel) / 2;
134 else if (dwStyle & TBS_LEFT) {
135 channel->left = lpRect.left + 10;
136 channel->right = channel->left + cyChannel;
138 else { /* TBS_RIGHT */
139 channel->right = lpRect.right - 10;
140 channel->left = channel->right - cyChannel;
143 else {
144 channel->left = lpRect.left + 8;
145 channel->right = lpRect.right - 8;
146 if (dwStyle & TBS_BOTH) {
147 channel->top = (lpRect.bottom - cyChannel) / 2;
148 channel->bottom = (lpRect.bottom + cyChannel) / 2;
150 else if (dwStyle & TBS_TOP) {
151 channel->top = lpRect.top + 10;
152 channel->bottom = channel->top + cyChannel;
154 else { /* TBS_BOTTOM */
155 channel->bottom = lpRect.bottom - 10;
156 channel->top = channel->bottom - cyChannel;
161 static VOID
162 TRACKBAR_CalcThumb (HWND hwnd, TRACKBAR_INFO *infoPtr)
165 RECT *thumb;
166 int range, width;
168 thumb=&infoPtr->rcThumb;
169 range=infoPtr->nRangeMax - infoPtr->nRangeMin;
170 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_VERT) {
171 width=infoPtr->rcChannel.bottom - infoPtr->rcChannel.top;
172 thumb->left = infoPtr->rcChannel.left - 1;
173 thumb->right = infoPtr->rcChannel.left + infoPtr->uThumbLen - 8;
174 thumb->top = infoPtr->rcChannel.top +
175 (width*infoPtr->nPos)/range - 5;
176 thumb->bottom = thumb->top + infoPtr->uThumbLen/3;
178 } else {
179 width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
180 thumb->left = infoPtr->rcChannel.left +
181 (width*infoPtr->nPos)/range - 5;
182 thumb->right = thumb->left + infoPtr->uThumbLen/3;
183 thumb->top = infoPtr->rcChannel.top - 1;
184 thumb->bottom = infoPtr->rcChannel.top + infoPtr->uThumbLen - 8;
188 static VOID
189 TRACKBAR_CalcSelection (HWND hwnd, TRACKBAR_INFO *infoPtr)
191 RECT *selection;
192 int range, width;
194 selection= & infoPtr->rcSelection;
195 range=infoPtr->nRangeMax - infoPtr->nRangeMin;
196 width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
198 if (range <= 0)
199 SetRectEmpty (selection);
200 else
201 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_VERT) {
202 selection->left = infoPtr->rcChannel.left +
203 (width*infoPtr->nSelMin)/range;
204 selection->right = infoPtr->rcChannel.left +
205 (width*infoPtr->nSelMax)/range;
206 selection->top = infoPtr->rcChannel.top + 2;
207 selection->bottom = infoPtr->rcChannel.bottom - 2;
208 } else {
209 selection->top = infoPtr->rcChannel.top +
210 (width*infoPtr->nSelMin)/range;
211 selection->bottom = infoPtr->rcChannel.top +
212 (width*infoPtr->nSelMax)/range;
213 selection->left = infoPtr->rcChannel.left + 2;
214 selection->right = infoPtr->rcChannel.right - 2;
219 static void
220 TRACKBAR_QueueRefresh (HWND hwnd)
222 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
224 TRACE (trackbar,"queued\n");
225 if (infoPtr->flags & TB_REFRESH_TIMER_SET) {
226 KillTimer (hwnd, TB_REFRESH_TIMER);
229 SetTimer (hwnd, TB_REFRESH_TIMER, TB_REFRESH_DELAY, 0);
230 infoPtr->flags|=TB_REFRESH_TIMER_SET;
237 /* Trackbar drawing code. I like my spaghetti done milanese. */
239 /* ticPos is in tic-units, not in pixels */
241 static VOID
242 TRACKBAR_DrawHorizTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos,
243 int flags, COLORREF clrTic)
246 RECT rcChannel=infoPtr->rcChannel;
247 int x,y,width,range,side;
249 range=infoPtr->nRangeMax - infoPtr->nRangeMin;
250 width=rcChannel.right - rcChannel.left;
252 if (flags & TBS_TOP) {
253 y=rcChannel.top-2;
254 side=-1;
255 } else {
256 y=rcChannel.bottom+2;
257 side=1;
260 if (flags & TIC_SELECTIONMARK) {
261 if (flags & TIC_SELECTIONMARKMIN)
262 x=rcChannel.left + (width*ticPos)/range - 1;
263 else
264 x=rcChannel.left + (width*ticPos)/range + 1;
266 SetPixel (hdc, x,y+6*side, clrTic);
267 SetPixel (hdc, x,y+7*side, clrTic);
268 return;
271 if ((ticPos>infoPtr->nRangeMin) && (ticPos<infoPtr->nRangeMax)) {
272 x=rcChannel.left + (width*ticPos)/range;
273 SetPixel (hdc, x,y+5*side, clrTic);
274 SetPixel (hdc, x,y+6*side, clrTic);
275 SetPixel (hdc, x,y+7*side, clrTic);
278 if (flags & TIC_EDGE) {
279 if (flags & TIC_LEFTEDGE)
280 x=rcChannel.left;
281 else
282 x=rcChannel.right;
284 SetPixel (hdc, x,y+5*side, clrTic);
285 SetPixel (hdc, x,y+6*side, clrTic);
286 SetPixel (hdc, x,y+7*side, clrTic);
287 SetPixel (hdc, x,y+8*side, clrTic);
292 static VOID
293 TRACKBAR_DrawVertTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos,
294 int flags, COLORREF clrTic)
297 RECT rcChannel=infoPtr->rcChannel;
298 int x,y,width,range,side;
300 range=infoPtr->nRangeMax - infoPtr->nRangeMin;
301 width=rcChannel.bottom - rcChannel.top;
303 if (flags & TBS_TOP) {
304 x=rcChannel.right-2;
305 side=-1;
306 } else {
307 x=rcChannel.left+2;
308 side=1;
312 if (flags & TIC_SELECTIONMARK) {
313 if (flags & TIC_SELECTIONMARKMIN)
314 y=rcChannel.top + (width*ticPos)/range - 1;
315 else
316 y=rcChannel.top + (width*ticPos)/range + 1;
318 SetPixel (hdc, x+6*side, y, clrTic);
319 SetPixel (hdc, x+7*side, y, clrTic);
320 return;
323 if ((ticPos>infoPtr->nRangeMin) && (ticPos<infoPtr->nRangeMax)) {
324 y=rcChannel.top + (width*ticPos)/range;
325 SetPixel (hdc, x+5*side, y, clrTic);
326 SetPixel (hdc, x+6*side, y, clrTic);
327 SetPixel (hdc, x+7*side, y, clrTic);
330 if (flags & TIC_EDGE) {
331 if (flags & TIC_LEFTEDGE)
332 y=rcChannel.top;
333 else
334 y=rcChannel.bottom;
336 SetPixel (hdc, x+5*side, y, clrTic);
337 SetPixel (hdc, x+6*side, y, clrTic);
338 SetPixel (hdc, x+7*side, y, clrTic);
339 SetPixel (hdc, x+8*side, y, clrTic);
345 static VOID
346 TRACKBAR_DrawTics (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos,
347 int flags, COLORREF clrTic)
351 if (flags & TBS_VERT) {
352 if ((flags & TBS_TOP) || (flags & TBS_BOTH))
353 TRACKBAR_DrawVertTic (infoPtr, hdc, ticPos,
354 flags | TBS_TOP , clrTic);
355 if (!(flags & TBS_TOP) || (flags & TBS_BOTH))
356 TRACKBAR_DrawVertTic (infoPtr, hdc, ticPos, flags, clrTic);
357 return;
360 if ((flags & TBS_TOP) || (flags & TBS_BOTH))
361 TRACKBAR_DrawHorizTic (infoPtr, hdc, ticPos, flags | TBS_TOP , clrTic);
363 if (!(flags & TBS_TOP) || (flags & TBS_BOTH))
364 TRACKBAR_DrawHorizTic (infoPtr, hdc, ticPos, flags, clrTic);
369 static VOID
370 TRACKBAR_Refresh (HWND hwnd, HDC hdc)
372 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
373 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
374 RECT rcClient, rcChannel, rcSelection;
375 HBRUSH hBrush = CreateSolidBrush (infoPtr->clrBk);
376 int i;
378 GetClientRect (hwnd, &rcClient);
379 hBrush = CreateSolidBrush (infoPtr->clrBk);
380 FillRect (hdc, &rcClient, hBrush);
381 DeleteObject (hBrush);
383 if (infoPtr->flags & TB_REFRESH_TIMER_SET) {
384 KillTimer (hwnd, TB_REFRESH_TIMER);
385 infoPtr->flags &= ~TB_REFRESH_TIMER_SET;
388 if (infoPtr->flags & TB_DRAGPOSVALID) {
389 infoPtr->nPos=infoPtr->dragPos;
390 infoPtr->flags |= TB_THUMBPOSCHANGED;
393 if (infoPtr->flags & TB_THUMBCHANGED) {
394 TRACKBAR_CalcThumb (hwnd, infoPtr);
395 if (infoPtr->flags & TB_THUMBSIZECHANGED)
396 TRACKBAR_CalcChannel (hwnd, infoPtr);
398 if (infoPtr->flags & TB_SELECTIONCHANGED)
399 TRACKBAR_CalcSelection (hwnd, infoPtr);
400 infoPtr->flags &= ~ (TB_THUMBCHANGED | TB_SELECTIONCHANGED | TB_DRAGPOSVALID);
402 /* draw channel */
404 rcChannel = infoPtr->rcChannel;
405 rcSelection= infoPtr->rcSelection;
406 DrawEdge (hdc, &rcChannel, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
408 if (dwStyle & TBS_ENABLESELRANGE) { /* fill the channel */
409 HBRUSH hbr = CreateSolidBrush (RGB(255,255,255));
410 FillRect (hdc, &rcChannel, hbr);
411 if (((dwStyle & TBS_VERT) &&
412 (rcSelection.left!=rcSelection.right)) ||
413 ((!(dwStyle & TBS_VERT)) &&
414 (rcSelection.left!=rcSelection.right))) {
415 hbr=CreateSolidBrush (COLOR_HIGHLIGHT);
416 FillRect (hdc, &rcSelection, hbr);
418 DeleteObject (hbr);
422 /* draw tics */
424 if (!(dwStyle & TBS_NOTICKS)) {
425 int ticFlags = dwStyle & 0x0f;
426 COLORREF clrTic=GetSysColor (COLOR_3DDKSHADOW);
428 for (i=0; i<infoPtr->uNumTics; i++)
429 TRACKBAR_DrawTics (infoPtr, hdc, infoPtr->tics[i],
430 ticFlags, clrTic);
432 TRACKBAR_DrawTics (infoPtr, hdc, 0, ticFlags | TIC_LEFTEDGE, clrTic);
433 TRACKBAR_DrawTics (infoPtr, hdc, 0, ticFlags | TIC_RIGHTEDGE, clrTic);
435 if ((dwStyle & TBS_ENABLESELRANGE) &&
436 (rcSelection.left!=rcSelection.right)) {
437 TRACKBAR_DrawTics (infoPtr, hdc, infoPtr->nSelMin,
438 ticFlags | TIC_SELECTIONMARKMIN, clrTic);
439 TRACKBAR_DrawTics (infoPtr, hdc, infoPtr->nSelMax,
440 ticFlags | TIC_SELECTIONMARKMAX, clrTic);
444 /* draw thumb */
446 if (!(dwStyle & TBS_NOTHUMB)) {
448 HBRUSH hbr = CreateSolidBrush (COLOR_BACKGROUND);
449 RECT thumb = infoPtr->rcThumb;
451 SelectObject (hdc, hbr);
453 if (dwStyle & TBS_BOTH) {
454 FillRect (hdc, &thumb, hbr);
455 DrawEdge (hdc, &thumb, EDGE_RAISED, BF_TOPLEFT);
456 } else {
458 POINT points[6];
460 /* first, fill the thumb */
461 /* FIXME: revamp. check for TBS_VERT */
463 SetPolyFillMode (hdc,WINDING);
464 points[0].x=thumb.left;
465 points[0].y=thumb.top;
466 points[1].x=thumb.right - 1;
467 points[1].y=thumb.top;
468 points[2].x=thumb.right - 1;
469 points[2].y=thumb.bottom -2;
470 points[3].x=(thumb.right + thumb.left-1)/2;
471 points[3].y=thumb.bottom+4;
472 points[4].x=thumb.left;
473 points[4].y=thumb.bottom -2;
474 points[5].x=points[0].x;
475 points[5].y=points[0].y;
476 Polygon (hdc, points, 6);
478 if (dwStyle & TBS_VERT) {
479 /* draw edge */
480 } else {
481 RECT triangle; /* for correct shadows of thumb */
482 DrawEdge (hdc, &thumb, EDGE_RAISED, BF_TOPLEFT);
484 /* draw notch */
486 triangle.right = thumb.right+5;
487 triangle.left = points[3].x+5;
488 triangle.top = thumb.bottom +5;
489 triangle.bottom= thumb.bottom +1;
490 DrawEdge (hdc, &triangle, EDGE_SUNKEN,
491 BF_DIAGONAL | BF_TOP | BF_RIGHT);
492 triangle.left = thumb.left+6;
493 triangle.right = points[3].x+6;
494 DrawEdge (hdc, &triangle, EDGE_RAISED,
495 BF_DIAGONAL | BF_TOP | BF_LEFT);
498 DeleteObject (hbr);
501 if (infoPtr->bFocus)
502 DrawFocusRect (hdc, &rcClient);
508 static VOID
509 TRACKBAR_AlignBuddies (HWND hwnd, TRACKBAR_INFO *infoPtr)
511 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
512 HWND hwndParent = GetParent (hwnd);
513 RECT rcSelf, rcBuddy;
514 INT x, y;
516 GetWindowRect (hwnd, &rcSelf);
517 MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcSelf, 2);
519 /* align buddy left or above */
520 if (infoPtr->hwndBuddyLA) {
521 GetWindowRect (infoPtr->hwndBuddyLA, &rcBuddy);
522 MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcBuddy, 2);
524 if (dwStyle & TBS_VERT) {
525 x = (infoPtr->rcChannel.right + infoPtr->rcChannel.left) / 2 -
526 (rcBuddy.right - rcBuddy.left) / 2 + rcSelf.left;
527 y = rcSelf.top - (rcBuddy.bottom - rcBuddy.top);
529 else {
530 x = rcSelf.left - (rcBuddy.right - rcBuddy.left);
531 y = (infoPtr->rcChannel.bottom + infoPtr->rcChannel.top) / 2 -
532 (rcBuddy.bottom - rcBuddy.top) / 2 + rcSelf.top;
535 SetWindowPos (infoPtr->hwndBuddyLA, 0, x, y, 0, 0,
536 SWP_NOZORDER | SWP_NOSIZE);
540 /* align buddy right or below */
541 if (infoPtr->hwndBuddyRB) {
542 GetWindowRect (infoPtr->hwndBuddyRB, &rcBuddy);
543 MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcBuddy, 2);
545 if (dwStyle & TBS_VERT) {
546 x = (infoPtr->rcChannel.right + infoPtr->rcChannel.left) / 2 -
547 (rcBuddy.right - rcBuddy.left) / 2 + rcSelf.left;
548 y = rcSelf.bottom;
550 else {
551 x = rcSelf.right;
552 y = (infoPtr->rcChannel.bottom + infoPtr->rcChannel.top) / 2 -
553 (rcBuddy.bottom - rcBuddy.top) / 2 + rcSelf.top;
555 SetWindowPos (infoPtr->hwndBuddyRB, 0, x, y, 0, 0,
556 SWP_NOZORDER | SWP_NOSIZE);
561 static LRESULT
562 TRACKBAR_ClearSel (HWND hwnd, WPARAM wParam, LPARAM lParam)
564 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
566 infoPtr->nSelMin = 0;
567 infoPtr->nSelMax = 0;
568 infoPtr->flags |=TB_SELECTIONCHANGED;
570 if ((BOOL)wParam) {
571 HDC hdc = GetDC (hwnd);
572 TRACKBAR_Refresh (hwnd, hdc);
573 ReleaseDC (hwnd, hdc);
576 return 0;
580 static LRESULT
581 TRACKBAR_ClearTics (HWND hwnd, WPARAM wParam, LPARAM lParam)
583 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
585 if (infoPtr->tics) {
586 COMCTL32_Free (infoPtr->tics);
587 infoPtr->tics = NULL;
588 infoPtr->uNumTics = 0;
591 if (wParam) {
592 HDC hdc = GetDC (hwnd);
593 TRACKBAR_Refresh (hwnd, hdc);
594 ReleaseDC (hwnd, hdc);
597 return 0;
601 static LRESULT
602 TRACKBAR_GetBuddy (HWND hwnd, WPARAM wParam, LPARAM lParam)
604 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
606 if (wParam) /* buddy is left or above */
607 return (LRESULT)infoPtr->hwndBuddyLA;
609 /* buddy is right or below */
610 return (LRESULT) infoPtr->hwndBuddyRB;
614 static LRESULT
615 TRACKBAR_GetChannelRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
617 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
618 LPRECT lprc = (LPRECT)lParam;
620 if (lprc == NULL)
621 return 0;
623 lprc->left = infoPtr->rcChannel.left;
624 lprc->right = infoPtr->rcChannel.right;
625 lprc->bottom = infoPtr->rcChannel.bottom;
626 lprc->top = infoPtr->rcChannel.top;
628 return 0;
632 static LRESULT
633 TRACKBAR_GetLineSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
635 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
637 return infoPtr->nLineSize;
641 static LRESULT
642 TRACKBAR_GetNumTics (HWND hwnd, WPARAM wParam, LPARAM lParam)
644 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
646 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_NOTICKS)
647 return 0;
649 return infoPtr->uNumTics+2;
653 static LRESULT
654 TRACKBAR_GetPageSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
656 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
658 return infoPtr->nPageSize;
662 static LRESULT
663 TRACKBAR_GetPos (HWND hwnd, WPARAM wParam, LPARAM lParam)
665 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
667 return infoPtr->nPos;
673 static LRESULT
674 TRACKBAR_GetRangeMax (HWND hwnd, WPARAM wParam, LPARAM lParam)
676 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
678 return infoPtr->nRangeMax;
682 static LRESULT
683 TRACKBAR_GetRangeMin (HWND hwnd, WPARAM wParam, LPARAM lParam)
685 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
687 return infoPtr->nRangeMin;
691 static LRESULT
692 TRACKBAR_GetSelEnd (HWND hwnd, WPARAM wParam, LPARAM lParam)
694 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
696 return infoPtr->nSelMax;
700 static LRESULT
701 TRACKBAR_GetSelStart (HWND hwnd, WPARAM wParam, LPARAM lParam)
703 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
705 return infoPtr->nSelMin;
709 static LRESULT
710 TRACKBAR_GetThumbLength (HWND hwnd, WPARAM wParam, LPARAM lParam)
712 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
714 return infoPtr->uThumbLen;
717 static LRESULT
718 TRACKBAR_GetPTics (HWND hwnd)
720 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
722 return (LRESULT) infoPtr->tics;
725 static LRESULT
726 TRACKBAR_GetThumbRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
728 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
729 LPRECT lprc = (LPRECT)lParam;
731 if (lprc == NULL)
732 return 0;
734 lprc->left = infoPtr->rcThumb.left;
735 lprc->right = infoPtr->rcThumb.right;
736 lprc->bottom = infoPtr->rcThumb.bottom;
737 lprc->top = infoPtr->rcThumb.top;
739 return 0;
746 static LRESULT
747 TRACKBAR_GetTic (HWND hwnd, WPARAM wParam, LPARAM lParam)
750 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
751 INT iTic;
753 iTic=(INT) wParam;
754 if ((iTic<0) || (iTic>infoPtr->uNumTics))
755 return -1;
757 return (LRESULT) infoPtr->tics[iTic];
762 static LRESULT
763 TRACKBAR_GetTicPos (HWND hwnd, WPARAM wParam, LPARAM lParam)
765 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
766 INT iTic, range, width, pos;
769 iTic=(INT ) wParam;
770 if ((iTic<0) || (iTic>infoPtr->uNumTics))
771 return -1;
773 range=infoPtr->nRangeMax - infoPtr->nRangeMin;
774 width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
775 pos=infoPtr->rcChannel.left + (width * infoPtr->tics[iTic]) / range;
778 return (LRESULT) pos;
781 static LRESULT
782 TRACKBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
784 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
786 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_TOOLTIPS)
787 return (LRESULT)infoPtr->hwndToolTip;
788 return 0;
792 /* case TBM_GETUNICODEFORMAT: */
795 static LRESULT
796 TRACKBAR_SetBuddy (HWND hwnd, WPARAM wParam, LPARAM lParam)
798 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
799 HWND hwndTemp;
801 if (wParam) {
802 /* buddy is left or above */
803 hwndTemp = infoPtr->hwndBuddyLA;
804 infoPtr->hwndBuddyLA = (HWND)lParam;
806 FIXME (trackbar, "move buddy!\n");
808 else {
809 /* buddy is right or below */
810 hwndTemp = infoPtr->hwndBuddyRB;
811 infoPtr->hwndBuddyRB = (HWND)lParam;
813 FIXME (trackbar, "move buddy!\n");
816 TRACKBAR_AlignBuddies (hwnd, infoPtr);
818 return (LRESULT)hwndTemp;
822 static LRESULT
823 TRACKBAR_SetLineSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
825 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
826 INT nTemp = infoPtr->nLineSize;
828 infoPtr->nLineSize = (INT)lParam;
830 return nTemp;
834 static LRESULT
835 TRACKBAR_SetPageSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
837 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
838 INT nTemp = infoPtr->nPageSize;
840 infoPtr->nPageSize = (INT)lParam;
842 return nTemp;
846 static LRESULT
847 TRACKBAR_SetPos (HWND hwnd, WPARAM wParam, LPARAM lParam)
849 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
851 infoPtr->nPos = (INT)HIWORD(lParam);
853 if (infoPtr->nPos < infoPtr->nRangeMin)
854 infoPtr->nPos = infoPtr->nRangeMin;
856 if (infoPtr->nPos > infoPtr->nRangeMax)
857 infoPtr->nPos = infoPtr->nRangeMax;
858 infoPtr->flags |=TB_THUMBPOSCHANGED;
860 if (wParam) {
861 HDC hdc = GetDC (hwnd);
862 TRACKBAR_Refresh (hwnd, hdc);
863 ReleaseDC (hwnd, hdc);
866 return 0;
870 static LRESULT
871 TRACKBAR_SetRange (HWND hwnd, WPARAM wParam, LPARAM lParam)
873 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
874 infoPtr->nRangeMin = (INT)LOWORD(lParam);
875 infoPtr->nRangeMax = (INT)HIWORD(lParam);
877 if (infoPtr->nPos < infoPtr->nRangeMin) {
878 infoPtr->nPos = infoPtr->nRangeMin;
879 infoPtr->flags |=TB_THUMBPOSCHANGED;
882 if (infoPtr->nPos > infoPtr->nRangeMax) {
883 infoPtr->nPos = infoPtr->nRangeMax;
884 infoPtr->flags |=TB_THUMBPOSCHANGED;
887 infoPtr->nPageSize=(infoPtr->nRangeMax - infoPtr->nRangeMin)/5;
888 TRACKBAR_RecalculateTics (infoPtr);
890 if (wParam) {
891 HDC hdc = GetDC (hwnd);
892 TRACKBAR_Refresh (hwnd, hdc);
893 ReleaseDC (hwnd, hdc);
896 return 0;
900 static LRESULT
901 TRACKBAR_SetRangeMax (HWND hwnd, WPARAM wParam, LPARAM lParam)
903 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
905 infoPtr->nRangeMax = (INT)lParam;
906 if (infoPtr->nPos > infoPtr->nRangeMax) {
907 infoPtr->nPos = infoPtr->nRangeMax;
908 infoPtr->flags |=TB_THUMBPOSCHANGED;
911 infoPtr->nPageSize=(infoPtr->nRangeMax - infoPtr->nRangeMin)/5;
912 TRACKBAR_RecalculateTics (infoPtr);
914 if (wParam) {
915 HDC hdc = GetDC (hwnd);
916 TRACKBAR_Refresh (hwnd, hdc);
917 ReleaseDC (hwnd, hdc);
920 return 0;
924 static LRESULT
925 TRACKBAR_SetRangeMin (HWND hwnd, WPARAM wParam, LPARAM lParam)
927 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
929 infoPtr->nRangeMin = (INT)lParam;
930 if (infoPtr->nPos < infoPtr->nRangeMin) {
931 infoPtr->nPos = infoPtr->nRangeMin;
932 infoPtr->flags |=TB_THUMBPOSCHANGED;
935 infoPtr->nPageSize=(infoPtr->nRangeMax - infoPtr->nRangeMin)/5;
936 TRACKBAR_RecalculateTics (infoPtr);
938 if (wParam) {
939 HDC hdc = GetDC (hwnd);
940 TRACKBAR_Refresh (hwnd, hdc);
941 ReleaseDC (hwnd, hdc);
944 return 0;
947 static LRESULT
948 TRACKBAR_SetTicFreq (HWND hwnd, WPARAM wParam)
950 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
951 HDC hdc;
953 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_AUTOTICKS)
954 infoPtr->uTicFreq=(UINT) wParam;
956 TRACKBAR_RecalculateTics (infoPtr);
958 hdc = GetDC (hwnd);
959 TRACKBAR_Refresh (hwnd, hdc);
960 ReleaseDC (hwnd, hdc);
962 return 0;
966 static LRESULT
967 TRACKBAR_SetSel (HWND hwnd, WPARAM wParam, LPARAM lParam)
969 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
971 infoPtr->nSelMin = (INT)LOWORD(lParam);
972 infoPtr->nSelMax = (INT)HIWORD(lParam);
973 infoPtr->flags |=TB_SELECTIONCHANGED;
975 if (!GetWindowLongA (hwnd, GWL_STYLE) & TBS_ENABLESELRANGE)
976 return 0;
978 if (infoPtr->nSelMin < infoPtr->nRangeMin)
979 infoPtr->nSelMin = infoPtr->nRangeMin;
980 if (infoPtr->nSelMax > infoPtr->nRangeMax)
981 infoPtr->nSelMax = infoPtr->nRangeMax;
983 if (wParam) {
984 HDC hdc = GetDC (hwnd);
985 TRACKBAR_Refresh (hwnd, hdc);
986 ReleaseDC (hwnd, hdc);
989 return 0;
993 static LRESULT
994 TRACKBAR_SetSelEnd (HWND hwnd, WPARAM wParam, LPARAM lParam)
996 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
998 if (!GetWindowLongA (hwnd, GWL_STYLE) & TBS_ENABLESELRANGE)
999 return 0;
1001 infoPtr->nSelMax = (INT)lParam;
1002 infoPtr->flags |=TB_SELECTIONCHANGED;
1004 if (infoPtr->nSelMax > infoPtr->nRangeMax)
1005 infoPtr->nSelMax = infoPtr->nRangeMax;
1007 if (wParam) {
1008 HDC hdc = GetDC (hwnd);
1009 TRACKBAR_Refresh (hwnd, hdc);
1010 ReleaseDC (hwnd, hdc);
1013 return 0;
1017 static LRESULT
1018 TRACKBAR_SetSelStart (HWND hwnd, WPARAM wParam, LPARAM lParam)
1020 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1022 if (!GetWindowLongA (hwnd, GWL_STYLE) & TBS_ENABLESELRANGE)
1023 return 0;
1025 infoPtr->nSelMin = (INT)lParam;
1026 infoPtr->flags |=TB_SELECTIONCHANGED;
1028 if (infoPtr->nSelMin < infoPtr->nRangeMin)
1029 infoPtr->nSelMin = infoPtr->nRangeMin;
1031 if (wParam) {
1032 HDC hdc = GetDC (hwnd);
1033 TRACKBAR_Refresh (hwnd, hdc);
1034 ReleaseDC (hwnd, hdc);
1037 return 0;
1041 static LRESULT
1042 TRACKBAR_SetThumbLength (HWND hwnd, WPARAM wParam, LPARAM lParam)
1044 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1045 HDC hdc;
1047 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_FIXEDLENGTH)
1048 infoPtr->uThumbLen = (UINT)wParam;
1050 infoPtr->flags |=TB_THUMBSIZECHANGED;
1052 hdc = GetDC (hwnd);
1053 TRACKBAR_Refresh (hwnd, hdc);
1054 ReleaseDC (hwnd, hdc);
1056 return 0;
1060 static LRESULT
1061 TRACKBAR_SetTic (HWND hwnd, WPARAM wParam, LPARAM lParam)
1063 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1064 INT nPos = (INT)lParam;
1065 HDC hdc;
1067 if ((nPos < infoPtr->nRangeMin) || (nPos> infoPtr->nRangeMax))
1068 return FALSE;
1070 infoPtr->uNumTics++;
1071 infoPtr->tics=COMCTL32_ReAlloc( infoPtr->tics,
1072 (infoPtr->uNumTics)*sizeof (DWORD));
1073 infoPtr->tics[infoPtr->uNumTics-1]=nPos;
1075 hdc = GetDC (hwnd);
1076 TRACKBAR_Refresh (hwnd, hdc);
1077 ReleaseDC (hwnd, hdc);
1079 return TRUE;
1085 static LRESULT
1086 TRACKBAR_SetTipSide (HWND hwnd, WPARAM wParam, LPARAM lParam)
1088 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1089 INT fTemp = infoPtr->fLocation;
1091 infoPtr->fLocation = (INT)wParam;
1093 return fTemp;
1097 static LRESULT
1098 TRACKBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
1100 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1102 infoPtr->hwndToolTip = (HWND)wParam;
1104 return 0;
1108 /* case TBM_SETUNICODEFORMAT: */
1111 static LRESULT
1112 TRACKBAR_InitializeThumb (HWND hwnd)
1114 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1116 infoPtr->uThumbLen = 23; /* initial thumb length */
1118 TRACKBAR_CalcChannel (hwnd,infoPtr);
1119 TRACKBAR_CalcThumb (hwnd, infoPtr);
1120 infoPtr->flags &= ~TB_SELECTIONCHANGED;
1122 return 0;
1126 static LRESULT
1127 TRACKBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
1129 TRACKBAR_INFO *infoPtr;
1131 infoPtr = (TRACKBAR_INFO *)COMCTL32_Alloc (sizeof(TRACKBAR_INFO));
1132 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
1134 /* set default values */
1135 infoPtr->nRangeMin = 0;
1136 infoPtr->nRangeMax = 100;
1137 infoPtr->nLineSize = 1;
1138 infoPtr->nPageSize = 20;
1139 infoPtr->nSelMin = 0;
1140 infoPtr->nSelMax = 0;
1141 infoPtr->nPos = 0;
1143 infoPtr->uNumTics = 0; /* start and end tic are not included in count*/
1144 infoPtr->uTicFreq = 1;
1145 infoPtr->tics = NULL;
1146 infoPtr->clrBk = GetSysColor (COLOR_BACKGROUND);
1147 infoPtr->hwndNotify = GetParent (hwnd);
1149 TRACKBAR_InitializeThumb (hwnd);
1151 /* Create tooltip control */
1152 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_TOOLTIPS) {
1153 TTTOOLINFOA ti;
1155 infoPtr->hwndToolTip =
1156 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
1157 CW_USEDEFAULT, CW_USEDEFAULT,
1158 CW_USEDEFAULT, CW_USEDEFAULT,
1159 hwnd, 0, 0, 0);
1161 /* Send NM_TOOLTIPSCREATED notification */
1162 if (infoPtr->hwndToolTip) {
1163 NMTOOLTIPSCREATED nmttc;
1165 nmttc.hdr.hwndFrom = hwnd;
1166 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1167 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1168 nmttc.hwndToolTips = infoPtr->hwndToolTip;
1170 SendMessageA (GetParent (hwnd), WM_NOTIFY,
1171 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
1174 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1175 ti.cbSize = sizeof(TTTOOLINFOA);
1176 ti.uFlags = TTF_IDISHWND | TTF_TRACK;
1177 ti.hwnd = hwnd;
1178 ti.uId = 0;
1179 ti.lpszText = "Test"; /* LPSTR_TEXTCALLBACK */
1180 SetRectEmpty (&ti.rect);
1182 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA, 0, (LPARAM)&ti);
1185 return 0;
1189 static LRESULT
1190 TRACKBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
1192 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1194 if (infoPtr->flags & TB_REFRESH_TIMER_SET)
1195 KillTimer (hwnd, TB_REFRESH_TIMER);
1197 /* delete tooltip control */
1198 if (infoPtr->hwndToolTip)
1199 DestroyWindow (infoPtr->hwndToolTip);
1201 COMCTL32_Free (infoPtr);
1202 return 0;
1206 static LRESULT
1207 TRACKBAR_KillFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
1209 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1211 TRACE (trackbar,"\n");
1213 infoPtr->bFocus = FALSE;
1214 infoPtr->flags &= ~TB_DRAG_MODE;
1216 TRACKBAR_QueueRefresh (hwnd);
1217 InvalidateRect (hwnd, NULL, TRUE);
1219 return 0;
1223 static LRESULT
1224 TRACKBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1226 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1227 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1228 int clickPlace,prevPos,clickPos,vertical;
1230 SetFocus (hwnd);
1232 vertical = dwStyle & TBS_VERT;
1233 if (vertical)
1234 clickPlace=(INT)HIWORD(lParam);
1235 else
1236 clickPlace=(INT)LOWORD(lParam);
1238 if ((vertical &&
1239 (clickPlace>infoPtr->rcThumb.top) &&
1240 (clickPlace<infoPtr->rcThumb.bottom)) ||
1241 (!vertical &&
1242 (clickPlace>infoPtr->rcThumb.left) &&
1243 (clickPlace<infoPtr->rcThumb.right))) {
1244 infoPtr->flags |= TB_DRAG_MODE;
1245 if (dwStyle & TBS_TOOLTIPS) { /* enable tooltip */
1246 TTTOOLINFOA ti;
1247 POINT pt;
1249 GetCursorPos (&pt);
1250 SendMessageA (infoPtr->hwndToolTip, TTM_TRACKPOSITION, 0,
1251 (LPARAM)MAKELPARAM(pt.x, pt.y));
1253 ti.cbSize = sizeof(TTTOOLINFOA);
1254 ti.uId = 0;
1255 ti.hwnd = (UINT)hwnd;
1257 infoPtr->flags |= TB_SHOW_TOOLTIP;
1258 SetCapture (hwnd);
1259 SendMessageA (infoPtr->hwndToolTip, TTM_TRACKACTIVATE,
1260 (WPARAM)TRUE, (LPARAM)&ti);
1262 return 0;
1265 clickPos=TRACKBAR_ConvertPlaceToPosition (infoPtr, clickPlace, vertical);
1266 prevPos = infoPtr->nPos;
1268 if (clickPos > prevPos) { /* similar to VK_NEXT */
1269 infoPtr->nPos += infoPtr->nPageSize;
1270 if (infoPtr->nPos > infoPtr->nRangeMax)
1271 infoPtr->nPos = infoPtr->nRangeMax;
1272 TRACKBAR_SendNotify (hwnd, TB_PAGEUP);
1273 } else {
1274 infoPtr->nPos -= infoPtr->nPageSize; /* similar to VK_PRIOR */
1275 if (infoPtr->nPos < infoPtr->nRangeMin)
1276 infoPtr->nPos = infoPtr->nRangeMin;
1277 TRACKBAR_SendNotify (hwnd, TB_PAGEDOWN);
1280 if (prevPos!=infoPtr->nPos) {
1281 infoPtr->flags |=TB_THUMBPOSCHANGED;
1282 TRACKBAR_QueueRefresh (hwnd);
1285 return 0;
1288 static LRESULT
1289 TRACKBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
1291 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1293 TRACKBAR_QueueRefresh (hwnd);
1294 TRACKBAR_SendNotify (hwnd, TB_ENDTRACK);
1296 infoPtr->flags &= ~TB_DRAG_MODE;
1298 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_TOOLTIPS) { /* disable tooltip */
1299 TTTOOLINFOA ti;
1301 ti.cbSize = sizeof(TTTOOLINFOA);
1302 ti.uId = 0;
1303 ti.hwnd = (UINT)hwnd;
1305 infoPtr->flags &= ~TB_SHOW_TOOLTIP;
1306 ReleaseCapture ();
1307 SendMessageA (infoPtr->hwndToolTip, TTM_TRACKACTIVATE,
1308 (WPARAM)FALSE, (LPARAM)&ti);
1311 return 0;
1314 static LRESULT
1315 TRACKBAR_CaptureChanged (HWND hwnd, WPARAM wParam, LPARAM lParam)
1317 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1319 if (infoPtr->flags & TB_DRAGPOSVALID) {
1320 infoPtr->nPos=infoPtr->dragPos;
1321 TRACKBAR_QueueRefresh (hwnd);
1324 infoPtr->flags &= ~ TB_DRAGPOSVALID;
1326 TRACKBAR_SendNotify (hwnd, TB_ENDTRACK);
1327 return 0;
1330 static LRESULT
1331 TRACKBAR_Paint (HWND hwnd, WPARAM wParam)
1333 HDC hdc;
1334 PAINTSTRUCT ps;
1336 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
1337 TRACKBAR_Refresh (hwnd, hdc);
1338 if(!wParam)
1339 EndPaint (hwnd, &ps);
1340 return 0;
1344 static LRESULT
1345 TRACKBAR_SetFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
1347 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1348 HDC hdc;
1350 TRACE (trackbar,"\n");
1351 infoPtr->bFocus = TRUE;
1353 hdc = GetDC (hwnd);
1354 TRACKBAR_Refresh (hwnd, hdc);
1355 ReleaseDC (hwnd, hdc);
1357 return 0;
1361 static LRESULT
1362 TRACKBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
1364 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1366 TRACKBAR_CalcChannel (hwnd, infoPtr);
1367 TRACKBAR_AlignBuddies (hwnd, infoPtr);
1369 return 0;
1374 static BOOL
1375 TRACKBAR_SendNotify (HWND hwnd, UINT code)
1378 TRACE (trackbar, "%x\n",code);
1380 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_VERT)
1381 return (BOOL) SendMessageA (GetParent (hwnd),
1382 WM_VSCROLL, (WPARAM)code, (LPARAM)hwnd);
1384 return (BOOL) SendMessageA (GetParent (hwnd),
1385 WM_HSCROLL, (WPARAM)code, (LPARAM)hwnd);
1388 static LRESULT
1389 TRACKBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
1391 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1392 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1393 INT clickPlace;
1394 HDC hdc;
1395 char buf[80];
1397 TRACE (trackbar, "%x\n",wParam);
1399 if (dwStyle & TBS_VERT)
1400 clickPlace=(INT)HIWORD(lParam);
1401 else
1402 clickPlace=(INT)LOWORD(lParam);
1404 if (!(infoPtr->flags & TB_DRAG_MODE))
1405 return TRUE;
1407 infoPtr->dragPos = TRACKBAR_ConvertPlaceToPosition (infoPtr, clickPlace, dwStyle & TBS_VERT);
1408 infoPtr->flags|= TB_DRAGPOSVALID;
1409 TRACKBAR_SendNotify (hwnd, TB_THUMBTRACK | (infoPtr->nPos>>16));
1411 if (infoPtr->flags & TB_SHOW_TOOLTIP) {
1412 POINT pt;
1413 TTTOOLINFOA ti;
1415 ti.cbSize = sizeof(TTTOOLINFOA);
1416 ti.hwnd = hwnd;
1417 ti.uId = 0;
1418 ti.hinst=0;
1419 sprintf (buf,"%d",infoPtr->nPos);
1420 ti.lpszText = (LPSTR) buf;
1421 GetCursorPos (&pt);
1423 if (dwStyle & TBS_VERT) {
1424 SendMessageA (infoPtr->hwndToolTip, TTM_TRACKPOSITION,
1425 0, (LPARAM)MAKELPARAM(pt.x+5, pt.y+15));
1426 } else {
1427 SendMessageA (infoPtr->hwndToolTip, TTM_TRACKPOSITION,
1428 0, (LPARAM)MAKELPARAM(pt.x+15, pt.y+5));
1430 SendMessageA (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTA,
1431 0, (LPARAM)&ti);
1434 hdc = GetDC (hwnd);
1435 TRACKBAR_Refresh (hwnd, hdc);
1436 ReleaseDC (hwnd, hdc);
1438 return TRUE;
1442 static LRESULT
1443 TRACKBAR_KeyDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1445 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1446 INT pos;
1448 TRACE (trackbar, "%x\n",wParam);
1450 pos=infoPtr->nPos;
1451 switch (wParam) {
1452 case VK_LEFT:
1453 case VK_UP:
1454 if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
1455 infoPtr->nPos -= infoPtr->nLineSize;
1456 if (infoPtr->nPos < infoPtr->nRangeMin)
1457 infoPtr->nPos = infoPtr->nRangeMin;
1458 TRACKBAR_SendNotify (hwnd, TB_LINEUP);
1459 break;
1460 case VK_RIGHT:
1461 case VK_DOWN:
1462 if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
1463 infoPtr->nPos += infoPtr->nLineSize;
1464 if (infoPtr->nPos > infoPtr->nRangeMax)
1465 infoPtr->nPos = infoPtr->nRangeMax;
1466 TRACKBAR_SendNotify (hwnd, TB_LINEDOWN);
1467 break;
1468 case VK_NEXT:
1469 if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
1470 infoPtr->nPos += infoPtr->nPageSize;
1471 if (infoPtr->nPos > infoPtr->nRangeMax)
1472 infoPtr->nPos = infoPtr->nRangeMax;
1473 TRACKBAR_SendNotify (hwnd, TB_PAGEUP);
1474 break;
1475 case VK_PRIOR:
1476 if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
1477 infoPtr->nPos -= infoPtr->nPageSize;
1478 if (infoPtr->nPos < infoPtr->nRangeMin)
1479 infoPtr->nPos = infoPtr->nRangeMin;
1480 TRACKBAR_SendNotify (hwnd, TB_PAGEDOWN);
1481 break;
1482 case VK_HOME:
1483 if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
1484 infoPtr->nPos = infoPtr->nRangeMin;
1485 TRACKBAR_SendNotify (hwnd, TB_TOP);
1486 break;
1487 case VK_END:
1488 if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
1489 infoPtr->nPos = infoPtr->nRangeMax;
1490 TRACKBAR_SendNotify (hwnd, TB_BOTTOM);
1491 break;
1494 if (pos!=infoPtr->nPos) {
1495 infoPtr->flags |=TB_THUMBPOSCHANGED;
1496 TRACKBAR_QueueRefresh (hwnd);
1499 return TRUE;
1502 static LRESULT
1503 TRACKBAR_KeyUp (HWND hwnd, WPARAM wParam)
1505 switch (wParam) {
1506 case VK_LEFT:
1507 case VK_UP:
1508 case VK_RIGHT:
1509 case VK_DOWN:
1510 case VK_NEXT:
1511 case VK_PRIOR:
1512 case VK_HOME:
1513 case VK_END:
1514 TRACKBAR_SendNotify (hwnd, TB_ENDTRACK);
1516 return TRUE;
1520 static LRESULT
1521 TRACKBAR_HandleTimer (HWND hwnd, WPARAM wParam, LPARAM lParam)
1523 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1524 HDC hdc;
1526 TRACE (trackbar,"timer\n");
1528 switch (wParam) {
1529 case TB_REFRESH_TIMER:
1530 KillTimer (hwnd, TB_REFRESH_TIMER );
1531 if (infoPtr->flags & TB_DRAGPOSVALID) {
1532 infoPtr->nPos=infoPtr->dragPos;
1533 infoPtr->flags |= TB_THUMBPOSCHANGED;
1535 infoPtr->flags &= ~ (TB_REFRESH_TIMER_SET | TB_DRAGPOSVALID);
1536 hdc=GetDC (hwnd);
1537 TRACKBAR_Refresh (hwnd, hdc);
1538 ReleaseDC (hwnd, hdc);
1539 return 0;
1541 return 1;
1545 LRESULT WINAPI
1546 TRACKBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1548 switch (uMsg)
1550 case TBM_CLEARSEL:
1551 return TRACKBAR_ClearSel (hwnd, wParam, lParam);
1553 case TBM_CLEARTICS:
1554 return TRACKBAR_ClearTics (hwnd, wParam, lParam);
1556 case TBM_GETBUDDY:
1557 return TRACKBAR_GetBuddy (hwnd, wParam, lParam);
1559 case TBM_GETCHANNELRECT:
1560 return TRACKBAR_GetChannelRect (hwnd, wParam, lParam);
1562 case TBM_GETLINESIZE:
1563 return TRACKBAR_GetLineSize (hwnd, wParam, lParam);
1565 case TBM_GETNUMTICS:
1566 return TRACKBAR_GetNumTics (hwnd, wParam, lParam);
1568 case TBM_GETPAGESIZE:
1569 return TRACKBAR_GetPageSize (hwnd, wParam, lParam);
1571 case TBM_GETPOS:
1572 return TRACKBAR_GetPos (hwnd, wParam, lParam);
1574 case TBM_GETPTICS:
1575 return TRACKBAR_GetPTics (hwnd);
1577 case TBM_GETRANGEMAX:
1578 return TRACKBAR_GetRangeMax (hwnd, wParam, lParam);
1580 case TBM_GETRANGEMIN:
1581 return TRACKBAR_GetRangeMin (hwnd, wParam, lParam);
1583 case TBM_GETSELEND:
1584 return TRACKBAR_GetSelEnd (hwnd, wParam, lParam);
1586 case TBM_GETSELSTART:
1587 return TRACKBAR_GetSelStart (hwnd, wParam, lParam);
1589 case TBM_GETTHUMBLENGTH:
1590 return TRACKBAR_GetThumbLength (hwnd, wParam, lParam);
1592 case TBM_GETTHUMBRECT:
1593 return TRACKBAR_GetThumbRect (hwnd, wParam, lParam);
1595 case TBM_GETTIC:
1596 return TRACKBAR_GetTic (hwnd, wParam, lParam);
1598 case TBM_GETTICPOS:
1599 return TRACKBAR_GetTicPos (hwnd, wParam, lParam);
1601 case TBM_GETTOOLTIPS:
1602 return TRACKBAR_GetToolTips (hwnd, wParam, lParam);
1604 /* case TBM_GETUNICODEFORMAT: */
1606 case TBM_SETBUDDY:
1607 return TRACKBAR_SetBuddy (hwnd, wParam, lParam);
1609 case TBM_SETLINESIZE:
1610 return TRACKBAR_SetLineSize (hwnd, wParam, lParam);
1612 case TBM_SETPAGESIZE:
1613 return TRACKBAR_SetPageSize (hwnd, wParam, lParam);
1615 case TBM_SETPOS:
1616 return TRACKBAR_SetPos (hwnd, wParam, lParam);
1618 case TBM_SETRANGE:
1619 return TRACKBAR_SetRange (hwnd, wParam, lParam);
1621 case TBM_SETRANGEMAX:
1622 return TRACKBAR_SetRangeMax (hwnd, wParam, lParam);
1624 case TBM_SETRANGEMIN:
1625 return TRACKBAR_SetRangeMin (hwnd, wParam, lParam);
1627 case TBM_SETSEL:
1628 return TRACKBAR_SetSel (hwnd, wParam, lParam);
1630 case TBM_SETSELEND:
1631 return TRACKBAR_SetSelEnd (hwnd, wParam, lParam);
1633 case TBM_SETSELSTART:
1634 return TRACKBAR_SetSelStart (hwnd, wParam, lParam);
1636 case TBM_SETTHUMBLENGTH:
1637 return TRACKBAR_SetThumbLength (hwnd, wParam, lParam);
1639 case TBM_SETTIC:
1640 return TRACKBAR_SetTic (hwnd, wParam, lParam);
1642 case TBM_SETTICFREQ:
1643 return TRACKBAR_SetTicFreq (hwnd, wParam);
1645 case TBM_SETTIPSIDE:
1646 return TRACKBAR_SetTipSide (hwnd, wParam, lParam);
1648 case TBM_SETTOOLTIPS:
1649 return TRACKBAR_SetToolTips (hwnd, wParam, lParam);
1651 /* case TBM_SETUNICODEFORMAT: */
1654 case WM_CAPTURECHANGED:
1655 return TRACKBAR_CaptureChanged (hwnd, wParam, lParam);
1657 case WM_CREATE:
1658 return TRACKBAR_Create (hwnd, wParam, lParam);
1660 case WM_DESTROY:
1661 return TRACKBAR_Destroy (hwnd, wParam, lParam);
1663 /* case WM_ENABLE: */
1665 /* case WM_ERASEBKGND: */
1666 /* return 0; */
1668 case WM_GETDLGCODE:
1669 return DLGC_WANTARROWS;
1671 case WM_KEYDOWN:
1672 return TRACKBAR_KeyDown (hwnd, wParam, lParam);
1674 case WM_KEYUP:
1675 return TRACKBAR_KeyUp (hwnd, wParam);
1677 case WM_KILLFOCUS:
1678 return TRACKBAR_KillFocus (hwnd, wParam, lParam);
1680 case WM_LBUTTONDOWN:
1681 return TRACKBAR_LButtonDown (hwnd, wParam, lParam);
1683 case WM_LBUTTONUP:
1684 return TRACKBAR_LButtonUp (hwnd, wParam, lParam);
1686 case WM_MOUSEMOVE:
1687 return TRACKBAR_MouseMove (hwnd, wParam, lParam);
1689 case WM_PAINT:
1690 return TRACKBAR_Paint (hwnd, wParam);
1692 case WM_SETFOCUS:
1693 return TRACKBAR_SetFocus (hwnd, wParam, lParam);
1695 case WM_SIZE:
1696 return TRACKBAR_Size (hwnd, wParam, lParam);
1698 case WM_TIMER:
1699 return TRACKBAR_HandleTimer (hwnd, wParam, lParam);
1701 case WM_WININICHANGE:
1702 return TRACKBAR_InitializeThumb (hwnd);
1704 default:
1705 if (uMsg >= WM_USER)
1706 ERR (trackbar, "unknown msg %04x wp=%08x lp=%08lx\n",
1707 uMsg, wParam, lParam);
1708 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1710 return 0;
1714 VOID
1715 TRACKBAR_Register (VOID)
1717 WNDCLASSA wndClass;
1719 if (GlobalFindAtomA (TRACKBAR_CLASSA)) return;
1721 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1722 wndClass.style = CS_GLOBALCLASS;
1723 wndClass.lpfnWndProc = (WNDPROC)TRACKBAR_WindowProc;
1724 wndClass.cbClsExtra = 0;
1725 wndClass.cbWndExtra = sizeof(TRACKBAR_INFO *);
1726 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
1727 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
1728 wndClass.lpszClassName = TRACKBAR_CLASSA;
1730 RegisterClassA (&wndClass);
1734 VOID
1735 TRACKBAR_Unregister (VOID)
1737 if (GlobalFindAtomA (TRACKBAR_CLASSA))
1738 UnregisterClassA (TRACKBAR_CLASSA, (HINSTANCE)NULL);