Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

scroll.cpp

Go to the documentation of this file.
00001 /* $Id: scroll.cpp,v 1.47 2001/11/16 16:11:01 sandervl Exp $ */
00002 /*
00003  * Scrollbar control
00004  *
00005  * Copyright 1999 Christoph Bratschi
00006  *
00007  * Copyright 1993 Martin Ayotte
00008  * Copyright 1994, 1996 Alexandre Julliard
00009  *
00010  * WINE version: 20000130
00011  *
00012  * Status:  complete
00013  * Version: 5.00
00014  */
00015 
00016 #include <stdlib.h>
00017 #include <os2win.h>
00018 #include "controls.h"
00019 #include "scroll.h"
00020 #include "win32wbase.h"
00021 #include "oslibwin.h"
00022 #include "initterm.h"
00023 #include "pmwindow.h"
00024 
00025 #define DBG_LOCALLOG    DBG_scroll
00026 #include "dbglocal.h"
00027 
00028 #define SCROLL_MIN_RECT  4 /* Minimum size of the rectangle between the arrows */
00029 #define SCROLL_MIN_THUMB 6 /* Minimum size of the thumb in pixels */
00030 
00031 #define SCROLL_ARROW_THUMB_OVERLAP 0 /* Overlap between arrows and thumb */
00032 
00033 #define SCROLL_FIRST_DELAY   200 /* Delay (in ms) before first repetition when holding the button down */
00034 #define SCROLL_REPEAT_DELAY  50  /* Delay (in ms) between scroll repetitions */
00035 #define SCROLL_BLINK_DELAY   1000
00036 
00037 #define SCROLL_TIMER   0 /* Scroll timer id */
00038 #define BLINK_TIMER    1
00039 
00040   /* Scroll-bar hit testing */
00041 enum SCROLL_HITTEST
00042 {
00043     SCROLL_NOWHERE,      /* Outside the scroll bar */
00044     SCROLL_TOP_ARROW,    /* Top or left arrow */
00045     SCROLL_TOP_RECT,     /* Rectangle between the top arrow and the thumb */
00046     SCROLL_THUMB,        /* Thumb rectangle */
00047     SCROLL_BOTTOM_RECT,  /* Rectangle between the thumb and the bottom arrow */
00048     SCROLL_BOTTOM_ARROW  /* Bottom or right arrow */
00049 };
00050 
00051  /* What to do in SetScrollInfo() */
00052 #define SA_SSI_HIDE             0x0001
00053 #define SA_SSI_SHOW             0x0002
00054 #define SA_SSI_REPAINT_INTERIOR 0x0004
00055 #define SA_SSI_REPAINT_ARROWS   0x0008
00056 #define SA_SSI_MOVE_THUMB       0x0010
00057 #define SA_SSI_REFRESH          0x0020
00058 
00059  /* Thumb-tracking info */
00060 static HWND SCROLL_TrackingWin = 0;
00061 static INT  SCROLL_TrackingBar = 0;
00062 static INT  SCROLL_TrackingPos = 0;
00063 static INT  SCROLL_TrackingVal = 0;
00064  /* Focus info */
00065 static HWND SCROLL_FocusWin    = 0;
00066 static BOOL SCROLL_HasFocus    = FALSE;
00067 static BOOL SCROLL_Highlighted = FALSE;
00068 static BOOL SCROLL_Scrolling   = FALSE;
00069 
00070  /* Hit test code of the last button-down event */
00071 static enum SCROLL_HITTEST SCROLL_trackHitTest;
00072 static enum SCROLL_HITTEST SCROLL_lastHitTest;
00073 static BOOL SCROLL_trackVertical;
00074 
00075  /* Is the moving thumb being displayed? */
00076 static BOOL SCROLL_MovingThumb = FALSE;
00077 
00078 static SCROLLBAR_INFO *SCROLL_GetInfoPtr( HWND hwnd, INT nBar )
00079 {
00080     Win32BaseWindow *win32wnd;
00081 
00082     switch(nBar)
00083     {
00084         case SB_HORZ:
00085         case SB_VERT:
00086         {
00087             SCROLLBAR_INFO *pInfo;
00088             win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
00089 
00090             if (!win32wnd) return NULL;
00091             pInfo = win32wnd->getScrollInfo(nBar);
00092             RELEASE_WNDOBJ(win32wnd);
00093             return pInfo;
00094         }
00095 
00096         case SB_CTL:
00097           return (SCROLLBAR_INFO*)GetInfoPtr(hwnd);
00098     }
00099 
00100     return NULL;
00101 }
00102 
00103 /* Scrollbar Functions */
00104 
00105 /***********************************************************************
00106  *           SCROLL_GetScrollBarRect
00107  *
00108  * Compute the scroll bar rectangle, in drawing coordinates (i.e. client
00109  * coords for SB_CTL, window coords for SB_VERT and SB_HORZ).
00110  * 'arrowSize' returns the width or height of an arrow (depending on
00111  * the orientation of the scrollbar), 'thumbSize' returns the size of
00112  * the thumb, and 'thumbPos' returns the position of the thumb
00113  * relative to the left or to the top.
00114  * Return TRUE if the scrollbar is vertical, FALSE if horizontal.
00115  */
00116 static BOOL SCROLL_GetScrollBarRect( HWND hwnd, INT nBar, RECT *lprect,
00117                                        INT *arrowSize, INT *thumbSize,
00118                                        INT *thumbPos )
00119 {
00120     INT pixels;
00121     BOOL vertical;
00122     RECT rectClient;
00123 
00124     switch(nBar)
00125     {
00126       case SB_HORZ:
00127       {
00128         Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
00129         RECT rectClient;
00130 
00131         if (!win32wnd) return FALSE;
00132         rectClient = *win32wnd->getClientRectPtr();
00133         lprect->left   = rectClient.left;
00134         lprect->top    = rectClient.bottom;
00135         lprect->right  = rectClient.right;
00136         lprect->bottom = lprect->top+GetSystemMetrics(SM_CYHSCROLL);
00137         if (win32wnd->getStyle() & WS_BORDER)
00138         {
00139           lprect->left--;
00140           lprect->right++;
00141         } 
00142         else 
00143         if (win32wnd->getStyle() & WS_VSCROLL)
00144             lprect->right++;
00145         RELEASE_WNDOBJ(win32wnd);
00146         vertical = FALSE;
00147         break;
00148       }
00149 
00150       case SB_VERT:
00151       {
00152         Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
00153         RECT rectClient;
00154 
00155         if (!win32wnd) return FALSE;
00156         rectClient = *win32wnd->getClientRectPtr();
00157         lprect->left   = rectClient.right;
00158         lprect->top    = rectClient.top;
00159         lprect->right  = lprect->left+GetSystemMetrics(SM_CXVSCROLL);
00160         lprect->bottom = rectClient.bottom;
00161         if(win32wnd->getStyle() & WS_BORDER)
00162         {
00163           lprect->top--;
00164           lprect->bottom++;
00165         } 
00166         else 
00167         if (win32wnd->getStyle() & WS_HSCROLL)
00168           lprect->bottom++;
00169         RELEASE_WNDOBJ(win32wnd);
00170         vertical = TRUE;
00171         break;
00172       }
00173 
00174       case SB_CTL:
00175       {
00176         DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
00177 
00178         GetClientRect( hwnd, lprect );
00179         vertical = ((dwStyle & SBS_VERT) != 0);
00180         break;
00181       }
00182 
00183     default:
00184         return FALSE;
00185     }
00186 
00187     if (vertical) pixels = lprect->bottom - lprect->top;
00188     else pixels = lprect->right - lprect->left;
00189 
00190     if (pixels <= 2*GetSystemMetrics(SM_CXVSCROLL) + SCROLL_MIN_RECT)
00191     {
00192         if (pixels > SCROLL_MIN_RECT)
00193             *arrowSize = (pixels - SCROLL_MIN_RECT) / 2;
00194         else
00195             *arrowSize = 0;
00196         *thumbPos = *thumbSize = 0;
00197     }
00198     else
00199     {
00200         SCROLLBAR_INFO *info = SCROLL_GetInfoPtr( hwnd, nBar );
00201 
00202         *arrowSize = GetSystemMetrics(SM_CXVSCROLL);
00203         pixels -= (2 * (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP));
00204 
00205         if (info->Page)
00206         {
00207             *thumbSize = pixels * info->Page / (info->MaxVal-info->MinVal+1);
00208             if (*thumbSize < SCROLL_MIN_THUMB) *thumbSize = SCROLL_MIN_THUMB;
00209         }
00210         else *thumbSize = GetSystemMetrics(SM_CXVSCROLL);
00211 
00212         if (((pixels -= *thumbSize ) < 0) ||
00213             ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH))
00214         {
00215             /* Rectangle too small or scrollbar disabled -> no thumb */
00216             *thumbPos = *thumbSize = 0;
00217         }
00218         else
00219         {
00220             INT max = info->MaxVal - MAX( info->Page-1, 0 );
00221             if (info->MinVal >= max)
00222                 *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
00223             else
00224                 *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP
00225                  + pixels * (info->CurVal-info->MinVal) / (max - info->MinVal);
00226         }
00227     }
00228     //testestest
00229     dprintf(("SCROLL_GetScrollBarRect: thumbPos %d thumbSize %d", *thumbPos, *thumbSize));
00230     return vertical;
00231 }
00232 
00233 /***********************************************************************
00234  *           SCROLL_PtInRectEx
00235  */
00236 static BOOL SCROLL_PtInRectEx( LPRECT lpRect, POINT pt, BOOL vertical )
00237 {
00238     RECT rect = *lpRect;
00239 
00240     if (vertical)
00241     {
00242       INT w = lpRect->right-lpRect->left;
00243 
00244       rect.left   -= w;
00245       rect.right  += w;
00246       rect.top    -= w;
00247       rect.bottom += w;
00248     } else
00249     {
00250       INT h = lpRect->bottom-lpRect->top;
00251 
00252       rect.top    -= h;
00253       rect.bottom += h;
00254       rect.left   -= h;
00255       rect.right  += h;
00256     }
00257 
00258     return PtInRect( &rect, pt );
00259 }
00260 
00261 /***********************************************************************
00262  *           SCROLL_HitTest
00263  *
00264  * Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!).
00265  */
00266 static enum SCROLL_HITTEST SCROLL_HitTest( HWND hwnd, INT nBar,
00267                                            POINT pt, BOOL bDragging )
00268 {
00269     INT arrowSize, thumbSize, thumbPos;
00270     RECT rect;
00271     SCROLLBAR_INFO *infoPtr = SCROLL_GetInfoPtr(hwnd,nBar);
00272 
00273     if (!infoPtr) return SCROLL_NOWHERE;
00274 
00275     BOOL vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
00276                                            &arrowSize, &thumbSize, &thumbPos );
00277 
00278     if ( (bDragging && !SCROLL_PtInRectEx( &rect, pt, vertical )) ||
00279          (!PtInRect( &rect, pt )) ) return SCROLL_NOWHERE;
00280 
00281     if (vertical)
00282     {
00283         if (pt.y < rect.top + arrowSize) return (infoPtr->flags & ESB_DISABLE_LTUP) ? SCROLL_NOWHERE:SCROLL_TOP_ARROW;
00284         if (pt.y >= rect.bottom - arrowSize) return (infoPtr->flags & ESB_DISABLE_RTDN) ? SCROLL_NOWHERE:SCROLL_BOTTOM_ARROW;
00285         if (!thumbPos) return ((infoPtr->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH) ? SCROLL_NOWHERE:SCROLL_TOP_RECT;
00286         pt.y -= rect.top;
00287         if (pt.y < thumbPos) return SCROLL_TOP_RECT;
00288         if (pt.y >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
00289     }
00290     else  /* horizontal */
00291     {
00292         if (pt.x < rect.left + arrowSize) return (infoPtr->flags & ESB_DISABLE_LTUP) ? SCROLL_NOWHERE:SCROLL_TOP_ARROW;
00293         if (pt.x >= rect.right - arrowSize) return (infoPtr->flags & ESB_DISABLE_RTDN) ? SCROLL_NOWHERE:SCROLL_BOTTOM_ARROW;
00294         if (!thumbPos) return ((infoPtr->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH) ? SCROLL_NOWHERE:SCROLL_TOP_RECT;
00295         pt.x -= rect.left;
00296         if (pt.x < thumbPos) return SCROLL_TOP_RECT;
00297         if (pt.x >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
00298     }
00299     return SCROLL_THUMB;
00300 }
00301 
00302 static void SCROLL_DrawTopArrow(HDC hdc,SCROLLBAR_INFO *infoPtr,RECT *rect,INT arrowSize,BOOL vertical,BOOL top_pressed)
00303 {
00304   RECT r;
00305 
00306   r = *rect;
00307   if( vertical )
00308     r.bottom = r.top + arrowSize;
00309   else
00310     r.right = r.left + arrowSize;
00311 
00312   DrawFrameControl( hdc, &r, DFC_SCROLL,
00313             (vertical ? DFCS_SCROLLUP : DFCS_SCROLLLEFT)
00314             | (top_pressed ? (DFCS_PUSHED | DFCS_FLAT) : 0 )
00315             | (infoPtr->flags&ESB_DISABLE_LTUP ? DFCS_INACTIVE : 0 ) );
00316 }
00317 
00318 static void SCROLL_DrawBottomArrow(HDC hdc,SCROLLBAR_INFO *infoPtr,RECT *rect,INT arrowSize,BOOL vertical,BOOL bottom_pressed)
00319 {
00320   RECT r;
00321 
00322   r = *rect;
00323   if( vertical )
00324     r.top = r.bottom-arrowSize;
00325   else
00326     r.left = r.right-arrowSize;
00327 
00328   DrawFrameControl( hdc, &r, DFC_SCROLL,
00329             (vertical ? DFCS_SCROLLDOWN : DFCS_SCROLLRIGHT)
00330             | (bottom_pressed ? (DFCS_PUSHED | DFCS_FLAT) : 0 )
00331             | (infoPtr->flags&ESB_DISABLE_RTDN ? DFCS_INACTIVE : 0) );
00332 }
00333 
00334 /***********************************************************************
00335  *           SCROLL_DrawArrows
00336  *
00337  * Draw the scroll bar arrows.
00338  */
00339 static void SCROLL_DrawArrows( HDC hdc, SCROLLBAR_INFO *infoPtr,
00340                                RECT *rect, INT arrowSize, BOOL vertical,
00341                                BOOL top_pressed, BOOL bottom_pressed )
00342 {
00343   SCROLL_DrawTopArrow(hdc,infoPtr,rect,arrowSize,vertical,top_pressed);
00344   SCROLL_DrawBottomArrow(hdc,infoPtr,rect,arrowSize,vertical,bottom_pressed);
00345 }
00346 
00347 static void SCROLL_DrawInterior( HWND hwnd, HDC hdc, INT nBar,
00348                                  RECT *rect, INT arrowSize,
00349                                  INT thumbSize, INT thumbPos,
00350                                  UINT flags, BOOL vertical,
00351                                  BOOL top_selected, BOOL bottom_selected )
00352 {
00353     RECT r;
00354     HPEN hSavePen;
00355     HBRUSH hSaveBrush,hBrush;
00356 
00357       /* Select the correct brush and pen */
00358 
00359     /* Only scrollbar controls send WM_CTLCOLORSCROLLBAR.
00360      * The window-owned scrollbars need to call DEFWND_ControlColor
00361      * to correctly setup default scrollbar colors
00362      */
00363     if (nBar == SB_CTL) {
00364         hBrush = (HBRUSH)SendMessageA( GetParent(hwnd), WM_CTLCOLORSCROLLBAR,
00365                                        (WPARAM)hdc,(LPARAM)hwnd);
00366     } else {
00367         hBrush = (HBRUSH)SendMessageA( hwnd, WM_CTLCOLORSCROLLBAR,
00368                                        (WPARAM)hdc,(LPARAM)hwnd);
00369 
00370     }
00371 
00372     hSavePen = SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
00373     hSaveBrush = SelectObject( hdc, hBrush );
00374 
00375       /* Calculate the scroll rectangle */
00376 
00377     r = *rect;
00378     if (vertical)
00379     {
00380         r.top    += arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
00381         r.bottom -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
00382     }
00383     else
00384     {
00385         r.left  += arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
00386         r.right -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
00387     }
00388 
00389     /* Draw the scroll rectangles and thumb */
00390     if (!thumbPos)  /* No thumb to draw */
00391     {
00392         PatBlt( hdc, r.left, r.top,
00393                      r.right - r.left, r.bottom - r.top,
00394                      PATCOPY );
00395 
00396         /* cleanup and return */
00397         SelectObject( hdc, hSavePen );
00398         SelectObject( hdc, hSaveBrush );
00399         return;
00400     }
00401 
00402     if (vertical)
00403     {
00404         PatBlt( hdc, r.left, r.top,
00405                   r.right - r.left,
00406                   thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP),
00407                   top_selected ? 0x0f0000 : PATCOPY );
00408         r.top += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
00409         PatBlt( hdc, r.left, r.top + thumbSize,
00410                   r.right - r.left,
00411                   r.bottom - r.top - thumbSize,
00412                   bottom_selected ? 0x0f0000 : PATCOPY );
00413         r.bottom = r.top + thumbSize;
00414     }
00415     else  /* horizontal */
00416     {
00417         PatBlt( hdc, r.left, r.top,
00418                   thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP),
00419                   r.bottom - r.top,
00420                   top_selected ? 0x0f0000 : PATCOPY );
00421         r.left += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
00422         PatBlt( hdc, r.left + thumbSize, r.top,
00423                   r.right - r.left - thumbSize,
00424                   r.bottom - r.top,
00425                   bottom_selected ? 0x0f0000 : PATCOPY );
00426         r.right = r.left + thumbSize;
00427     }
00428 
00429     /* Draw the thumb */
00430 
00431     DrawEdge(hdc,&r,EDGE_RAISED,BF_RECT | BF_ADJUST);
00432     FillRect(hdc,&r,(SCROLL_FocusWin == hwnd && SCROLL_Highlighted && !SCROLL_Scrolling) ? GetSysColorBrush(COLOR_3DSHADOW):GetSysColorBrush(COLOR_BTNFACE));
00433 
00434     /* cleanup */
00435     SelectObject( hdc, hSavePen );
00436     SelectObject( hdc, hSaveBrush );
00437 }
00438 
00439 /***********************************************************************
00440  *           SCROLL_DrawMovingThumb
00441  *
00442  * Draw the moving thumb rectangle.
00443  */
00444 static void SCROLL_DrawMovingThumb( HDC hdc, RECT *rect, BOOL vertical,
00445                        INT arrowSize, INT thumbSize )
00446 {
00447   INT pos = SCROLL_TrackingPos;
00448   INT max_size;
00449 
00450   if( vertical )
00451     max_size = rect->bottom - rect->top;
00452   else
00453     max_size = rect->right - rect->left;
00454 
00455   max_size -= (arrowSize-SCROLL_ARROW_THUMB_OVERLAP) + thumbSize;
00456 
00457   if( pos < (arrowSize-SCROLL_ARROW_THUMB_OVERLAP) )
00458     pos = (arrowSize-SCROLL_ARROW_THUMB_OVERLAP);
00459   else if( pos > max_size )
00460     pos = max_size;
00461 
00462   SCROLL_DrawInterior( SCROLL_TrackingWin, hdc, SCROLL_TrackingBar,
00463               rect, arrowSize, thumbSize, pos,
00464               0, vertical, FALSE, FALSE );
00465 }
00466 
00467 /***********************************************************************
00468  *           SCROLL_ClipPos
00469  */
00470 static POINT SCROLL_ClipPos( LPRECT lpRect, POINT pt )
00471 {
00472     if( pt.x < lpRect->left )
00473         pt.x = lpRect->left;
00474     else
00475     if( pt.x >= lpRect->right )
00476         pt.x = lpRect->right-1;
00477 
00478     if( pt.y < lpRect->top )
00479         pt.y = lpRect->top;
00480     else
00481     if( pt.y >= lpRect->bottom )
00482         pt.y = lpRect->bottom-1;
00483 
00484     return pt;
00485 }
00486 
00487 /***********************************************************************
00488  *           SCROLL_GetThumbVal
00489  *
00490  * Compute the current scroll position based on the thumb position in pixels
00491  * from the top of the scroll-bar.
00492  */
00493 static UINT SCROLL_GetThumbVal( SCROLLBAR_INFO *infoPtr, RECT *rect,
00494                                   BOOL vertical, INT pos )
00495 {
00496     INT thumbSize;
00497     INT pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left;
00498 
00499     if ((pixels -= 2*(GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)) <= 0)
00500         return infoPtr->MinVal;
00501 
00502     if (infoPtr->Page)
00503     {
00504         thumbSize = pixels * infoPtr->Page/(infoPtr->MaxVal-infoPtr->MinVal+1);
00505         if (thumbSize < SCROLL_MIN_THUMB) thumbSize = SCROLL_MIN_THUMB;
00506     }
00507     else thumbSize = GetSystemMetrics(SM_CXVSCROLL);
00508 
00509     if ((pixels -= thumbSize) <= 0) return infoPtr->MinVal;
00510 
00511     pos = MAX( 0, pos - (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP) );
00512     if (pos > pixels) pos = pixels;
00513 
00514     if (!infoPtr->Page) pos *= infoPtr->MaxVal - infoPtr->MinVal;
00515     else pos *= infoPtr->MaxVal - infoPtr->MinVal - infoPtr->Page + 1;
00516     return infoPtr->MinVal + ((pos + pixels / 2) / pixels);
00517 }
00518 
00519 void SCROLL_GetSizeBox(HWND hwnd,DWORD dwStyle,PRECT rect)
00520 {
00521   RECT clientRect;
00522   INT cx = GetSystemMetrics(SM_CXVSCROLL);
00523   INT cy = GetSystemMetrics(SM_CYHSCROLL);
00524 
00525   GetClientRect(hwnd,&clientRect);
00526 
00527   if (dwStyle & SBS_SIZEBOXTOPLEFTALIGN)
00528   {
00529     rect->left   = 0;
00530     rect->right  = cx;
00531     rect->bottom = cy;
00532     rect->top    = 0;
00533   } else
00534   {
00535     rect->left   = clientRect.right-cx;
00536     rect->right  = clientRect.right;
00537     rect->bottom = clientRect.bottom;
00538     rect->top    = clientRect.bottom-cy;
00539   }
00540 }
00541 
00542 void SCROLL_DrawSizeBox(HDC hdc,RECT rect)
00543 {
00544   POINT p1,p2;
00545   HPEN penDark = GetSysColorPen(COLOR_3DSHADOW);
00546   HPEN penWhite = GetSysColorPen(COLOR_3DHILIGHT);
00547   HPEN oldPen = SelectObject(hdc,penDark);
00548   INT x;
00549 
00550   p1.x = rect.right-1;
00551   p1.y = rect.bottom;
00552   p2.x = rect.right;
00553   p2.y = rect.bottom-1;
00554   for (x = 0;x < 3;x++)
00555   {
00556     SelectObject(hdc,penDark);
00557     MoveToEx(hdc,p1.x,p1.y,NULL);
00558     LineTo(hdc,p2.x,p2.y);
00559     p1.x--;
00560     p2.y--;
00561     MoveToEx(hdc,p1.x,p1.y,NULL);
00562     LineTo(hdc,p2.x,p2.y);
00563     SelectObject(hdc,penWhite);
00564     p1.x--;
00565     p2.y--;
00566     MoveToEx(hdc,p1.x,p1.y,NULL);
00567     LineTo(hdc,p2.x,p2.y);
00568     p1.x -= 2;
00569     p2.y -= 2;
00570   }
00571 
00572   SelectObject(hdc,oldPen);
00573 }
00574 
00575 /***********************************************************************
00576  *           SCROLL_DrawScrollBar
00577  *
00578  * Redraw the whole scrollbar.
00579  */
00580 void SCROLL_DrawScrollBar(HWND hwnd,HDC hdc,INT nBar,BOOL arrows,BOOL interior)
00581 {
00582     INT arrowSize, thumbSize, thumbPos;
00583     RECT rect;
00584     BOOL vertical;
00585     SCROLLBAR_INFO *infoPtr = SCROLL_GetInfoPtr( hwnd, nBar );
00586 
00587     if (!infoPtr) return;
00588     if (nBar == SB_CTL)
00589     {
00590       DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
00591 
00592       if (dwStyle & (SBS_SIZEBOX | SBS_SIZEGRIP))
00593       {
00594         RECT rect;
00595         HBRUSH hBrush;
00596 
00597         hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW));
00598         hBrush = GetSysColorBrush(COLOR_3DFACE);
00599         GetClientRect(hwnd,&rect);
00600         FillRect(hdc,&rect,hBrush);
00601 
00602         if (dwStyle & SBS_SIZEGRIP)
00603         {
00604           SCROLL_GetSizeBox(hwnd,dwStyle,&rect);
00605           SCROLL_DrawSizeBox(hdc,rect);
00606         }
00607 
00608         ReleaseDC(hwnd,hdc);
00609 
00610         return;
00611       }
00612     }
00613 
00614     vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
00615                                         &arrowSize, &thumbSize, &thumbPos );
00616 
00617       /* Draw the arrows */
00618 
00619     if (arrows && arrowSize)
00620     {
00621         if( vertical == SCROLL_trackVertical && GetCapture() == hwnd )
00622             SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
00623                                (SCROLL_trackHitTest == SCROLL_TOP_ARROW),
00624                                (SCROLL_trackHitTest == SCROLL_BOTTOM_ARROW) );
00625         else
00626             SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
00627                                                                FALSE, FALSE );
00628     }
00629 
00630     if (SCROLL_MovingThumb &&
00631         (SCROLL_TrackingWin == hwnd) &&
00632         (SCROLL_TrackingBar == nBar))
00633         SCROLL_DrawMovingThumb( hdc, &rect, vertical, arrowSize, thumbSize );
00634     else if( interior )
00635       SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
00636                            thumbPos, infoPtr->flags, vertical, SCROLL_trackHitTest == SCROLL_TOP_RECT && SCROLL_lastHitTest == SCROLL_TOP_RECT,SCROLL_trackHitTest == SCROLL_BOTTOM_RECT && SCROLL_lastHitTest == SCROLL_BOTTOM_RECT);
00637 }
00638 
00639 /***********************************************************************
00640  *           SCROLL_RefreshScrollBar
00641  *
00642  * Repaint the scroll bar interior after a SetScrollRange() or
00643  * SetScrollPos() call.
00644  */
00645 static void SCROLL_RefreshScrollBar( HWND hwnd, INT nBar,
00646                                      BOOL arrows, BOOL interior )
00647 {
00648   HDC hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0:DCX_WINDOW));
00649 
00650   if (!hdc) return;
00651 
00652   SCROLL_DrawScrollBar( hwnd, hdc, nBar, arrows, interior );
00653   ReleaseDC( hwnd, hdc );
00654 }
00655 
00656 /* Message Handler */
00657 
00658 LRESULT SCROLL_NCCreate(HWND hwnd,WPARAM wParam,LPARAM lParam)
00659 {
00660   SCROLLBAR_INFO *infoPtr = (SCROLLBAR_INFO*)malloc(sizeof(SCROLLBAR_INFO));
00661 
00662   infoPtr->MinVal = infoPtr->CurVal = infoPtr->Page = 0;
00663   infoPtr->MaxVal = 100;
00664   infoPtr->flags  = ESB_ENABLE_BOTH;
00665 
00666   SetInfoPtr(hwnd,(DWORD)infoPtr);
00667 
00668   return TRUE;
00669 }
00670 
00671 LRESULT SCROLL_Create(HWND hwnd,WPARAM wParam,LPARAM lParam)
00672 {
00673   CREATESTRUCTA *lpCreat = (CREATESTRUCTA *)lParam;
00674 
00675 #ifdef __WIN32OS2__
00676   if (!((lpCreat->style & (SBS_SIZEBOX | SBS_SIZEGRIP)) && !(lpCreat->style & (SBS_SIZEBOXTOPLEFTALIGN | SBS_SIZEBOXBOTTOMRIGHTALIGN))))
00677 #endif
00678   {
00679     if (lpCreat->style & SBS_VERT)
00680     {
00681       INT w,h;
00682 
00683       w = GetSystemMetrics(SM_CXVSCROLL);
00684 #ifdef __WIN32OS2__
00685       if(lpCreat->style & (SBS_SIZEBOX | SBS_SIZEGRIP)) {
00686            h = GetSystemMetrics(SM_CYHSCROLL);
00687       }
00688       else h = lpCreat->cy;
00689 #else
00690       h = lpCreat->cy;
00691 #endif
00692       if (lpCreat->style & SBS_LEFTALIGN)
00693         MoveWindow(hwnd,lpCreat->x,lpCreat->y,w,h,FALSE);
00694       else if (lpCreat->style & SBS_RIGHTALIGN)
00695         MoveWindow(hwnd,lpCreat->x+lpCreat->cx-w,lpCreat->y,w,h,FALSE);
00696     } else /* SBS_HORZ */
00697     {
00698       INT w,h;
00699 
00700 #ifdef __WIN32OS2__
00701       if(lpCreat->style & (SBS_SIZEBOX | SBS_SIZEGRIP)) {
00702            w = GetSystemMetrics(SM_CXVSCROLL);
00703       }
00704       else w = lpCreat->cx;
00705 #else
00706       w = lpCreat->cx;
00707 #endif
00708 
00709       h = GetSystemMetrics(SM_CYHSCROLL);
00710 
00711       if (lpCreat->style & SBS_TOPALIGN)
00712         MoveWindow(hwnd,lpCreat->x,lpCreat->y,w,h,FALSE);
00713       else if (lpCreat->style & SBS_BOTTOMALIGN)
00714         MoveWindow(hwnd,lpCreat->x,lpCreat->y+lpCreat->cy-h,w,h,FALSE);
00715     }
00716   }
00717 
00718   return 0;
00719 }
00720 
00721 static LRESULT SCROLL_Destroy(HWND hwnd,WPARAM wParam,LPARAM lParam)
00722 {
00723   SCROLLBAR_INFO* infoPtr = (SCROLLBAR_INFO*)GetInfoPtr(hwnd);
00724 
00725   free(infoPtr);
00726 
00727   return 0;
00728 }
00729 
00730 #ifdef __WIN32OS2__
00731 static LRESULT SCROLL_Enable(HWND hwnd, WPARAM wParam)
00732 {
00733   SCROLLBAR_INFO* infoPtr = (SCROLLBAR_INFO*)GetInfoPtr(hwnd);
00734 
00735   if (!infoPtr) return 0;
00736 
00737   EnableScrollBar(hwnd, SB_CTL, ESB_DISABLE_BOTH);
00738 
00739   return 0;
00740 }
00741 #endif
00742 
00743 /***********************************************************************
00744  *           SCROLL_HandleScrollEvent
00745  *
00746  * Handle a mouse or timer event for the scrollbar.
00747  * 'pt' is the location of the mouse event in client (for SB_CTL) or
00748  * windows coordinates.
00749  */
00750 LRESULT SCROLL_HandleScrollEvent(HWND hwnd,WPARAM wParam,LPARAM lParam,INT nBar,UINT msg)
00751 {
00752     static POINT prevPt;       /* Previous mouse position for timer events */
00753     static UINT trackThumbPos; /* Thumb position when tracking started. */
00754     static BOOL thumbTrackSent;
00755     static INT lastClickPos;   /* Position in the scroll-bar of the last button-down event. */
00756     static INT lastMousePos;   /* Position in the scroll-bar of the last mouse event. */
00757     static BOOL timerRunning;
00758 
00759     enum SCROLL_HITTEST hittest;
00760     HWND hwndOwner, hwndCtl;
00761     BOOL vertical;
00762     INT arrowSize, thumbSize, thumbPos;
00763     RECT rect;
00764     HDC hdc;
00765     POINT pt;
00766     LRESULT res = 0;
00767 
00768     SCROLLBAR_INFO *infoPtr = SCROLL_GetInfoPtr(hwnd,nBar);
00769     if (!infoPtr) return res;
00770 
00771     if (nBar == SB_CTL)
00772     {
00773       DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
00774 
00775       if ((dwStyle & (SBS_SIZEBOX | SBS_SIZEGRIP)))
00776       {
00777         if (!(dwStyle & SBS_SIZEGRIP)) return res;
00778 
00779         if (msg == WM_NCHITTEST)
00780         {
00781           if (dwStyle & SBS_SIZEGRIP)
00782           {
00783             RECT rect;
00784 
00785             pt.x = (SHORT)LOWORD(lParam);
00786             pt.y = (SHORT)HIWORD(lParam);
00787             ScreenToClient(hwnd,&pt);
00788             SCROLL_GetSizeBox(hwnd,dwStyle,&rect);
00789             if (PtInRect(&rect,pt))
00790             {
00791               if (dwStyle & SBS_SIZEBOXTOPLEFTALIGN)
00792                 return HTTOPLEFT;
00793               else
00794                 return HTBOTTOMRIGHT;
00795             }
00796           }
00797           return DefWindowProcA(hwnd,WM_NCHITTEST,wParam,lParam);
00798         } else if (msg == WM_LBUTTONDOWN)
00799         {
00800           return DefWindowProcA(hwnd,WM_LBUTTONDOWN,wParam,lParam);
00801         }
00802 
00803         return res;
00804       }
00805     }
00806 
00807     if (msg == WM_NCHITTEST) return DefWindowProcA(hwnd,WM_NCHITTEST,wParam,lParam);
00808 
00809     vertical = SCROLL_GetScrollBarRect(hwnd,nBar,&rect,&arrowSize,&thumbSize,&thumbPos);
00810     hwndOwner = (nBar == SB_CTL) ? GetParent(hwnd):hwnd;
00811 
00812     hwndCtl = (nBar == SB_CTL) ? hwnd:0;
00813 
00814     switch (msg)
00815     {
00816       case WM_LBUTTONDOWN:  /* Initialise mouse tracking */
00817         pt.x = (SHORT)LOWORD(lParam);
00818         pt.y = (SHORT)HIWORD(lParam);
00819         SCROLL_trackVertical = vertical;
00820         SCROLL_trackHitTest = hittest = SCROLL_HitTest(hwnd,nBar,pt,FALSE);
00821         if (SCROLL_trackHitTest == SCROLL_NOWHERE)
00822         {
00823           MessageBeep(MB_ICONEXCLAMATION);
00824 
00825           return res;
00826         }
00827         SCROLL_Scrolling = TRUE;
00828         timerRunning = FALSE;
00829         if ((SCROLL_FocusWin == hwnd) && SCROLL_Highlighted)
00830         {
00831           hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0:DCX_WINDOW));
00832           SCROLL_DrawScrollBar(hwnd,hdc,nBar,FALSE,TRUE);
00833           ReleaseDC(hwnd,hdc);
00834         }
00835         lastClickPos  = vertical ? pt.y:pt.x;
00836         lastMousePos  = lastClickPos;
00837         trackThumbPos = thumbPos;
00838         prevPt = pt;
00839         if (nBar == SB_CTL && (GetWindowLongA(hwnd, GWL_STYLE) & WS_TABSTOP)) SetFocus( hwnd );
00840         SetCapture(hwnd);
00841         break;
00842 
00843       case WM_MOUSEMOVE:
00844         if (SCROLL_Scrolling)
00845         {
00846           pt.x = (SHORT)LOWORD(lParam);
00847           pt.y = (SHORT)HIWORD(lParam);
00848           hittest = SCROLL_HitTest(hwnd,nBar,pt,TRUE);
00849           prevPt = pt;
00850         } else return res;
00851         break;
00852 
00853       case WM_LBUTTONUP:
00854         if (SCROLL_Scrolling)
00855         {
00856           pt.x = (SHORT)LOWORD(lParam);
00857           pt.y = (SHORT)HIWORD(lParam);
00858           hittest = SCROLL_NOWHERE;
00859           ReleaseCapture();
00860           SCROLL_Scrolling = FALSE;
00861         } else return res;
00862         break;
00863 
00864       case WM_CAPTURECHANGED:
00865         if (SCROLL_Scrolling)
00866         {
00867           hittest = SCROLL_NOWHERE;
00868           SCROLL_Scrolling = FALSE;
00869         } else return res;
00870         break;
00871 
00872       case WM_SETFOCUS:
00873         if (nBar == SB_CTL)
00874         {
00875           SCROLL_FocusWin   = hwnd;
00876           SCROLL_HasFocus   = TRUE;
00877           SCROLL_Highlighted = FALSE;
00878           SetSystemTimer(hwnd,BLINK_TIMER,SCROLL_BLINK_DELAY,(TIMERPROC)0);
00879         }
00880         return res;
00881 
00882       case WM_KILLFOCUS:
00883         if (SCROLL_FocusWin == hwnd)
00884         {
00885           SCROLL_FocusWin    = 0;
00886           SCROLL_HasFocus    = FALSE;
00887           if (SCROLL_Highlighted)
00888           {
00889             SCROLL_Highlighted = FALSE;
00890             hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0:DCX_WINDOW));
00891             SCROLL_DrawScrollBar(hwnd,hdc,nBar,FALSE,TRUE);
00892             ReleaseDC(hwnd,hdc);
00893           }
00894           KillSystemTimer(hwnd,BLINK_TIMER);
00895         }
00896         return res;
00897 
00898       case WM_SYSTIMER:
00899         if (wParam == SCROLL_TIMER)
00900         {
00901           pt = prevPt;
00902           hittest = SCROLL_HitTest( hwnd, nBar, pt, FALSE );
00903           break;
00904         } else if (wParam == BLINK_TIMER)
00905         {
00906           SCROLL_Highlighted = ~SCROLL_Highlighted;
00907           if (!SCROLL_Scrolling)
00908           {
00909             hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW));
00910             SCROLL_DrawScrollBar(hwnd,hdc,nBar,FALSE,TRUE);
00911             ReleaseDC(hwnd,hdc);
00912           }
00913           return res;
00914         } else return res;
00915 
00916       default:
00917         return res;  /* Should never happen */
00918     }
00919 
00920     hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW));
00921 
00922     switch(SCROLL_trackHitTest)
00923     {
00924       case SCROLL_NOWHERE:  /* No tracking in progress */
00925         break;
00926 
00927       case SCROLL_TOP_ARROW:
00928         if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
00929           KillSystemTimer(hwnd,SCROLL_TIMER);
00930         else if ((msg == WM_LBUTTONDOWN) || (!timerRunning && msg == WM_SYSTIMER))
00931         {
00932           SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
00933                           SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
00934                           (TIMERPROC)0 );
00935           if (msg != WM_LBUTTONDOWN) timerRunning = TRUE;
00936         }
00937 
00938         if ((msg == WM_LBUTTONDOWN) || (SCROLL_lastHitTest != hittest))
00939         {
00940           SCROLL_DrawTopArrow(hdc,infoPtr,&rect,arrowSize,vertical,(hittest == SCROLL_trackHitTest));
00941           SCROLL_lastHitTest = hittest;
00942         }
00943         if ((hittest == SCROLL_trackHitTest) && ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)))
00944           SendMessageA(hwndOwner,vertical ? WM_VSCROLL:WM_HSCROLL,SB_LINEUP,hwndCtl);
00945 
00946         break;
00947 
00948       case SCROLL_TOP_RECT:
00949         if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
00950           KillSystemTimer(hwnd,SCROLL_TIMER);
00951         else if ((msg == WM_LBUTTONDOWN) || (!timerRunning && (msg == WM_SYSTIMER)))
00952         {
00953           SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
00954                           SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
00955                           (TIMERPROC)0 );
00956           if (msg != WM_LBUTTONDOWN) timerRunning = TRUE;
00957         }
00958 
00959         if ((msg == WM_LBUTTONDOWN) || (SCROLL_lastHitTest != hittest))
00960         {
00961           SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
00962                              thumbPos, infoPtr->flags, vertical,
00963                              (hittest == SCROLL_trackHitTest), FALSE );
00964           SCROLL_lastHitTest = hittest;
00965         }
00966 
00967         if ((hittest == SCROLL_trackHitTest) && ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)))
00968           SendMessageA(hwndOwner,vertical ? WM_VSCROLL:WM_HSCROLL,SB_PAGEUP,hwndCtl);
00969 
00970         break;
00971 
00972       case SCROLL_THUMB:
00973         if (msg == WM_LBUTTONDOWN)
00974         {
00975             SCROLL_TrackingWin = hwnd;
00976             SCROLL_TrackingBar = nBar;
00977             SCROLL_TrackingPos = trackThumbPos + lastMousePos - lastClickPos;
00978             SCROLL_TrackingVal = infoPtr->CurVal;
00979             SCROLL_MovingThumb = TRUE;
00980             thumbTrackSent = FALSE;
00981             SCROLL_DrawMovingThumb(hdc, &rect, vertical, arrowSize, thumbSize);
00982         } else if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
00983         {
00984           UINT val;
00985           INT oldPos = infoPtr->CurVal;
00986 
00987           SCROLL_MovingThumb = FALSE;
00988           SCROLL_TrackingWin = 0;
00989           SCROLL_trackHitTest = SCROLL_NOWHERE;  /* Terminate tracking */
00990           val = SCROLL_GetThumbVal( infoPtr, &rect, vertical,
00991                                     trackThumbPos + lastMousePos - lastClickPos );
00992 
00993           if ((val != infoPtr->CurVal) || thumbTrackSent)
00994             SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
00995                           MAKEWPARAM( SB_THUMBPOSITION, val ), hwndCtl );
00996 
00997           if (oldPos == infoPtr->CurVal)
00998           {
00999             vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
01000                                         &arrowSize, &thumbSize, &thumbPos );
01001             SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
01002                                  thumbPos, infoPtr->flags, vertical,
01003                                  FALSE, FALSE );
01004           }
01005 
01006           ReleaseDC(hwnd,hdc);
01007           return res;
01008         } else if (msg == WM_MOUSEMOVE)
01009         {
01010             UINT pos;
01011 
01012 #ifdef __WIN32OS2__
01013             if (!SCROLL_PtInRectEx( &rect, pt, vertical ) && !fOS2Look) pos = lastClickPos;
01014 #else
01015             if (!SCROLL_PtInRectEx( &rect, pt, vertical )) pos = lastClickPos;
01016 #endif
01017             else
01018             {
01019                 pt = SCROLL_ClipPos( &rect, pt );
01020                 pos = vertical ? pt.y:pt.x;
01021             }
01022             if (pos != lastMousePos)
01023             {
01024                 lastMousePos = pos;
01025                 SCROLL_TrackingPos = trackThumbPos + pos - lastClickPos;
01026                 SCROLL_TrackingVal = SCROLL_GetThumbVal( infoPtr, &rect,
01027                                                          vertical,
01028                                                          SCROLL_TrackingPos );
01029                 SCROLL_DrawMovingThumb( hdc, &rect, vertical,
01030                                         arrowSize, thumbSize );
01031                 SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
01032                                 MAKEWPARAM( SB_THUMBTRACK, SCROLL_TrackingVal),
01033                                 hwndCtl );
01034                 thumbTrackSent = TRUE;
01035             }
01036         }
01037         break;
01038 
01039       case SCROLL_BOTTOM_RECT:
01040         if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
01041           KillSystemTimer(hwnd,SCROLL_TIMER);
01042         else if ((msg == WM_LBUTTONDOWN) || (!timerRunning && (msg == WM_SYSTIMER)))
01043         {
01044           SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
01045                           SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
01046                           (TIMERPROC)0 );
01047           if (msg != WM_LBUTTONDOWN) timerRunning = TRUE;
01048         }
01049 
01050         if ((msg == WM_LBUTTONDOWN) || (SCROLL_lastHitTest != hittest))
01051         {
01052           SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
01053                                thumbPos, infoPtr->flags, vertical,
01054                                FALSE, (hittest == SCROLL_trackHitTest) );
01055           SCROLL_lastHitTest = hittest;
01056         }
01057 
01058         if ((hittest == SCROLL_trackHitTest) && ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)))
01059           SendMessageA(hwndOwner,vertical ? WM_VSCROLL:WM_HSCROLL,SB_PAGEDOWN,hwndCtl);
01060 
01061         break;
01062 
01063       case SCROLL_BOTTOM_ARROW:
01064         if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
01065           KillSystemTimer(hwnd,SCROLL_TIMER);
01066         else if ((msg == WM_LBUTTONDOWN) || (!timerRunning && (msg == WM_SYSTIMER)))
01067         {
01068           SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
01069                           SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
01070                           (TIMERPROC)0 );
01071           if (msg != WM_LBUTTONDOWN) timerRunning = TRUE;
01072         }
01073 
01074         if ((msg == WM_LBUTTONDOWN) || (SCROLL_lastHitTest != hittest))
01075         {
01076           SCROLL_DrawBottomArrow(hdc,infoPtr,&rect,arrowSize,vertical,(hittest == SCROLL_trackHitTest));
01077           SCROLL_lastHitTest = hittest;
01078         }
01079         if ((hittest == SCROLL_trackHitTest) && ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)))
01080           SendMessageA(hwndOwner,vertical ? WM_VSCROLL:WM_HSCROLL,SB_LINEDOWN,hwndCtl);
01081 
01082         break;
01083     }
01084 
01085     if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
01086     {
01087       SCROLL_trackHitTest = SCROLL_NOWHERE;  /* Terminate tracking */
01088 
01089       SendMessageA(hwndOwner,vertical ? WM_VSCROLL:WM_HSCROLL,SB_ENDSCROLL,hwndCtl);
01090     }
01091 
01092     ReleaseDC( hwnd, hdc );
01093 
01094     return res;
01095 }
01096 
01097 /***********************************************************************
01098  *           SCROLL_HandleKbdEvent
01099  *
01100  * Handle a keyboard event (only for SB_CTL scrollbars).
01101  */
01102 LRESULT SCROLL_KeyDown(HWND hwnd,WPARAM wParam,LPARAM lParam)
01103 {
01104   DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
01105   UINT msg;
01106 
01107   if (dwStyle & (SBS_SIZEBOX | SBS_SIZEGRIP)) return 0;
01108 
01109   switch(wParam)
01110   {
01111     case VK_PRIOR: msg = SB_PAGEUP; break;
01112     case VK_NEXT:  msg = SB_PAGEDOWN; break;
01113     case VK_HOME:  msg = SB_TOP; break;
01114     case VK_END:   msg = SB_BOTTOM; break;
01115     case VK_UP:    msg = SB_LINEUP; break;
01116     case VK_DOWN:  msg = SB_LINEDOWN; break;
01117     default:
01118       return 0;
01119   }
01120   SendMessageA( GetParent(hwnd),
01121                 (dwStyle & SBS_VERT) ? WM_VSCROLL : WM_HSCROLL,
01122                 msg, hwnd );
01123 
01124   return 0;
01125 }
01126 
01127 LRESULT SCROLL_Paint(HWND hwnd,WPARAM wParam,LPARAM lParam,INT nBar)
01128 {
01129   PAINTSTRUCT ps;
01130   HDC hdc = wParam ? (HDC)wParam:BeginPaint( hwnd, &ps );
01131 
01132   SCROLL_DrawScrollBar( hwnd, hdc, nBar, TRUE, TRUE );
01133   if (!wParam) EndPaint( hwnd, &ps );
01134 
01135   return 0;
01136 }
01137 
01138 LRESULT SCROLL_SetRange(HWND hwnd,WPARAM wParam,LPARAM lParam,INT nBar,BOOL redraw)
01139 {
01140   SCROLLBAR_INFO *infoPtr = SCROLL_GetInfoPtr(hwnd,nBar);
01141   INT oldPos = infoPtr->CurVal;
01142 
01143   SetScrollRange(hwnd,nBar,wParam,lParam,redraw);
01144   return (oldPos != infoPtr->CurVal) ? infoPtr->CurVal:0;
01145 }
01146 
01147 /* Window Procedures */
01148 
01149 /***********************************************************************
01150  *           ScrollBarWndProc
01151  */
01152 LRESULT WINAPI ScrollBarWndProc( HWND hwnd, UINT message, WPARAM wParam,
01153                                  LPARAM lParam )
01154 {
01155   switch(message)
01156   {
01157     case WM_NCCREATE:
01158       return SCROLL_NCCreate(hwnd,wParam,lParam);
01159 
01160     case WM_CREATE:
01161       return SCROLL_Create(hwnd,wParam,lParam);
01162 
01163     case WM_DESTROY:
01164       return SCROLL_Destroy(hwnd,wParam,lParam);
01165 
01166     case WM_LBUTTONDOWN:
01167     case WM_LBUTTONUP:
01168     case WM_NCHITTEST:
01169     case WM_CAPTURECHANGED:
01170     case WM_MOUSEMOVE:
01171     case WM_SYSTIMER:
01172     case WM_SETFOCUS:
01173     case WM_KILLFOCUS:
01174       return SCROLL_HandleScrollEvent(hwnd,wParam,lParam,SB_CTL,message);
01175 
01176     case WM_KEYDOWN:
01177       return SCROLL_KeyDown(hwnd,wParam,lParam);
01178 
01179 #ifdef __WIN32OS2__
01180     case WM_ENABLE:
01181       return SCROLL_Enable(hwnd, wParam);
01182 
01183     case WM_SYSCOMMAND:
01184       //Not entirely sure this is 100% correct, but it seems the logical thing to do
01185       //(for scrollbar control windows with the size grip style)
01186       //Might need to send it to top parent
01187       return SendMessageA(GetParent(hwnd), message, wParam, lParam);
01188 #endif
01189 
01190     case WM_ERASEBKGND:
01191       return 1;
01192 
01193     case WM_GETDLGCODE:
01194       return DLGC_WANTARROWS; /* Windows returns this value */
01195 
01196     case WM_PAINT:
01197       return SCROLL_Paint(hwnd,wParam,lParam,SB_CTL);
01198 
01199     case SBM_SETPOS:
01200       return SetScrollPos( hwnd, SB_CTL, wParam, (BOOL)lParam );
01201 
01202     case SBM_GETPOS:
01203       return GetScrollPos( hwnd, SB_CTL );
01204 
01205     case SBM_SETRANGE:
01206       return SCROLL_SetRange(hwnd,wParam,lParam,SB_CTL,FALSE);
01207 
01208     case SBM_GETRANGE:
01209       GetScrollRange( hwnd, SB_CTL, (LPINT)wParam, (LPINT)lParam );
01210       return 0;
01211 
01212     case SBM_ENABLE_ARROWS:
01213       return EnableScrollBar( hwnd, SB_CTL, wParam );
01214 
01215     case SBM_SETRANGEREDRAW:
01216       return SCROLL_SetRange(hwnd,wParam,lParam,SB_CTL,TRUE);
01217 
01218     case SBM_SETSCROLLINFO:
01219       return SetScrollInfo(hwnd,SB_CTL,(SCROLLINFO*)lParam,wParam);
01220 
01221     case SBM_GETSCROLLINFO:
01222       return GetScrollInfo( hwnd, SB_CTL, (SCROLLINFO *)lParam );
01223 
01224     case 0x00e5:
01225     case 0x00e7:
01226     case 0x00e8:
01227     case 0x00eb:
01228     case 0x00ec:
01229     case 0x00ed:
01230     case 0x00ee:
01231     case 0x00ef:
01232         //ERR("unknown Win32 msg %04x wp=%08x lp=%08lx\n",
01233         //            message, wParam, lParam );
01234         break;
01235 
01236     default:
01237       return DefWindowProcA( hwnd, message, wParam, lParam );
01238   }
01239 
01240   return 0;
01241 }
01242 
01243 /* Scrollbar API */
01244 
01245 /*************************************************************************
01246  *           SetScrollInfo   (USER32.501)
01247  * SetScrollInfo32 can be used to set the position, upper bound,
01248  * lower bound, and page size of a scrollbar control.
01249  *
01250  * RETURNS
01251  *    Scrollbar position
01252  *
01253  * NOTE
01254  *    For 100 lines of text to be displayed in a window of 25 lines,
01255  *  one would for instance use info->nMin=0, info->nMax=75
01256  *  (corresponding to the 76 different positions of the window on
01257  *  the text), and info->nPage=25.
01258  */
01259 INT WINAPI SetScrollInfo(HWND hwnd,INT nBar,const SCROLLINFO *info,BOOL bRedraw)
01260 {
01261     /* Update the scrollbar state and set action flags according to
01262      * what has to be done graphics wise. */
01263 
01264     SCROLLBAR_INFO *infoPtr;
01265     UINT new_flags;
01266     INT action = 0;
01267     BOOL bChangeParams = FALSE; /* don't show/hide scrollbar if params don't change */
01268 
01269     dprintf(("USER32: SetScrollInfo %x %d",hwnd,nBar));
01270 
01271     if(info == NULL) return 0; //Last error not changed (NT4, SP6)
01272 
01273     if (!(infoPtr = SCROLL_GetInfoPtr(hwnd,nBar))) return 0;
01274     if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return 0;
01275     if ((info->cbSize != sizeof(*info)) &&
01276         (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return 0;
01277 
01278     /* Set the page size */
01279     if (info->fMask & SIF_PAGE)
01280     {
01281         if( infoPtr->Page != info->nPage )
01282         {
01283             infoPtr->Page = info->nPage;
01284             action |= SA_SSI_REPAINT_INTERIOR;
01285             bChangeParams = TRUE; 
01286         }
01287     }
01288 
01289     /* Set the scroll pos */
01290     if (info->fMask & SIF_POS)
01291     {
01292         //dsprintf(scroll, " pos=%d", info->nPos );
01293         if( infoPtr->CurVal != info->nPos )
01294         {
01295             infoPtr->CurVal = info->nPos;
01296             action |= SA_SSI_MOVE_THUMB;
01297         }
01298     }
01299 
01300     /* Set the scroll range */
01301     if (info->fMask & SIF_RANGE)
01302     {
01303         /* Invalid range -> range is set to (0,0) */
01304         if ((info->nMin > info->nMax) ||
01305             ((UINT)(info->nMax - info->nMin) >= 0x80000000))
01306         {
01307             //NOTE: This does not fail in NT4 (unlike SetScrollRange)
01308             infoPtr->MinVal = 0;
01309             infoPtr->MaxVal = 0;
01310             bChangeParams = TRUE; 
01311         }
01312         else
01313         {
01314             if( infoPtr->MinVal != info->nMin ||
01315                 infoPtr->MaxVal != info->nMax )
01316             {
01317                 action |= SA_SSI_REPAINT_INTERIOR;
01318                 infoPtr->MinVal = info->nMin;
01319                 infoPtr->MaxVal = info->nMax;
01320                 bChangeParams = TRUE; 
01321             }
01322         }
01323     }
01324 
01325     /* Make sure the page size is valid */
01326     if (infoPtr->Page < 0) infoPtr->Page = 0;
01327     else if (infoPtr->Page > infoPtr->MaxVal - infoPtr->MinVal + 1 )
01328         infoPtr->Page = infoPtr->MaxVal - infoPtr->MinVal + 1;
01329 
01330     /* Make sure the pos is inside the range */
01331 
01332     if (infoPtr->CurVal < infoPtr->MinVal)
01333         infoPtr->CurVal = infoPtr->MinVal;
01334     else if (infoPtr->CurVal > infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 ))
01335         infoPtr->CurVal = infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 );
01336 
01337     //testestest
01338     dprintf(("new values: page=%d pos=%d min=%d max=%d\n",
01339                  infoPtr->Page, infoPtr->CurVal,
01340                  infoPtr->MinVal, infoPtr->MaxVal ));
01341 
01342     /* don't change the scrollbar state if SetScrollInfo
01343      * is just called with SIF_DISABLENOSCROLL
01344      */
01345     if(!(info->fMask & SIF_ALL)) goto done;
01346 
01347     /* Check if the scrollbar should be hidden or disabled */
01348     if (info->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL))
01349     {
01350       new_flags = infoPtr->flags;
01351       if (infoPtr->MinVal >= infoPtr->MaxVal - MAX( infoPtr->Page-1, 0))
01352       {
01353         /* Hide or disable scroll-bar */
01354         if (info->fMask & SIF_DISABLENOSCROLL)
01355         {
01356           new_flags = ESB_DISABLE_BOTH;
01357           action |= SA_SSI_REFRESH;
01358         } 
01359         else 
01360         if (nBar != SB_CTL && bChangeParams)
01361         {
01362           action = SA_SSI_HIDE;
01363           infoPtr->flags = 0;
01364           goto done;
01365         }
01366       } 
01367       else  /* Show and enable scroll-bar */
01368       {
01369         new_flags = 0;
01370         if (nBar != SB_CTL && bChangeParams) action |= SA_SSI_SHOW;
01371         if (infoPtr->flags) action |= SA_SSI_REFRESH;
01372       }
01373 
01374       if (infoPtr->flags != new_flags) /* check arrow flags */
01375       {
01376         infoPtr->flags = new_flags;
01377         action |= SA_SSI_REPAINT_ARROWS;
01378       }
01379     }
01380 
01381 done:
01382     /* Update scrollbar */
01383 
01384     if( action & SA_SSI_HIDE )
01385       ShowScrollBar(hwnd,nBar,FALSE);
01386     else
01387     {
01388         if(action & SA_SSI_SHOW)
01389           ShowScrollBar(hwnd,nBar,TRUE);
01390 
01391         if (bRedraw)
01392         {
01393           if (action & SA_SSI_REFRESH)
01394             SCROLL_RefreshScrollBar(hwnd,nBar,TRUE,TRUE);
01395           else
01396           {
01397             if (action & (SA_SSI_REPAINT_INTERIOR | SA_SSI_MOVE_THUMB))
01398               SCROLL_RefreshScrollBar(hwnd,nBar,FALSE,TRUE);
01399             if (action & SA_SSI_REPAINT_ARROWS)
01400               SCROLL_RefreshScrollBar(hwnd,nBar,TRUE,FALSE);
01401           }
01402         }
01403     }
01404 
01405     /* Return current position */
01406 
01407     return infoPtr->CurVal;
01408 }
01409 /*************************************************************************
01410  *           GetScrollInfo   (USER32.284)
01411  * GetScrollInfo32 can be used to retrieve the position, upper bound,
01412  * lower bound, and page size of a scrollbar control.
01413  *
01414  * RETURNS STD
01415  */
01416 BOOL WINAPI GetScrollInfo(
01417                 HWND hwnd /* [I] Handle of window */ ,
01418                 INT nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */,
01419                 LPSCROLLINFO info /* [IO] (info.fMask [I] specifies which values are to retrieve) */)
01420 {
01421   SCROLLBAR_INFO *infoPtr;
01422 
01423     dprintf(("USER32: GetScrollInfo"));
01424 
01425     if (!(infoPtr = SCROLL_GetInfoPtr(hwnd,nBar))) return FALSE;
01426     if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return FALSE;
01427     if ((info->cbSize != sizeof(*info)) &&
01428         (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return FALSE;
01429 
01430     if (info->fMask & SIF_PAGE) info->nPage = infoPtr->Page;
01431     if (info->fMask & SIF_POS) info->nPos = infoPtr->CurVal;
01432     if ((info->fMask & SIF_TRACKPOS) && (info->cbSize == sizeof(*info)))
01433       info->nTrackPos = (SCROLL_MovingThumb && SCROLL_TrackingWin == hwnd && SCROLL_TrackingBar == nBar) ? SCROLL_TrackingVal:infoPtr->CurVal;
01434 
01435     if (info->fMask & SIF_RANGE)
01436     {
01437         info->nMin = infoPtr->MinVal;
01438         info->nMax = infoPtr->MaxVal;
01439     }
01440     return (info->fMask & SIF_ALL) != 0;
01441 }
01442 /*************************************************************************
01443  *           SetScrollPos   (USER32.502)
01444  *
01445  * RETURNS
01446  *    Success: Scrollbar position
01447  *    Failure: 0
01448  *
01449  * REMARKS
01450  *    Note the ambiguity when 0 is returned.  Use GetLastError
01451  *    to make sure there was an error (and to know which one).
01452  */
01453 INT WINAPI SetScrollPos(
01454                 HWND hwnd /* [I] Handle of window whose scrollbar will be affected */,
01455                 INT nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */,
01456                 INT nPos /* [I] New value */,
01457                 BOOL bRedraw /* [I] Should scrollbar be redrawn afterwards ? */ )
01458 {
01459   SCROLLINFO info;
01460   SCROLLBAR_INFO *infoPtr;
01461   INT oldPos;
01462 
01463     dprintf(("SetScrollPos %x %d %d %d", hwnd, nBar, nPos, bRedraw));
01464     if (!(infoPtr = SCROLL_GetInfoPtr(hwnd,nBar))) return 0;
01465     oldPos      = infoPtr->CurVal;
01466     info.cbSize = sizeof(info);
01467     info.nPos   = nPos;
01468     info.fMask  = SIF_POS;
01469     SetScrollInfo( hwnd, nBar, &info, bRedraw );
01470     return oldPos;
01471 }
01472 /*************************************************************************
01473  *           GetScrollPos   (USER32.285)
01474  *
01475  * RETURNS
01476  *    Success: Current position
01477  *    Failure: 0
01478  *
01479  * REMARKS
01480  *    Note the ambiguity when 0 is returned.  Use GetLastError
01481  *    to make sure there was an error (and to know which one).
01482  */
01483 INT WINAPI GetScrollPos(
01484                 HWND hwnd, /* [I] Handle of window */
01485                 INT nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */)
01486 {
01487   SCROLLBAR_INFO *infoPtr;
01488 
01489     dprintf(("GetScrollPos %x %d", hwnd, nBar));
01490 
01491     infoPtr = SCROLL_GetInfoPtr(hwnd,nBar);
01492     if (!infoPtr) return 0;
01493 
01494     return infoPtr->CurVal;
01495 }
01496 
01497 /*************************************************************************
01498  *           SetScrollRange   (USER32.503)
01499  *
01500  * RETURNS STD
01501  */
01502 BOOL WINAPI SetScrollRange(
01503                 HWND hwnd,   /* [I] Handle of window whose scrollbar will be affected */
01504                 INT nBar,    /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */
01505                 INT MinVal,  /* [I] New minimum value */
01506                 INT MaxVal,  /* [I] New maximum value */
01507                 BOOL bRedraw /* [I] Should scrollbar be redrawn afterwards ? */)
01508 {
01509   SCROLLINFO info;
01510 
01511     dprintf(("SetScrollRange %x %x %d %d %d", hwnd, nBar, MinVal, MaxVal, bRedraw));
01512 
01513     //This is what NT4 does
01514     if ((MinVal > MaxVal) ||
01515         ((UINT)(MaxVal - MinVal) >= 0x80000000))
01516     {
01517         dprintf(("Invalid range"));
01518         SetLastError(ERROR_INVALID_SCROLLBAR_RANGE);
01519         return FALSE;
01520     }
01521 
01522     info.cbSize = sizeof(info);
01523     info.nMin   = MinVal;
01524     info.nMax   = MaxVal;
01525     info.fMask  = SIF_RANGE;
01526 //testestset
01527     static int nestlevel = 0;
01528     
01529     //NOTE: This is an ugly workaround for an endless loop in CVP
01530     //      Need to make sure there isn't a better fix.
01531     if(++nestlevel == 1) 
01532         SetScrollInfo( hwnd, nBar, &info, bRedraw );
01533     nestlevel--;
01534 //testestset
01535     return TRUE;
01536 }
01537 
01538 /*************************************************************************
01539  *           GetScrollRange   (USER32.286)
01540  *
01541  * RETURNS STD
01542  */
01543 BOOL WINAPI GetScrollRange(
01544                 HWND hwnd,   /* [I] Handle of window */
01545                 INT nBar,    /* [I] One of SB_HORZ, SB_VERT, or SB_CTL  */
01546                 LPINT lpMin, /* [O] Where to store minimum value */
01547                 LPINT lpMax  /* [O] Where to store maximum value */)
01548 {
01549   SCROLLBAR_INFO *infoPtr;
01550 
01551     dprintf(("GetScrollRange %x %d %x %x", hwnd, nBar, lpMin, lpMax));
01552     infoPtr = SCROLL_GetInfoPtr(hwnd,nBar);
01553     if (!infoPtr)
01554     {
01555         if (lpMin) lpMin = 0;
01556         if (lpMax) lpMax = 0;
01557         return FALSE;
01558     }
01559     if (lpMin) *lpMin = infoPtr->MinVal;
01560     if (lpMax) *lpMax = infoPtr->MaxVal;
01561     return TRUE;
01562 }
01563 
01564 /*************************************************************************
01565  *           ShowScrollBar   (USER32.532)
01566  *
01567  * RETURNS STD
01568  */
01569 BOOL WINAPI ShowScrollBar(
01570                     HWND hwnd,  /* [I] Handle of window whose scrollbar(s) will be affected   */
01571                     INT nBar,   /* [I] One of SB_HORZ, SB_VERT, SB_BOTH or SB_CTL */
01572                     BOOL fShow  /* [I] TRUE = show, FALSE = hide  */)
01573 {
01574     BOOL fShowH = (nBar == SB_HORZ) ? fShow : 0;
01575     BOOL fShowV = (nBar == SB_VERT) ? fShow : 0;
01576     DWORD dwStyle;
01577 
01578     dprintf(("ShowScrollBar %04x %d %d\n", hwnd, nBar, fShow));
01579     if (!IsWindow(hwnd)) return FALSE;
01580 
01581     dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
01582 
01583     //CB: does Win32 send a WM_STYLECHANGED message?
01584     switch(nBar)
01585     {
01586       case SB_CTL:
01587        ShowWindow(hwnd,fShow ? SW_SHOW:SW_HIDE);
01588        return TRUE;
01589 
01590       case SB_BOTH:
01591       case SB_HORZ:
01592         if (fShow)
01593         {
01594             fShowH = !(dwStyle & WS_HSCROLL);
01595             SetWindowLongA(hwnd, GWL_STYLE, dwStyle | WS_HSCROLL);
01596         }
01597         else  /* hide it */
01598         {
01599             fShowH = (dwStyle & WS_HSCROLL);
01600             SetWindowLongA(hwnd, GWL_STYLE, dwStyle & ~WS_HSCROLL);
01601         }
01602         if( nBar == SB_HORZ )
01603         {
01604             fShowV = FALSE;
01605             break;
01606         }
01607         /* fall through */
01608 
01609     case SB_VERT:
01610         if (fShow)
01611         {
01612             fShowV = !(dwStyle & WS_VSCROLL);
01613             SetWindowLongA(hwnd, GWL_STYLE, dwStyle | WS_VSCROLL);
01614         }
01615         else  /* hide it */
01616         {
01617             fShowV = (dwStyle & WS_VSCROLL);
01618             SetWindowLongA(hwnd, GWL_STYLE, dwStyle & ~WS_VSCROLL);
01619         }
01620         if ( nBar == SB_VERT )
01621            fShowH = FALSE;
01622         break;
01623 
01624     default:
01625         return TRUE;  /* Nothing to do! */
01626     }
01627 
01628     if( fShowH || fShowV ) /* frame has been changed, let the window redraw itself */
01629     {
01630         SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE
01631                     | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
01632     }
01633 
01634     return TRUE;
01635 }
01636 
01637 /*************************************************************************
01638  *           EnableScrollBar   (USER32.171)
01639  */
01640 BOOL WINAPI EnableScrollBar( HWND hwnd, INT nBar, UINT flags)
01641 {
01642     BOOL bFineWithMe;
01643     SCROLLBAR_INFO *infoPtr;
01644 
01645     dprintf(("EnableScrollBar %04x %d %d\n", hwnd, nBar, flags));
01646 
01647     flags &= ESB_DISABLE_BOTH;
01648 
01649     if (nBar == SB_BOTH)
01650     {
01651         if (!(infoPtr = SCROLL_GetInfoPtr( hwnd, SB_VERT ))) return FALSE;
01652         if (!(bFineWithMe = (infoPtr->flags == flags)) )
01653         {
01654             infoPtr->flags = flags;
01655             SCROLL_RefreshScrollBar( hwnd, SB_VERT, TRUE, TRUE );
01656         }
01657         nBar = SB_HORZ;
01658     }
01659     else
01660         bFineWithMe = TRUE;
01661 
01662     if (!(infoPtr = SCROLL_GetInfoPtr( hwnd, nBar ))) return FALSE;
01663     if (bFineWithMe && infoPtr->flags == flags) return FALSE;
01664     infoPtr->flags = flags;
01665 
01666     SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
01667     return TRUE;
01668 }
01669 
01670 BOOL WINAPI GetScrollBarInfo(HWND hwnd,LONG idObject,PSCROLLBARINFO psbi)
01671 {
01672   if (!psbi || (psbi->cbSize != sizeof(SCROLLBARINFO)))
01673   {
01674     SetLastError(ERROR_INVALID_PARAMETER);
01675 
01676     return FALSE;
01677   }
01678 
01679   dprintf(("GetScrollBarInfo %x %d %x", hwnd, idObject, psbi));
01680 
01681   INT nBar,arrowSize;
01682 
01683   switch (idObject)
01684   {
01685     case OBJID_CLIENT:
01686       nBar = SB_CTL;
01687       break;
01688 
01689     case OBJID_HSCROLL:
01690       nBar = SB_HORZ;
01691       break;
01692 
01693     case OBJID_VSCROLL:
01694       nBar = SB_VERT;
01695       break;
01696 
01697     default:
01698       return FALSE;
01699   }
01700 
01701   SCROLL_GetScrollBarRect(hwnd,nBar,&psbi->rcScrollBar,&arrowSize,&psbi->dxyLineButton,&psbi->xyThumbTop);
01702   psbi->xyThumbBottom = psbi->xyThumbTop+psbi->dxyLineButton;
01703   psbi->bogus = 0; //CB: undocumented!
01704   psbi->rgstate[0] = IsWindowVisible(hwnd) ? STATE_SYSTEM_INVISIBLE:0;
01705   psbi->rgstate[1] = psbi->rgstate[2] = psbi->rgstate[3] = psbi->rgstate[4] = psbi->rgstate[5] = psbi->rgstate[0]; //CB: todo
01706 
01707   return TRUE;
01708 }
01709 //******************************************************************************
01710 //******************************************************************************
01711 BOOL SCROLLBAR_Register()
01712 {
01713     WNDCLASSA wndClass;
01714 
01715 //SvL: Don't check this now
01716 //    if (GlobalFindAtomA(SCROLLBARCLASSNAME)) return FALSE;
01717 
01718     ZeroMemory(&wndClass,sizeof(WNDCLASSA));
01719     wndClass.style         = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW | CS_PARENTDC;
01720     wndClass.lpfnWndProc   = (WNDPROC)ScrollBarWndProc;
01721     wndClass.cbClsExtra    = 0;
01722     wndClass.cbWndExtra    = sizeof(SCROLLBAR_INFO);
01723     wndClass.hCursor       = LoadCursorA(0,IDC_ARROWA);
01724     wndClass.hbrBackground = (HBRUSH)0;
01725     wndClass.lpszClassName = SCROLLBARCLASSNAME;
01726 
01727     return RegisterClassA(&wndClass);
01728 }
01729 //******************************************************************************
01730 //******************************************************************************
01731 BOOL SCROLLBAR_Unregister()
01732 {
01733     if (GlobalFindAtomA(SCROLLBARCLASSNAME))
01734         return UnregisterClassA(SCROLLBARCLASSNAME,(HINSTANCE)NULL);
01735     else return FALSE;
01736 }
01737 //******************************************************************************
01738 //******************************************************************************
01739 

Generated on Wed Jan 23 23:17:42 2002 for ODIN-user32 by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001