1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * PURPOSE: Scrollbars 5 * FILE: win32ss/user/ntuser/scrollbar.c 6 * PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net) 7 * Jason Filby (jasonfilby@yahoo.com) 8 */ 9 10 #include <win32k.h> 11 DBG_DEFAULT_CHANNEL(UserScrollbar); 12 13 /* Definitions for scrollbar hit testing [See SCROLLBARINFO in MSDN] */ 14 #define SCROLL_NOWHERE 0x00 /* Outside the scroll bar */ 15 #define SCROLL_TOP_ARROW 0x01 /* Top or left arrow */ 16 #define SCROLL_TOP_RECT 0x02 /* Rectangle between the top arrow and the thumb */ 17 #define SCROLL_THUMB 0x03 /* Thumb rectangle */ 18 #define SCROLL_BOTTOM_RECT 0x04 /* Rectangle between the thumb and the bottom arrow */ 19 #define SCROLL_BOTTOM_ARROW 0x05 /* Bottom or right arrow */ 20 21 #define SCROLL_FIRST_DELAY 200 /* Delay (in ms) before first repetition when 22 holding the button down */ 23 #define SCROLL_REPEAT_DELAY 50 /* Delay (in ms) between scroll repetitions */ 24 25 #define SCROLL_TIMER 0 /* Scroll timer id */ 26 27 /* Minimum size of the rectangle between the arrows */ 28 #define SCROLL_MIN_RECT 4 29 30 /* Minimum size of the thumb in pixels */ 31 #define SCROLL_MIN_THUMB 6 32 33 /* Overlap between arrows and thumb */ 34 #define SCROLL_ARROW_THUMB_OVERLAP 0 35 36 // 37 // 38 // 39 #define MINTRACKTHUMB 8 /* Minimum size of the rectangle between the arrows */ 40 41 /* What to do after SetScrollInfo() */ 42 #define SA_SSI_HIDE 0x0001 43 #define SA_SSI_SHOW 0x0002 44 #define SA_SSI_REFRESH 0x0004 45 #define SA_SSI_REPAINT_ARROWS 0x0008 46 47 #define SBRG_SCROLLBAR 0 /* The scrollbar itself */ 48 #define SBRG_TOPRIGHTBTN 1 /* The top or right button */ 49 #define SBRG_PAGEUPRIGHT 2 /* The page up or page right region */ 50 #define SBRG_SCROLLBOX 3 /* The scroll box */ 51 #define SBRG_PAGEDOWNLEFT 4 /* The page down or page left region */ 52 #define SBRG_BOTTOMLEFTBTN 5 /* The bottom or left button */ 53 54 #define CHANGERGSTATE(item, status) \ 55 if(Info->rgstate[(item)] != (status)) \ 56 Chg = TRUE; \ 57 Info->rgstate[(item)] = (status); 58 59 /* FUNCTIONS *****************************************************************/ 60 61 BOOL APIENTRY 62 IntEnableScrollBar(BOOL Horz, PSCROLLBARINFO Info, UINT wArrows); 63 64 static void 65 IntRefeshScrollInterior(PWND pWnd, INT nBar, PSCROLLBARINFO psbi); 66 67 68 /* Ported from WINE20020904 */ 69 /* Compute the scroll bar rectangle, in drawing coordinates (i.e. client coords for SB_CTL, window coords for SB_VERT and 70 * SB_HORZ). 'arrowSize' returns the width or height of an arrow (depending on * the orientation of the scrollbar), 71 * 'thumbSize' returns the size of the thumb, and 'thumbPos' returns the position of the thumb relative to the left or to 72 * the top. Return TRUE if the scrollbar is vertical, FALSE if horizontal. 73 */ 74 static inline void mirror_rect( const RECT *window_rect, RECT *rect ) 75 { 76 int width = window_rect->right - window_rect->left; 77 int tmp = rect->left; 78 rect->left = width - rect->right; 79 rect->right = width - tmp; 80 } 81 82 PSBDATA FASTCALL 83 IntGetSBData(PWND pwnd, INT Bar) 84 { 85 PSBWND pSBWnd; 86 PSBINFO pSBInfo; 87 88 pSBInfo = pwnd->pSBInfo; 89 switch (Bar) 90 { 91 case SB_HORZ: 92 return &pSBInfo->Horz; 93 case SB_VERT: 94 return &pSBInfo->Vert; 95 case SB_CTL: 96 if ( pwnd->cbwndExtra < (sizeof(SBWND)-sizeof(WND)) ) 97 { 98 ERR("IntGetSBData Wrong Extra bytes for CTL Scrollbar!\n"); 99 return 0; 100 } 101 pSBWnd = (PSBWND)pwnd; 102 return (PSBDATA)&pSBWnd->SBCalc; 103 default: 104 ERR("IntGetSBData Bad Bar!\n"); 105 } 106 return NULL; 107 } 108 109 BOOL FASTCALL 110 IntGetScrollBarRect (PWND Wnd, INT nBar, RECTL *lprect) 111 { 112 BOOL vertical; 113 *lprect = Wnd->rcClient; 114 115 RECTL_vOffsetRect( lprect, -Wnd->rcWindow.left, -Wnd->rcWindow.top ); 116 if (Wnd->ExStyle & WS_EX_LAYOUTRTL) 117 mirror_rect( &Wnd->rcWindow, lprect ); 118 119 switch (nBar) 120 { 121 case SB_HORZ: 122 lprect->top = lprect->bottom; 123 lprect->bottom += UserGetSystemMetrics (SM_CYHSCROLL); 124 if (Wnd->style & WS_BORDER) 125 { 126 lprect->left--; 127 lprect->right++; 128 } 129 else if (Wnd->style & WS_VSCROLL) 130 { 131 lprect->right++; 132 } 133 vertical = FALSE; 134 break; 135 136 case SB_VERT: 137 if(Wnd->ExStyle & WS_EX_LEFTSCROLLBAR) 138 { 139 lprect->right = lprect->left; 140 lprect->left -= UserGetSystemMetrics(SM_CXVSCROLL); 141 } 142 else 143 { 144 lprect->left = lprect->right; 145 lprect->right += UserGetSystemMetrics(SM_CXVSCROLL); 146 } 147 if (Wnd->style & WS_BORDER) 148 { 149 lprect->top--; 150 lprect->bottom++; 151 } 152 else if (Wnd->style & WS_HSCROLL) 153 { 154 lprect->bottom++; 155 } 156 vertical = TRUE; 157 break; 158 159 case SB_CTL: 160 IntGetClientRect (Wnd, lprect); 161 vertical = !!(Wnd->style & SBS_VERT); 162 break; 163 164 default: 165 return FALSE; 166 } 167 168 return vertical; 169 } 170 171 BOOL FASTCALL 172 IntCalculateThumb(PWND Wnd, LONG idObject, PSCROLLBARINFO psbi, PSBDATA pSBData) 173 { 174 INT Thumb, ThumbBox, ThumbPos, cxy, mx; 175 RECTL ClientRect; 176 177 switch(idObject) 178 { 179 case SB_HORZ: 180 Thumb = UserGetSystemMetrics(SM_CXHSCROLL); 181 cxy = psbi->rcScrollBar.right - psbi->rcScrollBar.left; 182 break; 183 case SB_VERT: 184 Thumb = UserGetSystemMetrics(SM_CYVSCROLL); 185 cxy = psbi->rcScrollBar.bottom - psbi->rcScrollBar.top; 186 break; 187 case SB_CTL: 188 IntGetClientRect(Wnd, &ClientRect); 189 if(Wnd->style & SBS_VERT) 190 { 191 Thumb = UserGetSystemMetrics(SM_CYVSCROLL); 192 cxy = ClientRect.bottom - ClientRect.top; 193 } 194 else 195 { 196 Thumb = UserGetSystemMetrics(SM_CXHSCROLL); 197 cxy = ClientRect.right - ClientRect.left; 198 } 199 break; 200 default: 201 return FALSE; 202 } 203 204 ThumbPos = Thumb; 205 /* Calculate Thumb */ 206 if(cxy <= (2 * Thumb)) 207 { 208 Thumb = cxy / 2; 209 psbi->xyThumbTop = 0; 210 psbi->xyThumbBottom = 0; 211 ThumbPos = Thumb; 212 } 213 else if (psbi->rgstate[SBRG_TOPRIGHTBTN] == STATE_SYSTEM_UNAVAILABLE && 214 psbi->rgstate[SBRG_BOTTOMLEFTBTN] == STATE_SYSTEM_UNAVAILABLE && 215 pSBData->posMin >= (int)(pSBData->posMax - max(pSBData->page - 1, 0))) 216 { 217 /* Nothing to scroll */ 218 psbi->xyThumbTop = 0; 219 psbi->xyThumbBottom = 0; 220 } 221 else 222 { 223 ThumbBox = pSBData->page ? MINTRACKTHUMB : UserGetSystemMetrics(SM_CXHTHUMB); 224 cxy -= (2 * Thumb); 225 if(cxy >= ThumbBox) 226 { 227 if(pSBData->page) 228 { 229 ThumbBox = max(EngMulDiv(cxy, pSBData->page, pSBData->posMax - pSBData->posMin + 1), ThumbBox); 230 } 231 232 if(cxy > ThumbBox) 233 { 234 mx = pSBData->posMax - max(pSBData->page - 1, 0); 235 if(pSBData->posMin < mx) 236 ThumbPos = Thumb + EngMulDiv(cxy - ThumbBox, pSBData->pos - pSBData->posMin, mx - pSBData->posMin); 237 else 238 ThumbPos = Thumb + ThumbBox; 239 } 240 241 psbi->xyThumbTop = ThumbPos; 242 psbi->xyThumbBottom = ThumbPos + ThumbBox; 243 } 244 else 245 { 246 psbi->xyThumbTop = 0; 247 psbi->xyThumbBottom = 0; 248 } 249 } 250 psbi->dxyLineButton = Thumb; 251 252 return TRUE; 253 } 254 /* 255 static VOID FASTCALL 256 IntUpdateSBInfo(PWND Window, int wBar) 257 { 258 PSCROLLBARINFO sbi; 259 PSBDATA pSBData; 260 261 ASSERT(Window); 262 ASSERT(Window->pSBInfo); 263 ASSERT(Window->pSBInfoex); 264 265 sbi = IntGetScrollbarInfoFromWindow(Window, wBar); 266 pSBData = IntGetSBData(Window, wBar); 267 IntGetScrollBarRect(Window, wBar, &(sbi->rcScrollBar)); 268 IntCalculateThumb(Window, wBar, sbi, pSBData); 269 } 270 */ 271 static BOOL FASTCALL 272 co_IntGetScrollInfo(PWND Window, INT nBar, PSBDATA pSBData, LPSCROLLINFO lpsi) 273 { 274 UINT Mask; 275 LPSCROLLINFO psi; 276 277 ASSERT_REFS_CO(Window); 278 279 lpsi->fMask &= ~SIF_THEMED; // Remove Theme bit 280 if(!SBID_IS_VALID(nBar)) 281 { 282 EngSetLastError(ERROR_INVALID_PARAMETER); 283 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", nBar); 284 return FALSE; 285 } 286 287 if (!Window->pSBInfo) 288 { 289 ERR("IntGetScrollInfo No window scrollbar info!\n"); 290 return FALSE; 291 } 292 293 psi = IntGetScrollInfoFromWindow(Window, nBar); 294 295 if (lpsi->fMask == SIF_ALL) 296 { 297 Mask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS; 298 } 299 else 300 { 301 Mask = lpsi->fMask; 302 } 303 304 if (0 != (Mask & SIF_PAGE)) 305 { 306 lpsi->nPage = psi->nPage; 307 } 308 309 if (0 != (Mask & SIF_POS)) 310 { 311 lpsi->nPos = psi->nPos; 312 } 313 314 if (0 != (Mask & SIF_RANGE)) 315 { 316 lpsi->nMin = psi->nMin; 317 lpsi->nMax = psi->nMax; 318 } 319 320 if (0 != (Mask & SIF_TRACKPOS)) 321 { 322 lpsi->nTrackPos = psi->nTrackPos; 323 } 324 325 return TRUE; 326 } 327 328 BOOL FASTCALL 329 NEWco_IntGetScrollInfo( 330 PWND pWnd, 331 INT nBar, 332 PSBDATA pSBData, 333 LPSCROLLINFO lpsi) 334 { 335 UINT Mask; 336 PSBTRACK pSBTrack = pWnd->head.pti->pSBTrack; 337 338 lpsi->fMask &= ~SIF_THEMED; // Remove Theme bit 339 if (!SBID_IS_VALID(nBar)) 340 { 341 EngSetLastError(ERROR_INVALID_PARAMETER); 342 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", nBar); 343 return FALSE; 344 } 345 346 if (!pWnd->pSBInfo || !pSBTrack) return FALSE; 347 348 Mask = lpsi->fMask; 349 350 if (0 != (Mask & SIF_PAGE)) 351 { 352 lpsi->nPage = pSBData->page; 353 } 354 355 if (0 != (Mask & SIF_POS)) 356 { 357 lpsi->nPos = pSBData->pos; 358 } 359 360 if (0 != (Mask & SIF_RANGE)) 361 { 362 lpsi->nMin = pSBData->posMin; 363 lpsi->nMax = pSBData->posMax; 364 } 365 366 if (0 != (Mask & SIF_TRACKPOS)) 367 { 368 if ( pSBTrack && 369 pSBTrack->nBar == nBar && 370 pSBTrack->spwndTrack == pWnd ) 371 lpsi->nTrackPos = pSBTrack->posNew; 372 else 373 lpsi->nTrackPos = pSBData->pos; 374 } 375 return (Mask & SIF_ALL) !=0; 376 } 377 378 /************************************************************************* 379 * SCROLL_GetScrollBarInfo 380 * 381 * Internal helper for the API function 382 * 383 * PARAMS 384 * hwnd [I] Handle of window with scrollbar(s) 385 * idObject [I] One of OBJID_CLIENT, OBJID_HSCROLL, or OBJID_VSCROLL 386 * info [IO] cbSize specifies the size of the structure 387 * 388 * RETURNS 389 * FALSE if failed 390 */ 391 #if 0 392 static BOOL SCROLL_GetScrollBarInfo(HWND hwnd, LONG idObject, LPSCROLLBARINFO info) 393 { 394 LPSCROLLBAR_INFO infoPtr; 395 INT nBar; 396 INT nDummy; 397 DWORD style = GetWindowLongW(hwnd, GWL_STYLE); 398 BOOL pressed; 399 RECT rect; 400 401 switch (idObject) 402 { 403 case OBJID_CLIENT: nBar = SB_CTL; break; 404 case OBJID_HSCROLL: nBar = SB_HORZ; break; 405 case OBJID_VSCROLL: nBar = SB_VERT; break; 406 default: return FALSE; 407 } 408 409 /* handle invalid data structure */ 410 if (info->cbSize != sizeof(*info)) 411 return FALSE; 412 413 SCROLL_GetScrollBarRect(hwnd, nBar, &info->rcScrollBar, &nDummy, 414 &info->dxyLineButton, &info->xyThumbTop); 415 /* rcScrollBar needs to be in screen coordinates */ 416 GetWindowRect(hwnd, &rect); 417 OffsetRect(&info->rcScrollBar, rect.left, rect.top); 418 419 info->xyThumbBottom = info->xyThumbTop + info->dxyLineButton; 420 421 infoPtr = SCROLL_GetInternalInfo(hwnd, nBar, TRUE); 422 if (!infoPtr) 423 return FALSE; 424 425 /* Scroll bar state */ 426 info->rgstate[0] = 0; 427 if ((nBar == SB_HORZ && !(style & WS_HSCROLL)) 428 || (nBar == SB_VERT && !(style & WS_VSCROLL))) 429 info->rgstate[0] |= STATE_SYSTEM_INVISIBLE; 430 if (infoPtr->minVal >= infoPtr->maxVal - max(infoPtr->page - 1, 0)) 431 { 432 if (!(info->rgstate[0] & STATE_SYSTEM_INVISIBLE)) 433 info->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE; 434 else 435 info->rgstate[0] |= STATE_SYSTEM_OFFSCREEN; 436 } 437 if (nBar == SB_CTL && !IsWindowEnabled(hwnd)) 438 info->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE; 439 440 pressed = ((nBar == SB_VERT) == SCROLL_trackVertical && GetCapture() == hwnd); 441 442 /* Top/left arrow button state. MSDN says top/right, but I don't believe it */ 443 info->rgstate[1] = 0; 444 if (pressed && SCROLL_trackHitTest == SCROLL_TOP_ARROW) 445 info->rgstate[1] |= STATE_SYSTEM_PRESSED; 446 if (infoPtr->flags & ESB_DISABLE_LTUP) 447 info->rgstate[1] |= STATE_SYSTEM_UNAVAILABLE; 448 449 /* Page up/left region state. MSDN says up/right, but I don't believe it */ 450 info->rgstate[2] = 0; 451 if (infoPtr->curVal == infoPtr->minVal) 452 info->rgstate[2] |= STATE_SYSTEM_INVISIBLE; 453 if (pressed && SCROLL_trackHitTest == SCROLL_TOP_RECT) 454 info->rgstate[2] |= STATE_SYSTEM_PRESSED; 455 456 /* Thumb state */ 457 info->rgstate[3] = 0; 458 if (pressed && SCROLL_trackHitTest == SCROLL_THUMB) 459 info->rgstate[3] |= STATE_SYSTEM_PRESSED; 460 461 /* Page down/right region state. MSDN says down/left, but I don't believe it */ 462 info->rgstate[4] = 0; 463 if (infoPtr->curVal >= infoPtr->maxVal - 1) 464 info->rgstate[4] |= STATE_SYSTEM_INVISIBLE; 465 if (pressed && SCROLL_trackHitTest == SCROLL_BOTTOM_RECT) 466 info->rgstate[4] |= STATE_SYSTEM_PRESSED; 467 468 /* Bottom/right arrow button state. MSDN says bottom/left, but I don't believe it */ 469 info->rgstate[5] = 0; 470 if (pressed && SCROLL_trackHitTest == SCROLL_BOTTOM_ARROW) 471 info->rgstate[5] |= STATE_SYSTEM_PRESSED; 472 if (infoPtr->flags & ESB_DISABLE_RTDN) 473 info->rgstate[5] |= STATE_SYSTEM_UNAVAILABLE; 474 475 return TRUE; 476 } 477 #endif 478 static DWORD FASTCALL 479 co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) 480 { 481 /* 482 * Update the scrollbar state and set action flags according to 483 * what has to be done graphics wise. 484 */ 485 486 LPSCROLLINFO Info; 487 PSCROLLBARINFO psbi; 488 UINT new_flags; 489 INT action = 0; 490 PSBDATA pSBData; 491 DWORD OldPos = 0, CurrentPos = 0; 492 BOOL bChangeParams = FALSE; /* Don't show/hide scrollbar if params don't change */ 493 UINT MaxPage; 494 int MaxPos; 495 /* [0] = SB_HORZ, [1] = SB_VERT, [2] = SB_CTL */ 496 static PWND PrevHwnd[3] = { 0 }; 497 static DWORD PrevPos[3] = { 0 }; 498 static DWORD PrevMax[3] = { 0 }; 499 static INT PrevAction[3] = { 0 }; 500 501 ASSERT_REFS_CO(Window); 502 503 if(!SBID_IS_VALID(nBar)) /* Assures nBar is 0, 1, or 2 */ 504 { 505 EngSetLastError(ERROR_INVALID_PARAMETER); 506 ERR("Trying to set scrollinfo for unknown scrollbar type %d", nBar); 507 return FALSE; 508 } 509 510 if(!co_IntCreateScrollBars(Window)) 511 { 512 return FALSE; 513 } 514 515 if (lpsi->cbSize != sizeof(SCROLLINFO) && 516 lpsi->cbSize != (sizeof(SCROLLINFO) - sizeof(lpsi->nTrackPos))) 517 { 518 EngSetLastError(ERROR_INVALID_PARAMETER); 519 return 0; 520 } 521 if ((lpsi->fMask & ~SIF_THEMED) & ~(SIF_ALL | SIF_DISABLENOSCROLL | SIF_PREVIOUSPOS)) 522 { 523 EngSetLastError(ERROR_INVALID_PARAMETER); 524 return 0; 525 } 526 527 psbi = IntGetScrollbarInfoFromWindow(Window, nBar); 528 Info = IntGetScrollInfoFromWindow(Window, nBar); 529 pSBData = IntGetSBData(Window, nBar); 530 531 if (lpsi->fMask & SIF_THEMED && !(Info->fMask & SIF_THEMED)) 532 { 533 Info->fMask |= SIF_THEMED; 534 } 535 536 /* Set the page size */ 537 if (lpsi->fMask & SIF_PAGE) 538 { 539 if (Info->nPage != lpsi->nPage) 540 { 541 Info->nPage = lpsi->nPage; 542 pSBData->page = lpsi->nPage; 543 bChangeParams = TRUE; 544 } 545 } 546 547 /* Set the scroll pos */ 548 if (lpsi->fMask & SIF_POS) 549 { 550 if (Info->nPos != lpsi->nPos) 551 { 552 OldPos = Info->nPos; 553 Info->nPos = lpsi->nPos; 554 pSBData->pos = lpsi->nPos; 555 } 556 } 557 558 /* Set the scroll range */ 559 if (lpsi->fMask & SIF_RANGE) 560 { 561 if (lpsi->nMin > lpsi->nMax) 562 { 563 Info->nMin = lpsi->nMin; 564 Info->nMax = lpsi->nMin; 565 pSBData->posMin = lpsi->nMin; 566 pSBData->posMax = lpsi->nMin; 567 bChangeParams = TRUE; 568 } 569 else if (Info->nMin != lpsi->nMin || Info->nMax != lpsi->nMax) 570 { 571 Info->nMin = lpsi->nMin; 572 Info->nMax = lpsi->nMax; 573 pSBData->posMin = lpsi->nMin; 574 pSBData->posMax = lpsi->nMax; 575 bChangeParams = TRUE; 576 } 577 } 578 579 /* Make sure the page size is valid */ 580 MaxPage = abs(Info->nMax - Info->nMin) + 1; 581 if (Info->nPage > MaxPage) 582 { 583 pSBData->page = Info->nPage = MaxPage; 584 } 585 586 /* Make sure the pos is inside the range */ 587 MaxPos = Info->nMax + 1 - (int)max(Info->nPage, 1); 588 ASSERT(MaxPos >= Info->nMin); 589 if (Info->nPos < Info->nMin) 590 { 591 pSBData->pos = Info->nPos = Info->nMin; 592 } 593 else if (Info->nPos > MaxPos) 594 { 595 pSBData->pos = Info->nPos = MaxPos; 596 } 597 598 /* 599 * Don't change the scrollbar state if SetScrollInfo is just called 600 * with SIF_DISABLENOSCROLL 601 */ 602 if (!(lpsi->fMask & SIF_ALL)) 603 { 604 //goto done; 605 return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos; 606 } 607 608 /* Check if the scrollbar should be hidden or disabled */ 609 if (lpsi->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL)) 610 { 611 new_flags = Window->pSBInfo->WSBflags; 612 if (Info->nMin + (int)max(Info->nPage, 1) > Info->nMax) 613 { 614 /* Hide or disable scroll-bar */ 615 if (lpsi->fMask & SIF_DISABLENOSCROLL) 616 { 617 new_flags = ESB_DISABLE_BOTH; 618 bChangeParams = TRUE; 619 } 620 else if ((nBar != SB_CTL) && bChangeParams) 621 { 622 action = SA_SSI_HIDE; 623 } 624 } 625 else /* Show and enable scroll-bar only if no page only changed. */ 626 if ((lpsi->fMask & ~SIF_THEMED) != SIF_PAGE) 627 { 628 if ((nBar != SB_CTL) && bChangeParams) 629 { 630 new_flags = ESB_ENABLE_BOTH; 631 action |= SA_SSI_SHOW; 632 } 633 else if (nBar == SB_CTL) 634 { 635 new_flags = ESB_ENABLE_BOTH; 636 } 637 } 638 639 if (Window->pSBInfo->WSBflags != new_flags) /* Check arrow flags */ 640 { 641 Window->pSBInfo->WSBflags = new_flags; 642 action |= SA_SSI_REPAINT_ARROWS; 643 } 644 } 645 646 //done: 647 if ((Window != PrevHwnd[nBar]) || (action != PrevAction[nBar])) 648 { 649 if ((action == SA_SSI_SHOW) && (PrevAction[nBar] == SA_SSI_HIDE)) 650 { 651 co_UserShowScrollBar(Window, nBar, TRUE, TRUE); 652 } 653 } 654 if ((action != PrevAction[nBar]) && action != 0) 655 PrevAction[nBar] = action; 656 657 if ( action & SA_SSI_HIDE ) 658 { 659 co_UserShowScrollBar(Window, nBar, FALSE, FALSE); 660 } 661 else 662 { 663 if ( action & SA_SSI_SHOW ) 664 if ( co_UserShowScrollBar(Window, nBar, TRUE, TRUE) ) 665 return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos; /* SetWindowPos() already did the painting */ 666 if (bRedraw) 667 { 668 if (!(Info->fMask & SIF_THEMED)) /* Not Using Themes */ 669 { 670 TRACE("Not using themes.\n"); 671 if (action & SA_SSI_REPAINT_ARROWS) 672 { 673 // Redraw the entire bar. 674 RECTL UpdateRect = psbi->rcScrollBar; 675 UpdateRect.left -= Window->rcClient.left - Window->rcWindow.left; 676 UpdateRect.right -= Window->rcClient.left - Window->rcWindow.left; 677 UpdateRect.top -= Window->rcClient.top - Window->rcWindow.top; 678 UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top; 679 co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME); 680 } 681 else 682 { 683 // Redraw only the interior part of the bar. 684 IntRefeshScrollInterior(Window, nBar, psbi); 685 } 686 } 687 else /* Using Themes */ 688 { 689 RECTL UpdateRect = psbi->rcScrollBar; 690 TRACE("Using themes.\n"); 691 UpdateRect.left -= Window->rcClient.left - Window->rcWindow.left; 692 UpdateRect.right -= Window->rcClient.left - Window->rcWindow.left; 693 UpdateRect.top -= Window->rcClient.top - Window->rcWindow.top; 694 UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top; 695 /* Just paint the interior and not the arrows. */ 696 if (!(action & SA_SSI_REPAINT_ARROWS)) 697 { 698 if (nBar == SB_HORZ) 699 { 700 UpdateRect.left += psbi->dxyLineButton; 701 UpdateRect.right -= psbi->dxyLineButton; 702 } 703 if (nBar == SB_VERT) 704 { 705 UpdateRect.top += psbi->dxyLineButton; 706 UpdateRect.bottom -= psbi->dxyLineButton; 707 } 708 } 709 CurrentPos = lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos; 710 /* Check for changes to Window or CurrentPos or lpsi->nMax */ 711 if ((Window != PrevHwnd[nBar]) || (CurrentPos != PrevPos[nBar]) || 712 (lpsi->nMax != PrevMax[nBar])) 713 { 714 co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME); 715 PrevHwnd[nBar] = Window; 716 PrevPos[nBar] = CurrentPos; 717 PrevMax[nBar] = lpsi->nMax; 718 } 719 } 720 } // FIXME: Arrows 721 /* else if( action & SA_SSI_REPAINT_ARROWS ) 722 { 723 RECTL UpdateRect = psbi->rcScrollBar; 724 UpdateRect.left -= Window->rcClient.left - Window->rcWindow.left; 725 UpdateRect.right -= Window->rcClient.left - Window->rcWindow.left; 726 UpdateRect.top -= Window->rcClient.top - Window->rcWindow.top; 727 UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top; 728 co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME); 729 } 730 */ } 731 732 if (bChangeParams && (nBar == SB_HORZ || nBar == SB_VERT) && (lpsi->fMask & SIF_DISABLENOSCROLL)) 733 { 734 IntEnableScrollBar(nBar == SB_HORZ, psbi, Window->pSBInfo->WSBflags); 735 } 736 737 /* Return current position */ 738 return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos; 739 } 740 741 BOOL FASTCALL 742 co_IntGetScrollBarInfo(PWND Window, LONG idObject, PSCROLLBARINFO psbi) 743 { 744 INT Bar; 745 PSCROLLBARINFO sbi; 746 PSBDATA pSBData; 747 ASSERT_REFS_CO(Window); 748 749 Bar = SBOBJ_TO_SBID(idObject); 750 751 if(!SBID_IS_VALID(Bar)) 752 { 753 EngSetLastError(ERROR_INVALID_PARAMETER); 754 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", Bar); 755 return FALSE; 756 } 757 758 if(!co_IntCreateScrollBars(Window)) 759 { 760 ERR("Failed to create scrollbars for window.\n"); 761 return FALSE; 762 } 763 764 sbi = IntGetScrollbarInfoFromWindow(Window, Bar); 765 pSBData = IntGetSBData(Window, Bar); 766 767 IntGetScrollBarRect(Window, Bar, &(sbi->rcScrollBar)); 768 IntCalculateThumb(Window, Bar, sbi, pSBData); 769 770 /* Scroll bar state */ 771 psbi->rgstate[0] = 0; 772 if ((Bar == SB_HORZ && !(Window->style & WS_HSCROLL)) 773 || (Bar == SB_VERT && !(Window->style & WS_VSCROLL))) 774 psbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE; 775 if (pSBData->posMin >= pSBData->posMax - max(pSBData->page - 1, 0)) 776 { 777 if (!(psbi->rgstate[0] & STATE_SYSTEM_INVISIBLE)) 778 psbi->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE; 779 else 780 psbi->rgstate[0] |= STATE_SYSTEM_OFFSCREEN; 781 } 782 if (Bar == SB_CTL && !(Window->style & WS_DISABLED)) 783 psbi->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE; 784 785 RtlCopyMemory(psbi, sbi, sizeof(SCROLLBARINFO)); 786 787 return TRUE; 788 } 789 790 BOOL FASTCALL 791 co_IntSetScrollBarInfo(PWND Window, LONG idObject, PSETSCROLLBARINFO psbi) 792 { 793 INT Bar; 794 PSCROLLBARINFO sbi; 795 LPSCROLLINFO psi; 796 ASSERT_REFS_CO(Window); 797 798 Bar = SBOBJ_TO_SBID(idObject); 799 800 if(!SBID_IS_VALID(Bar)) 801 { 802 EngSetLastError(ERROR_INVALID_PARAMETER); 803 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", Bar); 804 return FALSE; 805 } 806 807 if(!co_IntCreateScrollBars(Window)) 808 { 809 ERR("Failed to create scrollbars for window.\n"); 810 return FALSE; 811 } 812 813 sbi = IntGetScrollbarInfoFromWindow(Window, Bar); 814 psi = IntGetScrollInfoFromWindow(Window, Bar); 815 816 psi->nTrackPos = psbi->nTrackPos; 817 sbi->reserved = psbi->reserved; 818 RtlCopyMemory(&sbi->rgstate, &psbi->rgstate, sizeof(psbi->rgstate)); 819 820 return TRUE; 821 } 822 823 BOOL FASTCALL 824 co_IntCreateScrollBars(PWND Window) 825 { 826 PSCROLLBARINFO psbi; 827 PSBDATA pSBData; 828 ULONG Size, s; 829 INT i; 830 831 ASSERT_REFS_CO(Window); 832 833 if (Window->pSBInfo && Window->pSBInfoex) 834 { 835 /* No need to create it anymore */ 836 return TRUE; 837 } 838 839 /* Allocate memory for all scrollbars (HORZ, VERT, CONTROL) */ 840 Size = 3 * (sizeof(SBINFOEX)); 841 if(!(Window->pSBInfoex = ExAllocatePoolWithTag(PagedPool, Size, TAG_SBARINFO))) 842 { 843 ERR("Unable to allocate memory for scrollbar information for window %p\n", Window->head.h); 844 return FALSE; 845 } 846 847 RtlZeroMemory(Window->pSBInfoex, Size); 848 849 if(!(Window->pSBInfo = DesktopHeapAlloc( Window->head.rpdesk, sizeof(SBINFO)))) 850 { 851 ERR("Unable to allocate memory for scrollbar information for window %p\n", Window->head.h); 852 return FALSE; 853 } 854 855 RtlZeroMemory(Window->pSBInfo, sizeof(SBINFO)); 856 Window->pSBInfo->Vert.posMax = 100; 857 Window->pSBInfo->Horz.posMax = 100; 858 859 co_WinPosGetNonClientSize(Window, 860 &Window->rcWindow, 861 &Window->rcClient); 862 863 for(s = SB_HORZ; s <= SB_VERT; s++) 864 { 865 psbi = IntGetScrollbarInfoFromWindow(Window, s); 866 psbi->cbSize = sizeof(SCROLLBARINFO); 867 for (i = 0; i < CCHILDREN_SCROLLBAR + 1; i++) 868 psbi->rgstate[i] = 0; 869 870 pSBData = IntGetSBData(Window, s); 871 872 IntGetScrollBarRect(Window, s, &(psbi->rcScrollBar)); 873 IntCalculateThumb(Window, s, psbi, pSBData); 874 } 875 876 return TRUE; 877 } 878 879 BOOL FASTCALL 880 IntDestroyScrollBars(PWND Window) 881 { 882 if (Window->pSBInfo && Window->pSBInfoex) 883 { 884 DesktopHeapFree(Window->head.rpdesk, Window->pSBInfo); 885 Window->pSBInfo = NULL; 886 ExFreePoolWithTag(Window->pSBInfoex, TAG_SBARINFO); 887 Window->pSBInfoex = NULL; 888 return TRUE; 889 } 890 return FALSE; 891 } 892 893 BOOL APIENTRY 894 IntEnableScrollBar(BOOL Horz, PSCROLLBARINFO Info, UINT wArrows) 895 { 896 BOOL Chg = FALSE; 897 switch(wArrows) 898 { 899 case ESB_DISABLE_BOTH: 900 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE); 901 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE); 902 break; 903 case ESB_DISABLE_RTDN: 904 if(Horz) 905 { 906 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE); 907 } 908 else 909 { 910 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE); 911 } 912 break; 913 case ESB_DISABLE_LTUP: 914 if(Horz) 915 { 916 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE); 917 } 918 else 919 { 920 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE); 921 } 922 break; 923 case ESB_ENABLE_BOTH: 924 CHANGERGSTATE(SBRG_TOPRIGHTBTN, 0); 925 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, 0); 926 break; 927 } 928 return Chg; 929 } 930 931 /* Ported from WINE20020904 (SCROLL_ShowScrollBar) */ 932 DWORD FASTCALL 933 co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV) 934 { 935 ULONG old_style, set_bits = 0, clear_bits = 0; 936 937 ASSERT_REFS_CO(Wnd); 938 939 switch(nBar) 940 { 941 case SB_CTL: 942 { 943 //IntUpdateSBInfo(Wnd, SB_CTL); // Is this needed? Was tested w/o! 944 945 co_WinPosShowWindow(Wnd, fShowH ? SW_SHOW : SW_HIDE); 946 return TRUE; 947 } 948 case SB_BOTH: 949 case SB_HORZ: 950 if (fShowH) set_bits |= WS_HSCROLL; 951 else clear_bits |= WS_HSCROLL; 952 if( nBar == SB_HORZ ) break; 953 /* Fall through */ 954 case SB_VERT: 955 if (fShowV) set_bits |= WS_VSCROLL; 956 else clear_bits |= WS_VSCROLL; 957 break; 958 default: 959 EngSetLastError(ERROR_INVALID_PARAMETER); 960 return FALSE; /* Nothing to do! */ 961 } 962 963 old_style = IntSetStyle( Wnd, set_bits, clear_bits ); 964 if ((old_style & clear_bits) != 0 || (old_style & set_bits) != set_bits) 965 { 966 ///// Is this needed? Was tested w/o! 967 //if (Wnd->style & WS_HSCROLL) IntUpdateSBInfo(Wnd, SB_HORZ); 968 //if (Wnd->style & WS_VSCROLL) IntUpdateSBInfo(Wnd, SB_VERT); 969 ///// 970 /* Frame has been changed, let the window redraw itself */ 971 co_WinPosSetWindowPos( Wnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE 972 | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); 973 return TRUE; 974 } 975 return FALSE; /* no frame changes */ 976 } 977 978 static void 979 IntDrawScrollInterior(PWND pWnd, HDC hDC, INT nBar, BOOL Vertical, PSCROLLBARINFO ScrollBarInfo) 980 { 981 INT ThumbSize = ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop; 982 INT ThumbTop = ScrollBarInfo->xyThumbTop; 983 RECT Rect; 984 HBRUSH hSaveBrush, hBrush; 985 BOOL TopSelected = FALSE, BottomSelected = FALSE; 986 987 if (ScrollBarInfo->rgstate[SCROLL_TOP_RECT] & STATE_SYSTEM_PRESSED) 988 TopSelected = TRUE; 989 if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_RECT] & STATE_SYSTEM_PRESSED) 990 BottomSelected = TRUE; 991 992 /* 993 * Only scrollbar controls send WM_CTLCOLORSCROLLBAR. 994 * The window-owned scrollbars need to call DefWndControlColor 995 * to correctly setup default scrollbar colors 996 */ 997 if (nBar == SB_CTL) 998 { 999 hBrush = GetControlBrush( pWnd, hDC, WM_CTLCOLORSCROLLBAR); 1000 if (!hBrush) 1001 hBrush = IntGetSysColorBrush(COLOR_SCROLLBAR); 1002 } 1003 else 1004 { 1005 hBrush = DefWndControlColor(hDC, CTLCOLOR_SCROLLBAR); 1006 } 1007 1008 hSaveBrush = NtGdiSelectBrush(hDC, hBrush); 1009 1010 /* Calculate the scroll rectangle */ 1011 if (Vertical) 1012 { 1013 Rect.top = ScrollBarInfo->rcScrollBar.top + ScrollBarInfo->dxyLineButton; 1014 Rect.bottom = ScrollBarInfo->rcScrollBar.bottom - ScrollBarInfo->dxyLineButton; 1015 Rect.left = ScrollBarInfo->rcScrollBar.left; 1016 Rect.right = ScrollBarInfo->rcScrollBar.right; 1017 } 1018 else 1019 { 1020 Rect.top = ScrollBarInfo->rcScrollBar.top; 1021 Rect.bottom = ScrollBarInfo->rcScrollBar.bottom; 1022 Rect.left = ScrollBarInfo->rcScrollBar.left + ScrollBarInfo->dxyLineButton; 1023 Rect.right = ScrollBarInfo->rcScrollBar.right - ScrollBarInfo->dxyLineButton; 1024 } 1025 1026 /* Draw the scroll rectangles and thumb */ 1027 if (!ScrollBarInfo->xyThumbBottom) 1028 { 1029 NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right - Rect.left, 1030 Rect.bottom - Rect.top, PATCOPY); 1031 1032 /* Cleanup and return */ 1033 NtGdiSelectBrush(hDC, hSaveBrush); 1034 return; 1035 } 1036 1037 ThumbTop -= ScrollBarInfo->dxyLineButton; 1038 1039 if (ScrollBarInfo->dxyLineButton) 1040 { 1041 if (Vertical) 1042 { 1043 if (ThumbSize) 1044 { 1045 NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right - Rect.left, 1046 ThumbTop, TopSelected ? BLACKNESS : PATCOPY); 1047 Rect.top += ThumbTop; 1048 NtGdiPatBlt(hDC, Rect.left, Rect.top + ThumbSize, Rect.right - Rect.left, 1049 Rect.bottom - Rect.top - ThumbSize, BottomSelected ? BLACKNESS : PATCOPY); 1050 Rect.bottom = Rect.top + ThumbSize; 1051 } 1052 else 1053 { 1054 if (ThumbTop) 1055 { 1056 NtGdiPatBlt(hDC, Rect.left, ScrollBarInfo->dxyLineButton, 1057 Rect.right - Rect.left, Rect.bottom - Rect.top, PATCOPY); 1058 } 1059 } 1060 } 1061 else 1062 { 1063 if (ThumbSize) 1064 { 1065 NtGdiPatBlt(hDC, Rect.left, Rect.top, ThumbTop, 1066 Rect.bottom - Rect.top, TopSelected ? BLACKNESS : PATCOPY); 1067 Rect.left += ThumbTop; 1068 NtGdiPatBlt(hDC, Rect.left + ThumbSize, Rect.top, 1069 Rect.right - Rect.left - ThumbSize, Rect.bottom - Rect.top, 1070 BottomSelected ? BLACKNESS : PATCOPY); 1071 Rect.right = Rect.left + ThumbSize; 1072 } 1073 else 1074 { 1075 if (ThumbTop) 1076 { 1077 NtGdiPatBlt(hDC, ScrollBarInfo->dxyLineButton, Rect.top, 1078 Rect.right - Rect.left, Rect.bottom - Rect.top, PATCOPY); 1079 } 1080 } 1081 } 1082 } 1083 1084 /* Draw the thumb */ 1085 if (ThumbSize) 1086 DrawEdge(hDC, &Rect, EDGE_RAISED, BF_RECT | BF_MIDDLE); 1087 1088 /* Cleanup */ 1089 NtGdiSelectBrush(hDC, hSaveBrush); 1090 } 1091 1092 1093 static VOID FASTCALL 1094 IntDrawScrollArrows(HDC hDC, PSCROLLBARINFO ScrollBarInfo, BOOL Vertical) 1095 { 1096 RECT RectLT, RectRB; 1097 INT ScrollDirFlagLT, ScrollDirFlagRB; 1098 1099 RectLT = RectRB = ScrollBarInfo->rcScrollBar; 1100 if (Vertical) 1101 { 1102 ScrollDirFlagLT = DFCS_SCROLLUP; 1103 ScrollDirFlagRB = DFCS_SCROLLDOWN; 1104 RectLT.bottom = RectLT.top + ScrollBarInfo->dxyLineButton; 1105 RectRB.top = RectRB.bottom - ScrollBarInfo->dxyLineButton; 1106 } 1107 else 1108 { 1109 ScrollDirFlagLT = DFCS_SCROLLLEFT; 1110 ScrollDirFlagRB = DFCS_SCROLLRIGHT; 1111 RectLT.right = RectLT.left + ScrollBarInfo->dxyLineButton; 1112 RectRB.left = RectRB.right - ScrollBarInfo->dxyLineButton; 1113 } 1114 1115 if (ScrollBarInfo->rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_PRESSED) 1116 { 1117 ScrollDirFlagLT |= DFCS_PUSHED | DFCS_FLAT; 1118 } 1119 if (ScrollBarInfo->rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_UNAVAILABLE) 1120 { 1121 ScrollDirFlagLT |= DFCS_INACTIVE; 1122 } 1123 if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_PRESSED) 1124 { 1125 ScrollDirFlagRB |= DFCS_PUSHED | DFCS_FLAT; 1126 } 1127 if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_UNAVAILABLE) 1128 { 1129 ScrollDirFlagRB |= DFCS_INACTIVE; 1130 } 1131 1132 DrawFrameControl(hDC, &RectLT, DFC_SCROLL, ScrollDirFlagLT); 1133 DrawFrameControl(hDC, &RectRB, DFC_SCROLL, ScrollDirFlagRB); 1134 } 1135 1136 static LONG FASTCALL 1137 IntScrollGetObjectId(INT SBType) 1138 { 1139 if (SBType == SB_VERT) 1140 return OBJID_VSCROLL; 1141 if (SBType == SB_HORZ) 1142 return OBJID_HSCROLL; 1143 return OBJID_CLIENT; 1144 } 1145 1146 static void 1147 IntRefeshScrollInterior(PWND pWnd, INT nBar, PSCROLLBARINFO psbi) 1148 { 1149 HDC hdc; 1150 BOOL Vertical = ((nBar == SB_CTL) ? ((pWnd->style & SBS_VERT) != 0) : (nBar == SB_VERT)); 1151 1152 hdc = UserGetDCEx(pWnd, NULL, DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW)); 1153 if (hdc) 1154 { /* Get updated info. */ 1155 co_IntGetScrollBarInfo(pWnd, IntScrollGetObjectId(nBar), psbi); 1156 IntDrawScrollInterior(pWnd, hdc, nBar, Vertical, psbi); 1157 UserReleaseDC(pWnd, hdc, FALSE); 1158 } 1159 } 1160 1161 void 1162 IntDrawScrollBar(PWND Wnd, HDC DC, INT Bar) 1163 { 1164 //PSBWND pSBWnd; 1165 //INT ThumbSize; 1166 PTHREADINFO pti; 1167 SCROLLBARINFO Info; 1168 BOOL Vertical; 1169 1170 pti = PsGetCurrentThreadWin32Thread(); 1171 1172 /* 1173 * Get scroll bar info. 1174 */ 1175 switch (Bar) 1176 { 1177 case SB_HORZ: 1178 Vertical = FALSE; 1179 break; 1180 1181 case SB_VERT: 1182 Vertical = TRUE; 1183 break; 1184 1185 case SB_CTL: 1186 Vertical = (Wnd->style & SBS_VERT) != 0; 1187 break; 1188 1189 default: 1190 return; 1191 } 1192 1193 if (!co_IntGetScrollBarInfo(Wnd, IntScrollGetObjectId(Bar), &Info)) 1194 { 1195 return; 1196 } 1197 1198 if (RECTL_bIsEmptyRect(&Info.rcScrollBar)) 1199 { 1200 return; 1201 } 1202 1203 //ThumbSize = pSBWnd->pSBCalc->pxThumbBottom - pSBWnd->pSBCalc->pxThumbTop; 1204 1205 /* 1206 * Draw the arrows. 1207 */ 1208 if (Info.dxyLineButton) 1209 { 1210 IntDrawScrollArrows(DC, &Info, Vertical); 1211 } 1212 1213 /* 1214 * Draw the interior. 1215 */ 1216 IntDrawScrollInterior(Wnd, DC, Bar, Vertical, &Info); 1217 1218 /* 1219 * If scroll bar has focus, reposition the caret. 1220 */ 1221 if ( Wnd == pti->MessageQueue->spwndFocus && Bar == SB_CTL ) 1222 { 1223 if (Vertical) 1224 { 1225 co_IntSetCaretPos(Info.rcScrollBar.top + 1, Info.dxyLineButton + 1); 1226 } 1227 else 1228 { 1229 co_IntSetCaretPos(Info.dxyLineButton + 1, Info.rcScrollBar.top + 1); 1230 } 1231 } 1232 } 1233 1234 1235 LRESULT APIENTRY 1236 ScrollBarWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) 1237 { 1238 LRESULT lResult = 0; 1239 PWND pWnd; 1240 pWnd = UserGetWindowObject(hWnd); 1241 if (!pWnd) return 0; 1242 1243 switch(Msg) 1244 { 1245 case WM_ENABLE: 1246 { 1247 if (pWnd->pSBInfo) 1248 { 1249 pWnd->pSBInfo->WSBflags = wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH; 1250 } 1251 } 1252 break; 1253 } 1254 return lResult; 1255 } 1256 1257 //// 1258 1259 BOOL 1260 APIENTRY 1261 NtUserGetScrollBarInfo(HWND hWnd, LONG idObject, PSCROLLBARINFO psbi) 1262 { 1263 NTSTATUS Status; 1264 SCROLLBARINFO sbi; 1265 PWND Window; 1266 BOOL Ret; 1267 DECLARE_RETURN(BOOL); 1268 USER_REFERENCE_ENTRY Ref; 1269 1270 TRACE("Enter NtUserGetScrollBarInfo\n"); 1271 UserEnterExclusive(); 1272 1273 Status = MmCopyFromCaller(&sbi, psbi, sizeof(SCROLLBARINFO)); 1274 if(!NT_SUCCESS(Status) || (sbi.cbSize != sizeof(SCROLLBARINFO))) 1275 { 1276 SetLastNtError(Status); 1277 RETURN(FALSE); 1278 } 1279 1280 if(!(Window = UserGetWindowObject(hWnd))) 1281 { 1282 RETURN(FALSE); 1283 } 1284 1285 UserRefObjectCo(Window, &Ref); 1286 Ret = co_IntGetScrollBarInfo(Window, idObject, &sbi); 1287 UserDerefObjectCo(Window); 1288 1289 Status = MmCopyToCaller(psbi, &sbi, sizeof(SCROLLBARINFO)); 1290 if(!NT_SUCCESS(Status)) 1291 { 1292 SetLastNtError(Status); 1293 Ret = FALSE; 1294 } 1295 1296 RETURN( Ret); 1297 1298 CLEANUP: 1299 TRACE("Leave NtUserGetScrollBarInfo, ret=%i\n",_ret_); 1300 UserLeave(); 1301 END_CLEANUP; 1302 1303 } 1304 1305 BOOL 1306 APIENTRY 1307 NtUserSBGetParms( 1308 HWND hWnd, 1309 int fnBar, 1310 PSBDATA pSBData, 1311 LPSCROLLINFO lpsi) 1312 { 1313 PWND Window; 1314 SCROLLINFO psi; 1315 BOOL Ret; 1316 SBDATA SBDataSafe; 1317 DECLARE_RETURN(BOOL); 1318 USER_REFERENCE_ENTRY Ref; 1319 1320 TRACE("Enter NtUserGetScrollInfo\n"); 1321 UserEnterShared(); 1322 1323 _SEH2_TRY 1324 { 1325 RtlCopyMemory(&psi, lpsi, sizeof(SCROLLINFO)); 1326 if (pSBData) 1327 { 1328 RtlCopyMemory(&SBDataSafe, pSBData, sizeof(SBDATA)); 1329 } 1330 } 1331 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1332 { 1333 ERR("NtUserGetScrollInfo Failed size.\n"); 1334 SetLastNtError(_SEH2_GetExceptionCode()); 1335 _SEH2_YIELD(RETURN(FALSE)); 1336 } 1337 _SEH2_END 1338 1339 if(!(Window = UserGetWindowObject(hWnd))) 1340 { 1341 ERR("NtUserGetScrollInfo Bad window.\n"); 1342 RETURN(FALSE); 1343 } 1344 1345 UserRefObjectCo(Window, &Ref); 1346 Ret = co_IntGetScrollInfo(Window, fnBar, &SBDataSafe, &psi); 1347 UserDerefObjectCo(Window); 1348 1349 _SEH2_TRY 1350 { 1351 RtlCopyMemory(lpsi, &psi, sizeof(SCROLLINFO)); 1352 } 1353 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1354 { 1355 ERR("NtUserGetScrollInfo Failed copy to user.\n"); 1356 SetLastNtError(_SEH2_GetExceptionCode()); 1357 _SEH2_YIELD(RETURN(FALSE)); 1358 } 1359 _SEH2_END 1360 1361 RETURN( Ret); 1362 1363 CLEANUP: 1364 TRACE("Leave NtUserGetScrollInfo, ret=%i\n",_ret_); 1365 UserLeave(); 1366 END_CLEANUP; 1367 } 1368 1369 BOOL 1370 APIENTRY 1371 NtUserEnableScrollBar( 1372 HWND hWnd, 1373 UINT wSBflags, 1374 UINT wArrows) 1375 { 1376 UINT OrigArrows; 1377 PWND Window = NULL; 1378 PSCROLLBARINFO InfoV = NULL, InfoH = NULL; 1379 BOOL Chg = FALSE; 1380 DECLARE_RETURN(BOOL); 1381 USER_REFERENCE_ENTRY Ref; 1382 1383 TRACE("Enter NtUserEnableScrollBar\n"); 1384 UserEnterExclusive(); 1385 1386 if (!(Window = UserGetWindowObject(hWnd)) || 1387 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 1388 { 1389 RETURN(FALSE); 1390 } 1391 UserRefObjectCo(Window, &Ref); 1392 1393 if (!co_IntCreateScrollBars(Window)) 1394 { 1395 RETURN( FALSE); 1396 } 1397 1398 OrigArrows = Window->pSBInfo->WSBflags; 1399 Window->pSBInfo->WSBflags = wArrows; 1400 1401 if (wSBflags == SB_CTL) 1402 { 1403 if ((wArrows == ESB_DISABLE_BOTH || wArrows == ESB_ENABLE_BOTH)) 1404 IntEnableWindow(hWnd, (wArrows == ESB_ENABLE_BOTH)); 1405 1406 RETURN(TRUE); 1407 } 1408 1409 if(wSBflags != SB_BOTH && !SBID_IS_VALID(wSBflags)) 1410 { 1411 EngSetLastError(ERROR_INVALID_PARAMETER); 1412 ERR("Trying to set scrollinfo for unknown scrollbar type %u", wSBflags); 1413 RETURN(FALSE); 1414 } 1415 1416 switch(wSBflags) 1417 { 1418 case SB_BOTH: 1419 InfoV = IntGetScrollbarInfoFromWindow(Window, SB_VERT); 1420 /* Fall through */ 1421 case SB_HORZ: 1422 InfoH = IntGetScrollbarInfoFromWindow(Window, SB_HORZ); 1423 break; 1424 case SB_VERT: 1425 InfoV = IntGetScrollbarInfoFromWindow(Window, SB_VERT); 1426 break; 1427 default: 1428 RETURN(FALSE); 1429 } 1430 1431 if(InfoV) 1432 Chg = IntEnableScrollBar(FALSE, InfoV, wArrows); 1433 1434 if(InfoH) 1435 Chg = (IntEnableScrollBar(TRUE, InfoH, wArrows) || Chg); 1436 1437 ERR("FIXME: EnableScrollBar wSBflags %u wArrows %u Chg %d\n", wSBflags, wArrows, Chg); 1438 // Done in user32: 1439 // SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE ); 1440 1441 RETURN( Chg); 1442 if (OrigArrows == wArrows) RETURN( FALSE); 1443 RETURN( TRUE); 1444 1445 CLEANUP: 1446 if (Window) 1447 UserDerefObjectCo(Window); 1448 1449 TRACE("Leave NtUserEnableScrollBar, ret=%i\n",_ret_); 1450 UserLeave(); 1451 END_CLEANUP; 1452 } 1453 1454 DWORD 1455 APIENTRY 1456 NtUserSetScrollInfo( 1457 HWND hWnd, 1458 int fnBar, 1459 LPCSCROLLINFO lpsi, 1460 BOOL bRedraw) 1461 { 1462 PWND Window = NULL; 1463 NTSTATUS Status; 1464 SCROLLINFO ScrollInfo; 1465 DECLARE_RETURN(DWORD); 1466 USER_REFERENCE_ENTRY Ref; 1467 1468 TRACE("Enter NtUserSetScrollInfo\n"); 1469 UserEnterExclusive(); 1470 1471 if(!(Window = UserGetWindowObject(hWnd)) || 1472 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 1473 { 1474 RETURN( 0); 1475 } 1476 UserRefObjectCo(Window, &Ref); 1477 1478 Status = MmCopyFromCaller(&ScrollInfo, lpsi, sizeof(SCROLLINFO) - sizeof(ScrollInfo.nTrackPos)); 1479 if(!NT_SUCCESS(Status)) 1480 { 1481 SetLastNtError(Status); 1482 RETURN( 0); 1483 } 1484 1485 RETURN(co_IntSetScrollInfo(Window, fnBar, &ScrollInfo, bRedraw)); 1486 1487 CLEANUP: 1488 if (Window) 1489 UserDerefObjectCo(Window); 1490 1491 TRACE("Leave NtUserSetScrollInfo, ret=%lu\n", _ret_); 1492 UserLeave(); 1493 END_CLEANUP; 1494 1495 } 1496 1497 DWORD APIENTRY 1498 NtUserShowScrollBar(HWND hWnd, int nBar, DWORD bShow) 1499 { 1500 PWND Window; 1501 DECLARE_RETURN(DWORD); 1502 DWORD ret; 1503 USER_REFERENCE_ENTRY Ref; 1504 1505 TRACE("Enter NtUserShowScrollBar\n"); 1506 UserEnterExclusive(); 1507 1508 if (!(Window = UserGetWindowObject(hWnd))) 1509 { 1510 RETURN(0); 1511 } 1512 1513 UserRefObjectCo(Window, &Ref); 1514 ret = co_UserShowScrollBar(Window, nBar, (nBar == SB_VERT) ? 0 : bShow, 1515 (nBar == SB_HORZ) ? 0 : bShow); 1516 UserDerefObjectCo(Window); 1517 1518 RETURN(ret); 1519 1520 CLEANUP: 1521 TRACE("Leave NtUserShowScrollBar, ret%lu\n", _ret_); 1522 UserLeave(); 1523 END_CLEANUP; 1524 1525 } 1526 1527 1528 //// Ugly NtUser API //// 1529 1530 BOOL 1531 APIENTRY 1532 NtUserSetScrollBarInfo( 1533 HWND hWnd, 1534 LONG idObject, 1535 SETSCROLLBARINFO *info) 1536 { 1537 PWND Window = NULL; 1538 SETSCROLLBARINFO Safeinfo; 1539 PSCROLLBARINFO sbi; 1540 LPSCROLLINFO psi; 1541 NTSTATUS Status; 1542 LONG Obj; 1543 DECLARE_RETURN(BOOL); 1544 USER_REFERENCE_ENTRY Ref; 1545 1546 TRACE("Enter NtUserSetScrollBarInfo\n"); 1547 UserEnterExclusive(); 1548 1549 if(!(Window = UserGetWindowObject(hWnd))) 1550 { 1551 RETURN( FALSE); 1552 } 1553 UserRefObjectCo(Window, &Ref); 1554 1555 Obj = SBOBJ_TO_SBID(idObject); 1556 if(!SBID_IS_VALID(Obj)) 1557 { 1558 EngSetLastError(ERROR_INVALID_PARAMETER); 1559 ERR("Trying to set scrollinfo for unknown scrollbar type %d\n", Obj); 1560 RETURN( FALSE); 1561 } 1562 1563 if(!co_IntCreateScrollBars(Window)) 1564 { 1565 RETURN(FALSE); 1566 } 1567 1568 Status = MmCopyFromCaller(&Safeinfo, info, sizeof(SETSCROLLBARINFO)); 1569 if(!NT_SUCCESS(Status)) 1570 { 1571 SetLastNtError(Status); 1572 RETURN(FALSE); 1573 } 1574 1575 sbi = IntGetScrollbarInfoFromWindow(Window, Obj); 1576 psi = IntGetScrollInfoFromWindow(Window, Obj); 1577 1578 psi->nTrackPos = Safeinfo.nTrackPos; 1579 sbi->reserved = Safeinfo.reserved; 1580 RtlCopyMemory(&sbi->rgstate, &Safeinfo.rgstate, sizeof(Safeinfo.rgstate)); 1581 1582 RETURN(TRUE); 1583 1584 CLEANUP: 1585 if (Window) 1586 UserDerefObjectCo(Window); 1587 1588 TRACE("Leave NtUserSetScrollBarInfo, ret=%i\n",_ret_); 1589 UserLeave(); 1590 END_CLEANUP; 1591 } 1592 1593 /* EOF */ 1594