4 * Copyright 1998, 1999 Eric Kohl <ekohl@abo.rhein-zeitung.de>
5 * Copyright 1998, 1999 Alex Priem <alexp@sci.kun.nl>
6 * Copyright 2002 Dimitrie O. Paun <dimi@bigfoot.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * This code was audited for completeness against the documented features
25 * of Comctl32.dll version 6.0 on Sep. 12, 2002, by Dimitrie O. Paun.
27 * Unless otherwise noted, we believe this code to be complete, as per
28 * the specification mentioned above.
29 * If you discover missing features, or bugs, please note them below.
39 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(trackbar
);
71 #define TB_REFRESH_TIMER 1
72 #define TB_REFRESH_DELAY 500
74 #define TOOLTIP_OFFSET 2 /* distance from ctrl edge to tooltip */
76 /* Used by TRACKBAR_Refresh to find out which parts of the control
77 need to be recalculated */
79 #define TB_THUMBPOSCHANGED 1
80 #define TB_THUMBSIZECHANGED 2
81 #define TB_THUMBCHANGED (TB_THUMBPOSCHANGED | TB_THUMBSIZECHANGED)
82 #define TB_SELECTIONCHANGED 4
83 #define TB_DRAG_MODE 8 /* we're dragging the slider */
84 #define TB_AUTO_PAGE_LEFT 16
85 #define TB_AUTO_PAGE_RIGHT 32
86 #define TB_AUTO_PAGE (TB_AUTO_PAGE_LEFT | TB_AUTO_PAGE_RIGHT)
88 /* helper defines for TRACKBAR_DrawTic */
90 #define TIC_SELECTIONMARKMAX 0x80
91 #define TIC_SELECTIONMARKMIN 0x100
92 #define TIC_SELECTIONMARK (TIC_SELECTIONMARKMAX | TIC_SELECTIONMARKMIN)
94 static BOOL
TRACKBAR_SendNotify (TRACKBAR_INFO
*infoPtr
, UINT code
);
97 notify_customdraw(NMCUSTOMDRAW
*pnmcd
, int stage
)
99 pnmcd
->dwDrawStage
= stage
;
100 return SendMessageW (GetParent(pnmcd
->hdr
.hwndFrom
), WM_NOTIFY
,
101 pnmcd
->hdr
.idFrom
, (LPARAM
)pnmcd
);
104 static void TRACKBAR_RecalculateTics (TRACKBAR_INFO
*infoPtr
)
108 if (infoPtr
->uTicFreq
&& infoPtr
->lRangeMax
>= infoPtr
->lRangeMin
)
109 nrTics
=(infoPtr
->lRangeMax
- infoPtr
->lRangeMin
)/infoPtr
->uTicFreq
;
112 COMCTL32_Free (infoPtr
->tics
);
113 infoPtr
->tics
= NULL
;
114 infoPtr
->uNumTics
= 0;
118 if (nrTics
!= infoPtr
->uNumTics
) {
119 infoPtr
->tics
=COMCTL32_ReAlloc (infoPtr
->tics
,
120 (nrTics
+1)*sizeof (DWORD
));
121 if (!infoPtr
->tics
) {
122 infoPtr
->uNumTics
= 0;
123 TRACKBAR_SendNotify(infoPtr
, NM_OUTOFMEMORY
);
126 infoPtr
->uNumTics
= nrTics
;
129 tic
= infoPtr
->lRangeMin
+ infoPtr
->uTicFreq
;
130 for (i
= 0; i
< nrTics
; i
++, tic
+= infoPtr
->uTicFreq
)
131 infoPtr
->tics
[i
] = tic
;
134 /* converts from physical (mouse) position to logical position
135 (in range of trackbar) */
138 TRACKBAR_ConvertPlaceToPosition (TRACKBAR_INFO
*infoPtr
, int place
,
141 double range
, width
, pos
;
143 range
= infoPtr
->lRangeMax
- infoPtr
->lRangeMin
;
145 width
= infoPtr
->rcChannel
.bottom
- infoPtr
->rcChannel
.top
;
146 pos
= (range
*(place
- infoPtr
->rcChannel
.top
)) / width
;
148 width
= infoPtr
->rcChannel
.right
- infoPtr
->rcChannel
.left
;
149 pos
= (range
*(place
- infoPtr
->rcChannel
.left
)) / width
;
151 pos
+= infoPtr
->lRangeMin
;
152 if (pos
> infoPtr
->lRangeMax
)
153 pos
= infoPtr
->lRangeMax
;
154 else if (pos
< infoPtr
->lRangeMin
)
155 pos
= infoPtr
->lRangeMin
;
157 TRACE("%.2f\n", pos
);
158 return (LONG
)(pos
+ 0.5);
162 /* return: 0> prev, 0 none, >0 next */
164 TRACKBAR_GetAutoPageDirection (TRACKBAR_INFO
*infoPtr
, POINT clickPoint
)
166 DWORD dwStyle
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
);
169 if (dwStyle
& TBS_VERT
) {
170 pageRect
.top
= infoPtr
->rcChannel
.top
;
171 pageRect
.bottom
= infoPtr
->rcChannel
.bottom
;
172 pageRect
.left
= infoPtr
->rcThumb
.left
;
173 pageRect
.right
= infoPtr
->rcThumb
.right
;
175 pageRect
.top
= infoPtr
->rcThumb
.top
;
176 pageRect
.bottom
= infoPtr
->rcThumb
.bottom
;
177 pageRect
.left
= infoPtr
->rcChannel
.left
;
178 pageRect
.right
= infoPtr
->rcChannel
.right
;
182 if (PtInRect(&pageRect
, clickPoint
))
184 int clickPlace
= (dwStyle
& TBS_VERT
) ? clickPoint
.y
: clickPoint
.x
;
186 LONG clickPos
= TRACKBAR_ConvertPlaceToPosition(infoPtr
, clickPlace
,
188 return clickPos
- infoPtr
->lPos
;
195 TRACKBAR_PageUp (TRACKBAR_INFO
*infoPtr
)
197 if (infoPtr
->lPos
== infoPtr
->lRangeMax
) return;
199 infoPtr
->lPos
+= infoPtr
->lPageSize
;
200 if (infoPtr
->lPos
> infoPtr
->lRangeMax
)
201 infoPtr
->lPos
= infoPtr
->lRangeMax
;
202 TRACKBAR_SendNotify (infoPtr
, TB_PAGEUP
);
207 TRACKBAR_PageDown (TRACKBAR_INFO
*infoPtr
)
209 if (infoPtr
->lPos
== infoPtr
->lRangeMin
) return;
211 infoPtr
->lPos
-= infoPtr
->lPageSize
;
212 if (infoPtr
->lPos
< infoPtr
->lRangeMin
)
213 infoPtr
->lPos
= infoPtr
->lRangeMin
;
214 TRACKBAR_SendNotify (infoPtr
, TB_PAGEDOWN
);
218 TRACKBAR_CalcChannel (TRACKBAR_INFO
*infoPtr
)
220 DWORD dwStyle
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
);
221 INT cyChannel
, offsetthumb
, offsetedge
;
222 RECT lpRect
, *channel
= & infoPtr
->rcChannel
;
224 GetClientRect (infoPtr
->hwndSelf
, &lpRect
);
226 offsetthumb
= (int)(infoPtr
->uThumbLen
/4.5);
227 offsetedge
= offsetthumb
+ 3;
228 cyChannel
= (dwStyle
& TBS_ENABLESELRANGE
) ? (offsetthumb
+1)*3 : 4;
230 if (dwStyle
& TBS_VERT
) {
231 channel
->top
= lpRect
.top
+ offsetedge
;
232 channel
->bottom
= lpRect
.bottom
- offsetedge
;
233 channel
->left
= lpRect
.left
+ offsetthumb
;
234 if (dwStyle
& (TBS_BOTH
| TBS_LEFT
)) channel
->left
+= 8;
235 channel
->right
= channel
->left
+ cyChannel
;
237 channel
->left
= lpRect
.left
+ offsetedge
;
238 channel
->right
= lpRect
.right
- offsetedge
;
239 channel
->top
= lpRect
.top
+ offsetthumb
;
240 if (dwStyle
& (TBS_BOTH
| TBS_TOP
)) channel
->top
+= 8;
241 channel
->bottom
= channel
->top
+ cyChannel
;
246 TRACKBAR_CalcThumb (TRACKBAR_INFO
*infoPtr
, LONG lPos
, RECT
*thumb
)
248 int range
, width
, thumbdepth
;
249 DWORD dwStyle
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
);
251 range
=infoPtr
->lRangeMax
- infoPtr
->lRangeMin
;
252 thumbdepth
= ((int)(infoPtr
->uThumbLen
/ 4.5) * 2) + 2;
254 if (!range
) range
= 1;
256 if (dwStyle
& TBS_VERT
)
258 width
=infoPtr
->rcChannel
.bottom
- infoPtr
->rcChannel
.top
;
260 if (dwStyle
& (TBS_BOTH
| TBS_LEFT
))
264 thumb
->right
= thumb
-> left
+ infoPtr
->uThumbLen
;
265 thumb
->top
= infoPtr
->rcChannel
.top
+
266 (width
*(lPos
- infoPtr
->lRangeMin
))/range
-
268 thumb
->bottom
= thumb
->top
+ thumbdepth
;
272 width
=infoPtr
->rcChannel
.right
- infoPtr
->rcChannel
.left
;
274 thumb
->left
= infoPtr
->rcChannel
.left
+
275 (width
*(lPos
- infoPtr
->lRangeMin
))/range
-
277 thumb
->right
= thumb
->left
+ thumbdepth
;
278 if (dwStyle
& (TBS_BOTH
| TBS_TOP
))
282 thumb
->bottom
= thumb
->top
+ infoPtr
->uThumbLen
;
287 TRACKBAR_UpdateThumb (TRACKBAR_INFO
*infoPtr
)
289 TRACKBAR_CalcThumb(infoPtr
, infoPtr
->lPos
, &infoPtr
->rcThumb
);
293 TRACKBAR_InvalidateAll(TRACKBAR_INFO
* infoPtr
)
295 InvalidateRect(infoPtr
->hwndSelf
, NULL
, FALSE
);
299 TRACKBAR_InvalidateThumb (TRACKBAR_INFO
*infoPtr
, LONG thumbPos
)
303 TRACKBAR_CalcThumb(infoPtr
, thumbPos
, &rcThumb
);
304 InflateRect(&rcThumb
, 1, 1);
305 InvalidateRect(infoPtr
->hwndSelf
, &rcThumb
, FALSE
);
309 TRACKBAR_InvalidateThumbMove (TRACKBAR_INFO
*infoPtr
, LONG oldPos
, LONG newPos
)
311 TRACKBAR_InvalidateThumb (infoPtr
, oldPos
);
312 if (newPos
!= oldPos
)
313 TRACKBAR_InvalidateThumb (infoPtr
, newPos
);
317 TRACKBAR_HasSelection (TRACKBAR_INFO
*infoPtr
)
319 return infoPtr
->lSelMin
!= infoPtr
->lSelMax
;
323 TRACKBAR_CalcSelection (TRACKBAR_INFO
*infoPtr
)
325 RECT
*selection
= &infoPtr
->rcSelection
;
326 int range
= infoPtr
->lRangeMax
- infoPtr
->lRangeMin
;
329 SetRectEmpty (selection
);
331 if (GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
) & TBS_VERT
) {
332 int height
= infoPtr
->rcChannel
.right
- infoPtr
->rcChannel
.left
;
333 selection
->top
= infoPtr
->rcChannel
.top
+
334 (height
*infoPtr
->lSelMin
)/range
;
335 selection
->bottom
= infoPtr
->rcChannel
.top
+
336 (height
*infoPtr
->lSelMax
)/range
;
337 selection
->left
= infoPtr
->rcChannel
.left
+ 3;
338 selection
->right
= infoPtr
->rcChannel
.right
- 3;
340 int width
= infoPtr
->rcChannel
.right
- infoPtr
->rcChannel
.left
;
341 selection
->left
= infoPtr
->rcChannel
.left
+
342 (width
*infoPtr
->lSelMin
)/range
;
343 selection
->right
= infoPtr
->rcChannel
.left
+
344 (width
*infoPtr
->lSelMax
)/range
;
345 selection
->top
= infoPtr
->rcChannel
.top
+ 3;
346 selection
->bottom
= infoPtr
->rcChannel
.bottom
- 3;
350 TRACE("selection[left=%d, top=%d, right=%d, bottom=%d]\n",
351 selection
->left
, selection
->top
, selection
->right
, selection
->bottom
);
355 TRACKBAR_AutoPage (TRACKBAR_INFO
*infoPtr
, POINT clickPoint
)
357 LONG dir
= TRACKBAR_GetAutoPageDirection(infoPtr
, clickPoint
);
358 LONG prevPos
= infoPtr
->lPos
;
360 TRACE("x=%ld, y=%ld, dir=%ld\n", clickPoint
.x
, clickPoint
.y
, dir
);
362 if (dir
> 0 && (infoPtr
->flags
& TB_AUTO_PAGE_RIGHT
))
363 TRACKBAR_PageUp(infoPtr
);
364 else if (dir
< 0 && (infoPtr
->flags
& TB_AUTO_PAGE_LEFT
))
365 TRACKBAR_PageDown(infoPtr
);
368 infoPtr
->flags
|= TB_THUMBPOSCHANGED
;
369 TRACKBAR_InvalidateThumbMove (infoPtr
, prevPos
, infoPtr
->lPos
);
374 /* Trackbar drawing code. I like my spaghetti done milanese. */
377 TRACKBAR_DrawChannel (TRACKBAR_INFO
*infoPtr
, HDC hdc
, DWORD dwStyle
)
379 RECT rcChannel
= infoPtr
->rcChannel
;
381 DrawEdge (hdc
, &rcChannel
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
382 if (dwStyle
& TBS_ENABLESELRANGE
) { /* fill the channel */
383 FillRect (hdc
, &rcChannel
, GetStockObject(WHITE_BRUSH
));
384 if (TRACKBAR_HasSelection(infoPtr
))
385 FillRect (hdc
, &infoPtr
->rcSelection
, GetSysColorBrush(COLOR_HIGHLIGHT
));
390 TRACKBAR_DrawOneTic (TRACKBAR_INFO
*infoPtr
, HDC hdc
, LONG ticPos
, int flags
)
392 int x
, y
, ox
, oy
, range
, side
, offset
= 5, indent
= 0, len
= 3;
397 GetClientRect(infoPtr
->hwndSelf
, &rcTics
);
398 if (flags
& TBS_VERT
) {
399 rcTics
.top
= infoPtr
->rcChannel
.top
;
400 rcTics
.bottom
= infoPtr
->rcChannel
.bottom
;
402 rcTics
.left
= infoPtr
->rcChannel
.left
;
403 rcTics
.right
= infoPtr
->rcChannel
.right
;
406 if (flags
& (TBS_TOP
| TBS_LEFT
)) {
416 range
= infoPtr
->lRangeMax
- infoPtr
->lRangeMin
;
418 range
= 1; /* to avoid division by zero */
420 if (flags
& TIC_SELECTIONMARK
) {
421 indent
= (flags
& TIC_SELECTIONMARKMIN
) ? -1 : 1;
422 } else if (flags
& TIC_EDGE
) {
426 if (flags
& TBS_VERT
) {
427 int height
= rcTics
.bottom
= rcTics
.top
;
428 y
= rcTics
.top
+ (height
*(ticPos
- infoPtr
->lRangeMin
))/range
;
429 x
-= (offset
+ 2) * side
;
432 int width
= rcTics
.right
- rcTics
.left
;
433 x
= rcTics
.left
+ (width
*(ticPos
- infoPtr
->lRangeMin
))/range
;
435 y
-= (offset
+ 2) * side
;
440 MoveToEx(hdc
, x
, y
, 0);
441 if (flags
& TBS_VERT
) x
+= len
* side
;
442 else y
+= len
* side
;
445 if (flags
& TIC_SELECTIONMARK
) {
446 if (flags
& TBS_VERT
) {
451 MoveToEx(hdc
, x
, y
, 0);
452 if (flags
& TBS_VERT
) {
465 TRACKBAR_DrawTic (TRACKBAR_INFO
*infoPtr
, HDC hdc
, LONG ticPos
, int flags
)
467 if ((flags
& (TBS_LEFT
| TBS_TOP
)) || (flags
& TBS_BOTH
))
468 TRACKBAR_DrawOneTic (infoPtr
, hdc
, ticPos
, flags
| TBS_LEFT
);
470 if (!(flags
& (TBS_LEFT
| TBS_TOP
)) || (flags
& TBS_BOTH
))
471 TRACKBAR_DrawOneTic (infoPtr
, hdc
, ticPos
, flags
);
475 TRACKBAR_DrawTics (TRACKBAR_INFO
*infoPtr
, HDC hdc
, DWORD dwStyle
)
477 int i
, ticFlags
= dwStyle
& 0x0f;
478 LOGPEN ticPen
= { PS_SOLID
, {1, 0}, GetSysColor (COLOR_3DDKSHADOW
) };
479 HPEN hOldPen
, hTicPen
;
481 /* create the pen to draw the tics with */
482 hTicPen
= CreatePenIndirect(&ticPen
);
483 hOldPen
= hTicPen
? SelectObject(hdc
, hTicPen
) : 0;
485 /* actually draw the tics */
486 for (i
=0; i
<infoPtr
->uNumTics
; i
++)
487 TRACKBAR_DrawTic (infoPtr
, hdc
, infoPtr
->tics
[i
], ticFlags
);
489 TRACKBAR_DrawTic (infoPtr
, hdc
, infoPtr
->lRangeMin
, ticFlags
| TIC_EDGE
);
490 TRACKBAR_DrawTic (infoPtr
, hdc
, infoPtr
->lRangeMax
, ticFlags
| TIC_EDGE
);
492 if ((dwStyle
& TBS_ENABLESELRANGE
) && TRACKBAR_HasSelection(infoPtr
)) {
493 TRACKBAR_DrawTic (infoPtr
, hdc
, infoPtr
->lSelMin
,
494 ticFlags
| TIC_SELECTIONMARKMIN
);
495 TRACKBAR_DrawTic (infoPtr
, hdc
, infoPtr
->lSelMax
,
496 ticFlags
| TIC_SELECTIONMARKMAX
);
499 /* clean up the pen, if we created one */
501 SelectObject(hdc
, hOldPen
);
502 DeleteObject(hTicPen
);
507 TRACKBAR_DrawThumb(TRACKBAR_INFO
*infoPtr
, HDC hdc
, DWORD dwStyle
)
511 RECT thumb
= infoPtr
->rcThumb
;
517 static INT PointDepth
= 4;
519 fillClr
= infoPtr
->flags
& TB_DRAG_MODE
? COLOR_BTNHILIGHT
: COLOR_BTNFACE
;
520 oldbr
= SelectObject (hdc
, GetSysColorBrush(fillClr
));
521 SetPolyFillMode (hdc
, WINDING
);
523 if (dwStyle
& TBS_BOTH
)
525 points
[0].x
=thumb
.right
;
526 points
[0].y
=thumb
.top
;
527 points
[1].x
=thumb
.right
;
528 points
[1].y
=thumb
.bottom
;
529 points
[2].x
=thumb
.left
;
530 points
[2].y
=thumb
.bottom
;
531 points
[3].x
=thumb
.left
;
532 points
[3].y
=thumb
.top
;
533 points
[4].x
=points
[0].x
;
534 points
[4].y
=points
[0].y
;
540 if (dwStyle
& TBS_VERT
)
542 if (dwStyle
& TBS_LEFT
)
544 points
[0].x
=thumb
.right
;
545 points
[0].y
=thumb
.top
;
546 points
[1].x
=thumb
.right
;
547 points
[1].y
=thumb
.bottom
;
548 points
[2].x
=thumb
.left
+ PointDepth
;
549 points
[2].y
=thumb
.bottom
;
550 points
[3].x
=thumb
.left
;
551 points
[3].y
=(thumb
.bottom
- thumb
.top
) / 2 + thumb
.top
;
552 points
[4].x
=thumb
.left
+ PointDepth
;
553 points
[4].y
=thumb
.top
;
554 points
[5].x
=points
[0].x
;
555 points
[5].y
=points
[0].y
;
560 points
[0].x
=thumb
.right
;
561 points
[0].y
=(thumb
.bottom
- thumb
.top
) / 2 + thumb
.top
;
562 points
[1].x
=thumb
.right
- PointDepth
;
563 points
[1].y
=thumb
.bottom
;
564 points
[2].x
=thumb
.left
;
565 points
[2].y
=thumb
.bottom
;
566 points
[3].x
=thumb
.left
;
567 points
[3].y
=thumb
.top
;
568 points
[4].x
=thumb
.right
- PointDepth
;
569 points
[4].y
=thumb
.top
;
570 points
[5].x
=points
[0].x
;
571 points
[5].y
=points
[0].y
;
576 if (dwStyle
& TBS_TOP
)
578 points
[0].x
=(thumb
.right
- thumb
.left
) / 2 + thumb
.left
;
579 points
[0].y
=thumb
.top
;
580 points
[1].x
=thumb
.right
;
581 points
[1].y
=thumb
.top
+ PointDepth
;
582 points
[2].x
=thumb
.right
;
583 points
[2].y
=thumb
.bottom
;
584 points
[3].x
=thumb
.left
;
585 points
[3].y
=thumb
.bottom
;
586 points
[4].x
=thumb
.left
;
587 points
[4].y
=thumb
.top
+ PointDepth
;
588 points
[5].x
=points
[0].x
;
589 points
[5].y
=points
[0].y
;
594 points
[0].x
=thumb
.right
;
595 points
[0].y
=thumb
.top
;
596 points
[1].x
=thumb
.right
;
597 points
[1].y
=thumb
.bottom
- PointDepth
;
598 points
[2].x
=(thumb
.right
- thumb
.left
) / 2 + thumb
.left
;
599 points
[2].y
=thumb
.bottom
;
600 points
[3].x
=thumb
.left
;
601 points
[3].y
=thumb
.bottom
- PointDepth
;
602 points
[4].x
=thumb
.left
;
603 points
[4].y
=thumb
.top
;
604 points
[5].x
=points
[0].x
;
605 points
[5].y
=points
[0].y
;
611 /* Draw the thumb now */
612 Polygon (hdc
, points
, PointCount
);
613 oldpen
= SelectObject(hdc
, GetStockObject(BLACK_PEN
));
614 Polyline(hdc
,points
, BlackUntil
);
615 SelectObject(hdc
, GetStockObject(WHITE_PEN
));
616 Polyline(hdc
, &points
[BlackUntil
-1], PointCount
+1-BlackUntil
);
617 SelectObject(hdc
, oldpen
);
618 SelectObject(hdc
, oldbr
);
623 TRACKBAR_ActivateToolTip (TRACKBAR_INFO
*infoPtr
, BOOL fShow
)
627 if (!infoPtr
->hwndToolTip
) return;
629 ZeroMemory(&ti
, sizeof(ti
));
630 ti
.cbSize
= sizeof(ti
);
631 ti
.hwnd
= infoPtr
->hwndSelf
;
633 SendMessageW (infoPtr
->hwndToolTip
, TTM_TRACKACTIVATE
, fShow
, (LPARAM
)&ti
);
638 TRACKBAR_UpdateToolTip (TRACKBAR_INFO
*infoPtr
)
640 DWORD dwStyle
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
);
641 WCHAR buf
[80], fmt
[] = { '%', 'l', 'd', 0 };
647 if (!infoPtr
->hwndToolTip
) return;
649 ZeroMemory(&ti
, sizeof(ti
));
650 ti
.cbSize
= sizeof(ti
);
651 ti
.hwnd
= infoPtr
->hwndSelf
;
652 ti
.uFlags
= TTF_IDISHWND
| TTF_TRACK
| TTF_ABSOLUTE
;
654 wsprintfW (buf
, fmt
, infoPtr
->lPos
);
656 SendMessageW (infoPtr
->hwndToolTip
, TTM_UPDATETIPTEXTW
, 0, (LPARAM
)&ti
);
658 GetClientRect (infoPtr
->hwndSelf
, &rcClient
);
659 size
= SendMessageW (infoPtr
->hwndToolTip
, TTM_GETBUBBLESIZE
, 0, (LPARAM
)&ti
);
660 if (dwStyle
& TBS_VERT
) {
661 if (infoPtr
->fLocation
== TBTS_LEFT
)
662 pt
.x
= 0 - LOWORD(size
) - TOOLTIP_OFFSET
;
664 pt
.x
= rcClient
.right
+ TOOLTIP_OFFSET
;
665 pt
.y
= (infoPtr
->rcThumb
.top
+ infoPtr
->rcThumb
.bottom
- HIWORD(size
))/2;
667 if (infoPtr
->fLocation
== TBTS_TOP
)
668 pt
.y
= 0 - HIWORD(size
) - TOOLTIP_OFFSET
;
670 pt
.y
= rcClient
.bottom
+ TOOLTIP_OFFSET
;
671 pt
.x
= (infoPtr
->rcThumb
.left
+ infoPtr
->rcThumb
.right
- LOWORD(size
))/2;
673 ClientToScreen(infoPtr
->hwndSelf
, &pt
);
675 SendMessageW (infoPtr
->hwndToolTip
, TTM_TRACKPOSITION
,
676 0, (LPARAM
)MAKELPARAM(pt
.x
, pt
.y
));
681 TRACKBAR_Refresh (TRACKBAR_INFO
*infoPtr
, HDC hdcDst
)
683 DWORD dwStyle
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
);
686 HBITMAP hOldBmp
= 0, hOffScreenBmp
= 0;
690 if (infoPtr
->flags
& TB_THUMBCHANGED
) {
691 TRACKBAR_UpdateThumb (infoPtr
);
692 if (infoPtr
->flags
& TB_THUMBSIZECHANGED
)
693 TRACKBAR_CalcChannel (infoPtr
);
695 if (infoPtr
->flags
& TB_SELECTIONCHANGED
)
696 TRACKBAR_CalcSelection (infoPtr
);
698 if (infoPtr
->flags
& TB_DRAG_MODE
)
699 TRACKBAR_UpdateToolTip (infoPtr
);
701 infoPtr
->flags
&= ~ (TB_THUMBCHANGED
| TB_SELECTIONCHANGED
);
703 GetClientRect (infoPtr
->hwndSelf
, &rcClient
);
705 /* try to render offscreen, if we fail, carrry onscreen */
706 hdc
= CreateCompatibleDC(hdcDst
);
708 hOffScreenBmp
= CreateCompatibleBitmap(hdcDst
, rcClient
.right
, rcClient
.bottom
);
710 hOldBmp
= SelectObject(hdc
, hOffScreenBmp
);
719 ZeroMemory(&nmcd
, sizeof(nmcd
));
720 nmcd
.hdr
.hwndFrom
= infoPtr
->hwndSelf
;
721 nmcd
.hdr
.idFrom
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_ID
);
722 nmcd
.hdr
.code
= NM_CUSTOMDRAW
;
725 /* start the paint cycle */
727 gcdrf
= notify_customdraw(&nmcd
, CDDS_PREPAINT
);
728 if (gcdrf
& CDRF_SKIPDEFAULT
) goto cleanup
;
730 /* Erase backbround */
731 if (gcdrf
== CDRF_DODEFAULT
||
732 notify_customdraw(&nmcd
, CDDS_PREERASE
) != CDRF_SKIPDEFAULT
) {
733 FillRect (hdc
, &rcClient
, GetSysColorBrush(COLOR_BTNFACE
));
734 if (gcdrf
!= CDRF_DODEFAULT
)
735 notify_customdraw(&nmcd
, CDDS_POSTERASE
);
739 if (gcdrf
& CDRF_NOTIFYITEMDRAW
) {
740 nmcd
.dwItemSpec
= TBCD_CHANNEL
;
741 nmcd
.uItemState
= CDIS_DEFAULT
;
742 nmcd
.rc
= infoPtr
->rcChannel
;
743 icdrf
= notify_customdraw(&nmcd
, CDDS_ITEMPREPAINT
);
744 } else icdrf
= CDRF_DODEFAULT
;
745 if ( !(icdrf
& CDRF_SKIPDEFAULT
) ) {
746 TRACKBAR_DrawChannel (infoPtr
, hdc
, dwStyle
);
747 if (icdrf
& CDRF_NOTIFYPOSTPAINT
)
748 notify_customdraw(&nmcd
, CDDS_ITEMPOSTPAINT
);
753 if (!(dwStyle
& TBS_NOTICKS
)) {
754 if (gcdrf
& CDRF_NOTIFYITEMDRAW
) {
755 nmcd
.dwItemSpec
= TBCD_TICS
;
756 nmcd
.uItemState
= CDIS_DEFAULT
;
758 icdrf
= notify_customdraw(&nmcd
, CDDS_ITEMPREPAINT
);
759 } else icdrf
= CDRF_DODEFAULT
;
760 if ( !(icdrf
& CDRF_SKIPDEFAULT
) ) {
761 TRACKBAR_DrawTics (infoPtr
, hdc
, dwStyle
);
762 if (icdrf
& CDRF_NOTIFYPOSTPAINT
)
763 notify_customdraw(&nmcd
, CDDS_ITEMPOSTPAINT
);
768 if (!(dwStyle
& TBS_NOTHUMB
)) {
769 if (gcdrf
& CDRF_NOTIFYITEMDRAW
) {
770 nmcd
.dwItemSpec
= TBCD_THUMB
;
771 nmcd
.uItemState
= infoPtr
->flags
& TB_DRAG_MODE
? CDIS_HOT
: CDIS_DEFAULT
;
772 nmcd
.rc
= infoPtr
->rcThumb
;
773 icdrf
= notify_customdraw(&nmcd
, CDDS_ITEMPREPAINT
);
774 } else icdrf
= CDRF_DODEFAULT
;
775 if ( !(icdrf
& CDRF_SKIPDEFAULT
) ) {
776 TRACKBAR_DrawThumb(infoPtr
, hdc
, dwStyle
);
777 if (icdrf
& CDRF_NOTIFYPOSTPAINT
)
778 notify_customdraw(&nmcd
, CDDS_ITEMPOSTPAINT
);
782 /* finish up the painting */
783 if (gcdrf
& CDRF_NOTIFYPOSTPAINT
)
784 notify_customdraw(&nmcd
, CDDS_POSTPAINT
);
787 /* cleanup, if we rendered offscreen */
789 BitBlt(hdcDst
, 0, 0, rcClient
.right
, rcClient
.bottom
, hdc
, 0, 0, SRCCOPY
);
790 SelectObject(hdc
, hOldBmp
);
791 DeleteObject(hOffScreenBmp
);
798 TRACKBAR_AlignBuddies (TRACKBAR_INFO
*infoPtr
)
800 DWORD dwStyle
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
);
801 HWND hwndParent
= GetParent (infoPtr
->hwndSelf
);
802 RECT rcSelf
, rcBuddy
;
805 GetWindowRect (infoPtr
->hwndSelf
, &rcSelf
);
806 MapWindowPoints (HWND_DESKTOP
, hwndParent
, (LPPOINT
)&rcSelf
, 2);
808 /* align buddy left or above */
809 if (infoPtr
->hwndBuddyLA
) {
810 GetWindowRect (infoPtr
->hwndBuddyLA
, &rcBuddy
);
811 MapWindowPoints (HWND_DESKTOP
, hwndParent
, (LPPOINT
)&rcBuddy
, 2);
813 if (dwStyle
& TBS_VERT
) {
814 x
= (infoPtr
->rcChannel
.right
+ infoPtr
->rcChannel
.left
) / 2 -
815 (rcBuddy
.right
- rcBuddy
.left
) / 2 + rcSelf
.left
;
816 y
= rcSelf
.top
- (rcBuddy
.bottom
- rcBuddy
.top
);
819 x
= rcSelf
.left
- (rcBuddy
.right
- rcBuddy
.left
);
820 y
= (infoPtr
->rcChannel
.bottom
+ infoPtr
->rcChannel
.top
) / 2 -
821 (rcBuddy
.bottom
- rcBuddy
.top
) / 2 + rcSelf
.top
;
824 SetWindowPos (infoPtr
->hwndBuddyLA
, 0, x
, y
, 0, 0,
825 SWP_NOZORDER
| SWP_NOSIZE
);
829 /* align buddy right or below */
830 if (infoPtr
->hwndBuddyRB
) {
831 GetWindowRect (infoPtr
->hwndBuddyRB
, &rcBuddy
);
832 MapWindowPoints (HWND_DESKTOP
, hwndParent
, (LPPOINT
)&rcBuddy
, 2);
834 if (dwStyle
& TBS_VERT
) {
835 x
= (infoPtr
->rcChannel
.right
+ infoPtr
->rcChannel
.left
) / 2 -
836 (rcBuddy
.right
- rcBuddy
.left
) / 2 + rcSelf
.left
;
841 y
= (infoPtr
->rcChannel
.bottom
+ infoPtr
->rcChannel
.top
) / 2 -
842 (rcBuddy
.bottom
- rcBuddy
.top
) / 2 + rcSelf
.top
;
844 SetWindowPos (infoPtr
->hwndBuddyRB
, 0, x
, y
, 0, 0,
845 SWP_NOZORDER
| SWP_NOSIZE
);
851 TRACKBAR_ClearSel (TRACKBAR_INFO
*infoPtr
, BOOL fRedraw
)
853 infoPtr
->lSelMin
= 0;
854 infoPtr
->lSelMax
= 0;
855 infoPtr
->flags
|= TB_SELECTIONCHANGED
;
857 if (fRedraw
) TRACKBAR_InvalidateAll(infoPtr
);
864 TRACKBAR_ClearTics (TRACKBAR_INFO
*infoPtr
, BOOL fRedraw
)
867 COMCTL32_Free (infoPtr
->tics
);
868 infoPtr
->tics
= NULL
;
869 infoPtr
->uNumTics
= 0;
872 if (fRedraw
) TRACKBAR_InvalidateAll(infoPtr
);
878 static LRESULT
inline
879 TRACKBAR_GetChannelRect (TRACKBAR_INFO
*infoPtr
, LPRECT lprc
)
881 if (lprc
== NULL
) return 0;
883 lprc
->left
= infoPtr
->rcChannel
.left
;
884 lprc
->right
= infoPtr
->rcChannel
.right
;
885 lprc
->bottom
= infoPtr
->rcChannel
.bottom
;
886 lprc
->top
= infoPtr
->rcChannel
.top
;
893 TRACKBAR_GetNumTics (TRACKBAR_INFO
*infoPtr
)
895 if (GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
) & TBS_NOTICKS
)
898 return infoPtr
->uNumTics
+ 2;
902 static int comp_tics(const void *ap
, const void *bp
)
904 DWORD a
= *((DWORD
*)ap
);
905 DWORD b
= *((DWORD
*)bp
);
907 TRACE("(a=%ld, b=%ld)\n", a
, b
);
908 if (a
< b
) return -1;
915 TRACKBAR_GetTic (TRACKBAR_INFO
*infoPtr
, INT iTic
)
917 if ((iTic
< 0) || (iTic
>= infoPtr
->uNumTics
) || !infoPtr
->tics
)
920 qsort(infoPtr
->tics
, infoPtr
->uNumTics
, sizeof(DWORD
), comp_tics
);
921 return infoPtr
->tics
[iTic
];
926 TRACKBAR_GetTicPos (TRACKBAR_INFO
*infoPtr
, INT iTic
)
928 LONG range
, width
, pos
, tic
;
930 if ((iTic
< 0) || (iTic
>= infoPtr
->uNumTics
) || !infoPtr
->tics
)
933 tic
= TRACKBAR_GetTic (infoPtr
, iTic
);
934 range
= infoPtr
->lRangeMax
- infoPtr
->lRangeMin
;
935 width
= infoPtr
->rcChannel
.right
- infoPtr
->rcChannel
.left
;
936 pos
= infoPtr
->rcChannel
.left
+ (width
* tic
) / range
;
943 TRACKBAR_SetBuddy (TRACKBAR_INFO
*infoPtr
, BOOL fLocation
, HWND hwndBuddy
)
948 /* buddy is left or above */
949 hwndTemp
= infoPtr
->hwndBuddyLA
;
950 infoPtr
->hwndBuddyLA
= hwndBuddy
;
953 /* buddy is right or below */
954 hwndTemp
= infoPtr
->hwndBuddyRB
;
955 infoPtr
->hwndBuddyRB
= hwndBuddy
;
958 TRACKBAR_AlignBuddies (infoPtr
);
965 TRACKBAR_SetLineSize (TRACKBAR_INFO
*infoPtr
, LONG lLineSize
)
967 LONG lTemp
= infoPtr
->lLineSize
;
969 infoPtr
->lLineSize
= lLineSize
;
976 TRACKBAR_SetPageSize (TRACKBAR_INFO
*infoPtr
, LONG lPageSize
)
978 LONG lTemp
= infoPtr
->lPageSize
;
980 infoPtr
->lPageSize
= lPageSize
;
986 static LRESULT
inline
987 TRACKBAR_SetPos (TRACKBAR_INFO
*infoPtr
, BOOL fPosition
, LONG lPosition
)
989 LONG oldPos
= infoPtr
->lPos
;
990 infoPtr
->lPos
= lPosition
;
992 if (infoPtr
->lPos
< infoPtr
->lRangeMin
)
993 infoPtr
->lPos
= infoPtr
->lRangeMin
;
995 if (infoPtr
->lPos
> infoPtr
->lRangeMax
)
996 infoPtr
->lPos
= infoPtr
->lRangeMax
;
997 infoPtr
->flags
|= TB_THUMBPOSCHANGED
;
999 if (fPosition
) TRACKBAR_InvalidateThumbMove(infoPtr
, oldPos
, lPosition
);
1005 static LRESULT
inline
1006 TRACKBAR_SetRange (TRACKBAR_INFO
*infoPtr
, BOOL fRedraw
, LONG lRange
)
1008 infoPtr
->lRangeMin
= (SHORT
)LOWORD(lRange
);
1009 infoPtr
->lRangeMax
= (SHORT
)HIWORD(lRange
);
1011 if (infoPtr
->lPos
< infoPtr
->lRangeMin
) {
1012 infoPtr
->lPos
= infoPtr
->lRangeMin
;
1013 infoPtr
->flags
|= TB_THUMBPOSCHANGED
;
1016 if (infoPtr
->lPos
> infoPtr
->lRangeMax
) {
1017 infoPtr
->lPos
= infoPtr
->lRangeMax
;
1018 infoPtr
->flags
|= TB_THUMBPOSCHANGED
;
1021 infoPtr
->lPageSize
= (infoPtr
->lRangeMax
- infoPtr
->lRangeMin
) / 5;
1022 if (infoPtr
->lPageSize
== 0) infoPtr
->lPageSize
= 1;
1024 if (fRedraw
) TRACKBAR_InvalidateAll(infoPtr
);
1030 static LRESULT
inline
1031 TRACKBAR_SetRangeMax (TRACKBAR_INFO
*infoPtr
, BOOL fRedraw
, LONG lMax
)
1033 infoPtr
->lRangeMax
= lMax
;
1034 if (infoPtr
->lPos
> infoPtr
->lRangeMax
) {
1035 infoPtr
->lPos
= infoPtr
->lRangeMax
;
1036 infoPtr
->flags
|= TB_THUMBPOSCHANGED
;
1039 infoPtr
->lPageSize
= (infoPtr
->lRangeMax
- infoPtr
->lRangeMin
) / 5;
1040 if (infoPtr
->lPageSize
== 0) infoPtr
->lPageSize
= 1;
1042 if (fRedraw
) TRACKBAR_InvalidateAll(infoPtr
);
1048 static LRESULT
inline
1049 TRACKBAR_SetRangeMin (TRACKBAR_INFO
*infoPtr
, BOOL fRedraw
, LONG lMin
)
1051 infoPtr
->lRangeMin
= lMin
;
1052 if (infoPtr
->lPos
< infoPtr
->lRangeMin
) {
1053 infoPtr
->lPos
= infoPtr
->lRangeMin
;
1054 infoPtr
->flags
|= TB_THUMBPOSCHANGED
;
1057 infoPtr
->lPageSize
= (infoPtr
->lRangeMax
- infoPtr
->lRangeMin
) / 5;
1058 if (infoPtr
->lPageSize
== 0) infoPtr
->lPageSize
= 1;
1060 if (fRedraw
) TRACKBAR_InvalidateAll(infoPtr
);
1066 static LRESULT
inline
1067 TRACKBAR_SetSel (TRACKBAR_INFO
*infoPtr
, BOOL fRedraw
, LONG lSel
)
1069 if (!GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
) & TBS_ENABLESELRANGE
)
1072 infoPtr
->lSelMin
= (SHORT
)LOWORD(lSel
);
1073 infoPtr
->lSelMax
= (SHORT
)HIWORD(lSel
);
1074 infoPtr
->flags
|= TB_SELECTIONCHANGED
;
1076 if (infoPtr
->lSelMin
< infoPtr
->lRangeMin
)
1077 infoPtr
->lSelMin
= infoPtr
->lRangeMin
;
1078 if (infoPtr
->lSelMax
> infoPtr
->lRangeMax
)
1079 infoPtr
->lSelMax
= infoPtr
->lRangeMax
;
1081 if (fRedraw
) TRACKBAR_InvalidateAll(infoPtr
);
1087 static LRESULT
inline
1088 TRACKBAR_SetSelEnd (TRACKBAR_INFO
*infoPtr
, BOOL fRedraw
, LONG lEnd
)
1090 if (!GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
) & TBS_ENABLESELRANGE
)
1093 infoPtr
->lSelMax
= lEnd
;
1094 infoPtr
->flags
|= TB_SELECTIONCHANGED
;
1096 if (infoPtr
->lSelMax
> infoPtr
->lRangeMax
)
1097 infoPtr
->lSelMax
= infoPtr
->lRangeMax
;
1099 if (fRedraw
) TRACKBAR_InvalidateAll(infoPtr
);
1105 static LRESULT
inline
1106 TRACKBAR_SetSelStart (TRACKBAR_INFO
*infoPtr
, BOOL fRedraw
, LONG lStart
)
1108 if (!GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
) & TBS_ENABLESELRANGE
)
1111 infoPtr
->lSelMin
= lStart
;
1112 infoPtr
->flags
|=TB_SELECTIONCHANGED
;
1114 if (infoPtr
->lSelMin
< infoPtr
->lRangeMin
)
1115 infoPtr
->lSelMin
= infoPtr
->lRangeMin
;
1117 if (fRedraw
) TRACKBAR_InvalidateAll(infoPtr
);
1123 static LRESULT
inline
1124 TRACKBAR_SetThumbLength (TRACKBAR_INFO
*infoPtr
, UINT iLength
)
1126 if (GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
) & TBS_FIXEDLENGTH
)
1127 infoPtr
->uThumbLen
= iLength
;
1129 infoPtr
->flags
|= TB_THUMBSIZECHANGED
;
1131 InvalidateRect (infoPtr
->hwndSelf
, &infoPtr
->rcThumb
, FALSE
);
1137 static LRESULT
inline
1138 TRACKBAR_SetTic (TRACKBAR_INFO
*infoPtr
, LONG lPos
)
1140 if (GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
) & TBS_AUTOTICKS
)
1143 if ((lPos
< infoPtr
->lRangeMin
) || (lPos
> infoPtr
->lRangeMax
))
1146 TRACE("lPos=%ld\n", lPos
);
1148 infoPtr
->uNumTics
++;
1149 infoPtr
->tics
=COMCTL32_ReAlloc( infoPtr
->tics
,
1150 (infoPtr
->uNumTics
)*sizeof (DWORD
));
1151 if (!infoPtr
->tics
) {
1152 infoPtr
->uNumTics
= 0;
1153 TRACKBAR_SendNotify(infoPtr
, NM_OUTOFMEMORY
);
1156 infoPtr
->tics
[infoPtr
->uNumTics
-1] = lPos
;
1158 TRACKBAR_InvalidateAll(infoPtr
);
1164 static LRESULT
inline
1165 TRACKBAR_SetTicFreq (TRACKBAR_INFO
*infoPtr
, WORD wFreq
)
1167 if (GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
) & TBS_AUTOTICKS
) {
1168 infoPtr
->uTicFreq
= wFreq
;
1169 TRACKBAR_RecalculateTics (infoPtr
);
1170 TRACKBAR_InvalidateAll(infoPtr
);
1178 TRACKBAR_SetTipSide (TRACKBAR_INFO
*infoPtr
, INT fLocation
)
1180 INT fTemp
= infoPtr
->fLocation
;
1182 infoPtr
->fLocation
= fLocation
;
1188 static LRESULT
inline
1189 TRACKBAR_SetToolTips (TRACKBAR_INFO
*infoPtr
, HWND hwndTT
)
1191 infoPtr
->hwndToolTip
= hwndTT
;
1198 TRACKBAR_SetUnicodeFormat (TRACKBAR_INFO
*infoPtr
, BOOL fUnicode
)
1200 BOOL bTemp
= infoPtr
->bUnicode
;
1202 infoPtr
->bUnicode
= fUnicode
;
1209 TRACKBAR_InitializeThumb (TRACKBAR_INFO
*infoPtr
)
1211 infoPtr
->uThumbLen
= 23; /* initial thumb length */
1213 TRACKBAR_CalcChannel (infoPtr
);
1214 TRACKBAR_UpdateThumb (infoPtr
);
1215 infoPtr
->flags
&= ~TB_SELECTIONCHANGED
;
1222 TRACKBAR_Create (HWND hwnd
, LPCREATESTRUCTW lpcs
)
1224 TRACKBAR_INFO
*infoPtr
;
1225 DWORD oldStyle
, newStyle
;
1227 infoPtr
= (TRACKBAR_INFO
*)COMCTL32_Alloc (sizeof(TRACKBAR_INFO
));
1228 if (!infoPtr
) return -1;
1229 SetWindowLongW (hwnd
, 0, (DWORD
)infoPtr
);
1231 /* set default values */
1232 infoPtr
->hwndSelf
= hwnd
;
1233 infoPtr
->lRangeMin
= 0;
1234 infoPtr
->lRangeMax
= 100;
1235 infoPtr
->lLineSize
= 1;
1236 infoPtr
->lPageSize
= 20;
1237 infoPtr
->lSelMin
= 0;
1238 infoPtr
->lSelMax
= 0;
1240 infoPtr
->fLocation
= -1;
1241 infoPtr
->uNumTics
= 0; /* start and end tic are not included in count*/
1242 infoPtr
->uTicFreq
= 1;
1243 infoPtr
->tics
= NULL
;
1244 infoPtr
->hwndNotify
= GetParent (hwnd
);
1246 TRACKBAR_InitializeThumb (infoPtr
);
1248 oldStyle
= newStyle
= GetWindowLongW (hwnd
, GWL_STYLE
);
1249 if (oldStyle
& TBS_VERT
) {
1250 if (! (oldStyle
& (TBS_LEFT
| TBS_RIGHT
| TBS_BOTH
)) )
1251 newStyle
|= TBS_RIGHT
;
1253 if (! (oldStyle
& (TBS_TOP
| TBS_BOTTOM
| TBS_BOTH
)) )
1254 newStyle
|= TBS_BOTTOM
;
1256 if (newStyle
!= oldStyle
)
1257 SetWindowLongW (hwnd
, GWL_STYLE
, newStyle
);
1259 /* Create tooltip control */
1260 if (newStyle
& TBS_TOOLTIPS
) {
1262 infoPtr
->hwndToolTip
=
1263 CreateWindowExW (0, TOOLTIPS_CLASSW
, NULL
, 0,
1264 CW_USEDEFAULT
, CW_USEDEFAULT
,
1265 CW_USEDEFAULT
, CW_USEDEFAULT
,
1268 if (infoPtr
->hwndToolTip
) {
1270 TRACKBAR_SendNotify(infoPtr
, NM_TOOLTIPSCREATED
);
1272 ZeroMemory (&ti
, sizeof(ti
));
1273 ti
.cbSize
= sizeof(ti
);
1274 ti
.uFlags
= TTF_IDISHWND
| TTF_TRACK
| TTF_ABSOLUTE
;
1277 SendMessageW (infoPtr
->hwndToolTip
, TTM_ADDTOOLW
, 0, (LPARAM
)&ti
);
1286 TRACKBAR_Destroy (TRACKBAR_INFO
*infoPtr
)
1288 /* delete tooltip control */
1289 if (infoPtr
->hwndToolTip
)
1290 DestroyWindow (infoPtr
->hwndToolTip
);
1292 COMCTL32_Free (infoPtr
);
1293 SetWindowLongW (infoPtr
->hwndSelf
, 0, 0);
1299 TRACKBAR_KillFocus (TRACKBAR_INFO
*infoPtr
, HWND hwndGetFocus
)
1303 TRACKBAR_InvalidateAll(infoPtr
);
1309 TRACKBAR_LButtonDown (TRACKBAR_INFO
*infoPtr
, DWORD fwKeys
, POINTS pts
)
1311 POINT clickPoint
= { pts
.x
, pts
.y
};
1313 SetFocus(infoPtr
->hwndSelf
);
1315 if (PtInRect(&infoPtr
->rcThumb
, clickPoint
)) {
1316 infoPtr
->flags
|= TB_DRAG_MODE
;
1317 SetCapture (infoPtr
->hwndSelf
);
1318 TRACKBAR_UpdateToolTip (infoPtr
);
1319 TRACKBAR_ActivateToolTip (infoPtr
, TRUE
);
1320 TRACKBAR_InvalidateThumb(infoPtr
, infoPtr
->lPos
);
1322 LONG dir
= TRACKBAR_GetAutoPageDirection(infoPtr
, clickPoint
);
1323 if (dir
== 0) return 0;
1324 infoPtr
->flags
|= (dir
< 0) ? TB_AUTO_PAGE_LEFT
: TB_AUTO_PAGE_RIGHT
;
1325 TRACKBAR_AutoPage (infoPtr
, clickPoint
);
1326 SetCapture (infoPtr
->hwndSelf
);
1327 SetTimer(infoPtr
->hwndSelf
, TB_REFRESH_TIMER
, TB_REFRESH_DELAY
, 0);
1335 TRACKBAR_LButtonUp (TRACKBAR_INFO
*infoPtr
, DWORD fwKeys
, POINTS pts
)
1337 if (infoPtr
->flags
& TB_DRAG_MODE
) {
1338 TRACKBAR_SendNotify (infoPtr
, TB_ENDTRACK
);
1339 infoPtr
->flags
&= ~TB_DRAG_MODE
;
1341 TRACKBAR_SendNotify(infoPtr
, NM_RELEASEDCAPTURE
);
1342 TRACKBAR_ActivateToolTip(infoPtr
, FALSE
);
1343 TRACKBAR_InvalidateThumb(infoPtr
, infoPtr
->lPos
);
1345 if (infoPtr
->flags
& TB_AUTO_PAGE
) {
1346 KillTimer (infoPtr
->hwndSelf
, TB_REFRESH_TIMER
);
1347 infoPtr
->flags
&= ~TB_AUTO_PAGE
;
1349 TRACKBAR_SendNotify(infoPtr
, NM_RELEASEDCAPTURE
);
1357 TRACKBAR_CaptureChanged (TRACKBAR_INFO
*infoPtr
)
1359 TRACKBAR_SendNotify (infoPtr
, TB_ENDTRACK
);
1365 TRACKBAR_Paint (TRACKBAR_INFO
*infoPtr
, HDC hdc
)
1368 TRACKBAR_Refresh(infoPtr
, hdc
);
1371 hdc
= BeginPaint (infoPtr
->hwndSelf
, &ps
);
1372 TRACKBAR_Refresh (infoPtr
, hdc
);
1373 EndPaint (infoPtr
->hwndSelf
, &ps
);
1381 TRACKBAR_SetFocus (TRACKBAR_INFO
*infoPtr
, HWND hwndLoseFocus
)
1385 TRACKBAR_InvalidateAll(infoPtr
);
1392 TRACKBAR_Size (TRACKBAR_INFO
*infoPtr
, DWORD fwSizeType
, INT nWidth
, INT nHeight
)
1394 TRACKBAR_CalcChannel (infoPtr
);
1395 TRACKBAR_AlignBuddies (infoPtr
);
1402 TRACKBAR_Timer (TRACKBAR_INFO
*infoPtr
, INT wTimerID
, TIMERPROC
*tmrpc
)
1404 if (infoPtr
->flags
& TB_AUTO_PAGE
) {
1406 if (GetCursorPos(&pt
))
1407 if (ScreenToClient(infoPtr
->hwndSelf
, &pt
))
1408 TRACKBAR_AutoPage(infoPtr
, pt
);
1415 TRACKBAR_SendNotify (TRACKBAR_INFO
*infoPtr
, UINT code
)
1417 BOOL bVert
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
) & TBS_VERT
;
1419 TRACE("%x\n", code
);
1421 return (BOOL
) SendMessageW (GetParent (infoPtr
->hwndSelf
),
1422 bVert
? WM_VSCROLL
: WM_HSCROLL
,
1423 (WPARAM
)code
, (LPARAM
)infoPtr
->hwndSelf
);
1428 TRACKBAR_MouseMove (TRACKBAR_INFO
*infoPtr
, DWORD fwKeys
, POINTS pts
)
1430 DWORD dwStyle
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
);
1431 INT clickPlace
= (dwStyle
& TBS_VERT
) ? pts
.y
: pts
.x
;
1432 DOUBLE dragPos
, oldPos
= infoPtr
->lPos
;
1434 TRACE("(x=%d. y=%d)\n", pts
.x
, pts
.y
);
1436 if (infoPtr
->flags
& TB_AUTO_PAGE
) {
1438 POINTSTOPOINT(pt
, pts
);
1439 TRACKBAR_AutoPage (infoPtr
, pt
);
1443 if (!(infoPtr
->flags
& TB_DRAG_MODE
)) return TRUE
;
1445 dragPos
= TRACKBAR_ConvertPlaceToPosition (infoPtr
, clickPlace
,
1446 dwStyle
& TBS_VERT
);
1447 if (dragPos
> ((INT
)dragPos
) + 0.5) dragPos
++;
1449 if (dragPos
== oldPos
) return TRUE
;
1451 infoPtr
->lPos
= dragPos
;
1453 infoPtr
->flags
|= TB_THUMBPOSCHANGED
;
1454 TRACKBAR_SendNotify (infoPtr
, TB_THUMBTRACK
| (infoPtr
->lPos
<<16));
1457 TRACKBAR_InvalidateThumbMove(infoPtr
, oldPos
, dragPos
);
1458 UpdateWindow (infoPtr
->hwndSelf
);
1465 TRACKBAR_KeyDown (TRACKBAR_INFO
*infoPtr
, INT nVirtKey
, DWORD lKeyData
)
1467 BOOL downIsLeft
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_STYLE
) & TBS_DOWNISLEFT
;
1468 LONG pos
= infoPtr
->lPos
;
1470 TRACE("%x\n", nVirtKey
);
1474 if (downIsLeft
) goto step_right
;
1477 if (infoPtr
->lPos
== infoPtr
->lRangeMin
) return FALSE
;
1478 infoPtr
->lPos
-= infoPtr
->lLineSize
;
1479 if (infoPtr
->lPos
< infoPtr
->lRangeMin
)
1480 infoPtr
->lPos
= infoPtr
->lRangeMin
;
1481 TRACKBAR_SendNotify (infoPtr
, TB_LINEUP
);
1484 if (downIsLeft
) goto step_left
;
1487 if (infoPtr
->lPos
== infoPtr
->lRangeMax
) return FALSE
;
1488 infoPtr
->lPos
+= infoPtr
->lLineSize
;
1489 if (infoPtr
->lPos
> infoPtr
->lRangeMax
)
1490 infoPtr
->lPos
= infoPtr
->lRangeMax
;
1491 TRACKBAR_SendNotify (infoPtr
, TB_LINEDOWN
);
1494 if (downIsLeft
) goto page_left
;
1496 TRACKBAR_PageUp(infoPtr
);
1499 if (downIsLeft
) goto page_right
;
1501 TRACKBAR_PageDown(infoPtr
);
1504 if (infoPtr
->lPos
== infoPtr
->lRangeMin
) return FALSE
;
1505 infoPtr
->lPos
= infoPtr
->lRangeMin
;
1506 TRACKBAR_SendNotify (infoPtr
, TB_TOP
);
1509 if (infoPtr
->lPos
== infoPtr
->lRangeMax
) return FALSE
;
1510 infoPtr
->lPos
= infoPtr
->lRangeMax
;
1511 TRACKBAR_SendNotify (infoPtr
, TB_BOTTOM
);
1515 if (pos
!= infoPtr
->lPos
) {
1516 infoPtr
->flags
|=TB_THUMBPOSCHANGED
;
1517 TRACKBAR_InvalidateThumbMove (infoPtr
, pos
, infoPtr
->lPos
);
1525 TRACKBAR_KeyUp (TRACKBAR_INFO
*infoPtr
, INT nVirtKey
, DWORD lKeyData
)
1536 TRACKBAR_SendNotify (infoPtr
, TB_ENDTRACK
);
1542 static LRESULT WINAPI
1543 TRACKBAR_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1545 TRACKBAR_INFO
*infoPtr
= (TRACKBAR_INFO
*)GetWindowLongW (hwnd
, 0);
1547 TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", hwnd
, uMsg
, wParam
, lParam
);
1549 if (!infoPtr
&& (uMsg
!= WM_CREATE
))
1550 return DefWindowProcW (hwnd
, uMsg
, wParam
, lParam
);
1555 return TRACKBAR_ClearSel (infoPtr
, (BOOL
)wParam
);
1558 return TRACKBAR_ClearTics (infoPtr
, (BOOL
)wParam
);
1561 return (LRESULT
)(wParam
? infoPtr
->hwndBuddyLA
: infoPtr
->hwndBuddyRB
);
1563 case TBM_GETCHANNELRECT
:
1564 return TRACKBAR_GetChannelRect (infoPtr
, (LPRECT
)lParam
);
1566 case TBM_GETLINESIZE
:
1567 return infoPtr
->lLineSize
;
1569 case TBM_GETNUMTICS
:
1570 return TRACKBAR_GetNumTics (infoPtr
);
1572 case TBM_GETPAGESIZE
:
1573 return infoPtr
->lPageSize
;
1576 return infoPtr
->lPos
;
1579 return (LRESULT
)infoPtr
->tics
;
1581 case TBM_GETRANGEMAX
:
1582 return infoPtr
->lRangeMax
;
1584 case TBM_GETRANGEMIN
:
1585 return infoPtr
->lRangeMin
;
1588 return infoPtr
->lSelMax
;
1590 case TBM_GETSELSTART
:
1591 return infoPtr
->lSelMin
;
1593 case TBM_GETTHUMBLENGTH
:
1594 return infoPtr
->uThumbLen
;
1596 case TBM_GETTHUMBRECT
:
1597 return CopyRect((LPRECT
)lParam
, &infoPtr
->rcThumb
);
1600 return TRACKBAR_GetTic (infoPtr
, (INT
)wParam
);
1603 return TRACKBAR_GetTicPos (infoPtr
, (INT
)wParam
);
1605 case TBM_GETTOOLTIPS
:
1606 return (LRESULT
)infoPtr
->hwndToolTip
;
1608 case TBM_GETUNICODEFORMAT
:
1609 return infoPtr
->bUnicode
;
1612 return (LRESULT
) TRACKBAR_SetBuddy(infoPtr
, (BOOL
)wParam
, (HWND
)lParam
);
1614 case TBM_SETLINESIZE
:
1615 return TRACKBAR_SetLineSize (infoPtr
, (LONG
)lParam
);
1617 case TBM_SETPAGESIZE
:
1618 return TRACKBAR_SetPageSize (infoPtr
, (LONG
)lParam
);
1621 return TRACKBAR_SetPos (infoPtr
, (BOOL
)wParam
, (LONG
)lParam
);
1624 return TRACKBAR_SetRange (infoPtr
, (BOOL
)wParam
, (LONG
)lParam
);
1626 case TBM_SETRANGEMAX
:
1627 return TRACKBAR_SetRangeMax (infoPtr
, (BOOL
)wParam
, (LONG
)lParam
);
1629 case TBM_SETRANGEMIN
:
1630 return TRACKBAR_SetRangeMin (infoPtr
, (BOOL
)wParam
, (LONG
)lParam
);
1633 return TRACKBAR_SetSel (infoPtr
, (BOOL
)wParam
, (LONG
)lParam
);
1636 return TRACKBAR_SetSelEnd (infoPtr
, (BOOL
)wParam
, (LONG
)lParam
);
1638 case TBM_SETSELSTART
:
1639 return TRACKBAR_SetSelStart (infoPtr
, (BOOL
)wParam
, (LONG
)lParam
);
1641 case TBM_SETTHUMBLENGTH
:
1642 return TRACKBAR_SetThumbLength (infoPtr
, (UINT
)wParam
);
1645 return TRACKBAR_SetTic (infoPtr
, (LONG
)lParam
);
1647 case TBM_SETTICFREQ
:
1648 return TRACKBAR_SetTicFreq (infoPtr
, (WORD
)wParam
);
1650 case TBM_SETTIPSIDE
:
1651 return TRACKBAR_SetTipSide (infoPtr
, (INT
)wParam
);
1653 case TBM_SETTOOLTIPS
:
1654 return TRACKBAR_SetToolTips (infoPtr
, (HWND
)wParam
);
1656 case TBM_SETUNICODEFORMAT
:
1657 return TRACKBAR_SetUnicodeFormat (infoPtr
, (BOOL
)wParam
);
1660 case WM_CAPTURECHANGED
:
1661 return TRACKBAR_CaptureChanged (infoPtr
);
1664 return TRACKBAR_Create (hwnd
, (LPCREATESTRUCTW
)lParam
);
1667 return TRACKBAR_Destroy (infoPtr
);
1669 /* case WM_ENABLE: */
1675 return DLGC_WANTARROWS
;
1678 return TRACKBAR_KeyDown (infoPtr
, (INT
)wParam
, (DWORD
)lParam
);
1681 return TRACKBAR_KeyUp (infoPtr
, (INT
)wParam
, (DWORD
)lParam
);
1684 return TRACKBAR_KillFocus (infoPtr
, (HWND
)wParam
);
1686 case WM_LBUTTONDOWN
:
1687 return TRACKBAR_LButtonDown (infoPtr
, wParam
, MAKEPOINTS(lParam
));
1690 return TRACKBAR_LButtonUp (infoPtr
, wParam
, MAKEPOINTS(lParam
));
1693 return TRACKBAR_MouseMove (infoPtr
, wParam
, MAKEPOINTS(lParam
));
1696 return TRACKBAR_Paint (infoPtr
, (HDC
)wParam
);
1699 return TRACKBAR_SetFocus (infoPtr
, (HWND
)wParam
);
1702 return TRACKBAR_Size (infoPtr
, wParam
, LOWORD(lParam
), HIWORD(lParam
));
1705 return TRACKBAR_Timer (infoPtr
, (INT
)wParam
, (TIMERPROC
*)lParam
);
1707 case WM_WININICHANGE
:
1708 return TRACKBAR_InitializeThumb (infoPtr
);
1711 if ((uMsg
>= WM_USER
) && (uMsg
< WM_APP
))
1712 ERR("unknown msg %04x wp=%08x lp=%08lx\n", uMsg
, wParam
, lParam
);
1713 return DefWindowProcW (hwnd
, uMsg
, wParam
, lParam
);
1719 void TRACKBAR_Register (void)
1723 ZeroMemory (&wndClass
, sizeof(WNDCLASSW
));
1724 wndClass
.style
= CS_GLOBALCLASS
;
1725 wndClass
.lpfnWndProc
= (WNDPROC
)TRACKBAR_WindowProc
;
1726 wndClass
.cbClsExtra
= 0;
1727 wndClass
.cbWndExtra
= sizeof(TRACKBAR_INFO
*);
1728 wndClass
.hCursor
= LoadCursorW (0, IDC_ARROWW
);
1729 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_3DFACE
+ 1);
1730 wndClass
.lpszClassName
= TRACKBAR_CLASSW
;
1732 RegisterClassW (&wndClass
);
1736 void TRACKBAR_Unregister (void)
1738 UnregisterClassW (TRACKBAR_CLASSW
, NULL
);