ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

trackbar.c
Go to the documentation of this file.
00001 /*
00002  * Trackbar control
00003  *
00004  * Copyright 1998, 1999 Eric Kohl
00005  * Copyright 1998, 1999 Alex Priem
00006  * Copyright 2002 Dimitrie O. Paun
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00021  *
00022  * NOTE
00023  * 
00024  * This code was audited for completeness against the documented features
00025  * of Comctl32.dll version 6.0 on Sep. 12, 2002, by Dimitrie O. Paun.
00026  * 
00027  * Unless otherwise noted, we believe this code to be complete, as per
00028  * the specification mentioned above.
00029  * If you discover missing features, or bugs, please note them below.
00030  * 
00031  */
00032 
00033 #include <stdarg.h>
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037 
00038 #include "windef.h"
00039 #include "winbase.h"
00040 #include "wingdi.h"
00041 #include "winuser.h"
00042 #include "winnls.h"
00043 #include "commctrl.h"
00044 #include "uxtheme.h"
00045 #include "vssym32.h"
00046 #include "wine/debug.h"
00047 
00048 #include "comctl32.h"
00049 
00050 WINE_DEFAULT_DEBUG_CHANNEL(trackbar);
00051 
00052 typedef struct
00053 {
00054     HWND hwndSelf;
00055     DWORD dwStyle;
00056     LONG lRangeMin;
00057     LONG lRangeMax;
00058     LONG lLineSize;
00059     LONG lPageSize;
00060     LONG lSelMin;
00061     LONG lSelMax;
00062     LONG lPos;
00063     UINT uThumbLen;
00064     UINT uNumTics;
00065     UINT uTicFreq;
00066     HWND hwndNotify;
00067     HWND hwndToolTip;
00068     HWND hwndBuddyLA;
00069     HWND hwndBuddyRB;
00070     INT  fLocation;
00071     INT  flags;
00072     BOOL bUnicode;
00073     BOOL bFocussed;
00074     RECT rcChannel;
00075     RECT rcSelection;
00076     RECT rcThumb;
00077     LPLONG tics;
00078 } TRACKBAR_INFO;
00079 
00080 #define TB_REFRESH_TIMER    1
00081 #define TB_REFRESH_DELAY    500
00082 
00083 #define TOOLTIP_OFFSET      2     /* distance from ctrl edge to tooltip */
00084 
00085 #define TB_DEFAULTPAGESIZE  20
00086 
00087 /* Used by TRACKBAR_Refresh to find out which parts of the control
00088    need to be recalculated */
00089 
00090 #define TB_THUMBPOSCHANGED      1
00091 #define TB_THUMBSIZECHANGED     2
00092 #define TB_THUMBCHANGED     (TB_THUMBPOSCHANGED | TB_THUMBSIZECHANGED)
00093 #define TB_SELECTIONCHANGED     4
00094 #define TB_DRAG_MODE            8     /* we're dragging the slider */
00095 #define TB_AUTO_PAGE_LEFT   16
00096 #define TB_AUTO_PAGE_RIGHT  32
00097 #define TB_AUTO_PAGE        (TB_AUTO_PAGE_LEFT | TB_AUTO_PAGE_RIGHT)
00098 #define TB_THUMB_HOT            64    /* mouse hovers above thumb */
00099 
00100 /* helper defines for TRACKBAR_DrawTic */
00101 #define TIC_EDGE                0x20
00102 #define TIC_SELECTIONMARKMAX    0x80
00103 #define TIC_SELECTIONMARKMIN    0x100
00104 #define TIC_SELECTIONMARK       (TIC_SELECTIONMARKMAX | TIC_SELECTIONMARKMIN)
00105 
00106 static const WCHAR themeClass[] = { 'T','r','a','c','k','b','a','r',0 };
00107 
00108 static inline int 
00109 notify_customdraw (const TRACKBAR_INFO *infoPtr, NMCUSTOMDRAW *pnmcd, int stage)
00110 {
00111     pnmcd->dwDrawStage = stage;
00112     return SendMessageW (infoPtr->hwndNotify, WM_NOTIFY, 
00113                  pnmcd->hdr.idFrom, (LPARAM)pnmcd);
00114 }
00115 
00116 static LRESULT notify_hdr (const TRACKBAR_INFO *infoPtr, INT code, LPNMHDR pnmh)
00117 {
00118     LRESULT result;
00119     
00120     TRACE("(code=%d)\n", code);
00121 
00122     pnmh->hwndFrom = infoPtr->hwndSelf;
00123     pnmh->idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
00124     pnmh->code = code;
00125     result = SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, pnmh->idFrom, (LPARAM)pnmh);
00126 
00127     TRACE("  <= %ld\n", result);
00128 
00129     return result;
00130 }
00131 
00132 static inline int notify (const TRACKBAR_INFO *infoPtr, INT code)
00133 {
00134     NMHDR nmh;
00135     return notify_hdr(infoPtr, code, &nmh);
00136 }
00137 
00138 static void notify_with_scroll (const TRACKBAR_INFO *infoPtr, UINT code)
00139 {
00140     UINT scroll = infoPtr->dwStyle & TBS_VERT ? WM_VSCROLL : WM_HSCROLL;
00141 
00142     TRACE("%x\n", code);
00143 
00144     SendMessageW (infoPtr->hwndNotify, scroll, code, (LPARAM)infoPtr->hwndSelf);
00145 }
00146 
00147 static void TRACKBAR_RecalculateTics (TRACKBAR_INFO *infoPtr)
00148 {
00149     int tic;
00150     unsigned nrTics, i;
00151 
00152     if (infoPtr->uTicFreq && infoPtr->lRangeMax >= infoPtr->lRangeMin) {
00153         nrTics=(infoPtr->lRangeMax - infoPtr->lRangeMin)/infoPtr->uTicFreq;
00154         /* don't add extra tic if there's no remainder */
00155         if (nrTics && ((infoPtr->lRangeMax - infoPtr->lRangeMin) % infoPtr->uTicFreq == 0))
00156           nrTics--;
00157     }
00158     else {
00159         Free (infoPtr->tics);
00160         infoPtr->tics = NULL;
00161         infoPtr->uNumTics = 0;
00162         return;
00163     }
00164 
00165     if (nrTics != infoPtr->uNumTics) {
00166         infoPtr->tics=ReAlloc (infoPtr->tics,
00167                                         (nrTics+1)*sizeof (DWORD));
00168     if (!infoPtr->tics) {
00169         infoPtr->uNumTics = 0;
00170         notify(infoPtr, NM_OUTOFMEMORY);
00171         return;
00172     }
00173         infoPtr->uNumTics = nrTics;
00174     }
00175 
00176     tic = infoPtr->lRangeMin + infoPtr->uTicFreq;
00177     for (i = 0; i < nrTics; i++, tic += infoPtr->uTicFreq)
00178         infoPtr->tics[i] = tic;
00179 }
00180 
00181 /* converts from physical (mouse) position to logical position
00182    (in range of trackbar) */
00183 
00184 static inline LONG
00185 TRACKBAR_ConvertPlaceToPosition (const TRACKBAR_INFO *infoPtr, int place)
00186 {
00187     double range, width, pos, offsetthumb;
00188 
00189     range = infoPtr->lRangeMax - infoPtr->lRangeMin;
00190     if (infoPtr->dwStyle & TBS_VERT) {
00191         offsetthumb = (infoPtr->rcThumb.bottom - infoPtr->rcThumb.top)/2;
00192         width = infoPtr->rcChannel.bottom - infoPtr->rcChannel.top - (offsetthumb * 2) - 1;
00193         pos = (range*(place - infoPtr->rcChannel.top - offsetthumb)) / width;
00194     } else {
00195         offsetthumb = (infoPtr->rcThumb.right - infoPtr->rcThumb.left)/2;
00196         width = infoPtr->rcChannel.right - infoPtr->rcChannel.left - (offsetthumb * 2) - 1;
00197         pos = (range*(place - infoPtr->rcChannel.left - offsetthumb)) / width;
00198     }
00199     pos += infoPtr->lRangeMin;
00200     if (pos > infoPtr->lRangeMax)
00201         pos = infoPtr->lRangeMax;
00202     else if (pos < infoPtr->lRangeMin)
00203         pos = infoPtr->lRangeMin;
00204 
00205     TRACE("%.2f\n", pos);
00206     return (LONG)(pos + 0.5);
00207 }
00208 
00209 
00210 /* return: 0> prev, 0 none, >0 next */
00211 static LONG
00212 TRACKBAR_GetAutoPageDirection (const TRACKBAR_INFO *infoPtr, POINT clickPoint)
00213 {
00214     RECT pageRect;
00215 
00216     if (infoPtr->dwStyle & TBS_VERT) {
00217     pageRect.top = infoPtr->rcChannel.top;
00218     pageRect.bottom = infoPtr->rcChannel.bottom;
00219     pageRect.left = infoPtr->rcThumb.left;
00220     pageRect.right = infoPtr->rcThumb.right;
00221     } else {
00222     pageRect.top = infoPtr->rcThumb.top;
00223     pageRect.bottom = infoPtr->rcThumb.bottom;
00224     pageRect.left = infoPtr->rcChannel.left;
00225     pageRect.right = infoPtr->rcChannel.right;
00226     }
00227 
00228 
00229     if (PtInRect(&pageRect, clickPoint))
00230     {
00231     int clickPlace = (infoPtr->dwStyle & TBS_VERT) ? clickPoint.y : clickPoint.x;
00232 
00233         LONG clickPos = TRACKBAR_ConvertPlaceToPosition(infoPtr, clickPlace);
00234 
00235     return clickPos - infoPtr->lPos;
00236     }
00237 
00238     return 0;
00239 }
00240 
00241 static inline void
00242 TRACKBAR_PageDown (TRACKBAR_INFO *infoPtr)
00243 {
00244     if (infoPtr->lPos == infoPtr->lRangeMax) return;
00245 
00246     infoPtr->lPos += infoPtr->lPageSize;
00247     if (infoPtr->lPos > infoPtr->lRangeMax)
00248     infoPtr->lPos = infoPtr->lRangeMax;
00249     notify_with_scroll (infoPtr, TB_PAGEDOWN);
00250 }
00251 
00252 
00253 static inline void
00254 TRACKBAR_PageUp (TRACKBAR_INFO *infoPtr)
00255 {
00256     if (infoPtr->lPos == infoPtr->lRangeMin) return;
00257 
00258     infoPtr->lPos -= infoPtr->lPageSize;
00259     if (infoPtr->lPos < infoPtr->lRangeMin)
00260         infoPtr->lPos = infoPtr->lRangeMin;
00261     notify_with_scroll (infoPtr, TB_PAGEUP);
00262 }
00263 
00264 static inline void TRACKBAR_LineUp(TRACKBAR_INFO *infoPtr)
00265 {
00266     if (infoPtr->lPos == infoPtr->lRangeMin) return;
00267     infoPtr->lPos -= infoPtr->lLineSize;
00268     if (infoPtr->lPos < infoPtr->lRangeMin)
00269         infoPtr->lPos = infoPtr->lRangeMin;
00270     notify_with_scroll (infoPtr, TB_LINEUP);
00271 }
00272 
00273 static inline void TRACKBAR_LineDown(TRACKBAR_INFO *infoPtr)
00274 {
00275     if (infoPtr->lPos == infoPtr->lRangeMax) return;
00276     infoPtr->lPos += infoPtr->lLineSize;
00277     if (infoPtr->lPos > infoPtr->lRangeMax)
00278         infoPtr->lPos = infoPtr->lRangeMax;
00279     notify_with_scroll (infoPtr, TB_LINEDOWN);
00280 }
00281 
00282 static void
00283 TRACKBAR_CalcChannel (TRACKBAR_INFO *infoPtr)
00284 {
00285     INT cyChannel, offsetthumb, offsetedge;
00286     RECT lpRect, *channel = & infoPtr->rcChannel;
00287 
00288     GetClientRect (infoPtr->hwndSelf, &lpRect);
00289 
00290     offsetthumb = infoPtr->uThumbLen / 4;
00291     offsetedge  = offsetthumb + 3;
00292     cyChannel   = (infoPtr->dwStyle & TBS_ENABLESELRANGE) ? offsetthumb*3 : 4;
00293     if (infoPtr->dwStyle & TBS_VERT) {
00294         channel->top    = lpRect.top + offsetedge;
00295         channel->bottom = lpRect.bottom - offsetedge;
00296         if (infoPtr->dwStyle & TBS_ENABLESELRANGE)
00297             channel->left = lpRect.left + ((infoPtr->uThumbLen - cyChannel + 2) / 2);
00298         else
00299             channel->left = lpRect.left + (infoPtr->uThumbLen / 2) - 1;
00300         if (infoPtr->dwStyle & TBS_BOTH) {
00301             if (infoPtr->dwStyle & TBS_NOTICKS)
00302                 channel->left += 1;
00303             else
00304                 channel->left += 9;
00305         }
00306         else if (infoPtr->dwStyle & TBS_TOP) {
00307             if (infoPtr->dwStyle & TBS_NOTICKS)
00308                 channel->left += 2;
00309             else
00310                 channel->left += 10;
00311         }
00312         channel->right = channel->left + cyChannel;
00313     } else {
00314         channel->left = lpRect.left + offsetedge;
00315         channel->right = lpRect.right - offsetedge;
00316         if (infoPtr->dwStyle & TBS_ENABLESELRANGE)
00317             channel->top = lpRect.top + ((infoPtr->uThumbLen - cyChannel + 2) / 2);
00318         else
00319             channel->top = lpRect.top + (infoPtr->uThumbLen / 2) - 1;
00320         if (infoPtr->dwStyle & TBS_BOTH) {
00321             if (infoPtr->dwStyle & TBS_NOTICKS)
00322                 channel->top += 1;
00323             else
00324                 channel->top += 9;
00325         }
00326         else if (infoPtr->dwStyle & TBS_TOP) {
00327             if (infoPtr->dwStyle & TBS_NOTICKS)
00328                 channel->top += 2;
00329             else
00330                 channel->top += 10;
00331         }
00332         channel->bottom   = channel->top + cyChannel;
00333     }
00334 }
00335 
00336 static void
00337 TRACKBAR_CalcThumb (const TRACKBAR_INFO *infoPtr, LONG lPos, RECT *thumb)
00338 {
00339     int range, width, height, thumbwidth;
00340     RECT lpRect;
00341 
00342     range = infoPtr->lRangeMax - infoPtr->lRangeMin;
00343     thumbwidth = (infoPtr->uThumbLen / 2) | 1;
00344 
00345     if (!range) range = 1;
00346 
00347     GetClientRect(infoPtr->hwndSelf, &lpRect);
00348     if (infoPtr->dwStyle & TBS_VERT)
00349     {
00350         height = infoPtr->rcChannel.bottom - infoPtr->rcChannel.top - thumbwidth;
00351 
00352         if ((infoPtr->dwStyle & (TBS_BOTH | TBS_LEFT)) && !(infoPtr->dwStyle & TBS_NOTICKS))
00353             thumb->left = 10;
00354         else
00355             thumb->left = 2;
00356         thumb->right = thumb->left + infoPtr->uThumbLen;
00357         thumb->top = infoPtr->rcChannel.top +
00358                      (height*(lPos - infoPtr->lRangeMin))/range;
00359         thumb->bottom = thumb->top + thumbwidth;
00360     }
00361     else
00362     {
00363         width = infoPtr->rcChannel.right - infoPtr->rcChannel.left - thumbwidth;
00364 
00365         thumb->left = infoPtr->rcChannel.left +
00366                       (width*(lPos - infoPtr->lRangeMin))/range;
00367         thumb->right = thumb->left + thumbwidth;
00368         if ((infoPtr->dwStyle & (TBS_BOTH | TBS_TOP)) && !(infoPtr->dwStyle & TBS_NOTICKS))
00369             thumb->top = 10;
00370         else
00371             thumb->top = 2;
00372         thumb->bottom = thumb->top + infoPtr->uThumbLen;
00373     }
00374 }
00375 
00376 static inline void
00377 TRACKBAR_UpdateThumb (TRACKBAR_INFO *infoPtr)
00378 {
00379     TRACKBAR_CalcThumb(infoPtr, infoPtr->lPos, &infoPtr->rcThumb);
00380 }
00381 
00382 static inline void
00383 TRACKBAR_InvalidateAll (const TRACKBAR_INFO *infoPtr)
00384 {
00385     InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
00386 }
00387 
00388 static void
00389 TRACKBAR_InvalidateThumb (const TRACKBAR_INFO *infoPtr, LONG thumbPos)
00390 {
00391     RECT rcThumb;
00392 
00393     TRACKBAR_CalcThumb(infoPtr, thumbPos, &rcThumb);
00394     InflateRect(&rcThumb, 1, 1);
00395     InvalidateRect(infoPtr->hwndSelf, &rcThumb, FALSE);
00396 }
00397 
00398 static inline void
00399 TRACKBAR_InvalidateThumbMove (const TRACKBAR_INFO *infoPtr, LONG oldPos, LONG newPos)
00400 {
00401     TRACKBAR_InvalidateThumb (infoPtr, oldPos);
00402     if (newPos != oldPos)
00403         TRACKBAR_InvalidateThumb (infoPtr, newPos);
00404 }
00405 
00406 static inline BOOL
00407 TRACKBAR_HasSelection (const TRACKBAR_INFO *infoPtr)
00408 {
00409     return infoPtr->lSelMin != infoPtr->lSelMax;
00410 }
00411 
00412 static void
00413 TRACKBAR_CalcSelection (TRACKBAR_INFO *infoPtr)
00414 {
00415     RECT *selection = &infoPtr->rcSelection;
00416     int range = infoPtr->lRangeMax - infoPtr->lRangeMin;
00417     int offsetthumb, height, width;
00418 
00419     if (range <= 0) {
00420         SetRectEmpty (selection);
00421     } else {
00422         if (infoPtr->dwStyle & TBS_VERT) {
00423             offsetthumb = (infoPtr->rcThumb.bottom - infoPtr->rcThumb.top)/2;
00424             height = infoPtr->rcChannel.bottom - infoPtr->rcChannel.top - offsetthumb*2;
00425             selection->top    = infoPtr->rcChannel.top + offsetthumb +
00426                 (height*infoPtr->lSelMin)/range;
00427             selection->bottom = infoPtr->rcChannel.top + offsetthumb +
00428                 (height*infoPtr->lSelMax)/range;
00429             selection->left   = infoPtr->rcChannel.left + 3;
00430             selection->right  = infoPtr->rcChannel.right - 3;
00431         } else {
00432             offsetthumb = (infoPtr->rcThumb.right - infoPtr->rcThumb.left)/2;
00433             width = infoPtr->rcChannel.right - infoPtr->rcChannel.left - offsetthumb*2;
00434             selection->left   = infoPtr->rcChannel.left + offsetthumb +
00435                 (width*infoPtr->lSelMin)/range;
00436             selection->right  = infoPtr->rcChannel.left + offsetthumb +
00437                 (width*infoPtr->lSelMax)/range;
00438             selection->top    = infoPtr->rcChannel.top + 3;
00439             selection->bottom = infoPtr->rcChannel.bottom - 3;
00440         }
00441     }
00442 
00443     TRACE("selection[%s]\n", wine_dbgstr_rect(selection));
00444 }
00445 
00446 static BOOL
00447 TRACKBAR_AutoPage (TRACKBAR_INFO *infoPtr, POINT clickPoint)
00448 {
00449     LONG dir = TRACKBAR_GetAutoPageDirection(infoPtr, clickPoint);
00450     LONG prevPos = infoPtr->lPos;
00451 
00452     TRACE("x=%d, y=%d, dir=%d\n", clickPoint.x, clickPoint.y, dir);
00453 
00454     if (dir > 0 && (infoPtr->flags & TB_AUTO_PAGE_RIGHT))
00455     TRACKBAR_PageDown(infoPtr);
00456     else if (dir < 0 && (infoPtr->flags & TB_AUTO_PAGE_LEFT))
00457     TRACKBAR_PageUp(infoPtr);
00458     else return FALSE;
00459 
00460     infoPtr->flags |= TB_THUMBPOSCHANGED;
00461     TRACKBAR_InvalidateThumbMove (infoPtr, prevPos, infoPtr->lPos);
00462 
00463     return TRUE;
00464 }
00465 
00466 /* Trackbar drawing code. I like my spaghetti done milanese.  */
00467 
00468 static void
00469 TRACKBAR_DrawChannel (const TRACKBAR_INFO *infoPtr, HDC hdc)
00470 {
00471     RECT rcChannel = infoPtr->rcChannel;
00472     HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
00473 
00474     if (theme)
00475     {
00476         DrawThemeBackground (theme, hdc, 
00477             (infoPtr->dwStyle & TBS_VERT) ?
00478                 TKP_TRACKVERT : TKP_TRACK, TKS_NORMAL, &rcChannel, 0);
00479     }
00480     else
00481     {
00482         DrawEdge (hdc, &rcChannel, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
00483         if (infoPtr->dwStyle & TBS_ENABLESELRANGE) {         /* fill the channel */
00484             FillRect (hdc, &rcChannel, GetStockObject(WHITE_BRUSH));
00485             if (TRACKBAR_HasSelection(infoPtr))
00486                 FillRect (hdc, &infoPtr->rcSelection, GetSysColorBrush(COLOR_HIGHLIGHT));
00487         }
00488     }
00489 }
00490 
00491 static void
00492 TRACKBAR_DrawOneTic (const TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, int flags)
00493 {
00494     int x, y, ox, oy, range, side, indent = 0, len = 3;
00495     int offsetthumb;
00496     RECT rcTics;
00497 
00498     if (flags & TBS_VERT) {
00499         offsetthumb = (infoPtr->rcThumb.bottom - infoPtr->rcThumb.top)/2;
00500     rcTics.left = infoPtr->rcThumb.left - 2;
00501     rcTics.right = infoPtr->rcThumb.right + 2;
00502     rcTics.top    = infoPtr->rcChannel.top + offsetthumb + 1;
00503     rcTics.bottom = infoPtr->rcChannel.bottom - offsetthumb;
00504     } else {
00505         offsetthumb = (infoPtr->rcThumb.right - infoPtr->rcThumb.left)/2;
00506     rcTics.left   = infoPtr->rcChannel.left + offsetthumb + 1;
00507     rcTics.right  = infoPtr->rcChannel.right - offsetthumb;
00508     rcTics.top = infoPtr->rcThumb.top - 2;
00509     rcTics.bottom = infoPtr->rcThumb.bottom + 2;
00510     }
00511 
00512     if (flags & (TBS_TOP | TBS_LEFT)) {
00513     x = rcTics.left;
00514     y = rcTics.top;
00515     side = -1;
00516     } else {
00517     x = rcTics.right;
00518     y = rcTics.bottom;
00519     side = 1;
00520     }
00521 
00522     range = infoPtr->lRangeMax - infoPtr->lRangeMin;
00523     if (range <= 0)
00524       range = 1; /* to avoid division by zero */
00525 
00526     if (flags & TIC_SELECTIONMARK) {
00527     indent = (flags & TIC_SELECTIONMARKMIN) ? -1 : 1;
00528     } else if (flags & TIC_EDGE) {
00529     len++;
00530     }
00531 
00532     if (flags & TBS_VERT) {
00533     int height = rcTics.bottom - rcTics.top;
00534     y = rcTics.top + (height*(ticPos - infoPtr->lRangeMin))/range;
00535     } else {
00536         int width = rcTics.right - rcTics.left;
00537         x = rcTics.left + (width*(ticPos - infoPtr->lRangeMin))/range;
00538     }
00539 
00540     ox = x;
00541     oy = y;
00542     MoveToEx(hdc, x, y, 0);
00543     if (flags & TBS_VERT) x += len * side;
00544     else y += len * side;
00545     LineTo(hdc, x, y);
00546         
00547     if (flags & TIC_SELECTIONMARK) {
00548     if (flags & TBS_VERT) {
00549         x -= side;
00550     } else {
00551         y -= side;
00552     }
00553     MoveToEx(hdc, x, y, 0);
00554     if (flags & TBS_VERT) {
00555         y += 2 * indent;
00556     } else {
00557         x += 2 * indent;
00558     }
00559     
00560     LineTo(hdc, x, y);
00561     LineTo(hdc, ox, oy);
00562     }
00563 }
00564 
00565 
00566 static inline void
00567 TRACKBAR_DrawTic (const TRACKBAR_INFO *infoPtr, HDC hdc, LONG ticPos, int flags)
00568 {
00569     if ((flags & (TBS_LEFT | TBS_TOP)) || (flags & TBS_BOTH))
00570         TRACKBAR_DrawOneTic (infoPtr, hdc, ticPos, flags | TBS_LEFT);
00571 
00572     if (!(flags & (TBS_LEFT | TBS_TOP)) || (flags & TBS_BOTH))
00573         TRACKBAR_DrawOneTic (infoPtr, hdc, ticPos, flags & ~TBS_LEFT);
00574 }
00575 
00576 static void
00577 TRACKBAR_DrawTics (const TRACKBAR_INFO *infoPtr, HDC hdc)
00578 {
00579     unsigned int i;
00580     int ticFlags = infoPtr->dwStyle & 0x0f;
00581     LOGPEN ticPen = { PS_SOLID, {1, 0}, GetSysColor (COLOR_3DDKSHADOW) };
00582     HPEN hOldPen, hTicPen;
00583     HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
00584     
00585     if (theme)
00586     {
00587         int part = (infoPtr->dwStyle & TBS_VERT) ? TKP_TICSVERT : TKP_TICS;
00588         GetThemeColor (theme, part, TSS_NORMAL, TMT_COLOR, &ticPen.lopnColor);
00589     }
00590     /* create the pen to draw the tics with */
00591     hTicPen = CreatePenIndirect(&ticPen);
00592     hOldPen = hTicPen ? SelectObject(hdc, hTicPen) : 0;
00593 
00594     /* actually draw the tics */
00595     for (i=0; i<infoPtr->uNumTics; i++)
00596         TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->tics[i], ticFlags);
00597 
00598     TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lRangeMin, ticFlags | TIC_EDGE);
00599     TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lRangeMax, ticFlags | TIC_EDGE);
00600 
00601     if ((infoPtr->dwStyle & TBS_ENABLESELRANGE) && TRACKBAR_HasSelection(infoPtr)) {
00602         TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lSelMin,
00603                           ticFlags | TIC_SELECTIONMARKMIN);
00604         TRACKBAR_DrawTic (infoPtr, hdc, infoPtr->lSelMax,
00605                           ticFlags | TIC_SELECTIONMARKMAX);
00606     }
00607     
00608     /* clean up the pen, if we created one */
00609     if (hTicPen) {
00610     SelectObject(hdc, hOldPen);
00611     DeleteObject(hTicPen);
00612     }
00613 }
00614 
00615 static void
00616 TRACKBAR_DrawThumb (const TRACKBAR_INFO *infoPtr, HDC hdc)
00617 {
00618     HBRUSH oldbr;
00619     HPEN  oldpen;
00620     RECT thumb = infoPtr->rcThumb;
00621     int BlackUntil = 3;
00622     int PointCount = 6;
00623     POINT points[6];
00624     int fillClr;
00625     int PointDepth;
00626     HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
00627     
00628     if (theme)
00629     {
00630         int partId;
00631         int stateId;
00632         if (infoPtr->dwStyle & TBS_BOTH)
00633             partId = (infoPtr->dwStyle & TBS_VERT) ? TKP_THUMBVERT : TKP_THUMB;
00634         else if (infoPtr->dwStyle & TBS_LEFT)
00635             partId = (infoPtr->dwStyle & TBS_VERT) ? TKP_THUMBLEFT : TKP_THUMBTOP;
00636         else
00637             partId = (infoPtr->dwStyle & TBS_VERT) ? TKP_THUMBRIGHT : TKP_THUMBBOTTOM;
00638             
00639         if (infoPtr->dwStyle & WS_DISABLED)
00640             stateId = TUS_DISABLED;
00641         else if (infoPtr->flags & TB_DRAG_MODE)
00642             stateId = TUS_PRESSED;
00643         else if (infoPtr->flags & TB_THUMB_HOT)
00644             stateId = TUS_HOT;
00645         else
00646             stateId = TUS_NORMAL;
00647         
00648         DrawThemeBackground (theme, hdc, partId, stateId, &thumb, 0);
00649         
00650         return;
00651     }
00652 
00653     fillClr = infoPtr->flags & TB_DRAG_MODE ? COLOR_BTNHILIGHT : COLOR_BTNFACE;
00654     oldbr = SelectObject (hdc, GetSysColorBrush(fillClr));
00655     SetPolyFillMode (hdc, WINDING);
00656 
00657     if (infoPtr->dwStyle & TBS_BOTH)
00658     {
00659        points[0].x=thumb.right;
00660        points[0].y=thumb.top;
00661        points[1].x=thumb.right;
00662        points[1].y=thumb.bottom;
00663        points[2].x=thumb.left;
00664        points[2].y=thumb.bottom;
00665        points[3].x=thumb.left;
00666        points[3].y=thumb.top;
00667        points[4].x=points[0].x;
00668        points[4].y=points[0].y;
00669        PointCount = 5;
00670        BlackUntil = 3;
00671     }
00672     else
00673     {
00674         if (infoPtr->dwStyle & TBS_VERT)
00675         {
00676           PointDepth = (thumb.bottom - thumb.top) / 2;
00677           if (infoPtr->dwStyle & TBS_LEFT)
00678           {
00679             points[0].x=thumb.right;
00680             points[0].y=thumb.top;
00681             points[1].x=thumb.right;
00682             points[1].y=thumb.bottom;
00683             points[2].x=thumb.left + PointDepth;
00684             points[2].y=thumb.bottom;
00685             points[3].x=thumb.left;
00686             points[3].y=(thumb.bottom - thumb.top) / 2 + thumb.top + 1;
00687             points[4].x=thumb.left + PointDepth;
00688             points[4].y=thumb.top;
00689             points[5].x=points[0].x;
00690             points[5].y=points[0].y;
00691             BlackUntil = 4;
00692           }
00693           else
00694           {
00695             points[0].x=thumb.right;
00696             points[0].y=(thumb.bottom - thumb.top) / 2 + thumb.top + 1;
00697             points[1].x=thumb.right - PointDepth;
00698             points[1].y=thumb.bottom;
00699             points[2].x=thumb.left;
00700             points[2].y=thumb.bottom;
00701             points[3].x=thumb.left;
00702             points[3].y=thumb.top;
00703             points[4].x=thumb.right - PointDepth;
00704             points[4].y=thumb.top;
00705             points[5].x=points[0].x;
00706             points[5].y=points[0].y;
00707           }
00708         }
00709         else
00710         {
00711           PointDepth = (thumb.right - thumb.left) / 2;
00712           if (infoPtr->dwStyle & TBS_TOP)
00713           {
00714             points[0].x=(thumb.right - thumb.left) / 2 + thumb.left + 1;
00715             points[0].y=thumb.top;
00716             points[1].x=thumb.right;
00717             points[1].y=thumb.top + PointDepth;
00718             points[2].x=thumb.right;
00719             points[2].y=thumb.bottom;
00720             points[3].x=thumb.left;
00721             points[3].y=thumb.bottom;
00722             points[4].x=thumb.left;
00723             points[4].y=thumb.top + PointDepth;
00724             points[5].x=points[0].x;
00725             points[5].y=points[0].y;
00726             BlackUntil = 4;
00727           }
00728           else
00729           {
00730             points[0].x=thumb.right;
00731             points[0].y=thumb.top;
00732             points[1].x=thumb.right;
00733             points[1].y=thumb.bottom - PointDepth;
00734             points[2].x=(thumb.right - thumb.left) / 2 + thumb.left + 1;
00735             points[2].y=thumb.bottom;
00736             points[3].x=thumb.left;
00737             points[3].y=thumb.bottom - PointDepth;
00738             points[4].x=thumb.left;
00739             points[4].y=thumb.top;
00740             points[5].x=points[0].x;
00741             points[5].y=points[0].y;
00742           }
00743         }
00744 
00745     }
00746 
00747     /* Draw the thumb now */
00748     Polygon (hdc, points, PointCount);
00749     oldpen = SelectObject(hdc, GetStockObject(BLACK_PEN));
00750     Polyline(hdc,points, BlackUntil);
00751     SelectObject(hdc, GetStockObject(WHITE_PEN));
00752     Polyline(hdc, &points[BlackUntil-1], PointCount+1-BlackUntil);
00753     SelectObject(hdc, oldpen);
00754     SelectObject(hdc, oldbr);
00755 }
00756 
00757 
00758 static inline void
00759 TRACKBAR_ActivateToolTip (const TRACKBAR_INFO *infoPtr, BOOL fShow)
00760 {
00761     TTTOOLINFOW ti;
00762 
00763     if (!infoPtr->hwndToolTip) return;
00764 
00765     ZeroMemory(&ti, sizeof(ti));
00766     ti.cbSize = sizeof(ti);
00767     ti.hwnd   = infoPtr->hwndSelf;
00768 
00769     SendMessageW (infoPtr->hwndToolTip, TTM_TRACKACTIVATE, fShow, (LPARAM)&ti);
00770 }
00771 
00772 
00773 static void
00774 TRACKBAR_UpdateToolTip (const TRACKBAR_INFO *infoPtr)
00775 {
00776     WCHAR buf[80];
00777     static const WCHAR fmt[] = { '%', 'l', 'd', 0 };
00778     TTTOOLINFOW ti;
00779     POINT pt;
00780     RECT rcClient;
00781     LRESULT size;
00782 
00783     if (!infoPtr->hwndToolTip) return;
00784 
00785     ZeroMemory(&ti, sizeof(ti));
00786     ti.cbSize = sizeof(ti);
00787     ti.hwnd   = infoPtr->hwndSelf;
00788     ti.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
00789 
00790     wsprintfW (buf, fmt, infoPtr->lPos);
00791     ti.lpszText = buf;
00792     SendMessageW (infoPtr->hwndToolTip, TTM_UPDATETIPTEXTW, 0, (LPARAM)&ti);
00793 
00794     GetClientRect (infoPtr->hwndSelf, &rcClient);
00795     size = SendMessageW (infoPtr->hwndToolTip, TTM_GETBUBBLESIZE, 0, (LPARAM)&ti);
00796     if (infoPtr->dwStyle & TBS_VERT) {
00797     if (infoPtr->fLocation == TBTS_LEFT)
00798         pt.x = 0 - LOWORD(size) - TOOLTIP_OFFSET;
00799     else
00800         pt.x = rcClient.right + TOOLTIP_OFFSET;
00801         pt.y = (infoPtr->rcThumb.top + infoPtr->rcThumb.bottom - HIWORD(size))/2;
00802     } else {
00803     if (infoPtr->fLocation == TBTS_TOP)
00804         pt.y = 0 - HIWORD(size) - TOOLTIP_OFFSET;
00805     else
00806             pt.y = rcClient.bottom + TOOLTIP_OFFSET;
00807         pt.x = (infoPtr->rcThumb.left + infoPtr->rcThumb.right - LOWORD(size))/2;
00808     }
00809     ClientToScreen(infoPtr->hwndSelf, &pt);
00810 
00811     SendMessageW (infoPtr->hwndToolTip, TTM_TRACKPOSITION,
00812                   0, MAKELPARAM(pt.x, pt.y));
00813 }
00814 
00815 
00816 static void
00817 TRACKBAR_Refresh (TRACKBAR_INFO *infoPtr, HDC hdcDst)
00818 {
00819     RECT rcClient;
00820     HDC hdc;
00821     HBITMAP hOldBmp = 0, hOffScreenBmp = 0;
00822     NMCUSTOMDRAW nmcd;
00823     int gcdrf, icdrf;
00824 
00825     if (infoPtr->flags & TB_THUMBCHANGED) {
00826         TRACKBAR_UpdateThumb (infoPtr);
00827         if (infoPtr->flags & TB_THUMBSIZECHANGED)
00828             TRACKBAR_CalcChannel (infoPtr);
00829     }
00830     if (infoPtr->flags & TB_SELECTIONCHANGED)
00831         TRACKBAR_CalcSelection (infoPtr);
00832 
00833     if (infoPtr->flags & TB_DRAG_MODE)
00834         TRACKBAR_UpdateToolTip (infoPtr);
00835 
00836     infoPtr->flags &= ~ (TB_THUMBCHANGED | TB_SELECTIONCHANGED);
00837 
00838     GetClientRect (infoPtr->hwndSelf, &rcClient);
00839     
00840     /* try to render offscreen, if we fail, carrry onscreen */
00841     hdc = CreateCompatibleDC(hdcDst);
00842     if (hdc) {
00843         hOffScreenBmp = CreateCompatibleBitmap(hdcDst, rcClient.right, rcClient.bottom);
00844         if (hOffScreenBmp) {
00845         hOldBmp = SelectObject(hdc, hOffScreenBmp);
00846     } else {
00847         DeleteObject(hdc);
00848         hdc = hdcDst;
00849     }
00850     } else {
00851     hdc = hdcDst;
00852     }
00853 
00854     ZeroMemory(&nmcd, sizeof(nmcd));
00855     nmcd.hdr.hwndFrom = infoPtr->hwndSelf;
00856     nmcd.hdr.idFrom = GetWindowLongPtrW (infoPtr->hwndSelf, GWLP_ID);
00857     nmcd.hdr.code = NM_CUSTOMDRAW;
00858     nmcd.hdc = hdc;
00859 
00860     /* start the paint cycle */
00861     nmcd.rc = rcClient;
00862     gcdrf = notify_customdraw(infoPtr, &nmcd, CDDS_PREPAINT);
00863     if (gcdrf & CDRF_SKIPDEFAULT) goto cleanup;
00864     
00865     /* Erase background */
00866     if (gcdrf == CDRF_DODEFAULT ||
00867         notify_customdraw(infoPtr, &nmcd, CDDS_PREERASE) != CDRF_SKIPDEFAULT) {
00868         if (GetWindowTheme (infoPtr->hwndSelf)) {
00869             DrawThemeParentBackground (infoPtr->hwndSelf, hdc, 0);
00870         }
00871         else
00872         FillRect (hdc, &rcClient, GetSysColorBrush(COLOR_BTNFACE));
00873         if (gcdrf != CDRF_DODEFAULT)
00874         notify_customdraw(infoPtr, &nmcd, CDDS_POSTERASE);
00875     }
00876     
00877     /* draw channel */
00878     if (gcdrf & CDRF_NOTIFYITEMDRAW) {
00879         nmcd.dwItemSpec = TBCD_CHANNEL;
00880     nmcd.uItemState = CDIS_DEFAULT;
00881     nmcd.rc = infoPtr->rcChannel;
00882     icdrf = notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPREPAINT);
00883     } else icdrf = CDRF_DODEFAULT;
00884     if ( !(icdrf & CDRF_SKIPDEFAULT) ) {
00885     TRACKBAR_DrawChannel (infoPtr, hdc);
00886     if (icdrf & CDRF_NOTIFYPOSTPAINT)
00887         notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPOSTPAINT);
00888     }
00889 
00890 
00891     /* draw tics */
00892     if (!(infoPtr->dwStyle & TBS_NOTICKS)) {
00893         if (gcdrf & CDRF_NOTIFYITEMDRAW) {
00894             nmcd.dwItemSpec = TBCD_TICS;
00895         nmcd.uItemState = CDIS_DEFAULT;
00896         nmcd.rc = rcClient;
00897         icdrf = notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPREPAINT);
00898         } else icdrf = CDRF_DODEFAULT;
00899     if ( !(icdrf & CDRF_SKIPDEFAULT) ) {
00900         TRACKBAR_DrawTics (infoPtr, hdc);
00901         if (icdrf & CDRF_NOTIFYPOSTPAINT)
00902         notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPOSTPAINT);
00903     }
00904     }
00905     
00906     /* draw thumb */
00907     if (!(infoPtr->dwStyle & TBS_NOTHUMB)) {
00908     if (gcdrf & CDRF_NOTIFYITEMDRAW) {
00909         nmcd.dwItemSpec = TBCD_THUMB;
00910         nmcd.uItemState = infoPtr->flags & TB_DRAG_MODE ? CDIS_HOT : CDIS_DEFAULT;
00911         nmcd.rc = infoPtr->rcThumb;
00912         icdrf = notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPREPAINT);
00913     } else icdrf = CDRF_DODEFAULT;
00914     if ( !(icdrf & CDRF_SKIPDEFAULT) ) {
00915             TRACKBAR_DrawThumb(infoPtr, hdc);
00916         if (icdrf & CDRF_NOTIFYPOSTPAINT)
00917         notify_customdraw(infoPtr, &nmcd, CDDS_ITEMPOSTPAINT);
00918     }
00919     }
00920 
00921     /* draw focus rectangle */
00922     if (infoPtr->bFocussed) {
00923     DrawFocusRect(hdc, &rcClient);
00924     }
00925 
00926     /* finish up the painting */
00927     if (gcdrf & CDRF_NOTIFYPOSTPAINT)
00928     notify_customdraw(infoPtr, &nmcd, CDDS_POSTPAINT);
00929     
00930 cleanup:
00931     /* cleanup, if we rendered offscreen */
00932     if (hdc != hdcDst) {
00933     BitBlt(hdcDst, 0, 0, rcClient.right, rcClient.bottom, hdc, 0, 0, SRCCOPY);
00934     SelectObject(hdc, hOldBmp);
00935     DeleteObject(hOffScreenBmp);
00936     DeleteObject(hdc);
00937     }
00938 }
00939 
00940 
00941 static void
00942 TRACKBAR_AlignBuddies (const TRACKBAR_INFO *infoPtr)
00943 {
00944     HWND hwndParent = GetParent (infoPtr->hwndSelf);
00945     RECT rcSelf, rcBuddy;
00946     INT x, y;
00947 
00948     GetWindowRect (infoPtr->hwndSelf, &rcSelf);
00949     MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcSelf, 2);
00950 
00951     /* align buddy left or above */
00952     if (infoPtr->hwndBuddyLA) {
00953     GetWindowRect (infoPtr->hwndBuddyLA, &rcBuddy);
00954     MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcBuddy, 2);
00955 
00956     if (infoPtr->dwStyle & TBS_VERT) {
00957         x = (infoPtr->rcChannel.right + infoPtr->rcChannel.left) / 2 -
00958         (rcBuddy.right - rcBuddy.left) / 2 + rcSelf.left;
00959         y = rcSelf.top - (rcBuddy.bottom - rcBuddy.top);
00960     }
00961     else {
00962         x = rcSelf.left - (rcBuddy.right - rcBuddy.left);
00963         y = (infoPtr->rcChannel.bottom + infoPtr->rcChannel.top) / 2 -
00964         (rcBuddy.bottom - rcBuddy.top) / 2 + rcSelf.top;
00965     }
00966 
00967     SetWindowPos (infoPtr->hwndBuddyLA, 0, x, y, 0, 0,
00968                       SWP_NOZORDER | SWP_NOSIZE);
00969     }
00970 
00971 
00972     /* align buddy right or below */
00973     if (infoPtr->hwndBuddyRB) {
00974     GetWindowRect (infoPtr->hwndBuddyRB, &rcBuddy);
00975     MapWindowPoints (HWND_DESKTOP, hwndParent, (LPPOINT)&rcBuddy, 2);
00976 
00977     if (infoPtr->dwStyle & TBS_VERT) {
00978         x = (infoPtr->rcChannel.right + infoPtr->rcChannel.left) / 2 -
00979         (rcBuddy.right - rcBuddy.left) / 2 + rcSelf.left;
00980         y = rcSelf.bottom;
00981     }
00982     else {
00983         x = rcSelf.right;
00984         y = (infoPtr->rcChannel.bottom + infoPtr->rcChannel.top) / 2 -
00985         (rcBuddy.bottom - rcBuddy.top) / 2 + rcSelf.top;
00986     }
00987     SetWindowPos (infoPtr->hwndBuddyRB, 0, x, y, 0, 0,
00988                       SWP_NOZORDER | SWP_NOSIZE);
00989     }
00990 }
00991 
00992 
00993 static LRESULT
00994 TRACKBAR_ClearSel (TRACKBAR_INFO *infoPtr, BOOL fRedraw)
00995 {
00996     infoPtr->lSelMin = 0;
00997     infoPtr->lSelMax = 0;
00998     infoPtr->flags |= TB_SELECTIONCHANGED;
00999 
01000     if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
01001 
01002     return 0;
01003 }
01004 
01005 
01006 static LRESULT
01007 TRACKBAR_ClearTics (TRACKBAR_INFO *infoPtr, BOOL fRedraw)
01008 {
01009     if (infoPtr->tics) {
01010         Free (infoPtr->tics);
01011         infoPtr->tics = NULL;
01012         infoPtr->uNumTics = 0;
01013     }
01014 
01015     if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
01016 
01017     return 0;
01018 }
01019 
01020 
01021 static inline LRESULT
01022 TRACKBAR_GetChannelRect (const TRACKBAR_INFO *infoPtr, LPRECT lprc)
01023 {
01024     if (lprc == NULL) return 0;
01025 
01026     lprc->left   = infoPtr->rcChannel.left;
01027     lprc->right  = infoPtr->rcChannel.right;
01028     lprc->bottom = infoPtr->rcChannel.bottom;
01029     lprc->top    = infoPtr->rcChannel.top;
01030 
01031     return 0;
01032 }
01033 
01034 
01035 static inline LONG
01036 TRACKBAR_GetNumTics (const TRACKBAR_INFO *infoPtr)
01037 {
01038     if (infoPtr->dwStyle & TBS_NOTICKS) return 0;
01039 
01040     return infoPtr->uNumTics + 2;
01041 }
01042 
01043 
01044 static int comp_tics (const void *ap, const void *bp)
01045 {
01046     const DWORD a = *(const DWORD *)ap;
01047     const DWORD b = *(const DWORD *)bp;
01048 
01049     TRACE("(a=%d, b=%d)\n", a, b);
01050     if (a < b) return -1;
01051     if (a > b) return 1;
01052     return 0;
01053 }
01054 
01055 
01056 static inline LONG
01057 TRACKBAR_GetTic (const TRACKBAR_INFO *infoPtr, INT iTic)
01058 {
01059     if ((iTic < 0) || (iTic >= infoPtr->uNumTics) || !infoPtr->tics)
01060     return -1;
01061 
01062     qsort(infoPtr->tics, infoPtr->uNumTics, sizeof(DWORD), comp_tics);
01063     return infoPtr->tics[iTic];
01064 }
01065 
01066 
01067 static inline LONG
01068 TRACKBAR_GetTicPos (const TRACKBAR_INFO *infoPtr, INT iTic)
01069 {
01070     LONG range, width, pos, tic;
01071     int offsetthumb;
01072 
01073     if ((iTic < 0) || (iTic >= infoPtr->uNumTics) || !infoPtr->tics)
01074     return -1;
01075 
01076     tic   = TRACKBAR_GetTic (infoPtr, iTic);
01077     range = infoPtr->lRangeMax - infoPtr->lRangeMin;
01078     if (range <= 0) range = 1;
01079     offsetthumb = (infoPtr->rcThumb.right - infoPtr->rcThumb.left)/2;
01080     width = infoPtr->rcChannel.right - infoPtr->rcChannel.left - offsetthumb*2;
01081     pos   = infoPtr->rcChannel.left + offsetthumb + (width * tic) / range;
01082 
01083     return pos;
01084 }
01085 
01086 
01087 static HWND
01088 TRACKBAR_SetBuddy (TRACKBAR_INFO *infoPtr, BOOL fLocation, HWND hwndBuddy)
01089 {
01090     HWND hwndTemp;
01091 
01092     if (fLocation) {
01093     /* buddy is left or above */
01094     hwndTemp = infoPtr->hwndBuddyLA;
01095     infoPtr->hwndBuddyLA = hwndBuddy;
01096     }
01097     else {
01098         /* buddy is right or below */
01099         hwndTemp = infoPtr->hwndBuddyRB;
01100         infoPtr->hwndBuddyRB = hwndBuddy;
01101     }
01102 
01103     TRACKBAR_AlignBuddies (infoPtr);
01104 
01105     return hwndTemp;
01106 }
01107 
01108 
01109 static inline LONG
01110 TRACKBAR_SetLineSize (TRACKBAR_INFO *infoPtr, LONG lLineSize)
01111 {
01112     LONG lTemp = infoPtr->lLineSize;
01113 
01114     infoPtr->lLineSize = lLineSize;
01115 
01116     return lTemp;
01117 }
01118 
01119 
01120 static inline LONG
01121 TRACKBAR_SetPageSize (TRACKBAR_INFO *infoPtr, LONG lPageSize)
01122 {
01123     LONG lTemp = infoPtr->lPageSize;
01124 
01125     if (lPageSize != -1)
01126         infoPtr->lPageSize = lPageSize;
01127     else
01128         infoPtr->lPageSize = TB_DEFAULTPAGESIZE;
01129 
01130     return lTemp;
01131 }
01132 
01133 
01134 static inline LRESULT
01135 TRACKBAR_SetPos (TRACKBAR_INFO *infoPtr, BOOL fPosition, LONG lPosition)
01136 {
01137     LONG oldPos = infoPtr->lPos;
01138     infoPtr->lPos = lPosition;
01139 
01140     if (infoPtr->lPos < infoPtr->lRangeMin)
01141     infoPtr->lPos = infoPtr->lRangeMin;
01142 
01143     if (infoPtr->lPos > infoPtr->lRangeMax)
01144     infoPtr->lPos = infoPtr->lRangeMax;
01145     infoPtr->flags |= TB_THUMBPOSCHANGED;
01146 
01147     if (fPosition && oldPos != lPosition) TRACKBAR_InvalidateThumbMove(infoPtr, oldPos, lPosition);
01148 
01149     return 0;
01150 }
01151 
01152 
01153 static inline LRESULT
01154 TRACKBAR_SetRange (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lRange)
01155 {
01156     infoPtr->lRangeMin = (SHORT)LOWORD(lRange);
01157     infoPtr->lRangeMax = (SHORT)HIWORD(lRange);
01158 
01159     if (infoPtr->lPos < infoPtr->lRangeMin) {
01160         infoPtr->lPos = infoPtr->lRangeMin;
01161         infoPtr->flags |= TB_THUMBPOSCHANGED;
01162     }
01163 
01164     if (infoPtr->lPos > infoPtr->lRangeMax) {
01165         infoPtr->lPos = infoPtr->lRangeMax;
01166         infoPtr->flags |= TB_THUMBPOSCHANGED;
01167     }
01168 
01169     infoPtr->lPageSize = (infoPtr->lRangeMax - infoPtr->lRangeMin) / 5;
01170     if (infoPtr->lPageSize == 0) infoPtr->lPageSize = 1;
01171 
01172     if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
01173 
01174     return 0;
01175 }
01176 
01177 
01178 static inline LRESULT
01179 TRACKBAR_SetRangeMax (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lMax)
01180 {
01181     infoPtr->lRangeMax = lMax;
01182     if (infoPtr->lPos > infoPtr->lRangeMax) {
01183         infoPtr->lPos = infoPtr->lRangeMax;
01184         infoPtr->flags |= TB_THUMBPOSCHANGED;
01185     }
01186 
01187     infoPtr->lPageSize = (infoPtr->lRangeMax - infoPtr->lRangeMin) / 5;
01188     if (infoPtr->lPageSize == 0) infoPtr->lPageSize = 1;
01189 
01190     if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
01191 
01192     return 0;
01193 }
01194 
01195 
01196 static inline LRESULT
01197 TRACKBAR_SetRangeMin (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lMin)
01198 {
01199     infoPtr->lRangeMin = lMin;
01200     if (infoPtr->lPos < infoPtr->lRangeMin) {
01201         infoPtr->lPos = infoPtr->lRangeMin;
01202         infoPtr->flags |= TB_THUMBPOSCHANGED;
01203     }
01204 
01205     infoPtr->lPageSize = (infoPtr->lRangeMax - infoPtr->lRangeMin) / 5;
01206     if (infoPtr->lPageSize == 0) infoPtr->lPageSize = 1;
01207 
01208     if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
01209 
01210     return 0;
01211 }
01212 
01213 
01214 static inline LRESULT
01215 TRACKBAR_SetSel (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lSel)
01216 {
01217     if (!(infoPtr->dwStyle & TBS_ENABLESELRANGE)){
01218         infoPtr->lSelMin = 0;
01219         infoPtr->lSelMax = 0;
01220         return 0;
01221     }
01222 
01223     infoPtr->lSelMin = (SHORT)LOWORD(lSel);
01224     infoPtr->lSelMax = (SHORT)HIWORD(lSel);
01225     infoPtr->flags |= TB_SELECTIONCHANGED;
01226 
01227     if (infoPtr->lSelMin < infoPtr->lRangeMin)
01228         infoPtr->lSelMin = infoPtr->lRangeMin;
01229     if (infoPtr->lSelMax > infoPtr->lRangeMax)
01230         infoPtr->lSelMax = infoPtr->lRangeMax;
01231 
01232     if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
01233 
01234     return 0;
01235 }
01236 
01237 
01238 static inline LRESULT
01239 TRACKBAR_SetSelEnd (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lEnd)
01240 {
01241     if (!(infoPtr->dwStyle & TBS_ENABLESELRANGE)){
01242         infoPtr->lSelMax = 0;
01243     return 0;
01244     }
01245 
01246     infoPtr->lSelMax = lEnd;
01247     infoPtr->flags |= TB_SELECTIONCHANGED;
01248 
01249     if (infoPtr->lSelMax > infoPtr->lRangeMax)
01250         infoPtr->lSelMax = infoPtr->lRangeMax;
01251 
01252     if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
01253 
01254     return 0;
01255 }
01256 
01257 
01258 static inline LRESULT
01259 TRACKBAR_SetSelStart (TRACKBAR_INFO *infoPtr, BOOL fRedraw, LONG lStart)
01260 {
01261     if (!(infoPtr->dwStyle & TBS_ENABLESELRANGE)){
01262         infoPtr->lSelMin = 0;
01263     return 0;
01264     }
01265 
01266     infoPtr->lSelMin = lStart;
01267     infoPtr->flags  |=TB_SELECTIONCHANGED;
01268 
01269     if (infoPtr->lSelMin < infoPtr->lRangeMin)
01270         infoPtr->lSelMin = infoPtr->lRangeMin;
01271 
01272     if (fRedraw) TRACKBAR_InvalidateAll(infoPtr);
01273 
01274     return 0;
01275 }
01276 
01277 
01278 static inline LRESULT
01279 TRACKBAR_SetThumbLength (TRACKBAR_INFO *infoPtr, UINT iLength)
01280 {
01281     if (infoPtr->dwStyle & TBS_FIXEDLENGTH) {
01282         infoPtr->uThumbLen = iLength;
01283     infoPtr->flags |= TB_THUMBSIZECHANGED;
01284     InvalidateRect (infoPtr->hwndSelf, &infoPtr->rcThumb, FALSE);
01285     }
01286 
01287     return 0;
01288 }
01289 
01290 
01291 static inline LRESULT
01292 TRACKBAR_SetTic (TRACKBAR_INFO *infoPtr, LONG lPos)
01293 {
01294     if ((lPos < infoPtr->lRangeMin) || (lPos> infoPtr->lRangeMax))
01295         return FALSE;
01296 
01297     TRACE("lPos=%d\n", lPos);
01298 
01299     infoPtr->uNumTics++;
01300     infoPtr->tics=ReAlloc( infoPtr->tics,
01301                                     (infoPtr->uNumTics)*sizeof (DWORD));
01302     if (!infoPtr->tics) {
01303     infoPtr->uNumTics = 0;
01304     notify(infoPtr, NM_OUTOFMEMORY);
01305     return FALSE;
01306     }
01307     infoPtr->tics[infoPtr->uNumTics-1] = lPos;
01308 
01309     TRACKBAR_InvalidateAll(infoPtr);
01310 
01311     return TRUE;
01312 }
01313 
01314 
01315 static inline LRESULT
01316 TRACKBAR_SetTicFreq (TRACKBAR_INFO *infoPtr, WORD wFreq)
01317 {
01318     if (infoPtr->dwStyle & TBS_AUTOTICKS) {
01319         infoPtr->uTicFreq = wFreq;
01320     TRACKBAR_RecalculateTics (infoPtr);
01321     TRACKBAR_InvalidateAll(infoPtr);
01322     }
01323 
01324     return 0;
01325 }
01326 
01327 
01328 static inline INT
01329 TRACKBAR_SetTipSide (TRACKBAR_INFO *infoPtr, INT fLocation)
01330 {
01331     INT fTemp = infoPtr->fLocation;
01332 
01333     infoPtr->fLocation = fLocation;
01334 
01335     return fTemp;
01336 }
01337 
01338 
01339 static inline LRESULT
01340 TRACKBAR_SetToolTips (TRACKBAR_INFO *infoPtr, HWND hwndTT)
01341 {
01342     infoPtr->hwndToolTip = hwndTT;
01343 
01344     return 0;
01345 }
01346 
01347 
01348 static inline BOOL
01349 TRACKBAR_SetUnicodeFormat (TRACKBAR_INFO *infoPtr, BOOL fUnicode)
01350 {
01351     BOOL bTemp = infoPtr->bUnicode;
01352 
01353     infoPtr->bUnicode = fUnicode;
01354 
01355     return bTemp;
01356 }
01357 
01358 
01359 static LRESULT
01360 TRACKBAR_InitializeThumb (TRACKBAR_INFO *infoPtr)
01361 {
01362     RECT rect;
01363     int clientWidth, clientMetric;
01364 
01365     /* initial thumb length */
01366     clientMetric = (infoPtr->dwStyle & TBS_ENABLESELRANGE) ? 23 : 21;
01367     GetClientRect(infoPtr->hwndSelf,&rect);
01368     if (infoPtr->dwStyle & TBS_VERT) {
01369     clientWidth = rect.right - rect.left;
01370     } else {
01371     clientWidth = rect.bottom - rect.top;
01372     }
01373     if (clientWidth >= clientMetric)
01374         infoPtr->uThumbLen = clientMetric;
01375     else
01376         infoPtr->uThumbLen = clientWidth > 9 ? clientWidth - 6 : 4;
01377 
01378     TRACKBAR_CalcChannel (infoPtr);
01379     TRACKBAR_UpdateThumb (infoPtr);
01380     infoPtr->flags &= ~TB_SELECTIONCHANGED;
01381 
01382     return 0;
01383 }
01384 
01385 
01386 static LRESULT
01387 TRACKBAR_Create (HWND hwnd, const CREATESTRUCTW *lpcs)
01388 {
01389     TRACKBAR_INFO *infoPtr;
01390 
01391     infoPtr = Alloc (sizeof(TRACKBAR_INFO));
01392     if (!infoPtr) return -1;
01393     SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
01394 
01395     /* set default values */
01396     infoPtr->hwndSelf  = hwnd;
01397     infoPtr->dwStyle   = lpcs->style;
01398     infoPtr->lRangeMin = 0;
01399     infoPtr->lRangeMax = 100;
01400     infoPtr->lLineSize = 1;
01401     infoPtr->lPageSize = TB_DEFAULTPAGESIZE;
01402     infoPtr->lSelMin   = 0;
01403     infoPtr->lSelMax   = 0;
01404     infoPtr->lPos      = 0;
01405     infoPtr->fLocation = TBTS_TOP;
01406     infoPtr->uNumTics  = 0;    /* start and end tic are not included in count*/
01407     infoPtr->uTicFreq  = 1;
01408     infoPtr->tics      = NULL;
01409     infoPtr->hwndNotify= lpcs->hwndParent;
01410 
01411     TRACKBAR_InitializeThumb (infoPtr);
01412 
01413     /* Create tooltip control */
01414     if (infoPtr->dwStyle & TBS_TOOLTIPS) {
01415 
01416         infoPtr->hwndToolTip =
01417             CreateWindowExW (0, TOOLTIPS_CLASSW, NULL, WS_POPUP,
01418                              CW_USEDEFAULT, CW_USEDEFAULT,
01419                              CW_USEDEFAULT, CW_USEDEFAULT,
01420                              hwnd, 0, 0, 0);
01421 
01422         if (infoPtr->hwndToolTip) {
01423             TTTOOLINFOW ti;     
01424             ZeroMemory (&ti, sizeof(ti));
01425             ti.cbSize   = sizeof(ti);
01426             ti.uFlags   = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
01427         ti.hwnd     = hwnd;
01428 
01429             SendMessageW (infoPtr->hwndToolTip, TTM_ADDTOOLW, 0, (LPARAM)&ti);
01430      }
01431     }
01432     
01433     OpenThemeData (hwnd, themeClass);
01434 
01435     return 0;
01436 }
01437 
01438 
01439 static LRESULT
01440 TRACKBAR_Destroy (TRACKBAR_INFO *infoPtr)
01441 {
01442     /* delete tooltip control */
01443     if (infoPtr->hwndToolTip)
01444         DestroyWindow (infoPtr->hwndToolTip);
01445 
01446     Free (infoPtr->tics);
01447     infoPtr->tics = NULL;
01448 
01449     SetWindowLongPtrW (infoPtr->hwndSelf, 0, 0);
01450     CloseThemeData (GetWindowTheme (infoPtr->hwndSelf));
01451     Free (infoPtr);
01452 
01453     return 0;
01454 }
01455 
01456 
01457 static LRESULT
01458 TRACKBAR_KillFocus (TRACKBAR_INFO *infoPtr)
01459 {
01460     TRACE("\n");
01461     infoPtr->bFocussed = FALSE;
01462     TRACKBAR_InvalidateAll(infoPtr);
01463 
01464     return 0;
01465 }
01466 
01467 static LRESULT
01468 TRACKBAR_LButtonDown (TRACKBAR_INFO *infoPtr, INT x, INT y)
01469 {
01470     POINT clickPoint;
01471 
01472     clickPoint.x = x;
01473     clickPoint.y = y;
01474 
01475     SetFocus(infoPtr->hwndSelf);
01476 
01477     if (PtInRect(&infoPtr->rcThumb, clickPoint)) {
01478         infoPtr->flags |= TB_DRAG_MODE;
01479         SetCapture (infoPtr->hwndSelf);
01480     TRACKBAR_UpdateToolTip (infoPtr);
01481     TRACKBAR_ActivateToolTip (infoPtr, TRUE);
01482     TRACKBAR_InvalidateThumb(infoPtr, infoPtr->lPos);
01483     } else {
01484     LONG dir = TRACKBAR_GetAutoPageDirection(infoPtr, clickPoint);
01485     if (dir == 0) return 0;
01486     infoPtr->flags |= (dir < 0) ? TB_AUTO_PAGE_LEFT : TB_AUTO_PAGE_RIGHT;
01487     TRACKBAR_AutoPage (infoPtr, clickPoint);
01488         SetCapture (infoPtr->hwndSelf);
01489         SetTimer(infoPtr->hwndSelf, TB_REFRESH_TIMER, TB_REFRESH_DELAY, 0);
01490     }
01491 
01492     return 0;
01493 }
01494 
01495 
01496 static LRESULT
01497 TRACKBAR_LButtonUp (TRACKBAR_INFO *infoPtr)
01498 {
01499     if (infoPtr->flags & TB_DRAG_MODE) {
01500         notify_with_scroll (infoPtr, TB_THUMBPOSITION | (infoPtr->lPos<<16));
01501         notify_with_scroll (infoPtr, TB_ENDTRACK);
01502         infoPtr->flags &= ~TB_DRAG_MODE;
01503         ReleaseCapture ();
01504     notify(infoPtr, NM_RELEASEDCAPTURE);
01505         TRACKBAR_ActivateToolTip(infoPtr, FALSE);
01506     TRACKBAR_InvalidateThumb(infoPtr, infoPtr->lPos);
01507     }
01508     if (infoPtr->flags & TB_AUTO_PAGE) {
01509     KillTimer (infoPtr->hwndSelf, TB_REFRESH_TIMER);
01510         infoPtr->flags &= ~TB_AUTO_PAGE;
01511         notify_with_scroll (infoPtr, TB_ENDTRACK);
01512         ReleaseCapture ();
01513     notify(infoPtr, NM_RELEASEDCAPTURE);
01514     }
01515 
01516     return 0;
01517 }
01518 
01519 
01520 static LRESULT
01521 TRACKBAR_CaptureChanged (const TRACKBAR_INFO *infoPtr)
01522 {
01523     notify_with_scroll (infoPtr, TB_ENDTRACK);
01524     return 0;
01525 }
01526 
01527 
01528 static LRESULT
01529 TRACKBAR_Paint (TRACKBAR_INFO *infoPtr, HDC hdc)
01530 {
01531     if (hdc) {
01532     TRACKBAR_Refresh(infoPtr, hdc);
01533     } else {
01534     PAINTSTRUCT ps;
01535         hdc = BeginPaint (infoPtr->hwndSelf, &ps);
01536         TRACKBAR_Refresh (infoPtr, hdc);
01537         EndPaint (infoPtr->hwndSelf, &ps);
01538     }
01539 
01540     return 0;
01541 }
01542 
01543 
01544 static LRESULT
01545 TRACKBAR_SetFocus (TRACKBAR_INFO *infoPtr)
01546 {
01547     TRACE("\n");
01548     infoPtr->bFocussed = TRUE;
01549     TRACKBAR_InvalidateAll(infoPtr);
01550 
01551     return 0;
01552 }
01553 
01554 
01555 static LRESULT
01556 TRACKBAR_Size (TRACKBAR_INFO *infoPtr)
01557 {
01558     TRACKBAR_CalcChannel (infoPtr);
01559     TRACKBAR_UpdateThumb (infoPtr);
01560     TRACKBAR_AlignBuddies (infoPtr);
01561 
01562     return 0;
01563 }
01564 
01565 static LRESULT
01566 TRACKBAR_StyleChanged (TRACKBAR_INFO *infoPtr, WPARAM wStyleType,
01567                        const STYLESTRUCT *lpss)
01568 {
01569     if (wStyleType != GWL_STYLE) return 0;
01570 
01571     infoPtr->dwStyle = lpss->styleNew;
01572 
01573     return 0;
01574 }
01575 
01576 static LRESULT
01577 TRACKBAR_Timer (TRACKBAR_INFO *infoPtr)
01578 {
01579     if (infoPtr->flags & TB_AUTO_PAGE) {
01580     POINT pt;
01581     if (GetCursorPos(&pt))
01582         if (ScreenToClient(infoPtr->hwndSelf, &pt))
01583         TRACKBAR_AutoPage(infoPtr, pt);
01584     }
01585     return 0;
01586 }
01587 
01588 
01589 /* update theme after a WM_THEMECHANGED message */
01590 static LRESULT theme_changed (const TRACKBAR_INFO* infoPtr)
01591 {
01592     HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
01593     CloseThemeData (theme);
01594     OpenThemeData (infoPtr->hwndSelf, themeClass);
01595     return 0;
01596 }
01597 
01598 
01599 static LRESULT
01600 TRACKBAR_MouseMove (TRACKBAR_INFO *infoPtr, INT x, INT y)
01601 {
01602     INT clickPlace = (infoPtr->dwStyle & TBS_VERT) ? y : x;
01603     LONG dragPos, oldPos = infoPtr->lPos;
01604 
01605     TRACE("(x=%d. y=%d)\n", x, y);
01606 
01607     if (infoPtr->flags & TB_AUTO_PAGE) {
01608     POINT pt;
01609     pt.x = x;
01610     pt.y = y;
01611     TRACKBAR_AutoPage (infoPtr, pt);
01612     return TRUE;
01613     }
01614 
01615     if (!(infoPtr->flags & TB_DRAG_MODE)) 
01616     {
01617         if (GetWindowTheme (infoPtr->hwndSelf))
01618         {
01619             DWORD oldFlags = infoPtr->flags;
01620             POINT pt;
01621             pt.x = x;
01622             pt.y = y;
01623             if (PtInRect (&infoPtr->rcThumb, pt))
01624             {
01625                 TRACKMOUSEEVENT tme;
01626                 tme.cbSize = sizeof( tme );
01627                 tme.dwFlags = TME_LEAVE;
01628                 tme.hwndTrack = infoPtr->hwndSelf;
01629                 TrackMouseEvent( &tme );
01630                 infoPtr->flags |= TB_THUMB_HOT;
01631             }
01632             else
01633             {
01634                 TRACKMOUSEEVENT tme;
01635                 tme.cbSize = sizeof( tme );
01636                 tme.dwFlags = TME_CANCEL;
01637                 tme.hwndTrack = infoPtr->hwndSelf;
01638                 TrackMouseEvent( &tme );
01639                 infoPtr->flags &= ~TB_THUMB_HOT; 
01640             }
01641             if (oldFlags != infoPtr->flags) InvalidateRect (infoPtr->hwndSelf, &infoPtr->rcThumb, FALSE);
01642         }
01643         return TRUE;
01644     }
01645 
01646     dragPos = TRACKBAR_ConvertPlaceToPosition (infoPtr, clickPlace);
01647 
01648     if (dragPos == oldPos) return TRUE;
01649 
01650     infoPtr->lPos = dragPos;
01651 
01652     infoPtr->flags |= TB_THUMBPOSCHANGED;
01653     notify_with_scroll (infoPtr, TB_THUMBTRACK | (infoPtr->lPos<<16));
01654 
01655 
01656     TRACKBAR_InvalidateThumbMove(infoPtr, oldPos, dragPos);
01657     UpdateWindow (infoPtr->hwndSelf);
01658 
01659     return TRUE;
01660 }
01661 
01662 static BOOL
01663 TRACKBAR_KeyDown (TRACKBAR_INFO *infoPtr, INT nVirtKey)
01664 {
01665     BOOL downIsLeft = infoPtr->dwStyle & TBS_DOWNISLEFT;
01666     BOOL vert = infoPtr->dwStyle & TBS_VERT;
01667     LONG pos = infoPtr->lPos;
01668 
01669     TRACE("%x\n", nVirtKey);
01670 
01671     switch (nVirtKey) {
01672     case VK_UP:
01673     if (!vert && downIsLeft) TRACKBAR_LineDown(infoPtr);
01674         else TRACKBAR_LineUp(infoPtr);
01675         break;
01676     case VK_LEFT:
01677         if (vert && downIsLeft) TRACKBAR_LineDown(infoPtr);
01678         else TRACKBAR_LineUp(infoPtr);
01679         break;
01680     case VK_DOWN:
01681     if (!vert && downIsLeft) TRACKBAR_LineUp(infoPtr);
01682         else TRACKBAR_LineDown(infoPtr);
01683         break;
01684     case VK_RIGHT:
01685     if (vert && downIsLeft) TRACKBAR_LineUp(infoPtr);
01686         else TRACKBAR_LineDown(infoPtr);
01687         break;
01688     case VK_NEXT:
01689     if (!vert && downIsLeft) TRACKBAR_PageUp(infoPtr);
01690         else TRACKBAR_PageDown(infoPtr);
01691         break;
01692     case VK_PRIOR:
01693     if (!vert && downIsLeft) TRACKBAR_PageDown(infoPtr);
01694         else TRACKBAR_PageUp(infoPtr);
01695         break;
01696     case VK_HOME:
01697         if (infoPtr->lPos == infoPtr->lRangeMin) return FALSE;
01698         infoPtr->lPos = infoPtr->lRangeMin;
01699         notify_with_scroll (infoPtr, TB_TOP);
01700         break;
01701     case VK_END:
01702         if (infoPtr->lPos == infoPtr->lRangeMax) return FALSE;
01703         infoPtr->lPos = infoPtr->lRangeMax;
01704         notify_with_scroll (infoPtr, TB_BOTTOM);
01705         break;
01706     }
01707 
01708     if (pos != infoPtr->lPos) {
01709     infoPtr->flags |=TB_THUMBPOSCHANGED;
01710     TRACKBAR_InvalidateThumbMove (infoPtr, pos, infoPtr->lPos);
01711     }
01712 
01713     return TRUE;
01714 }
01715 
01716 
01717 static inline BOOL
01718 TRACKBAR_KeyUp (const TRACKBAR_INFO *infoPtr, INT nVirtKey)
01719 {
01720     switch (nVirtKey) {
01721     case VK_LEFT:
01722     case VK_UP:
01723     case VK_RIGHT:
01724     case VK_DOWN:
01725     case VK_NEXT:
01726     case VK_PRIOR:
01727     case VK_HOME:
01728     case VK_END:
01729         notify_with_scroll (infoPtr, TB_ENDTRACK);
01730     }
01731     return TRUE;
01732 }
01733 
01734 
01735 static LRESULT WINAPI
01736 TRACKBAR_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
01737 {
01738     TRACKBAR_INFO *infoPtr = (TRACKBAR_INFO *)GetWindowLongPtrW (hwnd, 0);
01739 
01740     TRACE("hwnd=%p msg=%x wparam=%lx lparam=%lx\n", hwnd, uMsg, wParam, lParam);
01741 
01742     if (!infoPtr && (uMsg != WM_CREATE))
01743         return DefWindowProcW (hwnd, uMsg, wParam, lParam);
01744 
01745     switch (uMsg)
01746     {
01747     case TBM_CLEARSEL:
01748         return TRACKBAR_ClearSel (infoPtr, (BOOL)wParam);
01749 
01750     case TBM_CLEARTICS:
01751         return TRACKBAR_ClearTics (infoPtr, (BOOL)wParam);
01752 
01753     case TBM_GETBUDDY:
01754         return (LRESULT)(wParam ? infoPtr->hwndBuddyLA : infoPtr->hwndBuddyRB);
01755 
01756     case TBM_GETCHANNELRECT:
01757         return TRACKBAR_GetChannelRect (infoPtr, (LPRECT)lParam);
01758 
01759     case TBM_GETLINESIZE:
01760         return infoPtr->lLineSize;
01761 
01762     case TBM_GETNUMTICS:
01763         return TRACKBAR_GetNumTics (infoPtr);
01764 
01765     case TBM_GETPAGESIZE:
01766         return infoPtr->lPageSize;
01767 
01768     case TBM_GETPOS:
01769         return infoPtr->lPos;
01770 
01771     case TBM_GETPTICS:
01772         return (LRESULT)infoPtr->tics;
01773 
01774     case TBM_GETRANGEMAX:
01775         return infoPtr->lRangeMax;
01776 
01777     case TBM_GETRANGEMIN:
01778         return infoPtr->lRangeMin;
01779 
01780     case TBM_GETSELEND:
01781         return infoPtr->lSelMax;
01782 
01783     case TBM_GETSELSTART:
01784         return infoPtr->lSelMin;
01785 
01786     case TBM_GETTHUMBLENGTH:
01787         return infoPtr->uThumbLen;
01788 
01789     case TBM_GETTHUMBRECT:
01790     return CopyRect((LPRECT)lParam, &infoPtr->rcThumb);
01791 
01792     case TBM_GETTIC:
01793         return TRACKBAR_GetTic (infoPtr, (INT)wParam);
01794 
01795     case TBM_GETTICPOS:
01796         return TRACKBAR_GetTicPos (infoPtr, (INT)wParam);
01797 
01798     case TBM_GETTOOLTIPS:
01799         return (LRESULT)infoPtr->hwndToolTip;
01800 
01801     case TBM_GETUNICODEFORMAT:
01802         return infoPtr->bUnicode;
01803 
01804     case TBM_SETBUDDY:
01805         return (LRESULT) TRACKBAR_SetBuddy(infoPtr, (BOOL)wParam, (HWND)lParam);
01806 
01807     case TBM_SETLINESIZE:
01808         return TRACKBAR_SetLineSize (infoPtr, (LONG)lParam);
01809 
01810     case TBM_SETPAGESIZE:
01811         return TRACKBAR_SetPageSize (infoPtr, (LONG)lParam);
01812 
01813     case TBM_SETPOS:
01814         return TRACKBAR_SetPos (infoPtr, (BOOL)wParam, (LONG)lParam);
01815 
01816     case TBM_SETRANGE:
01817         return TRACKBAR_SetRange (infoPtr, (BOOL)wParam, (LONG)lParam);
01818 
01819     case TBM_SETRANGEMAX:
01820         return TRACKBAR_SetRangeMax (infoPtr, (BOOL)wParam, (LONG)lParam);
01821 
01822     case TBM_SETRANGEMIN:
01823         return TRACKBAR_SetRangeMin (infoPtr, (BOOL)wParam, (LONG)lParam);
01824 
01825     case TBM_SETSEL:
01826         return TRACKBAR_SetSel (infoPtr, (BOOL)wParam, (LONG)lParam);
01827 
01828     case TBM_SETSELEND:
01829         return TRACKBAR_SetSelEnd (infoPtr, (BOOL)wParam, (LONG)lParam);
01830 
01831     case TBM_SETSELSTART:
01832         return TRACKBAR_SetSelStart (infoPtr, (BOOL)wParam, (LONG)lParam);
01833 
01834     case TBM_SETTHUMBLENGTH:
01835         return TRACKBAR_SetThumbLength (infoPtr, (UINT)wParam);
01836 
01837     case TBM_SETTIC:
01838         return TRACKBAR_SetTic (infoPtr, (LONG)lParam);
01839 
01840     case TBM_SETTICFREQ:
01841         return TRACKBAR_SetTicFreq (infoPtr, (WORD)wParam);
01842 
01843     case TBM_SETTIPSIDE:
01844         return TRACKBAR_SetTipSide (infoPtr, (INT)wParam);
01845 
01846     case TBM_SETTOOLTIPS:
01847         return TRACKBAR_SetToolTips (infoPtr, (HWND)wParam);
01848 
01849     case TBM_SETUNICODEFORMAT:
01850     return TRACKBAR_SetUnicodeFormat (infoPtr, (BOOL)wParam);
01851 
01852 
01853     case WM_CAPTURECHANGED:
01854         return TRACKBAR_CaptureChanged (infoPtr);
01855 
01856     case WM_CREATE:
01857         return TRACKBAR_Create (hwnd, (LPCREATESTRUCTW)lParam);
01858 
01859     case WM_DESTROY:
01860         return TRACKBAR_Destroy (infoPtr);
01861 
01862 /*  case WM_ENABLE: */
01863 
01864     case WM_ERASEBKGND:
01865     return 0;
01866 
01867     case WM_GETDLGCODE:
01868         return DLGC_WANTARROWS;
01869 
01870     case WM_KEYDOWN:
01871         return TRACKBAR_KeyDown (infoPtr, (INT)wParam);
01872 
01873     case WM_KEYUP:
01874         return TRACKBAR_KeyUp (infoPtr, (INT)wParam);
01875 
01876     case WM_KILLFOCUS:
01877         return TRACKBAR_KillFocus (infoPtr);
01878 
01879     case WM_LBUTTONDOWN:
01880         return TRACKBAR_LButtonDown (infoPtr, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
01881 
01882     case WM_LBUTTONUP:
01883         return TRACKBAR_LButtonUp (infoPtr);
01884 
01885     case WM_MOUSELEAVE:
01886         infoPtr->flags &= ~TB_THUMB_HOT; 
01887         InvalidateRect (infoPtr->hwndSelf, &infoPtr->rcThumb, FALSE);
01888         return 0;
01889     
01890     case WM_MOUSEMOVE:
01891         return TRACKBAR_MouseMove (infoPtr, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
01892 
01893     case WM_PRINTCLIENT:
01894     case WM_PAINT:
01895         return TRACKBAR_Paint (infoPtr, (HDC)wParam);
01896 
01897     case WM_SETFOCUS:
01898         return TRACKBAR_SetFocus (infoPtr);
01899 
01900     case WM_SIZE:
01901         return TRACKBAR_Size (infoPtr);
01902 
01903     case WM_STYLECHANGED:
01904         return TRACKBAR_StyleChanged (infoPtr, wParam, (LPSTYLESTRUCT)lParam);
01905 
01906     case WM_THEMECHANGED:
01907         return theme_changed (infoPtr);
01908 
01909     case WM_TIMER:
01910     return TRACKBAR_Timer (infoPtr);
01911 
01912     case WM_WININICHANGE:
01913         return TRACKBAR_InitializeThumb (infoPtr);
01914 
01915     default:
01916         if ((uMsg >= WM_USER) && (uMsg < WM_APP) && !COMCTL32_IsReflectedMessage(uMsg))
01917             ERR("unknown msg %04x wp=%08lx lp=%08lx\n", uMsg, wParam, lParam);
01918         return DefWindowProcW (hwnd, uMsg, wParam, lParam);
01919     }
01920 }
01921 
01922 
01923 void TRACKBAR_Register (void)
01924 {
01925     WNDCLASSW wndClass;
01926 
01927     ZeroMemory (&wndClass, sizeof(WNDCLASSW));
01928     wndClass.style         = CS_GLOBALCLASS;
01929     wndClass.lpfnWndProc   = TRACKBAR_WindowProc;
01930     wndClass.cbClsExtra    = 0;
01931     wndClass.cbWndExtra    = sizeof(TRACKBAR_INFO *);
01932     wndClass.hCursor       = LoadCursorW (0, (LPWSTR)IDC_ARROW);
01933     wndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
01934     wndClass.lpszClassName = TRACKBAR_CLASSW;
01935 
01936     RegisterClassW (&wndClass);
01937 }
01938 
01939 
01940 void TRACKBAR_Unregister (void)
01941 {
01942     UnregisterClassW (TRACKBAR_CLASSW, NULL);
01943 }

Generated on Sun May 27 2012 04:23:05 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.