Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenncscrollbar.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS uxtheme.dll 00004 * FILE: dll/win32/uxtheme/ncscrollbar.c 00005 * PURPOSE: uxtheme scrollbar support 00006 * PROGRAMMER: Giannis Adamopoulos 00007 * This file is heavily based on code from the wine project: 00008 * Copyright 1993 Martin Ayotte 00009 * Copyright 1994, 1996 Alexandre Julliard 00010 */ 00011 00012 #include "uxthemep.h" 00013 #include "wine/debug.h" 00014 00015 WINE_DEFAULT_DEBUG_CHANNEL(uxtheme); 00016 00017 static BOOL SCROLL_trackVertical; 00018 static enum SCROLL_HITTEST SCROLL_trackHitTest; 00019 /* Is the moving thumb being displayed? */ 00020 static BOOL SCROLL_MovingThumb = FALSE; 00021 static HWND SCROLL_TrackingWin = 0; 00022 static INT SCROLL_TrackingBar = 0; 00023 static INT SCROLL_TrackingPos = 0; 00024 static INT SCROLL_TrackingVal = 0; 00025 00026 void static ScreenToWindow( HWND hWnd, POINT* pt) 00027 { 00028 RECT rcWnd; 00029 GetWindowRect(hWnd, &rcWnd); 00030 pt->x -= rcWnd.left; 00031 pt->y -= rcWnd.top; 00032 } 00033 00034 static BOOL SCROLL_IsVertical(HWND hwnd, INT nBar) 00035 { 00036 switch(nBar) 00037 { 00038 case SB_HORZ: 00039 return FALSE; 00040 case SB_VERT: 00041 return TRUE; 00042 default: 00043 assert(FALSE); 00044 return FALSE; 00045 } 00046 } 00047 00048 static LONG SCROLL_getObjectId(INT nBar) 00049 { 00050 switch(nBar) 00051 { 00052 case SB_HORZ: 00053 return OBJID_HSCROLL; 00054 case SB_VERT: 00055 return OBJID_VSCROLL; 00056 default: 00057 assert(FALSE); 00058 return 0; 00059 } 00060 } 00061 00062 /*********************************************************************** 00063 * SCROLL_PtInRectEx 00064 */ 00065 static BOOL SCROLL_PtInRectEx( LPRECT lpRect, POINT pt, BOOL vertical ) 00066 { 00067 RECT rect = *lpRect; 00068 int scrollbarWidth; 00069 00070 /* Pad hit rect to allow mouse to be dragged outside of scrollbar and 00071 * still be considered in the scrollbar. */ 00072 if (vertical) 00073 { 00074 scrollbarWidth = lpRect->right - lpRect->left; 00075 rect.left -= scrollbarWidth*8; 00076 rect.right += scrollbarWidth*8; 00077 rect.top -= scrollbarWidth*2; 00078 rect.bottom += scrollbarWidth*2; 00079 } 00080 else 00081 { 00082 scrollbarWidth = lpRect->bottom - lpRect->top; 00083 rect.left -= scrollbarWidth*2; 00084 rect.right += scrollbarWidth*2; 00085 rect.top -= scrollbarWidth*8; 00086 rect.bottom += scrollbarWidth*8; 00087 } 00088 return PtInRect( &rect, pt ); 00089 } 00090 00091 00092 /*********************************************************************** 00093 * SCROLL_HitTest 00094 * 00095 * Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!). 00096 */ 00097 static enum SCROLL_HITTEST SCROLL_HitTest( HWND hwnd, SCROLLBARINFO* psbi, BOOL vertical, 00098 POINT pt, BOOL bDragging ) 00099 { 00100 if ( (bDragging && !SCROLL_PtInRectEx( &psbi->rcScrollBar, pt, vertical )) || 00101 (!PtInRect( &psbi->rcScrollBar, pt )) ) 00102 { 00103 return SCROLL_NOWHERE; 00104 } 00105 00106 if (vertical) 00107 { 00108 if (pt.y < psbi->rcScrollBar.top + psbi->dxyLineButton) 00109 return SCROLL_TOP_ARROW; 00110 if (pt.y >= psbi->rcScrollBar.bottom - psbi->dxyLineButton) 00111 return SCROLL_BOTTOM_ARROW; 00112 if (!psbi->xyThumbTop) 00113 return SCROLL_TOP_RECT; 00114 pt.y -= psbi->rcScrollBar.top; 00115 if (pt.y < psbi->xyThumbTop) 00116 return SCROLL_TOP_RECT; 00117 if (pt.y >= psbi->xyThumbTop + psbi->dxyLineButton) 00118 return SCROLL_BOTTOM_RECT; 00119 } 00120 else /* horizontal */ 00121 { 00122 if (pt.x < psbi->rcScrollBar.left + psbi->dxyLineButton) 00123 return SCROLL_TOP_ARROW; 00124 if (pt.x >= psbi->rcScrollBar.right - psbi->dxyLineButton) 00125 return SCROLL_BOTTOM_ARROW; 00126 if (!psbi->xyThumbTop) 00127 return SCROLL_TOP_RECT; 00128 pt.x -= psbi->rcScrollBar.left; 00129 if (pt.x < psbi->xyThumbTop) 00130 return SCROLL_TOP_RECT; 00131 if (pt.x >= psbi->xyThumbTop + psbi->dxyLineButton) 00132 return SCROLL_BOTTOM_RECT; 00133 } 00134 return SCROLL_THUMB; 00135 } 00136 00137 static void SCROLL_ThemeDrawPart(PDRAW_CONTEXT pcontext, int iPartId,int iStateId, SCROLLBARINFO* psbi, int htCurrent, int htDown, int htHot, RECT* r) 00138 { 00139 if(psbi->rgstate[htCurrent] & STATE_SYSTEM_UNAVAILABLE) 00140 iStateId += BUTTON_DISABLED - BUTTON_NORMAL; 00141 else if (htHot == htCurrent) 00142 iStateId += BUTTON_HOT - BUTTON_NORMAL; 00143 else if (htDown == htCurrent) 00144 iStateId += BUTTON_PRESSED - BUTTON_NORMAL; 00145 00146 DrawThemeBackground(pcontext->scrolltheme, pcontext->hDC, iPartId, iStateId, r, NULL); 00147 } 00148 00149 /*********************************************************************** 00150 * SCROLL_DrawArrows 00151 * 00152 * Draw the scroll bar arrows. 00153 */ 00154 static void SCROLL_DrawArrows( PDRAW_CONTEXT pcontext, SCROLLBARINFO* psbi, 00155 BOOL vertical, int htDown, int htHot ) 00156 { 00157 RECT r; 00158 int iStateId; 00159 00160 r = psbi->rcScrollBar; 00161 if( vertical ) 00162 { 00163 r.bottom = r.top + psbi->dxyLineButton; 00164 iStateId = ABS_UPNORMAL; 00165 } 00166 else 00167 { 00168 r.right = r.left + psbi->dxyLineButton; 00169 iStateId = ABS_LEFTNORMAL; 00170 } 00171 00172 SCROLL_ThemeDrawPart(pcontext, SBP_ARROWBTN, iStateId, psbi, SCROLL_TOP_ARROW, htDown, htHot, &r); 00173 00174 r = psbi->rcScrollBar; 00175 if( vertical ) 00176 { 00177 r.top = r.bottom - psbi->dxyLineButton; 00178 iStateId = ABS_DOWNNORMAL; 00179 } 00180 else 00181 { 00182 iStateId = ABS_RIGHTNORMAL; 00183 r.left = r.right - psbi->dxyLineButton; 00184 } 00185 00186 SCROLL_ThemeDrawPart(pcontext, SBP_ARROWBTN, iStateId, psbi, SCROLL_BOTTOM_ARROW, htDown, htHot, &r); 00187 } 00188 00189 static void SCROLL_DrawInterior( PDRAW_CONTEXT pcontext, SCROLLBARINFO* psbi, 00190 INT thumbPos, BOOL vertical, 00191 int htDown, int htHot ) 00192 { 00193 RECT r, rcPart; 00194 00195 r = psbi->rcScrollBar; 00196 if (vertical) 00197 { 00198 r.top += psbi->dxyLineButton; 00199 r.bottom -= (psbi->dxyLineButton); 00200 } 00201 else 00202 { 00203 r.left += psbi->dxyLineButton; 00204 r.right -= psbi->dxyLineButton; 00205 } 00206 00207 /* Draw the scroll rectangles and thumb */ 00208 00209 if (!thumbPos) /* No thumb to draw */ 00210 { 00211 rcPart = r; 00212 SCROLL_ThemeDrawPart(pcontext, vertical ? SBP_UPPERTRACKVERT: SBP_UPPERTRACKHORZ , BUTTON_NORMAL, psbi, SCROLL_THUMB, 0, 0, &rcPart); 00213 return; 00214 } 00215 00216 if (vertical) 00217 { 00218 rcPart = r; 00219 rcPart.bottom = rcPart.top + thumbPos - psbi->dxyLineButton; 00220 SCROLL_ThemeDrawPart(pcontext, SBP_UPPERTRACKVERT, BUTTON_NORMAL, psbi, SCROLL_TOP_RECT, htDown, htHot, &rcPart); 00221 r.top = rcPart.bottom; 00222 00223 rcPart = r; 00224 rcPart.top += psbi->dxyLineButton; 00225 SCROLL_ThemeDrawPart(pcontext, SBP_LOWERTRACKVERT, BUTTON_NORMAL, psbi, SCROLL_BOTTOM_RECT, htDown, htHot, &rcPart); 00226 r.bottom = rcPart.top; 00227 00228 SCROLL_ThemeDrawPart(pcontext, SBP_THUMBBTNVERT, BUTTON_NORMAL, psbi, SCROLL_THUMB, htDown, htHot, &r); 00229 SCROLL_ThemeDrawPart(pcontext, SBP_GRIPPERVERT, BUTTON_NORMAL, psbi, SCROLL_THUMB, htDown, htHot, &r); 00230 } 00231 else /* horizontal */ 00232 { 00233 rcPart = r; 00234 rcPart.right = rcPart.left + thumbPos - psbi->dxyLineButton; 00235 SCROLL_ThemeDrawPart(pcontext, SBP_UPPERTRACKHORZ, BUTTON_NORMAL, psbi, SCROLL_TOP_RECT, htDown, htHot, &rcPart); 00236 r.left = rcPart.right; 00237 00238 rcPart = r; 00239 rcPart.left += psbi->dxyLineButton; 00240 SCROLL_ThemeDrawPart(pcontext, SBP_LOWERTRACKHORZ, BUTTON_NORMAL, psbi, SCROLL_BOTTOM_RECT, htDown, htHot, &rcPart); 00241 r.right = rcPart.left; 00242 00243 SCROLL_ThemeDrawPart(pcontext, SBP_THUMBBTNHORZ, BUTTON_NORMAL, psbi, SCROLL_THUMB, htDown, htHot, &r); 00244 SCROLL_ThemeDrawPart(pcontext, SBP_GRIPPERHORZ, BUTTON_NORMAL, psbi, SCROLL_THUMB, htDown, htHot, &r); 00245 } 00246 } 00247 00248 static void SCROLL_DrawMovingThumb( PDRAW_CONTEXT pcontext, SCROLLBARINFO* psbi, BOOL vertical) 00249 { 00250 INT pos = SCROLL_TrackingPos; 00251 INT max_size; 00252 00253 if( vertical ) 00254 max_size = psbi->rcScrollBar.bottom - psbi->rcScrollBar.top; 00255 else 00256 max_size = psbi->rcScrollBar.right - psbi->rcScrollBar.left; 00257 00258 max_size -= (psbi->dxyLineButton -SCROLL_ARROW_THUMB_OVERLAP) + psbi->dxyLineButton; 00259 00260 if( pos < (psbi->dxyLineButton-SCROLL_ARROW_THUMB_OVERLAP) ) 00261 pos = (psbi->dxyLineButton-SCROLL_ARROW_THUMB_OVERLAP); 00262 else if( pos > max_size ) 00263 pos = max_size; 00264 00265 SCROLL_DrawInterior(pcontext, psbi, pos, vertical, SCROLL_THUMB, 0); 00266 00267 SCROLL_MovingThumb = !SCROLL_MovingThumb; 00268 } 00269 00270 00271 void 00272 ThemeDrawScrollBar(PDRAW_CONTEXT pcontext, INT nBar, POINT* pt) 00273 { 00274 SCROLLINFO si; 00275 SCROLLBARINFO sbi; 00276 BOOL vertical; 00277 enum SCROLL_HITTEST htHot = SCROLL_NOWHERE; 00278 00279 /* Retrieve scrollbar info */ 00280 sbi.cbSize = sizeof(sbi); 00281 si.cbSize = sizeof(si); 00282 si.fMask = SIF_ALL ; 00283 GetScrollInfo(pcontext->hWnd, nBar, &si); 00284 GetScrollBarInfo(pcontext->hWnd, SCROLL_getObjectId(nBar), &sbi); 00285 vertical = SCROLL_IsVertical(pcontext->hWnd, nBar); 00286 if(sbi.rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_UNAVAILABLE && 00287 sbi.rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_UNAVAILABLE ) 00288 { 00289 sbi.xyThumbTop = 0; 00290 } 00291 00292 #ifndef ROS_SUCKS 00293 /* The scrollbar rect is in screen coordinates */ 00294 // OffsetRect(&sbi.rcScrollBar, -pcontext->wi.rcWindow.left, -pcontext->wi.rcWindow.top); 00295 #endif 00296 00297 if(pt) 00298 { 00299 ScreenToWindow(pcontext->hWnd, pt); 00300 htHot = SCROLL_HitTest(pcontext->hWnd, &sbi, vertical, *pt, FALSE); 00301 } 00302 00303 if (((nBar == SB_VERT) && !(pcontext->wi.dwStyle & WS_VSCROLL)) || 00304 ((nBar == SB_HORZ) && !(pcontext->wi.dwStyle & WS_HSCROLL))) return; 00305 00306 /* do not draw if the scrollbar rectangle is empty */ 00307 if(IsRectEmpty(&sbi.rcScrollBar)) return; 00308 00309 /* Draw the scrollbar */ 00310 SCROLL_DrawArrows( pcontext, &sbi, vertical, 0, htHot ); 00311 SCROLL_DrawInterior( pcontext, &sbi, sbi.xyThumbTop, vertical, 0, htHot ); 00312 } 00313 00314 00315 00316 /*********************************************************************** 00317 * SCROLL_ClipPos 00318 */ 00319 static POINT SCROLL_ClipPos( LPRECT lpRect, POINT pt ) 00320 { 00321 if( pt.x < lpRect->left ) 00322 pt.x = lpRect->left; 00323 else 00324 if( pt.x > lpRect->right ) 00325 pt.x = lpRect->right; 00326 00327 if( pt.y < lpRect->top ) 00328 pt.y = lpRect->top; 00329 else 00330 if( pt.y > lpRect->bottom ) 00331 pt.y = lpRect->bottom; 00332 00333 return pt; 00334 } 00335 00336 00337 00338 /*********************************************************************** 00339 * SCROLL_GetThumbVal 00340 * 00341 * Compute the current scroll position based on the thumb position in pixels 00342 * from the top of the scroll-bar. 00343 */ 00344 static UINT SCROLL_GetThumbVal( SCROLLINFO *psi, RECT *rect, 00345 BOOL vertical, INT pos ) 00346 { 00347 INT thumbSize; 00348 INT pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left; 00349 INT range; 00350 00351 if ((pixels -= 2*(GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)) <= 0) 00352 return psi->nMin; 00353 00354 if (psi->nPage) 00355 { 00356 thumbSize = MulDiv(pixels,psi->nPage,(psi->nMax-psi->nMin+1)); 00357 if (thumbSize < SCROLL_MIN_THUMB) thumbSize = SCROLL_MIN_THUMB; 00358 } 00359 else thumbSize = GetSystemMetrics(SM_CXVSCROLL); 00360 00361 if ((pixels -= thumbSize) <= 0) return psi->nMin; 00362 00363 pos = max( 0, pos - (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP) ); 00364 if (pos > pixels) pos = pixels; 00365 00366 if (!psi->nPage) 00367 range = psi->nMax - psi->nMin; 00368 else 00369 range = psi->nMax - psi->nMin - psi->nPage + 1; 00370 00371 return psi->nMin + MulDiv(pos, range, pixels); 00372 } 00373 00374 static void 00375 SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt) 00376 { 00377 /* Previous mouse position for timer events */ 00378 static POINT prevPt; 00379 /* Thumb position when tracking started. */ 00380 static UINT trackThumbPos; 00381 /* Position in the scroll-bar of the last button-down event. */ 00382 static INT lastClickPos; 00383 /* Position in the scroll-bar of the last mouse event. */ 00384 static INT lastMousePos; 00385 00386 enum SCROLL_HITTEST hittest; 00387 HWND hwndOwner, hwndCtl; 00388 BOOL vertical; 00389 SCROLLINFO si; 00390 SCROLLBARINFO sbi; 00391 DRAW_CONTEXT context; 00392 00393 si.cbSize = sizeof(si); 00394 sbi.cbSize = sizeof(sbi); 00395 si.fMask = SIF_ALL; 00396 GetScrollInfo(hwnd, nBar, &si); 00397 GetScrollBarInfo(hwnd, SCROLL_getObjectId(nBar), &sbi); 00398 vertical = SCROLL_IsVertical(hwnd, nBar); 00399 if(sbi.rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_UNAVAILABLE && 00400 sbi.rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_UNAVAILABLE ) 00401 { 00402 return; 00403 } 00404 ThemeInitDrawContext(&context, hwnd, 0); 00405 00406 #ifndef ROS_SUCKS 00407 /* The scrollbar rect is in screen coordinates */ 00408 // OffsetRect(&sbi.rcScrollBar, -context.wi.rcWindow.left, -context.wi.rcWindow.top); 00409 #endif 00410 00411 if ((SCROLL_trackHitTest == SCROLL_NOWHERE) && (msg != WM_LBUTTONDOWN)) 00412 return; 00413 00414 hwndOwner = (nBar == SB_CTL) ? GetParent(hwnd) : hwnd; 00415 hwndCtl = (nBar == SB_CTL) ? hwnd : 0; 00416 00417 switch(msg) 00418 { 00419 case WM_LBUTTONDOWN: /* Initialise mouse tracking */ 00420 HideCaret(hwnd); /* hide caret while holding down LBUTTON */ 00421 SCROLL_trackVertical = vertical; 00422 SCROLL_trackHitTest = hittest = SCROLL_HitTest( hwnd, &sbi, vertical, pt, FALSE ); 00423 lastClickPos = vertical ? (pt.y - sbi.rcScrollBar.top) : (pt.x - sbi.rcScrollBar.left); 00424 lastMousePos = lastClickPos; 00425 trackThumbPos = sbi.xyThumbTop; 00426 prevPt = pt; 00427 SetCapture( hwnd ); 00428 break; 00429 00430 case WM_MOUSEMOVE: 00431 hittest = SCROLL_HitTest( hwnd, &sbi, vertical, pt, TRUE ); 00432 prevPt = pt; 00433 break; 00434 00435 case WM_LBUTTONUP: 00436 hittest = SCROLL_NOWHERE; 00437 ReleaseCapture(); 00438 /* if scrollbar has focus, show back caret */ 00439 if (hwnd==GetFocus()) 00440 ShowCaret(hwnd); 00441 break; 00442 00443 case WM_SYSTIMER: 00444 pt = prevPt; 00445 hittest = SCROLL_HitTest( hwnd, &sbi, vertical, pt, FALSE ); 00446 break; 00447 00448 default: 00449 return; /* Should never happen */ 00450 } 00451 00452 //TRACE("Event: hwnd=%p bar=%d msg=%s pt=%d,%d hit=%d\n", 00453 // hwnd, nBar, SPY_GetMsgName(msg,hwnd), pt.x, pt.y, hittest ); 00454 00455 switch(SCROLL_trackHitTest) 00456 { 00457 case SCROLL_NOWHERE: /* No tracking in progress */ 00458 break; 00459 00460 case SCROLL_TOP_ARROW: 00461 if (hittest == SCROLL_trackHitTest) 00462 { 00463 SCROLL_DrawArrows( &context, &sbi, vertical, SCROLL_trackHitTest, 0 ); 00464 if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)) 00465 { 00466 SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, 00467 SB_LINEUP, (LPARAM)hwndCtl ); 00468 } 00469 00470 SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? 00471 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL ); 00472 } 00473 else 00474 { 00475 SCROLL_DrawArrows( &context, &sbi, vertical, 0, 0 ); 00476 KillSystemTimer( hwnd, SCROLL_TIMER ); 00477 } 00478 00479 break; 00480 00481 case SCROLL_TOP_RECT: 00482 SCROLL_DrawInterior( &context, &sbi, sbi.xyThumbTop, vertical, SCROLL_trackHitTest, 0); 00483 if (hittest == SCROLL_trackHitTest) 00484 { 00485 if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)) 00486 { 00487 SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, 00488 SB_PAGEUP, (LPARAM)hwndCtl ); 00489 } 00490 SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? 00491 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL ); 00492 } 00493 else KillSystemTimer( hwnd, SCROLL_TIMER ); 00494 break; 00495 00496 case SCROLL_THUMB: 00497 if (msg == WM_LBUTTONDOWN) 00498 { 00499 SCROLL_TrackingWin = hwnd; 00500 SCROLL_TrackingBar = nBar; 00501 SCROLL_TrackingPos = trackThumbPos + lastMousePos - lastClickPos; 00502 SCROLL_TrackingVal = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar, 00503 vertical, SCROLL_TrackingPos ); 00504 if (!SCROLL_MovingThumb) 00505 SCROLL_DrawMovingThumb(&context, &sbi, vertical); 00506 } 00507 else if (msg == WM_LBUTTONUP) 00508 { 00509 if (SCROLL_MovingThumb) 00510 SCROLL_DrawMovingThumb(&context, &sbi, vertical); 00511 00512 SCROLL_DrawInterior( &context, &sbi, sbi.xyThumbTop, vertical, 0, SCROLL_trackHitTest ); 00513 } 00514 else /* WM_MOUSEMOVE */ 00515 { 00516 INT pos; 00517 00518 if (!SCROLL_PtInRectEx( &sbi.rcScrollBar, pt, vertical )) 00519 pos = lastClickPos; 00520 else 00521 { 00522 pt = SCROLL_ClipPos( &sbi.rcScrollBar, pt ); 00523 pos = vertical ? (pt.y - sbi.rcScrollBar.top) : (pt.x - sbi.rcScrollBar.left); 00524 } 00525 if ( (pos != lastMousePos) || (!SCROLL_MovingThumb) ) 00526 { 00527 if (SCROLL_MovingThumb) 00528 SCROLL_DrawMovingThumb( &context, &sbi, vertical); 00529 lastMousePos = pos; 00530 SCROLL_TrackingPos = trackThumbPos + pos - lastClickPos; 00531 SCROLL_TrackingVal = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar, 00532 vertical, 00533 SCROLL_TrackingPos ); 00534 SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, 00535 MAKEWPARAM( SB_THUMBTRACK, SCROLL_TrackingVal), 00536 (LPARAM)hwndCtl ); 00537 if (!SCROLL_MovingThumb) 00538 SCROLL_DrawMovingThumb( &context, &sbi, vertical); 00539 } 00540 } 00541 break; 00542 00543 case SCROLL_BOTTOM_RECT: 00544 if (hittest == SCROLL_trackHitTest) 00545 { 00546 SCROLL_DrawInterior( &context, &sbi, sbi.xyThumbTop, vertical, SCROLL_trackHitTest, 0 ); 00547 if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)) 00548 { 00549 SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, 00550 SB_PAGEDOWN, (LPARAM)hwndCtl ); 00551 } 00552 SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? 00553 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL ); 00554 } 00555 else 00556 { 00557 SCROLL_DrawInterior( &context, &sbi, sbi.xyThumbTop, vertical, 0, 0 ); 00558 KillSystemTimer( hwnd, SCROLL_TIMER ); 00559 } 00560 break; 00561 00562 case SCROLL_BOTTOM_ARROW: 00563 if (hittest == SCROLL_trackHitTest) 00564 { 00565 SCROLL_DrawArrows( &context, &sbi, vertical, SCROLL_trackHitTest, 0 ); 00566 if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)) 00567 { 00568 SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, 00569 SB_LINEDOWN, (LPARAM)hwndCtl ); 00570 } 00571 00572 SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? 00573 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL ); 00574 } 00575 else 00576 { 00577 SCROLL_DrawArrows( &context, &sbi, vertical, 0, 0 ); 00578 KillSystemTimer( hwnd, SCROLL_TIMER ); 00579 } 00580 break; 00581 } 00582 00583 if (msg == WM_LBUTTONDOWN) 00584 { 00585 00586 if (hittest == SCROLL_THUMB) 00587 { 00588 UINT val = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar, vertical, 00589 trackThumbPos + lastMousePos - lastClickPos ); 00590 SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, 00591 MAKEWPARAM( SB_THUMBTRACK, val ), (LPARAM)hwndCtl ); 00592 } 00593 } 00594 00595 if (msg == WM_LBUTTONUP) 00596 { 00597 hittest = SCROLL_trackHitTest; 00598 SCROLL_trackHitTest = SCROLL_NOWHERE; /* Terminate tracking */ 00599 00600 if (hittest == SCROLL_THUMB) 00601 { 00602 UINT val = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar, vertical, 00603 trackThumbPos + lastMousePos - lastClickPos ); 00604 SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, 00605 MAKEWPARAM( SB_THUMBPOSITION, val ), (LPARAM)hwndCtl ); 00606 } 00607 /* SB_ENDSCROLL doesn't report thumb position */ 00608 SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, 00609 SB_ENDSCROLL, (LPARAM)hwndCtl ); 00610 00611 /* Terminate tracking */ 00612 SCROLL_TrackingWin = 0; 00613 } 00614 00615 ThemeCleanupDrawContext(&context); 00616 } 00617 00618 static void 00619 SCROLL_TrackScrollBar( HWND hwnd, INT scrollbar, POINT pt ) 00620 { 00621 MSG msg; 00622 00623 ScreenToWindow(hwnd, &pt); 00624 00625 SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt ); 00626 00627 do 00628 { 00629 if (!GetMessageW( &msg, 0, 0, 0 )) break; 00630 if (CallMsgFilterW( &msg, MSGF_SCROLLBAR )) continue; 00631 if (msg.message == WM_LBUTTONUP || 00632 msg.message == WM_MOUSEMOVE || 00633 (msg.message == WM_SYSTIMER && msg.wParam == SCROLL_TIMER)) 00634 { 00635 pt.x = GET_X_LPARAM(msg.lParam); 00636 pt.y = GET_Y_LPARAM(msg.lParam); 00637 ClientToScreen(hwnd, &pt); 00638 ScreenToWindow(hwnd, &pt); 00639 SCROLL_HandleScrollEvent( hwnd, scrollbar, msg.message, pt ); 00640 } 00641 else 00642 { 00643 TranslateMessage( &msg ); 00644 DispatchMessageW( &msg ); 00645 } 00646 if (!IsWindow( hwnd )) 00647 { 00648 ReleaseCapture(); 00649 break; 00650 } 00651 } while (msg.message != WM_LBUTTONUP && GetCapture() == hwnd); 00652 } 00653 00654 void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt ) 00655 { 00656 INT scrollbar; 00657 00658 if ((wParam & 0xfff0) == SC_HSCROLL) 00659 { 00660 if ((wParam & 0x0f) != HTHSCROLL) return; 00661 scrollbar = SB_HORZ; 00662 } 00663 else /* SC_VSCROLL */ 00664 { 00665 if ((wParam & 0x0f) != HTVSCROLL) return; 00666 scrollbar = SB_VERT; 00667 } 00668 SCROLL_TrackScrollBar( hwnd, scrollbar, pt ); 00669 } Generated on Mon May 28 2012 04:26:24 for ReactOS by
1.7.6.1
|