/* * @implemented */ BOOL APIENTRY NtUserGetClipCursor( RECTL *lpRect) { /* FIXME: Check if process has WINSTA_READATTRIBUTES */ PSYSTEM_CURSORINFO CurInfo; RECTL Rect; NTSTATUS Status; DECLARE_RETURN(BOOL); TRACE("Enter NtUserGetClipCursor\n"); UserEnterExclusive(); if (!lpRect) RETURN(FALSE); CurInfo = IntGetSysCursorInfo(); if (CurInfo->bClipped) { Rect = CurInfo->rcClip; } else { Rect.left = 0; Rect.top = 0; Rect.right = UserGetSystemMetrics(SM_CXSCREEN); Rect.bottom = UserGetSystemMetrics(SM_CYSCREEN); } Status = MmCopyToCaller(lpRect, &Rect, sizeof(RECT)); if (!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN(FALSE); } RETURN(TRUE); CLEANUP: TRACE("Leave NtUserGetClipCursor, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; }
/* Compute the scroll bar rectangle, in drawing coordinates (i.e. client coords for SB_CTL, window coords for SB_VERT and * SB_HORZ). 'arrowSize' returns the width or height of an arrow (depending on * the orientation of the scrollbar), * 'thumbSize' returns the size of the thumb, and 'thumbPos' returns the position of the thumb relative to the left or to * the top. Return TRUE if the scrollbar is vertical, FALSE if horizontal. */ BOOL FASTCALL IntGetScrollBarRect (PWND Wnd, INT nBar, RECTL *lprect) { BOOL vertical; RECTL ClientRect = Wnd->rcClient; RECTL WindowRect = Wnd->rcWindow; switch (nBar) { case SB_HORZ: lprect->left = ClientRect.left - WindowRect.left; lprect->top = ClientRect.bottom - WindowRect.top; lprect->right = ClientRect.right - WindowRect.left; lprect->bottom = lprect->top + UserGetSystemMetrics (SM_CYHSCROLL); vertical = FALSE; break; case SB_VERT: if(Wnd->ExStyle & WS_EX_LEFTSCROLLBAR) { lprect->right = ClientRect.left - WindowRect.left; lprect->left = lprect->right - UserGetSystemMetrics(SM_CXVSCROLL); } else { lprect->left = ClientRect.right - WindowRect.left; lprect->right = lprect->left + UserGetSystemMetrics(SM_CXVSCROLL); } lprect->top = ClientRect.top - WindowRect.top; lprect->bottom = ClientRect.bottom - WindowRect.top; vertical = TRUE; break; case SB_CTL: IntGetClientRect (Wnd, lprect); vertical = ((Wnd->style & SBS_VERT) != 0); break; default: return FALSE; } return vertical; }
BOOL APIENTRY NtUserCreateCaret( HWND hWnd, HBITMAP hBitmap, int nWidth, int nHeight) { PWND Window; PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; DECLARE_RETURN(BOOL); TRACE("Enter NtUserCreateCaret\n"); UserEnterExclusive(); if(!(Window = UserGetWindowObject(hWnd))) { RETURN(FALSE); } if(Window->head.pti->pEThread != PsGetCurrentThread()) { EngSetLastError(ERROR_ACCESS_DENIED); RETURN(FALSE); } pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; if (ThreadQueue->CaretInfo->Visible) { IntKillTimer(Window, IDCARETTIMER, TRUE); co_IntHideCaret(ThreadQueue->CaretInfo); } ThreadQueue->CaretInfo->hWnd = hWnd; if(hBitmap) { ThreadQueue->CaretInfo->Bitmap = hBitmap; ThreadQueue->CaretInfo->Size.cx = ThreadQueue->CaretInfo->Size.cy = 0; } else { if (nWidth == 0) { nWidth = UserGetSystemMetrics(SM_CXBORDER); } if (nHeight == 0) { nHeight = UserGetSystemMetrics(SM_CYBORDER); } ThreadQueue->CaretInfo->Bitmap = (HBITMAP)0; ThreadQueue->CaretInfo->Size.cx = nWidth; ThreadQueue->CaretInfo->Size.cy = nHeight; } ThreadQueue->CaretInfo->Visible = 0; ThreadQueue->CaretInfo->Showing = 0; IntSetTimer( Window, IDCARETTIMER, gpsi->dtCaretBlink, CaretSystemTimerProc, TMRF_SYSTEM ); IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_CARET, CHILDID_SELF, 0); RETURN(TRUE); CLEANUP: TRACE("Leave NtUserCreateCaret, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; }
DWORD FASTCALL GetNCHitEx(PWND pWnd, POINT pt) { RECT rcWindow, rcClient; DWORD Style, ExStyle; if (!pWnd) return HTNOWHERE; if (pWnd == UserGetDesktopWindow()) // pWnd->fnid == FNID_DESKTOP) { rcClient.left = rcClient.top = rcWindow.left = rcWindow.top = 0; rcWindow.right = UserGetSystemMetrics(SM_CXSCREEN); rcWindow.bottom = UserGetSystemMetrics(SM_CYSCREEN); rcClient.right = UserGetSystemMetrics(SM_CXSCREEN); rcClient.bottom = UserGetSystemMetrics(SM_CYSCREEN); } else { rcClient = pWnd->rcClient; rcWindow = pWnd->rcWindow; } if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y)) return HTNOWHERE; Style = pWnd->style; ExStyle = pWnd->ExStyle; if (Style & WS_MINIMIZE) return HTCAPTION; if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTCLIENT; /* Check borders */ if (HAS_THICKFRAME( Style, ExStyle )) { RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXFRAME), -UserGetSystemMetrics(SM_CYFRAME) ); if (!RECTL_bPointInRect(&rcWindow, pt.x, pt.y )) { /* Check top sizing border */ if (pt.y < rcWindow.top) { if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT; if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT; return HTTOP; } /* Check bottom sizing border */ if (pt.y >= rcWindow.bottom) { if (pt.x < rcWindow.left+UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT; if (pt.x >= rcWindow.right-UserGetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT; return HTBOTTOM; } /* Check left sizing border */ if (pt.x < rcWindow.left) { if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT; if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT; return HTLEFT; } /* Check right sizing border */ if (pt.x >= rcWindow.right) { if (pt.y < rcWindow.top+UserGetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT; if (pt.y >= rcWindow.bottom-UserGetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT; return HTRIGHT; } } } else /* No thick frame */ { if (HAS_DLGFRAME( Style, ExStyle )) RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXDLGFRAME), -UserGetSystemMetrics(SM_CYDLGFRAME)); else if (HAS_THINFRAME( Style, ExStyle )) RECTL_vInflateRect(&rcWindow, -UserGetSystemMetrics(SM_CXBORDER), -UserGetSystemMetrics(SM_CYBORDER)); if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y )) return HTBORDER; } /* Check caption */ if ((Style & WS_CAPTION) == WS_CAPTION) { if (ExStyle & WS_EX_TOOLWINDOW) rcWindow.top += UserGetSystemMetrics(SM_CYSMCAPTION) - 1; else rcWindow.top += UserGetSystemMetrics(SM_CYCAPTION) - 1; if (!RECTL_bPointInRect( &rcWindow, pt.x, pt.y )) { BOOL min_or_max_box = (Style & WS_SYSMENU) && (Style & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX)); if (ExStyle & WS_EX_LAYOUTRTL) { /* Check system menu */ if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd)) { rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION) - 1; if (pt.x > rcWindow.right) return HTSYSMENU; } /* Check close button */ if (Style & WS_SYSMENU) { rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION); if (pt.x < rcWindow.left) return HTCLOSE; } /* Check maximize box */ /* In Win95 there is automatically a Maximize button when there is a minimize one */ if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW)) { rcWindow.left += UserGetSystemMetrics(SM_CXSIZE); if (pt.x < rcWindow.left) return HTMAXBUTTON; } /* Check minimize box */ if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW)) { rcWindow.left += UserGetSystemMetrics(SM_CXSIZE); if (pt.x < rcWindow.left) return HTMINBUTTON; } } else { /* Check system menu */ if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW) && NC_IconForWindow(pWnd)) { rcWindow.left += UserGetSystemMetrics(SM_CYCAPTION) - 1; if (pt.x < rcWindow.left) return HTSYSMENU; } /* Check close button */ if (Style & WS_SYSMENU) { rcWindow.right -= UserGetSystemMetrics(SM_CYCAPTION); if (pt.x > rcWindow.right) return HTCLOSE; } /* Check maximize box */ /* In Win95 there is automatically a Maximize button when there is a minimize one */ if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW)) { rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE); if (pt.x > rcWindow.right) return HTMAXBUTTON; } /* Check minimize box */ if (min_or_max_box && !(ExStyle & WS_EX_TOOLWINDOW)) { rcWindow.right -= UserGetSystemMetrics(SM_CXSIZE); if (pt.x > rcWindow.right) return HTMINBUTTON; } } return HTCAPTION; } } /* Check menu bar */ if (HAS_MENU( pWnd, Style ) && (pt.y < rcClient.top) && (pt.x >= rcClient.left) && (pt.x < rcClient.right)) return HTMENU; /* Check vertical scroll bar */ if (ExStyle & WS_EX_LAYOUTRTL) ExStyle ^= WS_EX_LEFTSCROLLBAR; if (Style & WS_VSCROLL) { if((ExStyle & WS_EX_LEFTSCROLLBAR) != 0) rcClient.left -= UserGetSystemMetrics(SM_CXVSCROLL); else rcClient.right += UserGetSystemMetrics(SM_CXVSCROLL); if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) return HTVSCROLL; } /* Check horizontal scroll bar */ if (Style & WS_HSCROLL) { rcClient.bottom += UserGetSystemMetrics(SM_CYHSCROLL); if (RECTL_bPointInRect( &rcClient, pt.x, pt.y )) { /* Check size box */ if ((Style & WS_VSCROLL) && ((((ExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (pt.x <= rcClient.left + UserGetSystemMetrics(SM_CXVSCROLL))) || (((ExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (pt.x >= rcClient.right - UserGetSystemMetrics(SM_CXVSCROLL))))) return HTSIZE; return HTHSCROLL; } } /* Has to return HTNOWHERE if nothing was found Could happen when a window has a customized non client area */ return HTNOWHERE; }
/* Mostly inspired from wine code. * We use low level functions because: * - at this point, the icon bitmap could have a different bit depth than the DC, * making it thus impossible to use NtCreateCompatibleDC and selecting the bitmap. * This happens after a mode setting change. * - it avoids massive GDI objects locking when only the destination surface needs it. * - It makes (small) performance gains. */ BOOL UserDrawIconEx( HDC hDc, INT xLeft, INT yTop, PCURICON_OBJECT pIcon, INT cxWidth, INT cyHeight, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags) { PSURFACE psurfDest, psurfMask, psurfColor; //, psurfOffScreen = NULL; PDC pdc = NULL; BOOL Ret = FALSE; HBITMAP hbmMask, hbmColor, hbmAlpha; BOOL bOffScreen; RECTL rcDest, rcSrc; CLIPOBJ* pdcClipObj = NULL; EXLATEOBJ exlo; /* Stupid case */ if((diFlags & DI_NORMAL) == 0) { ERR("DrawIconEx called without mask or color bitmap to draw.\n"); return FALSE; } if (pIcon->CURSORF_flags & CURSORF_ACON) { ACON* pAcon = (ACON*)pIcon; if(istepIfAniCur >= pAcon->cicur) { ERR("NtUserDrawIconEx: istepIfAniCur too big!\n"); return FALSE; } pIcon = pAcon->aspcur[pAcon->aicur[istepIfAniCur]]; } hbmMask = pIcon->hbmMask; hbmColor = pIcon->hbmColor; hbmAlpha = pIcon->hbmAlpha; /* * Get our objects. * Shared locks are enough, we are only reading those bitmaps */ psurfMask = SURFACE_ShareLockSurface(hbmMask); if(psurfMask == NULL) { ERR("Unable to lock the mask surface.\n"); return FALSE; } /* Color bitmap is not mandatory */ if(hbmColor == NULL) { /* But then the mask bitmap must have the information in it's bottom half */ ASSERT(psurfMask->SurfObj.sizlBitmap.cy == 2*pIcon->cy); psurfColor = NULL; } else if ((psurfColor = SURFACE_ShareLockSurface(hbmColor)) == NULL) { ERR("Unable to lock the color bitmap.\n"); SURFACE_ShareUnlockSurface(psurfMask); return FALSE; } pdc = DC_LockDc(hDc); if(!pdc) { ERR("Could not lock the destination DC.\n"); SURFACE_ShareUnlockSurface(psurfMask); if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); return FALSE; } /* Calculate destination rectangle */ RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight); IntLPtoDP(pdc, (LPPOINT)&rcDest, 2); RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y); /* Prepare the underlying surface */ DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest); /* We now have our destination surface and rectangle */ psurfDest = pdc->dclevel.pSurface; if(psurfDest == NULL) { /* Empty DC */ DC_vFinishBlit(pdc, NULL); DC_UnlockDc(pdc); SURFACE_ShareUnlockSurface(psurfMask); if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); return FALSE; } /* Set source rect */ RECTL_vSetRect(&rcSrc, 0, 0, pIcon->cx, pIcon->cy); /* Fix width parameter, if needed */ if (!cxWidth) { if(diFlags & DI_DEFAULTSIZE) cxWidth = is_icon(pIcon) ? UserGetSystemMetrics(SM_CXICON) : UserGetSystemMetrics(SM_CXCURSOR); else cxWidth = pIcon->cx; } /* Fix height parameter, if needed */ if (!cyHeight) { if(diFlags & DI_DEFAULTSIZE) cyHeight = is_icon(pIcon) ? UserGetSystemMetrics(SM_CYICON) : UserGetSystemMetrics(SM_CYCURSOR); else cyHeight = pIcon->cy; } /* Should we render off-screen? */ bOffScreen = hbrFlickerFreeDraw && (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH); if (bOffScreen) { /* Yes: Allocate and paint the offscreen surface */ EBRUSHOBJ eboFill; PBRUSH pbrush = BRUSH_ShareLockBrush(hbrFlickerFreeDraw); TRACE("Performing off-screen rendering.\n"); if(!pbrush) { ERR("Failed to get brush object.\n"); goto Cleanup; } #if 0 //We lock the hdc surface during the whole function it makes no sense to use an offscreen surface for "flicker free" drawing psurfOffScreen = SURFACE_AllocSurface(STYPE_BITMAP, cxWidth, cyHeight, psurfDest->SurfObj.iBitmapFormat, 0, 0, NULL); if(!psurfOffScreen) { ERR("Failed to allocate the off-screen surface.\n"); BRUSH_ShareUnlockBrush(pbrush); goto Cleanup; } /* Paint the brush */ EBRUSHOBJ_vInit(&eboFill, pbrush, psurfOffScreen, 0x00FFFFFF, 0, NULL); RECTL_vSetRect(&rcDest, 0, 0, cxWidth, cyHeight); Ret = IntEngBitBlt(&psurfOffScreen->SurfObj, NULL, NULL, NULL, NULL, &rcDest, NULL, NULL, &eboFill.BrushObject, &pbrush->ptOrigin, ROP4_PATCOPY); /* Clean up everything */ EBRUSHOBJ_vCleanup(&eboFill); BRUSH_ShareUnlockBrush(pbrush); if(!Ret) { ERR("Failed to paint the off-screen surface.\n"); goto Cleanup; } /* We now have our destination surface */ psurfDest = psurfOffScreen; #else pdcClipObj = pdc->rosdc.CombinedClip; /* Paint the brush */ EBRUSHOBJ_vInit(&eboFill, pbrush, psurfDest, 0x00FFFFFF, 0, NULL); Ret = IntEngBitBlt(&psurfDest->SurfObj, NULL, NULL, pdcClipObj, NULL, &rcDest, NULL, NULL, &eboFill.BrushObject, &pbrush->ptOrigin, ROP4_PATCOPY); /* Clean up everything */ EBRUSHOBJ_vCleanup(&eboFill); BRUSH_ShareUnlockBrush(pbrush); if(!Ret) { ERR("Failed to paint the off-screen surface.\n"); goto Cleanup; } #endif } else { /* We directly draw to the DC */ TRACE("Performing on screen rendering.\n"); pdcClipObj = pdc->rosdc.CombinedClip; // psurfOffScreen = NULL; } /* Now do the rendering */ if(hbmAlpha && ((diFlags & DI_NORMAL) == DI_NORMAL)) { BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } }; PSURFACE psurf = NULL; psurf = SURFACE_ShareLockSurface(hbmAlpha); if(!psurf) { ERR("SURFACE_LockSurface failed!\n"); goto NoAlpha; } /* Initialize color translation object */ EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xFFFFFFFF, 0xFFFFFFFF, 0); /* Now do it */ Ret = IntEngAlphaBlend(&psurfDest->SurfObj, &psurf->SurfObj, pdcClipObj, &exlo.xlo, &rcDest, &rcSrc, &blendobj); EXLATEOBJ_vCleanup(&exlo); SURFACE_ShareUnlockSurface(psurf); if(Ret) goto done; ERR("NtGdiAlphaBlend failed!\n"); } NoAlpha: if (diFlags & DI_MASK) { DWORD rop4 = (diFlags & DI_IMAGE) ? ROP4_SRCAND : ROP4_SRCCOPY; EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0); Ret = IntEngStretchBlt(&psurfDest->SurfObj, &psurfMask->SurfObj, NULL, pdcClipObj, &exlo.xlo, NULL, &rcDest, &rcSrc, NULL, NULL, NULL, rop4); EXLATEOBJ_vCleanup(&exlo); if(!Ret) { ERR("Failed to mask the bitmap data.\n"); goto Cleanup; } } if(diFlags & DI_IMAGE) { if (psurfColor) { DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY ; EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0); Ret = IntEngStretchBlt(&psurfDest->SurfObj, &psurfColor->SurfObj, NULL, pdcClipObj, &exlo.xlo, NULL, &rcDest, &rcSrc, NULL, NULL, NULL, rop4); EXLATEOBJ_vCleanup(&exlo); if(!Ret) { ERR("Failed to render the icon bitmap.\n"); goto Cleanup; } } else { /* Mask bitmap holds the information in its bottom half */ DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY; RECTL_vOffsetRect(&rcSrc, 0, pIcon->cy); EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0); Ret = IntEngStretchBlt(&psurfDest->SurfObj, &psurfMask->SurfObj, NULL, pdcClipObj, &exlo.xlo, NULL, &rcDest, &rcSrc, NULL, NULL, NULL, rop4); EXLATEOBJ_vCleanup(&exlo); if(!Ret) { ERR("Failed to render the icon bitmap.\n"); goto Cleanup; } } } done: #if 0 /* We're done. Was it a double buffered draw ? */ if(bOffScreen) { /* Yes. Draw it back to our DC */ POINTL ptSrc = {0, 0}; /* Calculate destination rectangle */ RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight); IntLPtoDP(pdc, (LPPOINT)&rcDest, 2); RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y); /* Get the clip object */ pdcClipObj = pdc->rosdc.CombinedClip; /* We now have our destination surface and rectangle */ psurfDest = pdc->dclevel.pSurface; /* Color translation */ EXLATEOBJ_vInitialize(&exlo, psurfOffScreen->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0); /* Blt it! */ Ret = IntEngBitBlt(&psurfDest->SurfObj, &psurfOffScreen->SurfObj, NULL, pdcClipObj, &exlo.xlo, &rcDest, &ptSrc, NULL, NULL, NULL, ROP4_SRCCOPY); EXLATEOBJ_vCleanup(&exlo); } #endif Cleanup: if(pdc) { DC_vFinishBlit(pdc, NULL); DC_UnlockDc(pdc); } #if 0 /* Delete off screen rendering surface */ if(psurfOffScreen) GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject); #endif /* Unlock other surfaces */ SURFACE_ShareUnlockSurface(psurfMask); if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor); return Ret; }
BOOL FASTCALL IntCalculateThumb(PWND Wnd, LONG idObject, PSCROLLBARINFO psbi, PSBDATA pSBData) { INT Thumb, ThumbBox, ThumbPos, cxy, mx; RECTL ClientRect; switch(idObject) { case SB_HORZ: Thumb = UserGetSystemMetrics(SM_CXHSCROLL); cxy = psbi->rcScrollBar.right - psbi->rcScrollBar.left; break; case SB_VERT: Thumb = UserGetSystemMetrics(SM_CYVSCROLL); cxy = psbi->rcScrollBar.bottom - psbi->rcScrollBar.top; break; case SB_CTL: IntGetClientRect(Wnd, &ClientRect); if(Wnd->style & SBS_VERT) { Thumb = UserGetSystemMetrics(SM_CYVSCROLL); cxy = ClientRect.bottom - ClientRect.top; } else { Thumb = UserGetSystemMetrics(SM_CXHSCROLL); cxy = ClientRect.right - ClientRect.left; } break; default: return FALSE; } ThumbPos = Thumb; /* Calculate Thumb */ if(cxy <= (2 * Thumb)) { Thumb = cxy / 2; psbi->xyThumbTop = 0; psbi->xyThumbBottom = 0; ThumbPos = Thumb; } else { ThumbBox = pSBData->page ? MINTRACKTHUMB : UserGetSystemMetrics(SM_CXHTHUMB); cxy -= (2 * Thumb); if(cxy >= ThumbBox) { if(pSBData->page) { ThumbBox = max(EngMulDiv(cxy, pSBData->page, pSBData->posMax - pSBData->posMin + 1), ThumbBox); } if(cxy > ThumbBox) { mx = pSBData->posMax - max(pSBData->page - 1, 0); if(pSBData->posMin < mx) ThumbPos = Thumb + EngMulDiv(cxy - ThumbBox, pSBData->pos - pSBData->posMin, mx - pSBData->posMin); else ThumbPos = Thumb + ThumbBox; } psbi->xyThumbTop = ThumbPos; psbi->xyThumbBottom = ThumbPos + ThumbBox; } else { psbi->xyThumbTop = 0; psbi->xyThumbBottom = 0; } } psbi->dxyLineButton = Thumb; return TRUE; }
BOOL FASTCALL IntGetScrollBarRect (PWND Wnd, INT nBar, RECTL *lprect) { BOOL vertical; *lprect = Wnd->rcClient; RECTL_vOffsetRect( lprect, -Wnd->rcWindow.left, -Wnd->rcWindow.top ); if (Wnd->ExStyle & WS_EX_LAYOUTRTL) mirror_rect( &Wnd->rcWindow, lprect ); switch (nBar) { case SB_HORZ: lprect->top = lprect->bottom; lprect->bottom += UserGetSystemMetrics (SM_CYHSCROLL); if (Wnd->style & WS_BORDER) { lprect->left--; lprect->right++; } else if (Wnd->style & WS_VSCROLL) { lprect->right++; } vertical = FALSE; break; case SB_VERT: if(Wnd->ExStyle & WS_EX_LEFTSCROLLBAR) { lprect->right = lprect->left; lprect->left -= UserGetSystemMetrics(SM_CXVSCROLL); } else { lprect->left = lprect->right; lprect->right += UserGetSystemMetrics(SM_CXVSCROLL); } if (Wnd->style & WS_BORDER) { lprect->top--; lprect->bottom++; } else if (Wnd->style & WS_HSCROLL) { lprect->bottom++; } vertical = TRUE; break; case SB_CTL: IntGetClientRect (Wnd, lprect); vertical = !!(Wnd->style & SBS_VERT); break; default: return FALSE; } return vertical; }