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