bool CAutoPanParameters::DoScroll(CWnd* pParentWnd, int nScrollStepsX, int nScrollStepsY) const { int nOriginX, nScrollToX, nMaxX, nSubstepsInAStepX; int nOriginY, nScrollToY, nMaxY, nSubstepsInAStepY; nSubstepsInAStepX = GetSubstepsInAStepX(pParentWnd, nScrollStepsX); nSubstepsInAStepY = GetSubstepsInAStepY(pParentWnd, nScrollStepsY); // Adjust current positions based on scroll bar constraints. nOriginX = nScrollToX = pParentWnd->GetScrollPos(SB_HORZ) * nSubstepsInAStepX; nOriginY = nScrollToY = pParentWnd->GetScrollPos(SB_VERT) * nSubstepsInAStepY; // Calculate the new positions if (nScrollStepsX != 0) { nMaxX = pParentWnd->GetScrollLimit(SB_HORZ) * nSubstepsInAStepX; nScrollToX += nScrollStepsX * nSubstepsInAStepX; //Sanity checks. if (nScrollToX < 0) nScrollToX = 0; else if (nScrollToX > nMaxX) nScrollToX = nMaxX; } if (nScrollStepsY != 0) { nMaxY = pParentWnd->GetScrollLimit(SB_VERT) * nSubstepsInAStepY; nScrollToY += nScrollStepsY * nSubstepsInAStepY; //Sanity checks. if (nScrollToY < 0) nScrollToY = 0; else if (nScrollToY > nMaxY) nScrollToY = nMaxY; } // If nothing changed, just return, no work to do. if (nScrollToX == nOriginX && nScrollToY == nOriginY) { return false; } return DoScrollWindow(pParentWnd, nScrollToX, nOriginX, nScrollToY, nOriginY); }
// update_bars() is called if anything changes that will cause the scroll // bars to change (move/resize etc). This will happen if total_, page_ // or line_ sizes change, the window is resized, font changed, etc. // If the parameter 'newpos' is not null_point then the display position // will be moved to that position. Note that the display may be redrawn. void CScrView::update_bars(CPointAp newpos) { if (in_update_ || m_hWnd == NULL) return; in_update_ = TRUE; // TRACE0("--- update_bars\n"); check_coords(); // Check that mapping mode not changed caret_hide(); // Get info needed in later calcs TEXTMETRIC tm; { CClientDC dc(this); OnPrepareDC(&dc); dc.GetTextMetrics(&tm); } // Get display area and convert to logical units (but with +ve values) CRect cli; GetDisplayRect(&cli); //CRectAp doc_rect = ConvertFromDP(cli) - GetScroll(); // If newpos not specified use old pos if (newpos == null_point) newpos = scrollpos_; ASSERT(newpos.x >= 0 && newpos.y >= 0); if (!page_specified_ || !line_specified_) { // Calculate amount of line and page scroll based on size of font if (!page_specified_) { // Recalc page size int lines = cli.Height()/tm.tmHeight + tm.tmExternalLeading - 1; if (lines < 1) lines = 1; page_.cx = cli.Width() - tm.tmAveCharWidth; page_.cy = lines * (tm.tmHeight + tm.tmExternalLeading); } if (!line_specified_) { // Recalc line size line_.cx = tm.tmAveCharWidth; line_.cy = tm.tmHeight + tm.tmExternalLeading; } } // Update display and scroll bars. ASSERT(total_.cx >= 0 && total_.cy >= 0); // If display position has changed redraw/scroll to it if (newpos != scrollpos_) { scroll_up_ = newpos.y < scrollpos_.y; // Get scroll & new positions in real logical coords CPointAp t_scroll = scrollpos_; if (negx()) t_scroll.x = -t_scroll.x; if (negy()) t_scroll.y = -t_scroll.y; CPointAp t_newpos = newpos; if (negx()) t_newpos.x = -t_newpos.x; if (negy()) t_newpos.y = -t_newpos.y; // // For OWNDC window and mapping mode != MM_TEXT ScrollWindow // // does not move caret properly!?!? - so we do it ourselves! __int64 tmp = t_scroll.y < t_newpos.y ? t_newpos.y - t_scroll.y : t_scroll.y - t_newpos.y; if (abs(int(t_scroll.x - t_newpos.x)) > cli.Width() || tmp > __int64(cli.Height())) DoInvalidate(); // ScrollWindow() can't handle big numbers else { // Work out scroll amount in device coordinates // LPtoDP can't handle more than 16 bits (signed) CPoint dev_scroll, dev_newpos; dev_scroll.x = t_scroll.x; dev_scroll.y = int(t_scroll.y); dev_newpos.x = t_newpos.x; dev_newpos.y = int(t_newpos.y); { // Put in compound statement so DC released ASAP CClientDC dc(this); OnPrepareDC(&dc); dc.LPtoDP(&dev_scroll); dc.LPtoDP(&dev_newpos); } DoScrollWindow(dev_scroll.x - dev_newpos.x, dev_scroll.y - dev_newpos.y); } } if (total_.cx <= 0) DoHScroll(0, 0, 0); // disable scroll bar else if (newpos.x > total_.cx - cli.Width()) { // Handle scroll position past right edge DoHScroll(int(((__int64)(newpos.x + cli.Width()) * maxbar_.cx) / total_.cx), (cli.Width() * maxbar_.cx) / total_.cx + 1, int(((__int64)newpos.x * maxbar_.cx) / total_.cx) ); } else { DoHScroll(maxbar_.cx, (cli.Width() * maxbar_.cx) / total_.cx + 1, int(((__int64)newpos.x * maxbar_.cx) / total_.cx) ); } if (total_.cy <= 0) DoVScroll(0, 0, 0); // disable scroll bar else if (newpos.y > total_.cy - cli.Height()) { // Handle scroll position if (somehow) moved past end DoVScroll(int(((__int64)(newpos.y + cli.Height()) * maxbar_.cy) / total_.cy), int((cli.Height() * maxbar_.cy) / total_.cy + 1), int(((__int64)newpos.y * maxbar_.cy) / total_.cy) ); } else { DoVScroll(int(maxbar_.cy), int((cli.Height() * maxbar_.cy) / total_.cy + 1), int(((__int64)newpos.y * maxbar_.cy) / total_.cy) ); } // Store new position and force redraw before restore of scroll_up_ scrollpos_ = newpos; // Keep track of where we moved to ASSERT(scrollpos_.x >= 0 && scrollpos_.y >= 0); // if (GetFocus() == this) caret_show(); DoUpdateWindow(); // Force redraw before changing scroll_up_ scroll_up_ = FALSE; // Make sure redraw defaults to downwards // Get client window again as changing the scroll bars may have changed it // (and nested size event was blocked by in_update_ flag) GetDisplayRect(&cli); CRectAp doc_rect = ConvertFromDP(cli); win_height_ = doc_rect.bottom - doc_rect.top; win_width_ = doc_rect.right - doc_rect.left; AfterScroll(newpos); in_update_ = FALSE; }