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