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 if(!SBID_IS_VALID(nBar)) 280 { 281 EngSetLastError(ERROR_INVALID_PARAMETER); 282 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", nBar); 283 return FALSE; 284 } 285 286 if (!Window->pSBInfo) 287 { 288 ERR("IntGetScrollInfo No window scrollbar info!\n"); 289 return FALSE; 290 } 291 292 psi = IntGetScrollInfoFromWindow(Window, nBar); 293 294 if (lpsi->fMask == SIF_ALL) 295 { 296 Mask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS; 297 } 298 else 299 { 300 Mask = lpsi->fMask; 301 } 302 303 if (0 != (Mask & SIF_PAGE)) 304 { 305 lpsi->nPage = psi->nPage; 306 } 307 308 if (0 != (Mask & SIF_POS)) 309 { 310 lpsi->nPos = psi->nPos; 311 } 312 313 if (0 != (Mask & SIF_RANGE)) 314 { 315 lpsi->nMin = psi->nMin; 316 lpsi->nMax = psi->nMax; 317 } 318 319 if (0 != (Mask & SIF_TRACKPOS)) 320 { 321 lpsi->nTrackPos = psi->nTrackPos; 322 } 323 324 return TRUE; 325 } 326 327 BOOL FASTCALL 328 NEWco_IntGetScrollInfo( 329 PWND pWnd, 330 INT nBar, 331 PSBDATA pSBData, 332 LPSCROLLINFO lpsi) 333 { 334 UINT Mask; 335 PSBTRACK pSBTrack = pWnd->head.pti->pSBTrack; 336 337 if (!SBID_IS_VALID(nBar)) 338 { 339 EngSetLastError(ERROR_INVALID_PARAMETER); 340 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", nBar); 341 return FALSE; 342 } 343 344 if (!pWnd->pSBInfo || !pSBTrack) return FALSE; 345 346 Mask = lpsi->fMask; 347 348 if (0 != (Mask & SIF_PAGE)) 349 { 350 lpsi->nPage = pSBData->page; 351 } 352 353 if (0 != (Mask & SIF_POS)) 354 { 355 lpsi->nPos = pSBData->pos; 356 } 357 358 if (0 != (Mask & SIF_RANGE)) 359 { 360 lpsi->nMin = pSBData->posMin; 361 lpsi->nMax = pSBData->posMax; 362 } 363 364 if (0 != (Mask & SIF_TRACKPOS)) 365 { 366 if ( pSBTrack && 367 pSBTrack->nBar == nBar && 368 pSBTrack->spwndTrack == pWnd ) 369 lpsi->nTrackPos = pSBTrack->posNew; 370 else 371 lpsi->nTrackPos = pSBData->pos; 372 } 373 return (Mask & SIF_ALL) !=0; 374 } 375 376 /************************************************************************* 377 * SCROLL_GetScrollBarInfo 378 * 379 * Internal helper for the API function 380 * 381 * PARAMS 382 * hwnd [I] Handle of window with scrollbar(s) 383 * idObject [I] One of OBJID_CLIENT, OBJID_HSCROLL, or OBJID_VSCROLL 384 * info [IO] cbSize specifies the size of the structure 385 * 386 * RETURNS 387 * FALSE if failed 388 */ 389 #if 0 390 static BOOL SCROLL_GetScrollBarInfo(HWND hwnd, LONG idObject, LPSCROLLBARINFO info) 391 { 392 LPSCROLLBAR_INFO infoPtr; 393 INT nBar; 394 INT nDummy; 395 DWORD style = GetWindowLongW(hwnd, GWL_STYLE); 396 BOOL pressed; 397 RECT rect; 398 399 switch (idObject) 400 { 401 case OBJID_CLIENT: nBar = SB_CTL; break; 402 case OBJID_HSCROLL: nBar = SB_HORZ; break; 403 case OBJID_VSCROLL: nBar = SB_VERT; break; 404 default: return FALSE; 405 } 406 407 /* handle invalid data structure */ 408 if (info->cbSize != sizeof(*info)) 409 return FALSE; 410 411 SCROLL_GetScrollBarRect(hwnd, nBar, &info->rcScrollBar, &nDummy, 412 &info->dxyLineButton, &info->xyThumbTop); 413 /* rcScrollBar needs to be in screen coordinates */ 414 GetWindowRect(hwnd, &rect); 415 OffsetRect(&info->rcScrollBar, rect.left, rect.top); 416 417 info->xyThumbBottom = info->xyThumbTop + info->dxyLineButton; 418 419 infoPtr = SCROLL_GetInternalInfo(hwnd, nBar, TRUE); 420 if (!infoPtr) 421 return FALSE; 422 423 /* Scroll bar state */ 424 info->rgstate[0] = 0; 425 if ((nBar == SB_HORZ && !(style & WS_HSCROLL)) 426 || (nBar == SB_VERT && !(style & WS_VSCROLL))) 427 info->rgstate[0] |= STATE_SYSTEM_INVISIBLE; 428 if (infoPtr->minVal >= infoPtr->maxVal - max(infoPtr->page - 1, 0)) 429 { 430 if (!(info->rgstate[0] & STATE_SYSTEM_INVISIBLE)) 431 info->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE; 432 else 433 info->rgstate[0] |= STATE_SYSTEM_OFFSCREEN; 434 } 435 if (nBar == SB_CTL && !IsWindowEnabled(hwnd)) 436 info->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE; 437 438 pressed = ((nBar == SB_VERT) == SCROLL_trackVertical && GetCapture() == hwnd); 439 440 /* Top/left arrow button state. MSDN says top/right, but I don't believe it */ 441 info->rgstate[1] = 0; 442 if (pressed && SCROLL_trackHitTest == SCROLL_TOP_ARROW) 443 info->rgstate[1] |= STATE_SYSTEM_PRESSED; 444 if (infoPtr->flags & ESB_DISABLE_LTUP) 445 info->rgstate[1] |= STATE_SYSTEM_UNAVAILABLE; 446 447 /* Page up/left region state. MSDN says up/right, but I don't believe it */ 448 info->rgstate[2] = 0; 449 if (infoPtr->curVal == infoPtr->minVal) 450 info->rgstate[2] |= STATE_SYSTEM_INVISIBLE; 451 if (pressed && SCROLL_trackHitTest == SCROLL_TOP_RECT) 452 info->rgstate[2] |= STATE_SYSTEM_PRESSED; 453 454 /* Thumb state */ 455 info->rgstate[3] = 0; 456 if (pressed && SCROLL_trackHitTest == SCROLL_THUMB) 457 info->rgstate[3] |= STATE_SYSTEM_PRESSED; 458 459 /* Page down/right region state. MSDN says down/left, but I don't believe it */ 460 info->rgstate[4] = 0; 461 if (infoPtr->curVal >= infoPtr->maxVal - 1) 462 info->rgstate[4] |= STATE_SYSTEM_INVISIBLE; 463 if (pressed && SCROLL_trackHitTest == SCROLL_BOTTOM_RECT) 464 info->rgstate[4] |= STATE_SYSTEM_PRESSED; 465 466 /* Bottom/right arrow button state. MSDN says bottom/left, but I don't believe it */ 467 info->rgstate[5] = 0; 468 if (pressed && SCROLL_trackHitTest == SCROLL_BOTTOM_ARROW) 469 info->rgstate[5] |= STATE_SYSTEM_PRESSED; 470 if (infoPtr->flags & ESB_DISABLE_RTDN) 471 info->rgstate[5] |= STATE_SYSTEM_UNAVAILABLE; 472 473 return TRUE; 474 } 475 #endif 476 static DWORD FASTCALL 477 co_IntSetScrollInfo(PWND Window, INT nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) 478 { 479 /* 480 * Update the scrollbar state and set action flags according to 481 * what has to be done graphics wise. 482 */ 483 484 LPSCROLLINFO Info; 485 PSCROLLBARINFO psbi; 486 UINT new_flags; 487 INT action = 0; 488 PSBDATA pSBData; 489 DWORD OldPos = 0; 490 BOOL bChangeParams = FALSE; /* Don't show/hide scrollbar if params don't change */ 491 UINT MaxPage; 492 int MaxPos; 493 494 ASSERT_REFS_CO(Window); 495 496 if(!SBID_IS_VALID(nBar)) 497 { 498 EngSetLastError(ERROR_INVALID_PARAMETER); 499 ERR("Trying to set scrollinfo for unknown scrollbar type %d", nBar); 500 return FALSE; 501 } 502 503 if(!co_IntCreateScrollBars(Window)) 504 { 505 return FALSE; 506 } 507 508 if (lpsi->cbSize != sizeof(SCROLLINFO) && 509 lpsi->cbSize != (sizeof(SCROLLINFO) - sizeof(lpsi->nTrackPos))) 510 { 511 EngSetLastError(ERROR_INVALID_PARAMETER); 512 return 0; 513 } 514 if (lpsi->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL | SIF_PREVIOUSPOS)) 515 { 516 EngSetLastError(ERROR_INVALID_PARAMETER); 517 return 0; 518 } 519 520 psbi = IntGetScrollbarInfoFromWindow(Window, nBar); 521 Info = IntGetScrollInfoFromWindow(Window, nBar); 522 pSBData = IntGetSBData(Window, nBar); 523 524 /* Set the page size */ 525 if (lpsi->fMask & SIF_PAGE) 526 { 527 if (Info->nPage != lpsi->nPage) 528 { 529 Info->nPage = lpsi->nPage; 530 pSBData->page = lpsi->nPage; 531 bChangeParams = TRUE; 532 } 533 } 534 535 /* Set the scroll pos */ 536 if (lpsi->fMask & SIF_POS) 537 { 538 if (Info->nPos != lpsi->nPos) 539 { 540 OldPos = Info->nPos; 541 Info->nPos = lpsi->nPos; 542 pSBData->pos = lpsi->nPos; 543 } 544 } 545 546 /* Set the scroll range */ 547 if (lpsi->fMask & SIF_RANGE) 548 { 549 if (lpsi->nMin > lpsi->nMax) 550 { 551 Info->nMin = lpsi->nMin; 552 Info->nMax = lpsi->nMin; 553 pSBData->posMin = lpsi->nMin; 554 pSBData->posMax = lpsi->nMin; 555 bChangeParams = TRUE; 556 } 557 else if (Info->nMin != lpsi->nMin || Info->nMax != lpsi->nMax) 558 { 559 Info->nMin = lpsi->nMin; 560 Info->nMax = lpsi->nMax; 561 pSBData->posMin = lpsi->nMin; 562 pSBData->posMax = lpsi->nMax; 563 bChangeParams = TRUE; 564 } 565 } 566 567 /* Make sure the page size is valid */ 568 MaxPage = abs(Info->nMax - Info->nMin) + 1; 569 if (Info->nPage > MaxPage) 570 { 571 pSBData->page = Info->nPage = MaxPage; 572 } 573 574 /* Make sure the pos is inside the range */ 575 MaxPos = Info->nMax + 1 - (int)max(Info->nPage, 1); 576 ASSERT(MaxPos >= Info->nMin); 577 if (Info->nPos < Info->nMin) 578 { 579 pSBData->pos = Info->nPos = Info->nMin; 580 } 581 else if (Info->nPos > MaxPos) 582 { 583 pSBData->pos = Info->nPos = MaxPos; 584 } 585 586 /* 587 * Don't change the scrollbar state if SetScrollInfo is just called 588 * with SIF_DISABLENOSCROLL 589 */ 590 if (!(lpsi->fMask & SIF_ALL)) 591 { 592 //goto done; 593 return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos; 594 } 595 596 /* Check if the scrollbar should be hidden or disabled */ 597 if (lpsi->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL)) 598 { 599 new_flags = Window->pSBInfo->WSBflags; 600 if (Info->nMin >= (int)(Info->nMax - max(Info->nPage - 1, 0))) 601 { 602 /* Hide or disable scroll-bar */ 603 if (lpsi->fMask & SIF_DISABLENOSCROLL) 604 { 605 new_flags = ESB_DISABLE_BOTH; 606 bChangeParams = TRUE; 607 } 608 else if ((nBar != SB_CTL) && bChangeParams) 609 { 610 action = SA_SSI_HIDE; 611 } 612 } 613 else /* Show and enable scroll-bar only if no page only changed. */ 614 if (lpsi->fMask != SIF_PAGE) 615 { 616 if ((nBar != SB_CTL) && bChangeParams) 617 { 618 new_flags = ESB_ENABLE_BOTH; 619 action |= SA_SSI_SHOW; 620 } 621 else if (nBar == SB_CTL) 622 { 623 new_flags = ESB_ENABLE_BOTH; 624 } 625 } 626 627 if (Window->pSBInfo->WSBflags != new_flags) /* Check arrow flags */ 628 { 629 Window->pSBInfo->WSBflags = new_flags; 630 action |= SA_SSI_REPAINT_ARROWS; 631 } 632 } 633 634 //done: 635 if ( action & SA_SSI_HIDE ) 636 { 637 co_UserShowScrollBar(Window, nBar, FALSE, FALSE); 638 } 639 else 640 { 641 if ( action & SA_SSI_SHOW ) 642 if ( co_UserShowScrollBar(Window, nBar, TRUE, TRUE) ) 643 return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos; /* SetWindowPos() already did the painting */ 644 if (bRedraw) 645 { 646 if (action & SA_SSI_REPAINT_ARROWS) 647 { // Redraw the entire bar. 648 RECTL UpdateRect = psbi->rcScrollBar; 649 UpdateRect.left -= Window->rcClient.left - Window->rcWindow.left; 650 UpdateRect.right -= Window->rcClient.left - Window->rcWindow.left; 651 UpdateRect.top -= Window->rcClient.top - Window->rcWindow.top; 652 UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top; 653 co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME); 654 } 655 else 656 { 657 // Redraw only the interior part of the bar. 658 IntRefeshScrollInterior(Window, nBar, psbi); 659 } 660 } // FIXME: Arrows 661 /* else if( action & SA_SSI_REPAINT_ARROWS ) 662 { 663 RECTL UpdateRect = psbi->rcScrollBar; 664 UpdateRect.left -= Window->rcClient.left - Window->rcWindow.left; 665 UpdateRect.right -= Window->rcClient.left - Window->rcWindow.left; 666 UpdateRect.top -= Window->rcClient.top - Window->rcWindow.top; 667 UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top; 668 co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME); 669 } 670 */ } 671 672 if (bChangeParams && (nBar == SB_HORZ || nBar == SB_VERT) && (lpsi->fMask & SIF_DISABLENOSCROLL)) 673 { 674 IntEnableScrollBar(nBar == SB_HORZ, psbi, Window->pSBInfo->WSBflags); 675 } 676 677 /* Return current position */ 678 return lpsi->fMask & SIF_PREVIOUSPOS ? OldPos : pSBData->pos; 679 } 680 681 BOOL FASTCALL 682 co_IntGetScrollBarInfo(PWND Window, LONG idObject, PSCROLLBARINFO psbi) 683 { 684 INT Bar; 685 PSCROLLBARINFO sbi; 686 PSBDATA pSBData; 687 ASSERT_REFS_CO(Window); 688 689 Bar = SBOBJ_TO_SBID(idObject); 690 691 if(!SBID_IS_VALID(Bar)) 692 { 693 EngSetLastError(ERROR_INVALID_PARAMETER); 694 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", Bar); 695 return FALSE; 696 } 697 698 if(!co_IntCreateScrollBars(Window)) 699 { 700 ERR("Failed to create scrollbars for window.\n"); 701 return FALSE; 702 } 703 704 sbi = IntGetScrollbarInfoFromWindow(Window, Bar); 705 pSBData = IntGetSBData(Window, Bar); 706 707 IntGetScrollBarRect(Window, Bar, &(sbi->rcScrollBar)); 708 IntCalculateThumb(Window, Bar, sbi, pSBData); 709 710 /* Scroll bar state */ 711 psbi->rgstate[0] = 0; 712 if ((Bar == SB_HORZ && !(Window->style & WS_HSCROLL)) 713 || (Bar == SB_VERT && !(Window->style & WS_VSCROLL))) 714 psbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE; 715 if (pSBData->posMin >= pSBData->posMax - max(pSBData->page - 1, 0)) 716 { 717 if (!(psbi->rgstate[0] & STATE_SYSTEM_INVISIBLE)) 718 psbi->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE; 719 else 720 psbi->rgstate[0] |= STATE_SYSTEM_OFFSCREEN; 721 } 722 if (Bar == SB_CTL && !(Window->style & WS_DISABLED)) 723 psbi->rgstate[0] |= STATE_SYSTEM_UNAVAILABLE; 724 725 RtlCopyMemory(psbi, sbi, sizeof(SCROLLBARINFO)); 726 727 return TRUE; 728 } 729 730 BOOL FASTCALL 731 co_IntSetScrollBarInfo(PWND Window, LONG idObject, PSETSCROLLBARINFO psbi) 732 { 733 INT Bar; 734 PSCROLLBARINFO sbi; 735 LPSCROLLINFO psi; 736 ASSERT_REFS_CO(Window); 737 738 Bar = SBOBJ_TO_SBID(idObject); 739 740 if(!SBID_IS_VALID(Bar)) 741 { 742 EngSetLastError(ERROR_INVALID_PARAMETER); 743 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", Bar); 744 return FALSE; 745 } 746 747 if(!co_IntCreateScrollBars(Window)) 748 { 749 ERR("Failed to create scrollbars for window.\n"); 750 return FALSE; 751 } 752 753 sbi = IntGetScrollbarInfoFromWindow(Window, Bar); 754 psi = IntGetScrollInfoFromWindow(Window, Bar); 755 756 psi->nTrackPos = psbi->nTrackPos; 757 sbi->reserved = psbi->reserved; 758 RtlCopyMemory(&sbi->rgstate, &psbi->rgstate, sizeof(psbi->rgstate)); 759 760 return TRUE; 761 } 762 763 BOOL FASTCALL 764 co_IntCreateScrollBars(PWND Window) 765 { 766 PSCROLLBARINFO psbi; 767 PSBDATA pSBData; 768 ULONG Size, s; 769 INT i; 770 771 ASSERT_REFS_CO(Window); 772 773 if (Window->pSBInfo && Window->pSBInfoex) 774 { 775 /* No need to create it anymore */ 776 return TRUE; 777 } 778 779 /* Allocate memory for all scrollbars (HORZ, VERT, CONTROL) */ 780 Size = 3 * (sizeof(SBINFOEX)); 781 if(!(Window->pSBInfoex = ExAllocatePoolWithTag(PagedPool, Size, TAG_SBARINFO))) 782 { 783 ERR("Unable to allocate memory for scrollbar information for window %p\n", Window->head.h); 784 return FALSE; 785 } 786 787 RtlZeroMemory(Window->pSBInfoex, Size); 788 789 if(!(Window->pSBInfo = DesktopHeapAlloc( Window->head.rpdesk, sizeof(SBINFO)))) 790 { 791 ERR("Unable to allocate memory for scrollbar information for window %p\n", Window->head.h); 792 return FALSE; 793 } 794 795 RtlZeroMemory(Window->pSBInfo, sizeof(SBINFO)); 796 Window->pSBInfo->Vert.posMax = 100; 797 Window->pSBInfo->Horz.posMax = 100; 798 799 co_WinPosGetNonClientSize(Window, 800 &Window->rcWindow, 801 &Window->rcClient); 802 803 for(s = SB_HORZ; s <= SB_VERT; s++) 804 { 805 psbi = IntGetScrollbarInfoFromWindow(Window, s); 806 psbi->cbSize = sizeof(SCROLLBARINFO); 807 for (i = 0; i < CCHILDREN_SCROLLBAR + 1; i++) 808 psbi->rgstate[i] = 0; 809 810 pSBData = IntGetSBData(Window, s); 811 812 IntGetScrollBarRect(Window, s, &(psbi->rcScrollBar)); 813 IntCalculateThumb(Window, s, psbi, pSBData); 814 } 815 816 return TRUE; 817 } 818 819 BOOL FASTCALL 820 IntDestroyScrollBars(PWND Window) 821 { 822 if (Window->pSBInfo && Window->pSBInfoex) 823 { 824 DesktopHeapFree(Window->head.rpdesk, Window->pSBInfo); 825 Window->pSBInfo = NULL; 826 ExFreePoolWithTag(Window->pSBInfoex, TAG_SBARINFO); 827 Window->pSBInfoex = NULL; 828 return TRUE; 829 } 830 return FALSE; 831 } 832 833 BOOL APIENTRY 834 IntEnableScrollBar(BOOL Horz, PSCROLLBARINFO Info, UINT wArrows) 835 { 836 BOOL Chg = FALSE; 837 switch(wArrows) 838 { 839 case ESB_DISABLE_BOTH: 840 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE); 841 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE); 842 break; 843 case ESB_DISABLE_RTDN: 844 if(Horz) 845 { 846 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE); 847 } 848 else 849 { 850 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE); 851 } 852 break; 853 case ESB_DISABLE_LTUP: 854 if(Horz) 855 { 856 CHANGERGSTATE(SBRG_TOPRIGHTBTN, STATE_SYSTEM_UNAVAILABLE); 857 } 858 else 859 { 860 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, STATE_SYSTEM_UNAVAILABLE); 861 } 862 break; 863 case ESB_ENABLE_BOTH: 864 CHANGERGSTATE(SBRG_TOPRIGHTBTN, 0); 865 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN, 0); 866 break; 867 } 868 return Chg; 869 } 870 871 /* Ported from WINE20020904 (SCROLL_ShowScrollBar) */ 872 DWORD FASTCALL 873 co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV) 874 { 875 ULONG old_style, set_bits = 0, clear_bits = 0; 876 877 ASSERT_REFS_CO(Wnd); 878 879 switch(nBar) 880 { 881 case SB_CTL: 882 { 883 //IntUpdateSBInfo(Wnd, SB_CTL); // Is this needed? Was tested w/o! 884 885 co_WinPosShowWindow(Wnd, fShowH ? SW_SHOW : SW_HIDE); 886 return TRUE; 887 } 888 case SB_BOTH: 889 case SB_HORZ: 890 if (fShowH) set_bits |= WS_HSCROLL; 891 else clear_bits |= WS_HSCROLL; 892 if( nBar == SB_HORZ ) break; 893 /* Fall through */ 894 case SB_VERT: 895 if (fShowV) set_bits |= WS_VSCROLL; 896 else clear_bits |= WS_VSCROLL; 897 break; 898 default: 899 EngSetLastError(ERROR_INVALID_PARAMETER); 900 return FALSE; /* Nothing to do! */ 901 } 902 903 old_style = IntSetStyle( Wnd, set_bits, clear_bits ); 904 if ((old_style & clear_bits) != 0 || (old_style & set_bits) != set_bits) 905 { 906 ///// Is this needed? Was tested w/o! 907 //if (Wnd->style & WS_HSCROLL) IntUpdateSBInfo(Wnd, SB_HORZ); 908 //if (Wnd->style & WS_VSCROLL) IntUpdateSBInfo(Wnd, SB_VERT); 909 ///// 910 /* Frame has been changed, let the window redraw itself */ 911 co_WinPosSetWindowPos( Wnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE 912 | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); 913 return TRUE; 914 } 915 return FALSE; /* no frame changes */ 916 } 917 918 static void 919 IntDrawScrollInterior(PWND pWnd, HDC hDC, INT nBar, BOOL Vertical, PSCROLLBARINFO ScrollBarInfo) 920 { 921 INT ThumbSize = ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop; 922 INT ThumbTop = ScrollBarInfo->xyThumbTop; 923 RECT Rect; 924 HBRUSH hSaveBrush, hBrush; 925 BOOL TopSelected = FALSE, BottomSelected = FALSE; 926 927 if (ScrollBarInfo->rgstate[SCROLL_TOP_RECT] & STATE_SYSTEM_PRESSED) 928 TopSelected = TRUE; 929 if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_RECT] & STATE_SYSTEM_PRESSED) 930 BottomSelected = TRUE; 931 932 /* 933 * Only scrollbar controls send WM_CTLCOLORSCROLLBAR. 934 * The window-owned scrollbars need to call DefWndControlColor 935 * to correctly setup default scrollbar colors 936 */ 937 if (nBar == SB_CTL) 938 { 939 hBrush = GetControlBrush( pWnd, hDC, WM_CTLCOLORSCROLLBAR); 940 if (!hBrush) 941 hBrush = IntGetSysColorBrush(COLOR_SCROLLBAR); 942 } 943 else 944 { 945 hBrush = DefWndControlColor(hDC, CTLCOLOR_SCROLLBAR); 946 } 947 948 hSaveBrush = NtGdiSelectBrush(hDC, hBrush); 949 950 /* Calculate the scroll rectangle */ 951 if (Vertical) 952 { 953 Rect.top = ScrollBarInfo->rcScrollBar.top + ScrollBarInfo->dxyLineButton; 954 Rect.bottom = ScrollBarInfo->rcScrollBar.bottom - ScrollBarInfo->dxyLineButton; 955 Rect.left = ScrollBarInfo->rcScrollBar.left; 956 Rect.right = ScrollBarInfo->rcScrollBar.right; 957 } 958 else 959 { 960 Rect.top = ScrollBarInfo->rcScrollBar.top; 961 Rect.bottom = ScrollBarInfo->rcScrollBar.bottom; 962 Rect.left = ScrollBarInfo->rcScrollBar.left + ScrollBarInfo->dxyLineButton; 963 Rect.right = ScrollBarInfo->rcScrollBar.right - ScrollBarInfo->dxyLineButton; 964 } 965 966 /* Draw the scroll rectangles and thumb */ 967 if (!ScrollBarInfo->xyThumbBottom) 968 { 969 NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right - Rect.left, 970 Rect.bottom - Rect.top, PATCOPY); 971 972 /* Cleanup and return */ 973 NtGdiSelectBrush(hDC, hSaveBrush); 974 return; 975 } 976 977 ThumbTop -= ScrollBarInfo->dxyLineButton; 978 979 if (ScrollBarInfo->dxyLineButton) 980 { 981 if (Vertical) 982 { 983 if (ThumbSize) 984 { 985 NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right - Rect.left, 986 ThumbTop, TopSelected ? BLACKNESS : PATCOPY); 987 Rect.top += ThumbTop; 988 NtGdiPatBlt(hDC, Rect.left, Rect.top + ThumbSize, Rect.right - Rect.left, 989 Rect.bottom - Rect.top - ThumbSize, BottomSelected ? BLACKNESS : PATCOPY); 990 Rect.bottom = Rect.top + ThumbSize; 991 } 992 else 993 { 994 if (ThumbTop) 995 { 996 NtGdiPatBlt(hDC, Rect.left, ScrollBarInfo->dxyLineButton, 997 Rect.right - Rect.left, Rect.bottom - Rect.top, PATCOPY); 998 } 999 } 1000 } 1001 else 1002 { 1003 if (ThumbSize) 1004 { 1005 NtGdiPatBlt(hDC, Rect.left, Rect.top, ThumbTop, 1006 Rect.bottom - Rect.top, TopSelected ? BLACKNESS : PATCOPY); 1007 Rect.left += ThumbTop; 1008 NtGdiPatBlt(hDC, Rect.left + ThumbSize, Rect.top, 1009 Rect.right - Rect.left - ThumbSize, Rect.bottom - Rect.top, 1010 BottomSelected ? BLACKNESS : PATCOPY); 1011 Rect.right = Rect.left + ThumbSize; 1012 } 1013 else 1014 { 1015 if (ThumbTop) 1016 { 1017 NtGdiPatBlt(hDC, ScrollBarInfo->dxyLineButton, Rect.top, 1018 Rect.right - Rect.left, Rect.bottom - Rect.top, PATCOPY); 1019 } 1020 } 1021 } 1022 } 1023 1024 /* Draw the thumb */ 1025 if (ThumbSize) 1026 DrawEdge(hDC, &Rect, EDGE_RAISED, BF_RECT | BF_MIDDLE); 1027 1028 /* Cleanup */ 1029 NtGdiSelectBrush(hDC, hSaveBrush); 1030 } 1031 1032 1033 static VOID FASTCALL 1034 IntDrawScrollArrows(HDC hDC, PSCROLLBARINFO ScrollBarInfo, BOOL Vertical) 1035 { 1036 RECT RectLT, RectRB; 1037 INT ScrollDirFlagLT, ScrollDirFlagRB; 1038 1039 RectLT = RectRB = ScrollBarInfo->rcScrollBar; 1040 if (Vertical) 1041 { 1042 ScrollDirFlagLT = DFCS_SCROLLUP; 1043 ScrollDirFlagRB = DFCS_SCROLLDOWN; 1044 RectLT.bottom = RectLT.top + ScrollBarInfo->dxyLineButton; 1045 RectRB.top = RectRB.bottom - ScrollBarInfo->dxyLineButton; 1046 } 1047 else 1048 { 1049 ScrollDirFlagLT = DFCS_SCROLLLEFT; 1050 ScrollDirFlagRB = DFCS_SCROLLRIGHT; 1051 RectLT.right = RectLT.left + ScrollBarInfo->dxyLineButton; 1052 RectRB.left = RectRB.right - ScrollBarInfo->dxyLineButton; 1053 } 1054 1055 if (ScrollBarInfo->rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_PRESSED) 1056 { 1057 ScrollDirFlagLT |= DFCS_PUSHED | DFCS_FLAT; 1058 } 1059 if (ScrollBarInfo->rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_UNAVAILABLE) 1060 { 1061 ScrollDirFlagLT |= DFCS_INACTIVE; 1062 } 1063 if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_PRESSED) 1064 { 1065 ScrollDirFlagRB |= DFCS_PUSHED | DFCS_FLAT; 1066 } 1067 if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_UNAVAILABLE) 1068 { 1069 ScrollDirFlagRB |= DFCS_INACTIVE; 1070 } 1071 1072 DrawFrameControl(hDC, &RectLT, DFC_SCROLL, ScrollDirFlagLT); 1073 DrawFrameControl(hDC, &RectRB, DFC_SCROLL, ScrollDirFlagRB); 1074 } 1075 1076 static LONG FASTCALL 1077 IntScrollGetObjectId(INT SBType) 1078 { 1079 if (SBType == SB_VERT) 1080 return OBJID_VSCROLL; 1081 if (SBType == SB_HORZ) 1082 return OBJID_HSCROLL; 1083 return OBJID_CLIENT; 1084 } 1085 1086 static void 1087 IntRefeshScrollInterior(PWND pWnd, INT nBar, PSCROLLBARINFO psbi) 1088 { 1089 HDC hdc; 1090 BOOL Vertical = ((nBar == SB_CTL) ? ((pWnd->style & SBS_VERT) != 0) : (nBar == SB_VERT)); 1091 1092 hdc = UserGetDCEx(pWnd, NULL, DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW)); 1093 if (hdc) 1094 { /* Get updated info. */ 1095 co_IntGetScrollBarInfo(pWnd, IntScrollGetObjectId(nBar), psbi); 1096 IntDrawScrollInterior(pWnd, hdc, nBar, Vertical, psbi); 1097 UserReleaseDC(pWnd, hdc, FALSE); 1098 } 1099 } 1100 1101 void 1102 IntDrawScrollBar(PWND Wnd, HDC DC, INT Bar) 1103 { 1104 //PSBWND pSBWnd; 1105 //INT ThumbSize; 1106 PTHREADINFO pti; 1107 SCROLLBARINFO Info; 1108 BOOL Vertical; 1109 1110 pti = PsGetCurrentThreadWin32Thread(); 1111 1112 /* 1113 * Get scroll bar info. 1114 */ 1115 switch (Bar) 1116 { 1117 case SB_HORZ: 1118 Vertical = FALSE; 1119 break; 1120 1121 case SB_VERT: 1122 Vertical = TRUE; 1123 break; 1124 1125 case SB_CTL: 1126 Vertical = (Wnd->style & SBS_VERT) != 0; 1127 break; 1128 1129 default: 1130 return; 1131 } 1132 1133 if (!co_IntGetScrollBarInfo(Wnd, IntScrollGetObjectId(Bar), &Info)) 1134 { 1135 return; 1136 } 1137 1138 if (RECTL_bIsEmptyRect(&Info.rcScrollBar)) 1139 { 1140 return; 1141 } 1142 1143 //ThumbSize = pSBWnd->pSBCalc->pxThumbBottom - pSBWnd->pSBCalc->pxThumbTop; 1144 1145 /* 1146 * Draw the arrows. 1147 */ 1148 if (Info.dxyLineButton) 1149 { 1150 IntDrawScrollArrows(DC, &Info, Vertical); 1151 } 1152 1153 /* 1154 * Draw the interior. 1155 */ 1156 IntDrawScrollInterior(Wnd, DC, Bar, Vertical, &Info); 1157 1158 /* 1159 * If scroll bar has focus, reposition the caret. 1160 */ 1161 if ( Wnd == pti->MessageQueue->spwndFocus && Bar == SB_CTL ) 1162 { 1163 if (Vertical) 1164 { 1165 co_IntSetCaretPos(Info.rcScrollBar.top + 1, Info.dxyLineButton + 1); 1166 } 1167 else 1168 { 1169 co_IntSetCaretPos(Info.dxyLineButton + 1, Info.rcScrollBar.top + 1); 1170 } 1171 } 1172 } 1173 1174 1175 LRESULT APIENTRY 1176 ScrollBarWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) 1177 { 1178 LRESULT lResult = 0; 1179 PWND pWnd; 1180 pWnd = UserGetWindowObject(hWnd); 1181 if (!pWnd) return 0; 1182 1183 switch(Msg) 1184 { 1185 case WM_ENABLE: 1186 { 1187 if (pWnd->pSBInfo) 1188 { 1189 pWnd->pSBInfo->WSBflags = wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH; 1190 } 1191 } 1192 break; 1193 } 1194 return lResult; 1195 } 1196 1197 //// 1198 1199 BOOL 1200 APIENTRY 1201 NtUserGetScrollBarInfo(HWND hWnd, LONG idObject, PSCROLLBARINFO psbi) 1202 { 1203 NTSTATUS Status; 1204 SCROLLBARINFO sbi; 1205 PWND Window; 1206 BOOL Ret; 1207 DECLARE_RETURN(BOOL); 1208 USER_REFERENCE_ENTRY Ref; 1209 1210 TRACE("Enter NtUserGetScrollBarInfo\n"); 1211 UserEnterExclusive(); 1212 1213 Status = MmCopyFromCaller(&sbi, psbi, sizeof(SCROLLBARINFO)); 1214 if(!NT_SUCCESS(Status) || (sbi.cbSize != sizeof(SCROLLBARINFO))) 1215 { 1216 SetLastNtError(Status); 1217 RETURN(FALSE); 1218 } 1219 1220 if(!(Window = UserGetWindowObject(hWnd))) 1221 { 1222 RETURN(FALSE); 1223 } 1224 1225 UserRefObjectCo(Window, &Ref); 1226 Ret = co_IntGetScrollBarInfo(Window, idObject, &sbi); 1227 UserDerefObjectCo(Window); 1228 1229 Status = MmCopyToCaller(psbi, &sbi, sizeof(SCROLLBARINFO)); 1230 if(!NT_SUCCESS(Status)) 1231 { 1232 SetLastNtError(Status); 1233 Ret = FALSE; 1234 } 1235 1236 RETURN( Ret); 1237 1238 CLEANUP: 1239 TRACE("Leave NtUserGetScrollBarInfo, ret=%i\n",_ret_); 1240 UserLeave(); 1241 END_CLEANUP; 1242 1243 } 1244 1245 BOOL 1246 APIENTRY 1247 NtUserSBGetParms( 1248 HWND hWnd, 1249 int fnBar, 1250 PSBDATA pSBData, 1251 LPSCROLLINFO lpsi) 1252 { 1253 PWND Window; 1254 SCROLLINFO psi; 1255 BOOL Ret; 1256 SBDATA SBDataSafe; 1257 DECLARE_RETURN(BOOL); 1258 USER_REFERENCE_ENTRY Ref; 1259 1260 TRACE("Enter NtUserGetScrollInfo\n"); 1261 UserEnterShared(); 1262 1263 _SEH2_TRY 1264 { 1265 RtlCopyMemory(&psi, lpsi, sizeof(SCROLLINFO)); 1266 if (pSBData) 1267 { 1268 RtlCopyMemory(&SBDataSafe, pSBData, sizeof(SBDATA)); 1269 } 1270 } 1271 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1272 { 1273 ERR("NtUserGetScrollInfo Failed size.\n"); 1274 SetLastNtError(_SEH2_GetExceptionCode()); 1275 _SEH2_YIELD(RETURN(FALSE)); 1276 } 1277 _SEH2_END 1278 1279 if(!(Window = UserGetWindowObject(hWnd))) 1280 { 1281 ERR("NtUserGetScrollInfo Bad window.\n"); 1282 RETURN(FALSE); 1283 } 1284 1285 UserRefObjectCo(Window, &Ref); 1286 Ret = co_IntGetScrollInfo(Window, fnBar, &SBDataSafe, &psi); 1287 UserDerefObjectCo(Window); 1288 1289 _SEH2_TRY 1290 { 1291 RtlCopyMemory(lpsi, &psi, sizeof(SCROLLINFO)); 1292 } 1293 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1294 { 1295 ERR("NtUserGetScrollInfo Failed copy to user.\n"); 1296 SetLastNtError(_SEH2_GetExceptionCode()); 1297 _SEH2_YIELD(RETURN(FALSE)); 1298 } 1299 _SEH2_END 1300 1301 RETURN( Ret); 1302 1303 CLEANUP: 1304 TRACE("Leave NtUserGetScrollInfo, ret=%i\n",_ret_); 1305 UserLeave(); 1306 END_CLEANUP; 1307 } 1308 1309 BOOL 1310 APIENTRY 1311 NtUserEnableScrollBar( 1312 HWND hWnd, 1313 UINT wSBflags, 1314 UINT wArrows) 1315 { 1316 UINT OrigArrows; 1317 PWND Window = NULL; 1318 PSCROLLBARINFO InfoV = NULL, InfoH = NULL; 1319 BOOL Chg = FALSE; 1320 DECLARE_RETURN(BOOL); 1321 USER_REFERENCE_ENTRY Ref; 1322 1323 TRACE("Enter NtUserEnableScrollBar\n"); 1324 UserEnterExclusive(); 1325 1326 if (!(Window = UserGetWindowObject(hWnd)) || 1327 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 1328 { 1329 RETURN(FALSE); 1330 } 1331 UserRefObjectCo(Window, &Ref); 1332 1333 if (!co_IntCreateScrollBars(Window)) 1334 { 1335 RETURN( FALSE); 1336 } 1337 1338 OrigArrows = Window->pSBInfo->WSBflags; 1339 Window->pSBInfo->WSBflags = wArrows; 1340 1341 if (wSBflags == SB_CTL) 1342 { 1343 if ((wArrows == ESB_DISABLE_BOTH || wArrows == ESB_ENABLE_BOTH)) 1344 IntEnableWindow(hWnd, (wArrows == ESB_ENABLE_BOTH)); 1345 1346 RETURN(TRUE); 1347 } 1348 1349 if(wSBflags != SB_BOTH && !SBID_IS_VALID(wSBflags)) 1350 { 1351 EngSetLastError(ERROR_INVALID_PARAMETER); 1352 ERR("Trying to set scrollinfo for unknown scrollbar type %u", wSBflags); 1353 RETURN(FALSE); 1354 } 1355 1356 switch(wSBflags) 1357 { 1358 case SB_BOTH: 1359 InfoV = IntGetScrollbarInfoFromWindow(Window, SB_VERT); 1360 /* Fall through */ 1361 case SB_HORZ: 1362 InfoH = IntGetScrollbarInfoFromWindow(Window, SB_HORZ); 1363 break; 1364 case SB_VERT: 1365 InfoV = IntGetScrollbarInfoFromWindow(Window, SB_VERT); 1366 break; 1367 default: 1368 RETURN(FALSE); 1369 } 1370 1371 if(InfoV) 1372 Chg = IntEnableScrollBar(FALSE, InfoV, wArrows); 1373 1374 if(InfoH) 1375 Chg = (IntEnableScrollBar(TRUE, InfoH, wArrows) || Chg); 1376 1377 ERR("FIXME: EnableScrollBar wSBflags %u wArrows %u Chg %d\n", wSBflags, wArrows, Chg); 1378 // Done in user32: 1379 // SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE ); 1380 1381 RETURN( Chg); 1382 if (OrigArrows == wArrows) RETURN( FALSE); 1383 RETURN( TRUE); 1384 1385 CLEANUP: 1386 if (Window) 1387 UserDerefObjectCo(Window); 1388 1389 TRACE("Leave NtUserEnableScrollBar, ret=%i\n",_ret_); 1390 UserLeave(); 1391 END_CLEANUP; 1392 } 1393 1394 DWORD 1395 APIENTRY 1396 NtUserSetScrollInfo( 1397 HWND hWnd, 1398 int fnBar, 1399 LPCSCROLLINFO lpsi, 1400 BOOL bRedraw) 1401 { 1402 PWND Window = NULL; 1403 NTSTATUS Status; 1404 SCROLLINFO ScrollInfo; 1405 DECLARE_RETURN(DWORD); 1406 USER_REFERENCE_ENTRY Ref; 1407 1408 TRACE("Enter NtUserSetScrollInfo\n"); 1409 UserEnterExclusive(); 1410 1411 if(!(Window = UserGetWindowObject(hWnd)) || 1412 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 1413 { 1414 RETURN( 0); 1415 } 1416 UserRefObjectCo(Window, &Ref); 1417 1418 Status = MmCopyFromCaller(&ScrollInfo, lpsi, sizeof(SCROLLINFO) - sizeof(ScrollInfo.nTrackPos)); 1419 if(!NT_SUCCESS(Status)) 1420 { 1421 SetLastNtError(Status); 1422 RETURN( 0); 1423 } 1424 1425 RETURN(co_IntSetScrollInfo(Window, fnBar, &ScrollInfo, bRedraw)); 1426 1427 CLEANUP: 1428 if (Window) 1429 UserDerefObjectCo(Window); 1430 1431 TRACE("Leave NtUserSetScrollInfo, ret=%lu\n", _ret_); 1432 UserLeave(); 1433 END_CLEANUP; 1434 1435 } 1436 1437 DWORD APIENTRY 1438 NtUserShowScrollBar(HWND hWnd, int nBar, DWORD bShow) 1439 { 1440 PWND Window; 1441 DECLARE_RETURN(DWORD); 1442 DWORD ret; 1443 USER_REFERENCE_ENTRY Ref; 1444 1445 TRACE("Enter NtUserShowScrollBar\n"); 1446 UserEnterExclusive(); 1447 1448 if (!(Window = UserGetWindowObject(hWnd))) 1449 { 1450 RETURN(0); 1451 } 1452 1453 UserRefObjectCo(Window, &Ref); 1454 ret = co_UserShowScrollBar(Window, nBar, (nBar == SB_VERT) ? 0 : bShow, 1455 (nBar == SB_HORZ) ? 0 : bShow); 1456 UserDerefObjectCo(Window); 1457 1458 RETURN(ret); 1459 1460 CLEANUP: 1461 TRACE("Leave NtUserShowScrollBar, ret%lu\n", _ret_); 1462 UserLeave(); 1463 END_CLEANUP; 1464 1465 } 1466 1467 1468 //// Ugly NtUser API //// 1469 1470 BOOL 1471 APIENTRY 1472 NtUserSetScrollBarInfo( 1473 HWND hWnd, 1474 LONG idObject, 1475 SETSCROLLBARINFO *info) 1476 { 1477 PWND Window = NULL; 1478 SETSCROLLBARINFO Safeinfo; 1479 PSCROLLBARINFO sbi; 1480 LPSCROLLINFO psi; 1481 NTSTATUS Status; 1482 LONG Obj; 1483 DECLARE_RETURN(BOOL); 1484 USER_REFERENCE_ENTRY Ref; 1485 1486 TRACE("Enter NtUserSetScrollBarInfo\n"); 1487 UserEnterExclusive(); 1488 1489 if(!(Window = UserGetWindowObject(hWnd))) 1490 { 1491 RETURN( FALSE); 1492 } 1493 UserRefObjectCo(Window, &Ref); 1494 1495 Obj = SBOBJ_TO_SBID(idObject); 1496 if(!SBID_IS_VALID(Obj)) 1497 { 1498 EngSetLastError(ERROR_INVALID_PARAMETER); 1499 ERR("Trying to set scrollinfo for unknown scrollbar type %d\n", Obj); 1500 RETURN( FALSE); 1501 } 1502 1503 if(!co_IntCreateScrollBars(Window)) 1504 { 1505 RETURN(FALSE); 1506 } 1507 1508 Status = MmCopyFromCaller(&Safeinfo, info, sizeof(SETSCROLLBARINFO)); 1509 if(!NT_SUCCESS(Status)) 1510 { 1511 SetLastNtError(Status); 1512 RETURN(FALSE); 1513 } 1514 1515 sbi = IntGetScrollbarInfoFromWindow(Window, Obj); 1516 psi = IntGetScrollInfoFromWindow(Window, Obj); 1517 1518 psi->nTrackPos = Safeinfo.nTrackPos; 1519 sbi->reserved = Safeinfo.reserved; 1520 RtlCopyMemory(&sbi->rgstate, &Safeinfo.rgstate, sizeof(Safeinfo.rgstate)); 1521 1522 RETURN(TRUE); 1523 1524 CLEANUP: 1525 if (Window) 1526 UserDerefObjectCo(Window); 1527 1528 TRACE("Leave NtUserSetScrollBarInfo, ret=%i\n",_ret_); 1529 UserLeave(); 1530 END_CLEANUP; 1531 } 1532 1533 /* EOF */ 1534