- Fix some spelling problems.
[wine/multimedia.git] / dlls / comctl32 / trackbar.c
blob5dc431dc850c29c09d0aa46551e866fd773c8e7e
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>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * TODO:
22 * - Some messages.
23 * - handle dragging slider better
24 * - better tic handling.
25 * - more notifications.
29 /* known bugs:
31 -TBM_SETRANGEMAX & TBM_SETRANGEMIN should only change the view of the
32 trackbar, not the actual amount of tics in the list.
33 -TBM_GETTIC & TBM_GETTICPOS shouldn't rely on infoPtr->tics being sorted.
37 #include <stdio.h>
38 #include <string.h>
40 #include "winbase.h"
41 #include "commctrl.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(trackbar);
46 typedef struct
48 INT nRangeMin;
49 INT nRangeMax;
50 INT nLineSize;
51 INT nPageSize;
52 INT nSelMin;
53 INT nSelMax;
54 INT nPos;
55 UINT uThumbLen;
56 UINT uNumTics;
57 UINT uTicFreq;
58 HWND hwndNotify;
59 HWND hwndToolTip;
60 HWND hwndBuddyLA;
61 HWND hwndBuddyRB;
62 INT fLocation;
63 COLORREF clrBk;
64 INT flags;
65 BOOL bFocus;
66 RECT rcChannel;
67 RECT rcSelection;
68 RECT rcThumb;
69 INT dragPos;
70 LPLONG tics;
71 } TRACKBAR_INFO;
73 /* #define TB_REFRESH_TIMER 1 */
74 /* #define TB_REFRESH_DELAY 1 */
76 #define TRACKBAR_GetInfoPtr(wndPtr) ((TRACKBAR_INFO *)GetWindowLongA (hwnd,0))
79 /* Used by TRACKBAR_Refresh to find out which parts of the control
80 need to be recalculated */
82 #define TB_THUMBPOSCHANGED 1
83 #define TB_THUMBSIZECHANGED 2
84 #define TB_THUMBCHANGED (TB_THUMBPOSCHANGED | TB_THUMBPOSCHANGED)
85 #define TB_SELECTIONCHANGED 4
86 #define TB_DRAG_MODE 16 /* we're dragging the slider */
87 #define TB_DRAGPOSVALID 32 /* current Position is in dragPos */
88 #define TB_SHOW_TOOLTIP 64 /* tooltip-style enabled and tooltip on */
90 /* helper defines for TRACKBAR_DrawTic */
91 #define TIC_LEFTEDGE 0x20
92 #define TIC_RIGHTEDGE 0x40
93 #define TIC_EDGE (TIC_LEFTEDGE | TIC_RIGHTEDGE)
94 #define TIC_SELECTIONMARKMAX 0x80
95 #define TIC_SELECTIONMARKMIN 0x100
96 #define TIC_SELECTIONMARK (TIC_SELECTIONMARKMAX | TIC_SELECTIONMARKMIN)
98 static BOOL TRACKBAR_SendNotify (HWND hwnd, UINT code);
100 static void TRACKBAR_RecalculateTics (TRACKBAR_INFO *infoPtr)
102 int i,tic,nrTics;
104 if (infoPtr->uTicFreq && infoPtr->nRangeMax >= infoPtr->nRangeMin)
105 nrTics=(infoPtr->nRangeMax - infoPtr->nRangeMin)/infoPtr->uTicFreq;
106 else {
107 nrTics=0;
108 COMCTL32_Free (infoPtr->tics);
109 infoPtr->tics=NULL;
110 infoPtr->uNumTics=0;
111 return;
114 if (nrTics!=infoPtr->uNumTics) {
115 infoPtr->tics=COMCTL32_ReAlloc (infoPtr->tics,
116 (nrTics+1)*sizeof (DWORD));
117 infoPtr->uNumTics=nrTics;
119 infoPtr->uNumTics=nrTics;
120 tic=infoPtr->nRangeMin+infoPtr->uTicFreq;
121 for (i=0; i<nrTics; i++,tic+=infoPtr->uTicFreq)
122 infoPtr->tics[i]=tic;
126 /* converts from physical (mouse) position to logical position
127 (in range of trackbar) */
129 static inline DOUBLE
130 TRACKBAR_ConvertPlaceToPosition (TRACKBAR_INFO *infoPtr, int place,
131 int vertical)
133 double range,width,pos;
135 range=infoPtr->nRangeMax - infoPtr->nRangeMin;
136 if (vertical) {
137 width=infoPtr->rcChannel.bottom - infoPtr->rcChannel.top;
138 pos=(range*(place - infoPtr->rcChannel.top)) / width;
139 } else {
140 width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
141 pos=(range*(place - infoPtr->rcChannel.left)) / width;
143 pos+=infoPtr->nRangeMin;
144 if (pos > infoPtr->nRangeMax)
145 pos = infoPtr->nRangeMax;
146 else if (pos < infoPtr->nRangeMin)
147 pos = infoPtr->nRangeMin;
149 TRACE("%.2f\n",pos);
150 return pos;
154 static VOID
155 TRACKBAR_CalcChannel (HWND hwnd, TRACKBAR_INFO *infoPtr)
157 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
158 INT cyChannel,offsettop,offsetedge;
159 RECT lpRect,*channel = & infoPtr->rcChannel;
161 GetClientRect (hwnd, &lpRect);
163 if (dwStyle & TBS_ENABLESELRANGE)
164 cyChannel = ((int)(infoPtr->uThumbLen/4.5)+1)*3;
165 else
166 cyChannel = 4;
168 offsettop = (int)(infoPtr->uThumbLen/4.5);
169 offsetedge = (int)(infoPtr->uThumbLen/4.5) + 3;
171 if (dwStyle & TBS_VERT) {
172 channel->top = lpRect.top + offsetedge;
173 channel->bottom = lpRect.bottom - offsetedge;
175 if (dwStyle & (TBS_BOTH | TBS_LEFT)) {
176 channel->left = lpRect.left + offsettop + 8 ;
177 channel->right = channel->left + cyChannel;
179 else { /* TBS_RIGHT */
180 channel->left = lpRect.left + offsettop;
181 channel->right = channel->left + cyChannel;
184 else {
185 channel->left = lpRect.left + offsetedge;
186 channel->right = lpRect.right - offsetedge;
188 if (dwStyle & (TBS_BOTH|TBS_TOP)) {
189 channel->top = lpRect.top + offsettop + 8 ;
190 channel->bottom = channel->top + cyChannel;
192 else { /* TBS_BOTTOM */
193 channel->top = lpRect.top + offsettop;
194 channel->bottom = channel->top + cyChannel;
199 static VOID
200 TRACKBAR_CalcThumb (HWND hwnd, TRACKBAR_INFO *infoPtr)
202 RECT *thumb;
203 int range, width, thumbdepth;
204 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
206 thumb=&infoPtr->rcThumb;
207 range=infoPtr->nRangeMax - infoPtr->nRangeMin;
208 thumbdepth = ((INT)((FLOAT)infoPtr->uThumbLen / 4.5) * 2) + 2;
210 if (!range) return; /* FIXME: may this happen? */
212 if (dwStyle & TBS_VERT)
214 width=infoPtr->rcChannel.bottom - infoPtr->rcChannel.top;
216 if (dwStyle & (TBS_BOTH | TBS_LEFT))
217 thumb->left = 10;
218 else
219 thumb-> left =2;
220 thumb->right = thumb -> left + infoPtr->uThumbLen;
221 thumb->top = infoPtr->rcChannel.top +
222 (width*(infoPtr->nPos - infoPtr->nRangeMin))/range -
223 thumbdepth/2;
224 thumb->bottom = thumb->top + thumbdepth;
226 else
228 width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
230 thumb->left = infoPtr->rcChannel.left +
231 (width*(infoPtr->nPos - infoPtr->nRangeMin))/range -
232 thumbdepth/2;
233 thumb->right = thumb->left + thumbdepth;
234 if (dwStyle & (TBS_BOTH | TBS_TOP))
235 thumb->top = 10;
236 else
237 thumb->top = 2;
238 thumb->bottom = thumb -> top + infoPtr->uThumbLen;
242 static VOID
243 TRACKBAR_CalcSelection (HWND hwnd, TRACKBAR_INFO *infoPtr)
245 RECT *selection;
246 int range, width;
248 selection= & infoPtr->rcSelection;
249 range=infoPtr->nRangeMax - infoPtr->nRangeMin;
250 width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
252 if (range <= 0)
253 SetRectEmpty (selection);
254 else
255 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_VERT) {
256 selection->left = infoPtr->rcChannel.left +
257 (width*infoPtr->nSelMin)/range;
258 selection->right = infoPtr->rcChannel.left +
259 (width*infoPtr->nSelMax)/range;
260 selection->top = infoPtr->rcChannel.top + 2;
261 selection->bottom = infoPtr->rcChannel.bottom - 2;
262 } else {
263 selection->top = infoPtr->rcChannel.top +
264 (width*infoPtr->nSelMin)/range;
265 selection->bottom = infoPtr->rcChannel.top +
266 (width*infoPtr->nSelMax)/range;
267 selection->left = infoPtr->rcChannel.left + 2;
268 selection->right = infoPtr->rcChannel.right - 2;
272 /* Trackbar drawing code. I like my spaghetti done milanese. */
274 /* ticPos is in tic-units, not in pixels */
276 static VOID
277 TRACKBAR_DrawHorizTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos,
278 int flags, COLORREF clrTic)
280 RECT rcChannel=infoPtr->rcChannel;
281 int x,y,width,range,side;
283 range=infoPtr->nRangeMax - infoPtr->nRangeMin;
284 width=rcChannel.right - rcChannel.left;
286 if (flags & TBS_TOP) {
287 y=rcChannel.top-2;
288 side=-1;
289 } else {
290 y=rcChannel.bottom+2;
291 side=1;
294 if (flags & TIC_SELECTIONMARK) {
295 if (flags & TIC_SELECTIONMARKMIN)
296 x=rcChannel.left + (width*(ticPos - infoPtr->nRangeMin))/range - 1;
297 else
298 x=rcChannel.left + (width*(ticPos - infoPtr->nRangeMin))/range + 1;
300 SetPixel (hdc, x,y+6*side, clrTic);
301 SetPixel (hdc, x,y+7*side, clrTic);
302 return;
305 if ((ticPos>infoPtr->nRangeMin) && (ticPos<infoPtr->nRangeMax)) {
306 x=rcChannel.left + (width*(ticPos - infoPtr->nRangeMin))/range;
307 SetPixel (hdc, x,y+5*side, clrTic);
308 SetPixel (hdc, x,y+6*side, clrTic);
309 SetPixel (hdc, x,y+7*side, clrTic);
312 if (flags & TIC_EDGE) {
313 if (flags & TIC_LEFTEDGE)
314 x=rcChannel.left;
315 else
316 x=rcChannel.right;
318 SetPixel (hdc, x,y+5*side, clrTic);
319 SetPixel (hdc, x,y+6*side, clrTic);
320 SetPixel (hdc, x,y+7*side, clrTic);
321 SetPixel (hdc, x,y+8*side, clrTic);
326 static VOID
327 TRACKBAR_DrawVertTic (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos,
328 int flags, COLORREF clrTic)
330 RECT rcChannel=infoPtr->rcChannel;
331 int x,y,width,range,side;
333 range=infoPtr->nRangeMax - infoPtr->nRangeMin;
334 width=rcChannel.bottom - rcChannel.top;
336 if (flags & TBS_TOP) {
337 x=rcChannel.left-2;
338 side=-1;
339 } else {
340 x=rcChannel.right+2;
341 side=1;
345 if (flags & TIC_SELECTIONMARK) {
346 if (flags & TIC_SELECTIONMARKMIN)
347 y=rcChannel.top + (width*(ticPos - infoPtr->nRangeMin))/range - 1;
348 else
349 y=rcChannel.top + (width*(ticPos - infoPtr->nRangeMin))/range + 1;
351 SetPixel (hdc, x+6*side, y, clrTic);
352 SetPixel (hdc, x+7*side, y, clrTic);
353 return;
356 if ((ticPos>infoPtr->nRangeMin) && (ticPos<infoPtr->nRangeMax)) {
357 y=rcChannel.top + (width*(ticPos - infoPtr->nRangeMin))/range;
358 SetPixel (hdc, x+5*side, y, clrTic);
359 SetPixel (hdc, x+6*side, y, clrTic);
360 SetPixel (hdc, x+7*side, y, clrTic);
363 if (flags & TIC_EDGE) {
364 if (flags & TIC_LEFTEDGE)
365 y=rcChannel.top;
366 else
367 y=rcChannel.bottom;
369 SetPixel (hdc, x+5*side, y, clrTic);
370 SetPixel (hdc, x+6*side, y, clrTic);
371 SetPixel (hdc, x+7*side, y, clrTic);
372 SetPixel (hdc, x+8*side, y, clrTic);
378 static VOID
379 TRACKBAR_DrawTics (TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos,
380 int flags, COLORREF clrTic)
383 if (flags & TBS_VERT) {
384 if ((flags & TBS_TOP) || (flags & TBS_BOTH))
385 TRACKBAR_DrawVertTic (infoPtr, hdc, ticPos,
386 flags | TBS_TOP , clrTic);
387 if (!(flags & TBS_TOP) || (flags & TBS_BOTH))
388 TRACKBAR_DrawVertTic (infoPtr, hdc, ticPos, flags, clrTic);
389 return;
392 if ((flags & TBS_TOP) || (flags & TBS_BOTH))
393 TRACKBAR_DrawHorizTic (infoPtr, hdc, ticPos, flags | TBS_TOP , clrTic);
395 if (!(flags & TBS_TOP) || (flags & TBS_BOTH))
396 TRACKBAR_DrawHorizTic (infoPtr, hdc, ticPos, flags, clrTic);
400 static VOID
401 TRACKBAR_DrawThumb(TRACKBAR_INFO *infoPtr, HDC hdc, DWORD dwStyle)
403 HBRUSH oldbr,hbr = GetSysColorBrush(COLOR_BTNFACE);
404 HPEN oldpen=(HPEN)NULL,hpn;
405 RECT thumb = infoPtr->rcThumb;
406 int BlackUntil=3;
407 int PointCount=6;
408 POINT points[6];
410 static INT PointDepth = 4;
412 oldbr = SelectObject (hdc, hbr);
413 SetPolyFillMode (hdc,WINDING);
415 if (dwStyle & TBS_BOTH)
417 points[0].x=thumb.right;
418 points[0].y=thumb.top;
419 points[1].x=thumb.right;
420 points[1].y=thumb.bottom;
421 points[2].x=thumb.left;
422 points[2].y=thumb.bottom;
423 points[3].x=thumb.left;
424 points[3].y=thumb.top;
425 points[4].x=points[0].x;
426 points[4].y=points[0].y;
427 PointCount = 5;
428 BlackUntil = 3;
430 else
432 if (dwStyle & TBS_VERT)
434 if (dwStyle & TBS_LEFT)
436 points[0].x=thumb.right;
437 points[0].y=thumb.top;
438 points[1].x=thumb.right;
439 points[1].y=thumb.bottom;
440 points[2].x=thumb.left + PointDepth;
441 points[2].y=thumb.bottom;
442 points[3].x=thumb.left;
443 points[3].y=(thumb.bottom - thumb.top) / 2 + thumb.top;
444 points[4].x=thumb.left + PointDepth;
445 points[4].y=thumb.top;
446 points[5].x=points[0].x;
447 points[5].y=points[0].y;
448 BlackUntil = 4;
450 else
452 points[0].x=thumb.right;
453 points[0].y=(thumb.bottom - thumb.top) / 2 + thumb.top;
454 points[1].x=thumb.right - PointDepth;
455 points[1].y=thumb.bottom;
456 points[2].x=thumb.left;
457 points[2].y=thumb.bottom;
458 points[3].x=thumb.left;
459 points[3].y=thumb.top;
460 points[4].x=thumb.right - PointDepth;
461 points[4].y=thumb.top;
462 points[5].x=points[0].x;
463 points[5].y=points[0].y;
466 else
468 if (dwStyle & TBS_TOP)
470 points[0].x=(thumb.right - thumb.left) / 2 + thumb.left ;
471 points[0].y=thumb.top;
472 points[1].x=thumb.right;
473 points[1].y=thumb.top + PointDepth;
474 points[2].x=thumb.right;
475 points[2].y=thumb.bottom;
476 points[3].x=thumb.left;
477 points[3].y=thumb.bottom;
478 points[4].x=thumb.left;
479 points[4].y=thumb.top + PointDepth;
480 points[5].x=points[0].x;
481 points[5].y=points[0].y;
482 BlackUntil = 4;
484 else
486 points[0].x=thumb.right;
487 points[0].y=thumb.top;
488 points[1].x=thumb.right;
489 points[1].y=thumb.bottom - PointDepth;
490 points[2].x=(thumb.right - thumb.left) / 2 + thumb.left ;
491 points[2].y=thumb.bottom;
492 points[3].x=thumb.left;
493 points[3].y=thumb.bottom - PointDepth;
494 points[4].x=thumb.left;
495 points[4].y=thumb.top;
496 points[5].x=points[0].x;
497 points[5].y=points[0].y;
504 * Fill the shape
506 Polygon (hdc, points, PointCount);
509 * Draw the edge
511 hpn = GetStockObject(BLACK_PEN);
512 oldpen = SelectObject(hdc,hpn);
515 * Black part
517 Polyline(hdc,points,BlackUntil);
519 SelectObject(hdc,oldpen);
520 hpn = GetStockObject(WHITE_PEN);
521 SelectObject(hdc,hpn);
524 * White Part
526 Polyline(hdc,&points[BlackUntil-1],PointCount+1-BlackUntil);
529 * restore the brush and pen
531 SelectObject(hdc,oldbr);
532 if (oldpen)
533 SelectObject(hdc,oldpen);
536 static VOID
537 TRACKBAR_Refresh (HWND hwnd, HDC hdc)
539 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
540 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
541 RECT rcClient, rcChannel, rcSelection;
542 HBRUSH hBrush;
543 int i;
545 GetClientRect (hwnd, &rcClient);
546 hBrush = CreateSolidBrush (infoPtr->clrBk);
547 FillRect (hdc, &rcClient, hBrush);
548 DeleteObject (hBrush);
550 if (infoPtr->flags & TB_DRAGPOSVALID) {
551 infoPtr->nPos=infoPtr->dragPos;
552 infoPtr->flags |= TB_THUMBPOSCHANGED;
555 if (infoPtr->flags & TB_THUMBCHANGED) {
556 TRACKBAR_CalcThumb (hwnd, infoPtr);
557 if (infoPtr->flags & TB_THUMBSIZECHANGED)
558 TRACKBAR_CalcChannel (hwnd, infoPtr);
560 if (infoPtr->flags & TB_SELECTIONCHANGED)
561 TRACKBAR_CalcSelection (hwnd, infoPtr);
562 infoPtr->flags &= ~ (TB_THUMBCHANGED | TB_SELECTIONCHANGED |
563 TB_DRAGPOSVALID);
565 /* draw channel */
567 rcChannel = infoPtr->rcChannel;
568 rcSelection= infoPtr->rcSelection;
569 DrawEdge (hdc, &rcChannel, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
571 if (dwStyle & TBS_ENABLESELRANGE) { /* fill the channel */
572 HBRUSH hbr = CreateSolidBrush (RGB(255,255,255));
573 FillRect (hdc, &rcChannel, hbr);
574 if (((dwStyle & TBS_VERT) &&
575 (rcSelection.left!=rcSelection.right)) ||
576 ((!(dwStyle & TBS_VERT)) &&
577 (rcSelection.left!=rcSelection.right))) {
578 hbr=CreateSolidBrush (COLOR_HIGHLIGHT);
579 FillRect (hdc, &rcSelection, hbr);
581 DeleteObject (hbr);
585 /* draw tics */
587 if (!(dwStyle & TBS_NOTICKS)) {
588 int ticFlags = dwStyle & 0x0f;
589 COLORREF clrTic=GetSysColor (COLOR_3DDKSHADOW);
591 for (i=0; i<infoPtr->uNumTics; i++)
592 TRACKBAR_DrawTics (infoPtr, hdc, infoPtr->tics[i],
593 ticFlags, clrTic);
595 TRACKBAR_DrawTics (infoPtr, hdc, 0, ticFlags | TIC_LEFTEDGE, clrTic);
596 TRACKBAR_DrawTics (infoPtr, hdc, 0, ticFlags | TIC_RIGHTEDGE, clrTic);
598 if ((dwStyle & TBS_ENABLESELRANGE) &&
599 (rcSelection.left!=rcSelection.right)) {
600 TRACKBAR_DrawTics (infoPtr, hdc, infoPtr->nSelMin,
601 ticFlags | TIC_SELECTIONMARKMIN, clrTic);
602 TRACKBAR_DrawTics (infoPtr, hdc, infoPtr->nSelMax,
603 ticFlags | TIC_SELECTIONMARKMAX, clrTic);
607 /* draw thumb */
609 if (!(dwStyle & TBS_NOTHUMB))
611 TRACKBAR_DrawThumb(infoPtr,hdc,dwStyle);
614 if (infoPtr->bFocus)
615 DrawFocusRect (hdc, &rcClient);
619 static VOID
620 TRACKBAR_AlignBuddies (HWND hwnd, TRACKBAR_INFO *infoPtr)
622 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
623 HWND hwndParent = GetParent (hwnd);
624 RECT rcSelf, rcBuddy;
625 INT x, y;
627 GetWindowRect (hwnd, &rcSelf);
628 MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcSelf, 2);
630 /* align buddy left or above */
631 if (infoPtr->hwndBuddyLA) {
632 GetWindowRect (infoPtr->hwndBuddyLA, &rcBuddy);
633 MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcBuddy, 2);
635 if (dwStyle & TBS_VERT) {
636 x = (infoPtr->rcChannel.right + infoPtr->rcChannel.left) / 2 -
637 (rcBuddy.right - rcBuddy.left) / 2 + rcSelf.left;
638 y = rcSelf.top - (rcBuddy.bottom - rcBuddy.top);
640 else {
641 x = rcSelf.left - (rcBuddy.right - rcBuddy.left);
642 y = (infoPtr->rcChannel.bottom + infoPtr->rcChannel.top) / 2 -
643 (rcBuddy.bottom - rcBuddy.top) / 2 + rcSelf.top;
646 SetWindowPos (infoPtr->hwndBuddyLA, 0, x, y, 0, 0,
647 SWP_NOZORDER | SWP_NOSIZE);
651 /* align buddy right or below */
652 if (infoPtr->hwndBuddyRB) {
653 GetWindowRect (infoPtr->hwndBuddyRB, &rcBuddy);
654 MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcBuddy, 2);
656 if (dwStyle & TBS_VERT) {
657 x = (infoPtr->rcChannel.right + infoPtr->rcChannel.left) / 2 -
658 (rcBuddy.right - rcBuddy.left) / 2 + rcSelf.left;
659 y = rcSelf.bottom;
661 else {
662 x = rcSelf.right;
663 y = (infoPtr->rcChannel.bottom + infoPtr->rcChannel.top) / 2 -
664 (rcBuddy.bottom - rcBuddy.top) / 2 + rcSelf.top;
666 SetWindowPos (infoPtr->hwndBuddyRB, 0, x, y, 0, 0,
667 SWP_NOZORDER | SWP_NOSIZE);
672 static LRESULT
673 TRACKBAR_ClearSel (HWND hwnd, WPARAM wParam, LPARAM lParam)
675 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
677 infoPtr->nSelMin = 0;
678 infoPtr->nSelMax = 0;
679 infoPtr->flags |= TB_SELECTIONCHANGED;
681 if ((BOOL)wParam)
682 InvalidateRect (hwnd, NULL, FALSE);
684 return 0;
688 static LRESULT
689 TRACKBAR_ClearTics (HWND hwnd, WPARAM wParam, LPARAM lParam)
691 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
693 if (infoPtr->tics) {
694 COMCTL32_Free (infoPtr->tics);
695 infoPtr->tics = NULL;
696 infoPtr->uNumTics = 0;
699 if (wParam)
700 InvalidateRect (hwnd, NULL, FALSE);
702 return 0;
706 static LRESULT
707 TRACKBAR_GetBuddy (HWND hwnd, WPARAM wParam, LPARAM lParam)
709 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
711 if (wParam) /* buddy is left or above */
712 return (LRESULT)infoPtr->hwndBuddyLA;
714 /* buddy is right or below */
715 return (LRESULT) infoPtr->hwndBuddyRB;
719 static LRESULT
720 TRACKBAR_GetChannelRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
722 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
723 LPRECT lprc = (LPRECT)lParam;
725 if (lprc == NULL)
726 return 0;
728 lprc->left = infoPtr->rcChannel.left;
729 lprc->right = infoPtr->rcChannel.right;
730 lprc->bottom = infoPtr->rcChannel.bottom;
731 lprc->top = infoPtr->rcChannel.top;
733 return 0;
737 static LRESULT
738 TRACKBAR_GetLineSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
740 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
742 return infoPtr->nLineSize;
746 static LRESULT
747 TRACKBAR_GetNumTics (HWND hwnd, WPARAM wParam, LPARAM lParam)
749 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
751 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_NOTICKS)
752 return 0;
754 return infoPtr->uNumTics+2;
758 static LRESULT
759 TRACKBAR_GetPageSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
761 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
763 return infoPtr->nPageSize;
767 static LRESULT
768 TRACKBAR_GetPos (HWND hwnd, WPARAM wParam, LPARAM lParam)
770 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
772 return infoPtr->nPos;
776 static LRESULT
777 TRACKBAR_GetRangeMax (HWND hwnd, WPARAM wParam, LPARAM lParam)
779 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
781 return infoPtr->nRangeMax;
785 static LRESULT
786 TRACKBAR_GetRangeMin (HWND hwnd, WPARAM wParam, LPARAM lParam)
788 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
790 return infoPtr->nRangeMin;
794 static LRESULT
795 TRACKBAR_GetSelEnd (HWND hwnd, WPARAM wParam, LPARAM lParam)
797 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
799 return infoPtr->nSelMax;
803 static LRESULT
804 TRACKBAR_GetSelStart (HWND hwnd, WPARAM wParam, LPARAM lParam)
806 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
808 return infoPtr->nSelMin;
812 static LRESULT
813 TRACKBAR_GetThumbLength (HWND hwnd, WPARAM wParam, LPARAM lParam)
815 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
817 return infoPtr->uThumbLen;
820 static LRESULT
821 TRACKBAR_GetPTics (HWND hwnd)
823 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
825 return (LRESULT) infoPtr->tics;
828 static LRESULT
829 TRACKBAR_GetThumbRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
831 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
832 LPRECT lprc = (LPRECT)lParam;
834 if (lprc == NULL)
835 return 0;
837 lprc->left = infoPtr->rcThumb.left;
838 lprc->right = infoPtr->rcThumb.right;
839 lprc->bottom = infoPtr->rcThumb.bottom;
840 lprc->top = infoPtr->rcThumb.top;
842 return 0;
846 static LRESULT
847 TRACKBAR_GetTic (HWND hwnd, WPARAM wParam, LPARAM lParam)
849 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
850 INT iTic;
852 iTic=(INT) wParam;
853 if ((iTic<0) || (iTic>infoPtr->uNumTics))
854 return -1;
856 return (LRESULT) infoPtr->tics[iTic];
861 static LRESULT
862 TRACKBAR_GetTicPos (HWND hwnd, WPARAM wParam, LPARAM lParam)
864 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
865 INT iTic, range, width, pos;
868 iTic=(INT ) wParam;
869 if ((iTic<0) || (iTic>infoPtr->uNumTics))
870 return -1;
872 range=infoPtr->nRangeMax - infoPtr->nRangeMin;
873 width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
874 pos=infoPtr->rcChannel.left + (width * infoPtr->tics[iTic]) / range;
877 return (LRESULT) pos;
881 static LRESULT
882 TRACKBAR_GetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
884 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
886 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_TOOLTIPS)
887 return (LRESULT)infoPtr->hwndToolTip;
888 return 0;
892 /* case TBM_GETUNICODEFORMAT: */
895 static LRESULT
896 TRACKBAR_SetBuddy (HWND hwnd, WPARAM wParam, LPARAM lParam)
898 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
899 HWND hwndTemp;
901 if (wParam) {
902 /* buddy is left or above */
903 hwndTemp = infoPtr->hwndBuddyLA;
904 infoPtr->hwndBuddyLA = (HWND)lParam;
906 FIXME("move buddy!\n");
908 else {
909 /* buddy is right or below */
910 hwndTemp = infoPtr->hwndBuddyRB;
911 infoPtr->hwndBuddyRB = (HWND)lParam;
913 FIXME("move buddy!\n");
916 TRACKBAR_AlignBuddies (hwnd, infoPtr);
918 return (LRESULT)hwndTemp;
922 static LRESULT
923 TRACKBAR_SetLineSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
925 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
926 INT nTemp = infoPtr->nLineSize;
928 infoPtr->nLineSize = (INT)lParam;
930 return nTemp;
934 static LRESULT
935 TRACKBAR_SetPageSize (HWND hwnd, WPARAM wParam, LPARAM lParam)
937 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
938 INT nTemp = infoPtr->nPageSize;
940 infoPtr->nPageSize = (INT)lParam;
942 return nTemp;
946 static LRESULT
947 TRACKBAR_SetPos (HWND hwnd, WPARAM wParam, LPARAM lParam)
949 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
951 infoPtr->nPos = (INT)lParam;
953 if (infoPtr->nPos < infoPtr->nRangeMin)
954 infoPtr->nPos = infoPtr->nRangeMin;
956 if (infoPtr->nPos > infoPtr->nRangeMax)
957 infoPtr->nPos = infoPtr->nRangeMax;
958 infoPtr->flags |= TB_THUMBPOSCHANGED;
960 if (wParam)
961 InvalidateRect (hwnd, NULL, FALSE);
963 return 0;
967 static LRESULT
968 TRACKBAR_SetRange (HWND hwnd, WPARAM wParam, LPARAM lParam)
970 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
971 infoPtr->nRangeMin = (INT)LOWORD(lParam);
972 infoPtr->nRangeMax = (INT)HIWORD(lParam);
974 if (infoPtr->nPos < infoPtr->nRangeMin) {
975 infoPtr->nPos = infoPtr->nRangeMin;
976 infoPtr->flags |=TB_THUMBPOSCHANGED;
979 if (infoPtr->nPos > infoPtr->nRangeMax) {
980 infoPtr->nPos = infoPtr->nRangeMax;
981 infoPtr->flags |=TB_THUMBPOSCHANGED;
984 infoPtr->nPageSize=(infoPtr->nRangeMax - infoPtr->nRangeMin)/5;
985 if (infoPtr->nPageSize == 0)
986 infoPtr->nPageSize = 1;
987 TRACKBAR_RecalculateTics (infoPtr);
989 if (wParam)
990 InvalidateRect (hwnd, NULL, FALSE);
992 return 0;
996 static LRESULT
997 TRACKBAR_SetRangeMax (HWND hwnd, WPARAM wParam, LPARAM lParam)
999 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1001 infoPtr->nRangeMax = (INT)lParam;
1002 if (infoPtr->nPos > infoPtr->nRangeMax) {
1003 infoPtr->nPos = infoPtr->nRangeMax;
1004 infoPtr->flags |=TB_THUMBPOSCHANGED;
1007 infoPtr->nPageSize=(infoPtr->nRangeMax - infoPtr->nRangeMin)/5;
1008 if (infoPtr->nPageSize == 0)
1009 infoPtr->nPageSize = 1;
1010 TRACKBAR_RecalculateTics (infoPtr);
1012 if (wParam)
1013 InvalidateRect (hwnd, NULL, FALSE);
1015 return 0;
1019 static LRESULT
1020 TRACKBAR_SetRangeMin (HWND hwnd, WPARAM wParam, LPARAM lParam)
1022 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1024 infoPtr->nRangeMin = (INT)lParam;
1025 if (infoPtr->nPos < infoPtr->nRangeMin) {
1026 infoPtr->nPos = infoPtr->nRangeMin;
1027 infoPtr->flags |=TB_THUMBPOSCHANGED;
1030 infoPtr->nPageSize=(infoPtr->nRangeMax - infoPtr->nRangeMin)/5;
1031 if (infoPtr->nPageSize == 0)
1032 infoPtr->nPageSize = 1;
1033 TRACKBAR_RecalculateTics (infoPtr);
1035 if (wParam)
1036 InvalidateRect (hwnd, NULL, FALSE);
1038 return 0;
1042 static LRESULT
1043 TRACKBAR_SetTicFreq (HWND hwnd, WPARAM wParam)
1045 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1047 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_AUTOTICKS)
1048 infoPtr->uTicFreq=(UINT) wParam;
1050 TRACKBAR_RecalculateTics (infoPtr);
1052 InvalidateRect (hwnd, NULL, FALSE);
1054 return 0;
1058 static LRESULT
1059 TRACKBAR_SetSel (HWND hwnd, WPARAM wParam, LPARAM lParam)
1061 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1063 infoPtr->nSelMin = (INT)LOWORD(lParam);
1064 infoPtr->nSelMax = (INT)HIWORD(lParam);
1065 infoPtr->flags |=TB_SELECTIONCHANGED;
1067 if (!GetWindowLongA (hwnd, GWL_STYLE) & TBS_ENABLESELRANGE)
1068 return 0;
1070 if (infoPtr->nSelMin < infoPtr->nRangeMin)
1071 infoPtr->nSelMin = infoPtr->nRangeMin;
1072 if (infoPtr->nSelMax > infoPtr->nRangeMax)
1073 infoPtr->nSelMax = infoPtr->nRangeMax;
1075 if (wParam)
1076 InvalidateRect (hwnd, NULL, FALSE);
1079 return 0;
1083 static LRESULT
1084 TRACKBAR_SetSelEnd (HWND hwnd, WPARAM wParam, LPARAM lParam)
1086 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1088 if (!GetWindowLongA (hwnd, GWL_STYLE) & TBS_ENABLESELRANGE)
1089 return 0;
1091 infoPtr->nSelMax = (INT)lParam;
1092 infoPtr->flags |= TB_SELECTIONCHANGED;
1094 if (infoPtr->nSelMax > infoPtr->nRangeMax)
1095 infoPtr->nSelMax = infoPtr->nRangeMax;
1097 if (wParam)
1098 InvalidateRect (hwnd, NULL, FALSE);
1100 return 0;
1104 static LRESULT
1105 TRACKBAR_SetSelStart (HWND hwnd, WPARAM wParam, LPARAM lParam)
1107 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1109 if (!GetWindowLongA (hwnd, GWL_STYLE) & TBS_ENABLESELRANGE)
1110 return 0;
1112 infoPtr->nSelMin = (INT)lParam;
1113 infoPtr->flags |=TB_SELECTIONCHANGED;
1115 if (infoPtr->nSelMin < infoPtr->nRangeMin)
1116 infoPtr->nSelMin = infoPtr->nRangeMin;
1118 if (wParam)
1119 InvalidateRect (hwnd, NULL, FALSE);
1121 return 0;
1125 static LRESULT
1126 TRACKBAR_SetThumbLength (HWND hwnd, WPARAM wParam, LPARAM lParam)
1128 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1130 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_FIXEDLENGTH)
1131 infoPtr->uThumbLen = (UINT)wParam;
1133 infoPtr->flags |= TB_THUMBSIZECHANGED;
1135 InvalidateRect (hwnd, NULL, FALSE);
1137 return 0;
1141 static LRESULT
1142 TRACKBAR_SetTic (HWND hwnd, WPARAM wParam, LPARAM lParam)
1144 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1145 INT nPos = (INT)lParam;
1147 if ((nPos < infoPtr->nRangeMin) || (nPos> infoPtr->nRangeMax))
1148 return FALSE;
1150 infoPtr->uNumTics++;
1151 infoPtr->tics=COMCTL32_ReAlloc( infoPtr->tics,
1152 (infoPtr->uNumTics)*sizeof (DWORD));
1153 infoPtr->tics[infoPtr->uNumTics-1]=nPos;
1155 InvalidateRect (hwnd, NULL, FALSE);
1157 return TRUE;
1161 static LRESULT
1162 TRACKBAR_SetTipSide (HWND hwnd, WPARAM wParam, LPARAM lParam)
1164 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1165 INT fTemp = infoPtr->fLocation;
1167 infoPtr->fLocation = (INT)wParam;
1169 return fTemp;
1173 static LRESULT
1174 TRACKBAR_SetToolTips (HWND hwnd, WPARAM wParam, LPARAM lParam)
1176 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1178 infoPtr->hwndToolTip = (HWND)wParam;
1180 return 0;
1184 /* case TBM_SETUNICODEFORMAT: */
1187 static LRESULT
1188 TRACKBAR_InitializeThumb (HWND hwnd)
1190 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1192 infoPtr->uThumbLen = 23; /* initial thumb length */
1194 TRACKBAR_CalcChannel (hwnd,infoPtr);
1195 TRACKBAR_CalcThumb (hwnd, infoPtr);
1196 infoPtr->flags &= ~TB_SELECTIONCHANGED;
1198 return 0;
1202 static LRESULT
1203 TRACKBAR_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
1205 TRACKBAR_INFO *infoPtr;
1207 infoPtr = (TRACKBAR_INFO *)COMCTL32_Alloc (sizeof(TRACKBAR_INFO));
1208 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
1210 /* set default values */
1211 infoPtr->nRangeMin = 0;
1212 infoPtr->nRangeMax = 100;
1213 infoPtr->nLineSize = 1;
1214 infoPtr->nPageSize = 20;
1215 infoPtr->nSelMin = 0;
1216 infoPtr->nSelMax = 0;
1217 infoPtr->nPos = 0;
1219 infoPtr->uNumTics = 0; /* start and end tic are not included in count*/
1220 infoPtr->uTicFreq = 1;
1221 infoPtr->tics = NULL;
1222 infoPtr->clrBk = GetSysColor (COLOR_BTNFACE);
1223 infoPtr->hwndNotify = GetParent (hwnd);
1225 TRACKBAR_InitializeThumb (hwnd);
1227 /* Create tooltip control */
1228 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_TOOLTIPS) {
1229 TTTOOLINFOA ti;
1231 infoPtr->hwndToolTip =
1232 CreateWindowExA (0, TOOLTIPS_CLASSA, NULL, 0,
1233 CW_USEDEFAULT, CW_USEDEFAULT,
1234 CW_USEDEFAULT, CW_USEDEFAULT,
1235 hwnd, 0, 0, 0);
1237 /* Send NM_TOOLTIPSCREATED notification */
1238 if (infoPtr->hwndToolTip) {
1239 NMTOOLTIPSCREATED nmttc;
1241 nmttc.hdr.hwndFrom = hwnd;
1242 nmttc.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
1243 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1244 nmttc.hwndToolTips = infoPtr->hwndToolTip;
1246 SendMessageA (GetParent (hwnd), WM_NOTIFY,
1247 (WPARAM)nmttc.hdr.idFrom, (LPARAM)&nmttc);
1250 ZeroMemory (&ti, sizeof(TTTOOLINFOA));
1251 ti.cbSize = sizeof(TTTOOLINFOA);
1252 ti.uFlags = TTF_IDISHWND | TTF_TRACK;
1253 ti.hwnd = hwnd;
1254 ti.uId = 0;
1255 ti.lpszText = "Test"; /* LPSTR_TEXTCALLBACK */
1256 SetRectEmpty (&ti.rect);
1258 SendMessageA (infoPtr->hwndToolTip, TTM_ADDTOOLA, 0, (LPARAM)&ti);
1261 return 0;
1265 static LRESULT
1266 TRACKBAR_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
1268 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1270 /* delete tooltip control */
1271 if (infoPtr->hwndToolTip)
1272 DestroyWindow (infoPtr->hwndToolTip);
1274 COMCTL32_Free (infoPtr);
1275 SetWindowLongA (hwnd, 0, 0);
1276 return 0;
1280 static LRESULT
1281 TRACKBAR_KillFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
1283 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1285 TRACE("\n");
1287 infoPtr->bFocus = FALSE;
1288 infoPtr->flags &= ~TB_DRAG_MODE;
1290 InvalidateRect (hwnd, NULL, FALSE);
1292 return 0;
1296 static LRESULT
1297 TRACKBAR_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1299 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1300 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1301 POINT clickPoint;
1303 SetFocus (hwnd);
1305 clickPoint.y = HIWORD(lParam);
1306 clickPoint.x = LOWORD(lParam);
1308 if (PtInRect(&(infoPtr->rcThumb),clickPoint))
1310 infoPtr->flags |= TB_DRAG_MODE;
1311 if (dwStyle & TBS_TOOLTIPS) { /* enable tooltip */
1312 TTTOOLINFOA ti;
1313 POINT pt;
1315 GetCursorPos (&pt);
1316 SendMessageA (infoPtr->hwndToolTip, TTM_TRACKPOSITION, 0,
1317 (LPARAM)MAKELPARAM(pt.x, pt.y));
1319 ti.cbSize = sizeof(TTTOOLINFOA);
1320 ti.uId = 0;
1321 ti.hwnd = (UINT)hwnd;
1323 infoPtr->flags |= TB_SHOW_TOOLTIP;
1324 SetCapture (hwnd);
1325 SendMessageA (infoPtr->hwndToolTip, TTM_TRACKACTIVATE,
1326 (WPARAM)TRUE, (LPARAM)&ti);
1328 return 0;
1330 else if (PtInRect(&(infoPtr->rcChannel),clickPoint))
1332 int clickPlace,prevPos,vertical;
1333 DOUBLE clickPos;
1335 vertical = (dwStyle & TBS_VERT) ? 1 : 0;
1336 if (vertical)
1337 clickPlace=(INT)HIWORD(lParam);
1338 else
1339 clickPlace=(INT)LOWORD(lParam);
1341 clickPos = TRACKBAR_ConvertPlaceToPosition(infoPtr, clickPlace,
1342 vertical);
1343 prevPos = infoPtr->nPos;
1344 if (clickPos > (int)prevPos)
1345 { /* similar to VK_NEXT */
1346 infoPtr->nPos += infoPtr->nPageSize;
1347 if (infoPtr->nPos > infoPtr->nRangeMax)
1348 infoPtr->nPos = infoPtr->nRangeMax;
1349 TRACKBAR_SendNotify (hwnd, TB_PAGEUP);
1351 else
1353 infoPtr->nPos -= infoPtr->nPageSize; /* similar to VK_PRIOR */
1354 if (infoPtr->nPos < infoPtr->nRangeMin)
1355 infoPtr->nPos = infoPtr->nRangeMin;
1356 TRACKBAR_SendNotify (hwnd, TB_PAGEDOWN);
1359 if (prevPos!=infoPtr->nPos) {
1360 infoPtr->flags |= TB_THUMBPOSCHANGED;
1361 InvalidateRect (hwnd, NULL, FALSE);
1365 return 0;
1369 static LRESULT
1370 TRACKBAR_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
1372 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1374 TRACKBAR_SendNotify (hwnd, TB_ENDTRACK);
1376 if (infoPtr->flags & TB_DRAG_MODE)
1378 infoPtr->flags &= ~TB_DRAG_MODE;
1379 ReleaseCapture ();
1382 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_TOOLTIPS) { /* disable tooltip */
1383 TTTOOLINFOA ti;
1385 ti.cbSize = sizeof(TTTOOLINFOA);
1386 ti.uId = 0;
1387 ti.hwnd = (UINT)hwnd;
1389 infoPtr->flags &= ~TB_SHOW_TOOLTIP;
1390 SendMessageA (infoPtr->hwndToolTip, TTM_TRACKACTIVATE,
1391 (WPARAM)FALSE, (LPARAM)&ti);
1394 InvalidateRect (hwnd, NULL, FALSE);
1396 return 0;
1400 static LRESULT
1401 TRACKBAR_CaptureChanged (HWND hwnd, WPARAM wParam, LPARAM lParam)
1403 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1405 if (infoPtr->flags & TB_DRAGPOSVALID) {
1406 infoPtr->nPos=infoPtr->dragPos;
1407 InvalidateRect (hwnd, NULL, FALSE);
1410 infoPtr->flags &= ~ TB_DRAGPOSVALID;
1412 TRACKBAR_SendNotify (hwnd, TB_ENDTRACK);
1413 return 0;
1417 static LRESULT
1418 TRACKBAR_Paint (HWND hwnd, WPARAM wParam)
1420 HDC hdc;
1421 PAINTSTRUCT ps;
1423 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
1424 TRACKBAR_Refresh (hwnd, hdc);
1425 if(!wParam)
1426 EndPaint (hwnd, &ps);
1427 return 0;
1431 static LRESULT
1432 TRACKBAR_SetFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
1434 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1436 TRACE("\n");
1437 infoPtr->bFocus = TRUE;
1439 InvalidateRect (hwnd, NULL, FALSE);
1441 return 0;
1445 static LRESULT
1446 TRACKBAR_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
1448 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1450 TRACKBAR_CalcChannel (hwnd, infoPtr);
1451 TRACKBAR_AlignBuddies (hwnd, infoPtr);
1453 return 0;
1457 static BOOL
1458 TRACKBAR_SendNotify (HWND hwnd, UINT code)
1460 TRACE("%x\n",code);
1462 if (GetWindowLongA (hwnd, GWL_STYLE) & TBS_VERT)
1463 return (BOOL) SendMessageA (GetParent (hwnd),
1464 WM_VSCROLL, (WPARAM)code, (LPARAM)hwnd);
1466 return (BOOL) SendMessageA (GetParent (hwnd),
1467 WM_HSCROLL, (WPARAM)code, (LPARAM)hwnd);
1471 static LRESULT
1472 TRACKBAR_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
1474 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1475 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1476 SHORT clickPlace;
1477 DOUBLE dragPos;
1478 char buf[80];
1480 TRACE("%x\n",wParam);
1482 if (dwStyle & TBS_VERT)
1483 clickPlace=(SHORT)HIWORD(lParam);
1484 else
1485 clickPlace=(SHORT)LOWORD(lParam);
1487 if (!(infoPtr->flags & TB_DRAG_MODE))
1488 return TRUE;
1490 SetCapture (hwnd);
1491 dragPos = TRACKBAR_ConvertPlaceToPosition (infoPtr, clickPlace,
1492 dwStyle & TBS_VERT);
1493 if (dragPos > ((INT)dragPos) + 0.5)
1494 infoPtr->dragPos = dragPos + 1;
1495 else
1496 infoPtr->dragPos = dragPos;
1498 infoPtr->flags |= TB_DRAGPOSVALID;
1499 TRACKBAR_SendNotify (hwnd, TB_THUMBTRACK | (infoPtr->nPos<<16));
1501 if (infoPtr->flags & TB_SHOW_TOOLTIP) {
1502 POINT pt;
1503 TTTOOLINFOA ti;
1505 ti.cbSize = sizeof(TTTOOLINFOA);
1506 ti.hwnd = hwnd;
1507 ti.uId = 0;
1508 ti.hinst=0;
1509 sprintf (buf,"%d",infoPtr->nPos);
1510 ti.lpszText = (LPSTR) buf;
1511 GetCursorPos (&pt);
1513 if (dwStyle & TBS_VERT) {
1514 SendMessageA (infoPtr->hwndToolTip, TTM_TRACKPOSITION,
1515 0, (LPARAM)MAKELPARAM(pt.x+5, pt.y+15));
1516 } else {
1517 SendMessageA (infoPtr->hwndToolTip, TTM_TRACKPOSITION,
1518 0, (LPARAM)MAKELPARAM(pt.x+15, pt.y+5));
1520 SendMessageA (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTA,
1521 0, (LPARAM)&ti);
1524 InvalidateRect (hwnd, NULL, FALSE);
1525 UpdateWindow (hwnd);
1527 return TRUE;
1531 static LRESULT
1532 TRACKBAR_KeyDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1534 TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr (hwnd);
1535 INT pos;
1537 TRACE("%x\n",wParam);
1539 pos=infoPtr->nPos;
1540 switch (wParam) {
1541 case VK_LEFT:
1542 case VK_UP:
1543 if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
1544 infoPtr->nPos -= infoPtr->nLineSize;
1545 if (infoPtr->nPos < infoPtr->nRangeMin)
1546 infoPtr->nPos = infoPtr->nRangeMin;
1547 TRACKBAR_SendNotify (hwnd, TB_LINEUP);
1548 break;
1549 case VK_RIGHT:
1550 case VK_DOWN:
1551 if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
1552 infoPtr->nPos += infoPtr->nLineSize;
1553 if (infoPtr->nPos > infoPtr->nRangeMax)
1554 infoPtr->nPos = infoPtr->nRangeMax;
1555 TRACKBAR_SendNotify (hwnd, TB_LINEDOWN);
1556 break;
1557 case VK_NEXT:
1558 if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
1559 infoPtr->nPos += infoPtr->nPageSize;
1560 if (infoPtr->nPos > infoPtr->nRangeMax)
1561 infoPtr->nPos = infoPtr->nRangeMax;
1562 TRACKBAR_SendNotify (hwnd, TB_PAGEUP);
1563 break;
1564 case VK_PRIOR:
1565 if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
1566 infoPtr->nPos -= infoPtr->nPageSize;
1567 if (infoPtr->nPos < infoPtr->nRangeMin)
1568 infoPtr->nPos = infoPtr->nRangeMin;
1569 TRACKBAR_SendNotify (hwnd, TB_PAGEDOWN);
1570 break;
1571 case VK_HOME:
1572 if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
1573 infoPtr->nPos = infoPtr->nRangeMin;
1574 TRACKBAR_SendNotify (hwnd, TB_TOP);
1575 break;
1576 case VK_END:
1577 if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
1578 infoPtr->nPos = infoPtr->nRangeMax;
1579 TRACKBAR_SendNotify (hwnd, TB_BOTTOM);
1580 break;
1583 if (pos!=infoPtr->nPos) {
1584 infoPtr->flags |=TB_THUMBPOSCHANGED;
1585 InvalidateRect (hwnd, NULL, FALSE);
1588 return TRUE;
1592 static LRESULT
1593 TRACKBAR_KeyUp (HWND hwnd, WPARAM wParam)
1595 switch (wParam) {
1596 case VK_LEFT:
1597 case VK_UP:
1598 case VK_RIGHT:
1599 case VK_DOWN:
1600 case VK_NEXT:
1601 case VK_PRIOR:
1602 case VK_HOME:
1603 case VK_END:
1604 TRACKBAR_SendNotify (hwnd, TB_ENDTRACK);
1606 return TRUE;
1610 static LRESULT WINAPI
1611 TRACKBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1613 TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hwnd, uMsg, wParam, lParam);
1614 if (!TRACKBAR_GetInfoPtr (hwnd) && (uMsg != WM_CREATE))
1615 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1616 switch (uMsg)
1618 case TBM_CLEARSEL:
1619 return TRACKBAR_ClearSel (hwnd, wParam, lParam);
1621 case TBM_CLEARTICS:
1622 return TRACKBAR_ClearTics (hwnd, wParam, lParam);
1624 case TBM_GETBUDDY:
1625 return TRACKBAR_GetBuddy (hwnd, wParam, lParam);
1627 case TBM_GETCHANNELRECT:
1628 return TRACKBAR_GetChannelRect (hwnd, wParam, lParam);
1630 case TBM_GETLINESIZE:
1631 return TRACKBAR_GetLineSize (hwnd, wParam, lParam);
1633 case TBM_GETNUMTICS:
1634 return TRACKBAR_GetNumTics (hwnd, wParam, lParam);
1636 case TBM_GETPAGESIZE:
1637 return TRACKBAR_GetPageSize (hwnd, wParam, lParam);
1639 case TBM_GETPOS:
1640 return TRACKBAR_GetPos (hwnd, wParam, lParam);
1642 case TBM_GETPTICS:
1643 return TRACKBAR_GetPTics (hwnd);
1645 case TBM_GETRANGEMAX:
1646 return TRACKBAR_GetRangeMax (hwnd, wParam, lParam);
1648 case TBM_GETRANGEMIN:
1649 return TRACKBAR_GetRangeMin (hwnd, wParam, lParam);
1651 case TBM_GETSELEND:
1652 return TRACKBAR_GetSelEnd (hwnd, wParam, lParam);
1654 case TBM_GETSELSTART:
1655 return TRACKBAR_GetSelStart (hwnd, wParam, lParam);
1657 case TBM_GETTHUMBLENGTH:
1658 return TRACKBAR_GetThumbLength (hwnd, wParam, lParam);
1660 case TBM_GETTHUMBRECT:
1661 return TRACKBAR_GetThumbRect (hwnd, wParam, lParam);
1663 case TBM_GETTIC:
1664 return TRACKBAR_GetTic (hwnd, wParam, lParam);
1666 case TBM_GETTICPOS:
1667 return TRACKBAR_GetTicPos (hwnd, wParam, lParam);
1669 case TBM_GETTOOLTIPS:
1670 return TRACKBAR_GetToolTips (hwnd, wParam, lParam);
1672 /* case TBM_GETUNICODEFORMAT: */
1674 case TBM_SETBUDDY:
1675 return TRACKBAR_SetBuddy (hwnd, wParam, lParam);
1677 case TBM_SETLINESIZE:
1678 return TRACKBAR_SetLineSize (hwnd, wParam, lParam);
1680 case TBM_SETPAGESIZE:
1681 return TRACKBAR_SetPageSize (hwnd, wParam, lParam);
1683 case TBM_SETPOS:
1684 return TRACKBAR_SetPos (hwnd, wParam, lParam);
1686 case TBM_SETRANGE:
1687 return TRACKBAR_SetRange (hwnd, wParam, lParam);
1689 case TBM_SETRANGEMAX:
1690 return TRACKBAR_SetRangeMax (hwnd, wParam, lParam);
1692 case TBM_SETRANGEMIN:
1693 return TRACKBAR_SetRangeMin (hwnd, wParam, lParam);
1695 case TBM_SETSEL:
1696 return TRACKBAR_SetSel (hwnd, wParam, lParam);
1698 case TBM_SETSELEND:
1699 return TRACKBAR_SetSelEnd (hwnd, wParam, lParam);
1701 case TBM_SETSELSTART:
1702 return TRACKBAR_SetSelStart (hwnd, wParam, lParam);
1704 case TBM_SETTHUMBLENGTH:
1705 return TRACKBAR_SetThumbLength (hwnd, wParam, lParam);
1707 case TBM_SETTIC:
1708 return TRACKBAR_SetTic (hwnd, wParam, lParam);
1710 case TBM_SETTICFREQ:
1711 return TRACKBAR_SetTicFreq (hwnd, wParam);
1713 case TBM_SETTIPSIDE:
1714 return TRACKBAR_SetTipSide (hwnd, wParam, lParam);
1716 case TBM_SETTOOLTIPS:
1717 return TRACKBAR_SetToolTips (hwnd, wParam, lParam);
1719 /* case TBM_SETUNICODEFORMAT: */
1722 case WM_CAPTURECHANGED:
1723 return TRACKBAR_CaptureChanged (hwnd, wParam, lParam);
1725 case WM_CREATE:
1726 return TRACKBAR_Create (hwnd, wParam, lParam);
1728 case WM_DESTROY:
1729 return TRACKBAR_Destroy (hwnd, wParam, lParam);
1731 /* case WM_ENABLE: */
1733 /* case WM_ERASEBKGND: */
1734 /* return 0; */
1736 case WM_GETDLGCODE:
1737 return DLGC_WANTARROWS;
1739 case WM_KEYDOWN:
1740 return TRACKBAR_KeyDown (hwnd, wParam, lParam);
1742 case WM_KEYUP:
1743 return TRACKBAR_KeyUp (hwnd, wParam);
1745 case WM_KILLFOCUS:
1746 return TRACKBAR_KillFocus (hwnd, wParam, lParam);
1748 case WM_LBUTTONDOWN:
1749 return TRACKBAR_LButtonDown (hwnd, wParam, lParam);
1751 case WM_LBUTTONUP:
1752 return TRACKBAR_LButtonUp (hwnd, wParam, lParam);
1754 case WM_MOUSEMOVE:
1755 return TRACKBAR_MouseMove (hwnd, wParam, lParam);
1757 case WM_PAINT:
1758 return TRACKBAR_Paint (hwnd, wParam);
1760 case WM_SETFOCUS:
1761 return TRACKBAR_SetFocus (hwnd, wParam, lParam);
1763 case WM_SIZE:
1764 return TRACKBAR_Size (hwnd, wParam, lParam);
1766 case WM_WININICHANGE:
1767 return TRACKBAR_InitializeThumb (hwnd);
1769 default:
1770 if ((uMsg >= WM_USER) && (uMsg < WM_APP))
1771 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
1772 uMsg, wParam, lParam);
1773 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
1775 return 0;
1779 VOID
1780 TRACKBAR_Register (void)
1782 WNDCLASSA wndClass;
1784 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1785 wndClass.style = CS_GLOBALCLASS;
1786 wndClass.lpfnWndProc = (WNDPROC)TRACKBAR_WindowProc;
1787 wndClass.cbClsExtra = 0;
1788 wndClass.cbWndExtra = sizeof(TRACKBAR_INFO *);
1789 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
1790 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
1791 wndClass.lpszClassName = TRACKBAR_CLASSA;
1793 RegisterClassA (&wndClass);
1797 VOID
1798 TRACKBAR_Unregister (void)
1800 UnregisterClassA (TRACKBAR_CLASSA, (HINSTANCE)NULL);