rangeslider.c
上传用户:xmgzy123
上传日期:2007-01-07
资源大小:373k
文件大小:17k
源码类别:

SCSI/ASPI

开发平台:

WINDOWS

  1. #include <windows.h>
  2. #include "rangeslider.h"
  3. #include "globals.h"
  4. #define HEIGHTSLIDER 13
  5. typedef struct {
  6.   DWORD min;
  7.   DWORD max;
  8.   DWORD start;
  9.   DWORD finish;
  10.   int xOfsStart;        // possibly useless
  11.   SHORT xStart;         // x-offset of starting position
  12.   SHORT yStart;         // y-offset of starting position
  13.   int which;
  14.   RECT rc;
  15.   BOOL bInDrag;
  16.   HDC hCompDC;
  17.   HBITMAP hBmp;
  18.   HBITMAP hTop;
  19.   HBITMAP hBottom;
  20.   HPEN hDkGreyPen;
  21.   HPEN hLtGreyPen;
  22.   HPEN hBlackPen;
  23.   HPEN hWhitePen;
  24.   HBRUSH hBackground;
  25.   HBRUSH hGreenBrush;
  26.   int numTics;
  27.   DWORD tic[100];
  28. } RANGESLIDERSTRUCT, FAR *LPRANGESLIDERSTRUCT;
  29. void PaintRangeSliderWnd( HWND hWnd, LPRANGESLIDERSTRUCT lpr );
  30. LRESULT CALLBACK RangeSliderBarProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  31. void CreateSliderBitmaps( HDC hDC, LPRANGESLIDERSTRUCT lpr );
  32. BOOL SliderHitTest( HWND hWnd, int which, LPARAM lParam, LPRANGESLIDERSTRUCT lpr );
  33. BOOL sliderHandleLButtonDown( HWND hWnd, LPRANGESLIDERSTRUCT lpr, LPARAM lParam );
  34. BOOL sliderHandleLButtonUp( HWND hWnd, LPRANGESLIDERSTRUCT lpr, LPARAM lParam );
  35. BOOL sliderHandleMouseMove( HWND hWnd, LPRANGESLIDERSTRUCT lpr, LPARAM lParam );
  36. BOOL sliderHandleSnap( HWND hWnd, WPARAM wParam, BOOL bRight, LPRANGESLIDERSTRUCT lpr );
  37. BOOL SliderLeftHitTest( HWND hWnd, int which, LPARAM lParam,
  38.  LPRANGESLIDERSTRUCT lpr );
  39. BOOL SliderRightHitTest( HWND hWnd, int which, LPARAM lParam,
  40.  LPRANGESLIDERSTRUCT lpr );
  41. BOOL SendSliderNotifyChanging( HWND hWnd, LPRANGESLIDERSTRUCT lpr, DWORD dwNew );
  42. BOOL SendSliderNotifyChanged( HWND hWnd, LPRANGESLIDERSTRUCT lpr );
  43. static char szRangeSliderClass[] = "ak_rangeslider";
  44. int InitRangeSliderClass( void )
  45. {
  46.   WNDCLASSEX wc;
  47.   
  48.   ZeroMemory( &wc, sizeof(wc) );
  49.   wc.cbSize          = sizeof(wc);
  50.   wc.style           = CS_HREDRAW | CS_VREDRAW;
  51.   wc.lpfnWndProc     = (WNDPROC)RangeSliderBarProc;
  52.   wc.hInstance       = ghInstance;
  53.   wc.hCursor         = LoadCursor( NULL, IDC_ARROW );
  54.   wc.hbrBackground   = (HBRUSH)(COLOR_BTNFACE+1);
  55.   wc.lpszClassName   = szRangeSliderClass;
  56.   if ( !RegisterClassEx( &wc ) )
  57.     return 0;
  58.   return -1;
  59. }
  60. /*
  61.  * Implements a sliding range bar control.  The control is used to select
  62.  * a range using two slide controls -- one on top and one on bottom.
  63.  *
  64.  * Message          wParam      lParam
  65.  * ---------------- ----------- ------------------------------------------
  66.  * RSB_SETMIN       bRepaint    minimum allowed value
  67.  * RSB_SETMAX       bRepaint    maxiumum allowed value
  68.  * RSB_GETMIN       0           0
  69.  * RSB_GETMAX       0           0
  70.  * RSB_RESET        0           0
  71.  * RSB_SETSTART     bRepaint    starting position of selected range
  72.  * RSB_SETFINISH    bRepaint    ending position of selected range
  73.  * RSB_SNAP         top/bottom  0 = left, 1 = right
  74.  */
  75. LRESULT CALLBACK RangeSliderBarProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  76. {
  77.   LPRANGESLIDERSTRUCT lpr;
  78.   DWORD dwTmp;
  79.   lpr = (LPRANGESLIDERSTRUCT)GetWindowLong( hWnd, GWL_USERDATA );
  80.   if ( !lpr && (uMsg != WM_CREATE) )
  81.     return DefWindowProc( hWnd, uMsg, wParam, lParam );
  82.   switch( uMsg )
  83.     {
  84.     case WM_CREATE:
  85.       dwTmp = sizeof(*lpr);
  86.       lpr = (LPRANGESLIDERSTRUCT)GlobalAlloc( GPTR, sizeof(*lpr) );
  87.       lpr->min = 0;
  88.       lpr->max = 100;
  89.       lpr->start = 0;
  90.       lpr->finish = 0;
  91.       lpr->hTop = (HBITMAP)LoadBitmap( ghInstance, "SliderTop" );
  92.       lpr->hBottom = (HBITMAP)LoadBitmap( ghInstance, "SliderBottom" );
  93.       lpr->hWhitePen = (HPEN)GetStockObject( WHITE_PEN );
  94.       lpr->hBlackPen = (HPEN)GetStockObject( BLACK_PEN );
  95.       lpr->hDkGreyPen = CreatePen( PS_SOLID, 1, RGB( 128, 128, 128 ) );
  96.       lpr->hLtGreyPen = CreatePen( PS_SOLID, 1, RGB( 192, 192, 192 ) );
  97.       lpr->hBackground = CreateSolidBrush( GetSysColor( COLOR_MENU ) );
  98.       lpr->hGreenBrush = CreateSolidBrush( RGB( 0, 255, 0 ) );
  99.       GetClientRect( hWnd, &lpr->rc );
  100.       SetWindowLong( hWnd, GWL_USERDATA, (LONG)lpr );
  101.       break;
  102.     case WM_DESTROY:
  103.       DeleteObject( lpr->hTop );
  104.       DeleteObject( lpr->hBottom );
  105.       DeleteObject( lpr->hDkGreyPen );
  106.       DeleteObject( lpr->hLtGreyPen );
  107.       DeleteObject( lpr->hBackground );
  108.       DeleteObject( lpr->hGreenBrush );
  109.       if ( lpr->hCompDC )
  110. ReleaseDC( hWnd, lpr->hCompDC );
  111.       if ( lpr->hBmp )
  112. DeleteObject( lpr->hBmp );
  113.       GlobalFree( (HGLOBAL)lpr );
  114.       break;
  115.     case WM_PAINT:
  116.       PaintRangeSliderWnd( hWnd, lpr );
  117.       break;
  118.     case WM_LBUTTONDOWN:
  119.       if ( sliderHandleLButtonDown( hWnd, lpr, lParam ) )
  120. {
  121.   InvalidateRect( hWnd, &lpr->rc, FALSE );
  122.   UpdateWindow( hWnd );
  123. }
  124.       break;
  125.     case WM_LBUTTONUP:
  126.       if ( sliderHandleLButtonUp( hWnd, lpr, lParam ) )
  127. {
  128.   InvalidateRect( hWnd, &lpr->rc, FALSE );
  129.   UpdateWindow( hWnd );
  130. }
  131.       break;
  132.     case WM_MOUSEMOVE:
  133.       if ( sliderHandleMouseMove( hWnd, lpr, lParam ) )
  134. {
  135.   InvalidateRect( hWnd, &lpr->rc, FALSE );
  136.   UpdateWindow( hWnd );
  137. }
  138.       break;
  139.     case WM_SETFOCUS:
  140.       break;
  141.     case RSB_SETMIN:
  142.       dwTmp = (DWORD)lParam;
  143.       if ( dwTmp >= lpr->max )
  144. dwTmp = lpr->max - 1;
  145.       lpr->min = dwTmp;
  146.       break;
  147.     case RSB_SETMAX:
  148.       dwTmp = (DWORD)lParam;
  149.       if ( dwTmp <= lpr->min )
  150. dwTmp = lpr->min + 1;
  151.       lpr->max = dwTmp;
  152.       break;
  153.     case RSB_SETSTART:
  154.       dwTmp = (DWORD)lParam;
  155.       if ( dwTmp < lpr->min )
  156. dwTmp = lpr->min;
  157.       else if ( dwTmp >= lpr->max )
  158. dwTmp = lpr->max-1;
  159.       lpr->start = dwTmp;
  160.       if ( wParam )
  161. {
  162.   InvalidateRect( hWnd, &lpr->rc, FALSE );
  163.   UpdateWindow( hWnd );
  164. }
  165.       break;
  166.     case RSB_SETFINISH:
  167.       dwTmp = (DWORD)lParam;
  168.       if ( dwTmp <= lpr->min )
  169. dwTmp = lpr->min + 1;
  170.       else if ( dwTmp > lpr->max )
  171. dwTmp = lpr->max;
  172.       lpr->finish = dwTmp;
  173.       if ( wParam )
  174. {
  175.   InvalidateRect( hWnd, &lpr->rc, FALSE );
  176.   UpdateWindow( hWnd );
  177. }
  178.       break;
  179.     case RSB_GETMIN:
  180.       return (LRESULT)lpr->min;
  181.     case RSB_GETMAX:
  182.       return (LRESULT)lpr->max;
  183.     case RSB_GETSTART:
  184.       return (LRESULT)lpr->start;
  185.     case RSB_GETFINISH:
  186.       return (LRESULT)lpr->finish;
  187.     case RSB_SETTIC:
  188.       if ( lpr->numTics < 100 )
  189. lpr->tic[lpr->numTics++] = (DWORD)lParam;
  190.       break;
  191.     case RSB_SNAP:
  192.       if ( sliderHandleSnap( hWnd, wParam, (BOOL)lParam, lpr ) )
  193. {
  194.   InvalidateRect( hWnd, &lpr->rc, FALSE );
  195.   UpdateWindow( hWnd );
  196. }
  197.       break;
  198.     default:
  199.       return DefWindowProc( hWnd, uMsg, wParam, lParam );
  200.     }
  201.   return 0L;
  202. }
  203. BOOL SliderHitTest( HWND hWnd, int which, LPARAM lParam,
  204.     LPRANGESLIDERSTRUCT lpr )
  205. {
  206.   int xOfs;
  207.   POINTS pt;
  208.   pt = MAKEPOINTS( lParam );
  209.   switch( which )
  210.     {
  211.     case TOPSLIDER:
  212.       xOfs = (lpr->rc.right-7) * lpr->start / (lpr->max - lpr->min);
  213.       if ( (pt.x >= xOfs) && (pt.x <= (xOfs + 7)) &&
  214.    (pt.y >= 0) && (pt.y <= 14) )
  215. {
  216.   OutputDebugString( "SliderHitTest: TOPSLIDER hit!" );
  217.   return TRUE;
  218. }
  219.       break;
  220.     case BOTTOMSLIDER:
  221.       xOfs = (lpr->rc.right-7) * lpr->finish / (lpr->max - lpr->min);
  222.       if ( (pt.x >= xOfs) && (pt.x <= (xOfs + 7)) &&
  223.    (pt.y >= 25+HEIGHTSLIDER) && (pt.y <= 39+HEIGHTSLIDER) )
  224. {
  225.   OutputDebugString( "SliderHitTest: BOTTOMSLIDER hit!" );
  226.   return TRUE;
  227. }
  228.       break;
  229.     }
  230.   OutputDebugString( "SliderHitTest: no slider hit..." );
  231.   return FALSE;
  232. }
  233. BOOL SliderLeftHitTest( HWND hWnd, int which, LPARAM lParam,
  234. LPRANGESLIDERSTRUCT lpr )
  235. {
  236.   int xOfs;
  237.   POINTS pt;
  238.   pt = MAKEPOINTS( lParam );
  239.   switch( which )
  240.     {
  241.     case TOPSLIDER:
  242.       xOfs = (lpr->rc.right-7) * lpr->start / (lpr->max - lpr->min);
  243.       if ( (pt.x < xOfs) && (pt.y >= 0) && (pt.y <= 14) )
  244. {
  245.   return TRUE;
  246. }
  247.       break;
  248.     case BOTTOMSLIDER:
  249.       xOfs = (lpr->rc.right-7) * lpr->finish / (lpr->max - lpr->min);
  250.       if ( (pt.x < xOfs) && (pt.y >= 25+HEIGHTSLIDER) && (pt.y <= 39+HEIGHTSLIDER) )
  251. {
  252.   return TRUE;
  253. }
  254.       break;
  255.     }
  256.   return FALSE;
  257. }
  258. BOOL SliderRightHitTest( HWND hWnd, int which, LPARAM lParam,
  259.  LPRANGESLIDERSTRUCT lpr )
  260. {
  261.   int xOfs;
  262.   POINTS pt;
  263.   pt = MAKEPOINTS( lParam );
  264.   switch( which )
  265.     {
  266.     case TOPSLIDER:
  267.       xOfs = (lpr->rc.right-7) * lpr->start / (lpr->max - lpr->min);
  268.       if ( (pt.x > xOfs+7) && (pt.y >= 0) && (pt.y <= 14) )
  269. {
  270.   return TRUE;
  271. }
  272.       break;
  273.     case BOTTOMSLIDER:
  274.       xOfs = (lpr->rc.right-7) * lpr->finish / (lpr->max - lpr->min);
  275.       if ( (pt.x > xOfs+7) && (pt.y >= 25+HEIGHTSLIDER) && (pt.y <= 39+HEIGHTSLIDER) )
  276. {
  277.   return TRUE;
  278. }
  279.       break;
  280.     }
  281.   return FALSE;
  282. }
  283. #define HEIGHTSLIDER 13
  284. void PaintRangeSliderWnd( HWND hWnd, LPRANGESLIDERSTRUCT lpr )
  285. {
  286.   PAINTSTRUCT p;
  287.   RECT rc;
  288.   HDC hDC, hCompDC;
  289.   HBITMAP hBmp;
  290.   POINT pt[10];
  291.   int w, h, xOfs, i;
  292.   hDC = BeginPaint( hWnd, &p );
  293.   rc = lpr->rc;
  294.   w = rc.right;
  295.   h = rc.bottom;
  296. #if 1
  297.   if ( !lpr->hCompDC )
  298.     lpr->hCompDC = CreateCompatibleDC( hDC );
  299.   hCompDC = lpr->hCompDC;
  300.   if ( !lpr->hBmp )
  301.     lpr->hBmp = CreateCompatibleBitmap( hDC, w, h );
  302.   hBmp = lpr->hBmp;
  303. #else
  304.   hCompDC = CreateCompatibleDC( hDC );
  305.   hBmp = CreateCompatibleBitmap( hDC, w, h );
  306. #endif
  307.   SelectObject( hCompDC, hBmp );
  308.   FillRect( hCompDC, &rc, lpr->hBackground );
  309.   // Draw the tic marks
  310.   SelectObject( hCompDC, lpr->hBlackPen );
  311.   for( i = 0; i < lpr->numTics; i++ )
  312.     {
  313.       xOfs = ((w - 7) * lpr->tic[i] / (lpr->max - lpr->min)) + 3;
  314.       pt[0].x = xOfs; pt[0].y = 15;
  315.       pt[1].x = xOfs; pt[1].y = 19;
  316.       Polyline( hCompDC, pt, 2 );
  317.       pt[0].y = 24 + HEIGHTSLIDER;
  318.       pt[1].y = 20 + HEIGHTSLIDER;
  319.       Polyline( hCompDC, pt, 2 );
  320.     }
  321. #if 0
  322.   pt[0].x = w - 4; pt[0].y = 15;
  323.   pt[1].x = w - 4; pt[1].y = 19;
  324.   Polyline( hCompDC, pt, 2 );
  325.   pt[0].x = w - 4; pt[0].y = 24 + HEIGHTSLIDER;
  326.   pt[1].x = w - 4; pt[1].y = 20 + HEIGHTSLIDER;
  327.   Polyline( hCompDC, pt, 2 );
  328. #endif
  329.   rc.left = 1;
  330.   rc.right = w - 1;
  331.   rc.top = 20;
  332.   rc.bottom = rc.top + HEIGHTSLIDER;
  333.   FillRect( hCompDC, &rc, (HBRUSH)GetStockObject( WHITE_BRUSH ) );
  334.   // draw 3-d edge
  335.   SelectObject( hCompDC, lpr->hDkGreyPen );
  336.   pt[0].x = rc.left; pt[0].y = rc.top + HEIGHTSLIDER - 2;
  337.   pt[1].x = rc.left; pt[1].y = rc.top; 
  338.   pt[2].x = rc.right - 1; pt[2].y = rc.top;
  339.   Polyline( hCompDC, pt, 3 );
  340.   SelectObject( hCompDC, lpr->hBlackPen );
  341.   pt[0].x++;  pt[0].y--;
  342.   pt[1].x++;  pt[1].y++;
  343.   pt[2].x--;  pt[2].y++;
  344.   Polyline( hCompDC, pt, 3 );
  345.   SelectObject( hCompDC, lpr->hLtGreyPen );
  346.   pt[0].y++;
  347.   pt[1].x = rc.right-2; pt[1].y = pt[0].y;
  348.   pt[2].x = rc.right-2; pt[2].y--;
  349.   Polyline( hCompDC, pt, 3 );
  350.   rc.top += 2;
  351.   rc.bottom -= 2;
  352.   rc.left = ((w - 7) * lpr->start / (lpr->max - lpr->min)) + 3;
  353.   // we have to increment the right corner, since FillRect fills up to, but
  354.   // not including the right and bottom edges.
  355.   rc.right = ((w - 7) * lpr->finish / (lpr->max - lpr->min)) + 4;
  356.   FillRect( hCompDC, &rc, lpr->hGreenBrush );
  357.   BitBlt( hDC, 0, 0, w, h, hCompDC, 0, 0, SRCCOPY );
  358.   rc.left = 3;
  359.   rc.right = w - 4;
  360.   rc.top = 20;
  361.   rc.bottom = rc.top + HEIGHTSLIDER;
  362.   //xOfs = (rc.right - rc.left) * lpr->start / (lpr->max - lpr->min);
  363.   xOfs = (w-7) * lpr->start / (lpr->max - lpr->min);
  364.   SelectObject( hCompDC, lpr->hTop );
  365.   BitBlt( hDC, xOfs, 0, 7, 14, hCompDC, 0, 0, SRCCOPY );
  366.   xOfs = (w-7) * lpr->finish / (lpr->max - lpr->min);
  367.   SelectObject( hCompDC, lpr->hBottom );
  368.   BitBlt( hDC, xOfs, 25 + HEIGHTSLIDER, 7, 14, hCompDC, 0, 0, SRCCOPY );
  369.   //DeleteDC( hCompDC );
  370.   //DeleteObject( hBmp );
  371.   EndPaint( hWnd, &p );
  372. }
  373. BOOL sliderHandleLButtonDown( HWND hWnd, LPRANGESLIDERSTRUCT lpr, 
  374.       LPARAM lParam )
  375. {
  376.   POINTS pt = MAKEPOINTS( lParam );
  377.   if ( !lpr->bInDrag )
  378.     {
  379.       if ( SliderHitTest( hWnd, TOPSLIDER, lParam, lpr ) )
  380. {
  381.   SetCapture( hWnd );
  382.   lpr->bInDrag = TRUE;
  383.   lpr->which = TOPSLIDER;
  384. }
  385.       else if ( SliderHitTest( hWnd, BOTTOMSLIDER, lParam, lpr ) )
  386. {
  387.   SetCapture( hWnd );
  388.   lpr->bInDrag = TRUE;
  389.   lpr->which = BOTTOMSLIDER;
  390.   lpr->xOfsStart = (lpr->rc.right - 7) * lpr->finish / (lpr->max - lpr->min) + 3;
  391. }
  392.       else if ( SliderLeftHitTest( hWnd, TOPSLIDER, lParam, lpr ) )
  393. {
  394.   SendMessage( hWnd, RSB_SNAP, TOPSLIDER, 0 );
  395.   return TRUE;
  396. }
  397.       else if ( SliderLeftHitTest( hWnd, BOTTOMSLIDER, lParam, lpr ) )
  398. {
  399.   SendMessage( hWnd, RSB_SNAP, BOTTOMSLIDER, 0 );
  400.   return TRUE;
  401. }
  402.       else if ( SliderRightHitTest( hWnd, TOPSLIDER, lParam, lpr ) )
  403. {
  404.   SendMessage( hWnd, RSB_SNAP, TOPSLIDER, 1 );
  405.   return TRUE;
  406. }
  407.       else if ( SliderRightHitTest( hWnd, BOTTOMSLIDER, lParam, lpr ) )
  408. {
  409.   SendMessage( hWnd, RSB_SNAP, BOTTOMSLIDER, 1 );
  410.   return TRUE;
  411. }
  412.       if ( lpr->bInDrag )
  413. {
  414.   lpr->xStart = pt.x;
  415.   lpr->yStart = pt.y;
  416. }
  417.     }
  418.   return FALSE;
  419. }
  420. BOOL sliderHandleLButtonUp( HWND hWnd, LPRANGESLIDERSTRUCT lpr, LPARAM lParam )
  421. {
  422.   if ( lpr->bInDrag )
  423.     {
  424.       ReleaseCapture();
  425.       lpr->bInDrag = FALSE;
  426.       SendSliderNotifyChanged( hWnd, lpr );
  427.     }
  428.   return FALSE;
  429. }
  430. #if 0
  431.   rc.left = ((w - 7) * lpr->start / (lpr->max - lpr->min)) + 3;
  432.   rc.right = ((w - 7) * lpr->finish / (lpr->max - lpr->min)) + 3;
  433. #endif
  434. BOOL sliderHandleMouseMove( HWND hWnd, LPRANGESLIDERSTRUCT lpr, LPARAM lParam )
  435. {
  436.   int xOfs;
  437.   POINTS pt;
  438.   DWORD dwNewValue;
  439.   pt = MAKEPOINTS( lParam );
  440.   if ( lpr->bInDrag )
  441.     {
  442.       xOfs = pt.x - 3;
  443.       if ( xOfs < 0 )
  444. xOfs = 0;
  445.       else if ( xOfs > (lpr->rc.right - 7) )
  446. xOfs = lpr->rc.right - 7;
  447.       switch( lpr->which )
  448. {
  449. case TOPSLIDER:
  450.   dwNewValue = xOfs * (lpr->max - lpr->min) / (lpr->rc.right - 7);
  451.   if ( SendSliderNotifyChanging( hWnd, lpr, dwNewValue ) )
  452.     {
  453.       lpr->start = dwNewValue;
  454.       //SendSliderNotifyChanged( hWnd, lpr );
  455.     }
  456.   return TRUE;
  457. case BOTTOMSLIDER:
  458.   dwNewValue = xOfs * (lpr->max - lpr->min) / (lpr->rc.right - 7);
  459.   if ( SendSliderNotifyChanging( hWnd, lpr, dwNewValue ) )
  460.     {
  461.       lpr->finish = dwNewValue;
  462.       //SendSliderNotifyChanged( hWnd, lpr );
  463.     }
  464.   return TRUE;
  465. }
  466.     }
  467.   return FALSE;
  468. }
  469. /*
  470.  * "Snaps" a slider either left or right to the nearest tic mark.
  471.  *
  472.  * wParam: which slider (TOPSLIDER or BOTTOMSLIDER)
  473.  * lParam: left (0) or right (1)
  474.  */
  475. BOOL sliderHandleSnap( HWND hWnd, WPARAM wParam, BOOL bRight, LPRANGESLIDERSTRUCT lpr )
  476. {
  477.   int i;
  478.   DWORD dwPos;
  479.   DWORD dwCurrent;
  480.   if ( (wParam != TOPSLIDER) && (wParam != BOTTOMSLIDER) )
  481.     return FALSE;
  482.   if ( lpr->numTics == 0 )
  483.     return FALSE;
  484.   if ( bRight )
  485.     dwPos = lpr->min;
  486.   else
  487.     dwPos = lpr->max;
  488.   lpr->which = (int)wParam;
  489.   // find the leftmost or rightmost tic mark
  490.   for( i = 0; i < lpr->numTics; i++ )
  491.     {
  492.       if ( bRight )
  493. {
  494.   if ( lpr->tic[i] > dwPos )
  495.     dwPos = lpr->tic[i];
  496. }
  497.       else
  498. {
  499.   if ( lpr->tic[i] < dwPos )
  500.     dwPos = lpr->tic[i];
  501. }
  502.     }
  503.   dwCurrent = (wParam == TOPSLIDER)?lpr->start:lpr->finish;
  504.   for( i = 0; i < lpr->numTics; i++ )
  505.     {
  506.       if ( bRight )
  507. {
  508.   if ( (lpr->tic[i] > dwCurrent) && (lpr->tic[i] < dwPos) )
  509.     dwPos = lpr->tic[i];
  510. }
  511.       else
  512. {
  513.   if ( (lpr->tic[i] < dwCurrent) && (lpr->tic[i] > dwPos) )
  514.     dwPos = lpr->tic[i];
  515. }
  516.     }
  517.   lpr->which = (int)wParam;
  518.   if ( wParam == TOPSLIDER )
  519.     {
  520.       if ( SendSliderNotifyChanging( hWnd, lpr, dwPos ) )
  521. lpr->start = dwPos;
  522.     }
  523.   else
  524.     {
  525.       if ( SendSliderNotifyChanging( hWnd, lpr, dwPos ) )
  526. lpr->finish = dwPos;
  527.     }
  528.   SendSliderNotifyChanged( hWnd, lpr );  
  529.   return TRUE;
  530. }
  531. BOOL SendSliderNotifyChanging( HWND hWnd, LPRANGESLIDERSTRUCT lpr, DWORD dwNew )
  532. {
  533.   RSBNOTIFY rsb;
  534.   ZeroMemory( &rsb, sizeof(rsb) );
  535.   rsb.hdr.hwndFrom = hWnd;
  536.   rsb.hdr.idFrom = (UINT)GetWindowLong( hWnd, GWL_ID );
  537.   rsb.which = lpr->which;
  538.   if ( lpr->which == TOPSLIDER )
  539.     {
  540.       rsb.hdr.code = RSBN_STARTCHANGING;
  541.       rsb.newStart = dwNew;
  542.       rsb.newFinish = lpr->finish;
  543.     }
  544.   else
  545.     {
  546.       rsb.hdr.code = RSBN_FINISHCHANGING;
  547.       rsb.newStart = lpr->start;
  548.       rsb.newFinish = dwNew;
  549.     }
  550.   rsb.start = lpr->start;
  551.   rsb.finish = lpr->finish;
  552.   if ( SendMessage( GetParent( hWnd ), WM_NOTIFY, (WPARAM)rsb.hdr.idFrom,
  553.     (LPARAM)&rsb ) )
  554.     return TRUE;
  555.   return FALSE;
  556. }
  557. BOOL SendSliderNotifyChanged( HWND hWnd, LPRANGESLIDERSTRUCT lpr )
  558. {
  559.   RSBNOTIFY rsb;
  560.   ZeroMemory( &rsb, sizeof(rsb) );
  561.   rsb.hdr.hwndFrom = hWnd;
  562.   rsb.hdr.idFrom = (UINT)GetWindowLong( hWnd, GWL_ID );
  563.   rsb.which = lpr->which;
  564.   if ( lpr->which == TOPSLIDER )
  565.     {
  566.       rsb.hdr.code = RSBN_STARTCHANGED;
  567.     }
  568.   else
  569.     {
  570.       rsb.hdr.code = RSBN_FINISHCHANGED;
  571.     }
  572.   rsb.start = lpr->start;
  573.   rsb.finish = lpr->finish;
  574.   rsb.newStart = lpr->start;
  575.   rsb.newFinish = lpr->finish;
  576.   SendMessage( GetParent( hWnd ), WM_NOTIFY, (WPARAM)rsb.hdr.idFrom,
  577.     (LPARAM)&rsb );
  578.   return TRUE;
  579. }