GME
13
|
00001 // SrollZoomView.cpp : implementation file 00002 // 00003 00004 00005 #include "stdafx.h" 00006 #include "ScrollZoomView.h" 00007 00008 #include "GMEApp.h" 00009 #include "Mainfrm.h" 00010 // 00011 00012 #ifdef _DEBUG 00013 #define new DEBUG_NEW 00014 #undef THIS_FILE 00015 static char THIS_FILE[] = __FILE__; 00016 #endif 00017 00018 #define CX_BORDER 1 00019 #define CY_BORDER 1 00020 00022 // CScrollZoomView 00023 IMPLEMENT_DYNAMIC(CScrollZoomView, CView) 00024 BEGIN_MESSAGE_MAP(CScrollZoomView, CView) 00025 //{{AFX_MSG_MAP(CScrollZoomView) 00026 ON_WM_SIZE() 00027 ON_WM_HSCROLL() 00028 ON_WM_VSCROLL() 00029 ON_WM_MOUSEWHEEL() 00030 //}}AFX_MSG_MAP 00031 END_MESSAGE_MAP() 00032 00033 // Special mapping modes just for CScrollZoomView implementation 00034 #define MM_NONE 0 00035 #define MM_SCALETOFIT (-1) 00036 // standard GDI mapping modes are > 0 00037 00038 00039 UINT CScrollZoomView::uCachedScrollLines = 3; 00040 bool CScrollZoomView::bScrollLinesRequested = false; 00041 00043 // CScrollZoomView construction/destruction 00044 00045 CScrollZoomView::CScrollZoomView() : 00046 m_nMapMode(MM_NONE), 00047 m_totalLog(0,0), 00048 m_totalDev(0,0), 00049 m_pageDev(0,0), 00050 m_lineDev(0,0), 00051 m_scalePercent(0), 00052 m_bCenter(FALSE), 00053 m_bInsideUpdate(FALSE), 00054 m_zoomP(0,0), 00055 m_zoomScroll(false), 00056 m_noHscroll(true), 00057 m_noVscroll(true) 00058 { 00059 } 00060 00061 CScrollZoomView::~CScrollZoomView() 00062 { 00063 } 00064 00065 UINT CScrollZoomView::GetMouseScrollLines(void) 00066 { 00067 00068 // if we've already got it and we're not refreshing, 00069 // return what we've already got 00070 if (bScrollLinesRequested) 00071 return uCachedScrollLines; 00072 00073 // try system settings 00074 ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &uCachedScrollLines, 0); 00075 bScrollLinesRequested = true; 00076 00077 return uCachedScrollLines; 00078 } 00079 00081 // CScrollZoomView painting 00082 00083 void CScrollZoomView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo) 00084 { 00085 ASSERT_VALID(pDC); 00086 00087 #ifdef _DEBUG 00088 if (m_nMapMode == MM_NONE) 00089 { 00090 TRACE0("Error: must call SetScrollSizes() or SetScaleToFitSize()"); 00091 TRACE0("\tbefore painting scroll view.\n"); 00092 ASSERT(FALSE); 00093 return; 00094 } 00095 #endif //_DEBUG 00096 ASSERT(m_totalDev.cx >= 0 && m_totalDev.cy >= 0); 00097 switch (m_nMapMode) 00098 { 00099 case MM_SCALETOFIT: 00100 pDC->SetMapMode(MM_ANISOTROPIC); 00101 pDC->SetWindowExt(m_totalLog); // window is in logical coordinates 00102 pDC->SetViewportExt(m_totalDev); 00103 #ifdef DEBUG 00104 if (m_totalDev.cx == 0 || m_totalDev.cy == 0) 00105 TRACE0("Warning: CScrollZoomView scaled to nothing.\n"); 00106 #endif 00107 break; 00108 00109 case MM_ISOTROPIC: 00110 pDC->SetMapMode(m_nMapMode); 00111 pDC->SetWindowExt(100,100); 00112 pDC->SetViewportExt(m_scalePercent, m_scalePercent); 00113 break; 00114 default: 00115 ASSERT(m_nMapMode > 0); 00116 pDC->SetMapMode(m_nMapMode); 00117 break; 00118 } 00119 00120 CPoint ptVpOrg(0, 0); // assume no shift for printing 00121 if (!pDC->IsPrinting()) 00122 { 00123 ASSERT(pDC->GetWindowOrg() == CPoint(0,0)); 00124 00125 // by default shift viewport origin in negative direction of scroll 00126 ptVpOrg = -GetDeviceScrollPosition(); 00127 00128 if (m_bCenter) 00129 { 00130 CRect rect; 00131 GetClientRect(&rect); 00132 00133 // if client area is larger than total device size, 00134 // override scroll positions to place origin such that 00135 // output is centered in the window 00136 if (m_totalDev.cx < rect.Width()) 00137 ptVpOrg.x = (rect.Width() - m_totalDev.cx) / 2; 00138 if (m_totalDev.cy < rect.Height()) 00139 ptVpOrg.y = (rect.Height() - m_totalDev.cy) / 2; 00140 } 00141 } 00142 pDC->SetViewportOrg(ptVpOrg); 00143 00144 CView::OnPrepareDC(pDC, pInfo); // For default Printing behavior 00145 } 00146 00148 // Set mode and scaling/scrolling sizes 00149 00150 void CScrollZoomView::SetScaleToFitSize(SIZE sizeTotal) 00151 { 00152 // Note: It is possible to set sizeTotal members to negative values to 00153 // effectively invert either the X or Y axis. 00154 00155 ASSERT(m_hWnd != NULL && FromHandlePermanent(m_hWnd) != NULL); // See comment about this at a later FromHandlePermanent 00156 m_nMapMode = MM_SCALETOFIT; // special internal value 00157 m_totalLog = sizeTotal; 00158 00159 // reset and turn any scroll bars off 00160 if (m_hWnd != NULL && (GetStyle() & (WS_HSCROLL|WS_VSCROLL))) 00161 { 00162 SetScrollPos(SB_HORZ, 0); 00163 SetScrollPos(SB_VERT, 0); 00164 EnableScrollBarCtrl(SB_BOTH, FALSE); 00165 m_noHscroll = true; // hack terge 00166 m_noVscroll = true; // hack terge 00167 SetScrollRange(SB_HORZ, 0, 0, TRUE); 00168 SetScrollRange(SB_VERT, 0, 0, TRUE); 00169 ASSERT((GetStyle() & (WS_HSCROLL|WS_VSCROLL)) == 0); 00170 } 00171 00172 CRect rectT; 00173 GetClientRect(rectT); 00174 m_totalDev = rectT.Size(); 00175 00176 if (m_hWnd != NULL && FromHandlePermanent(m_hWnd) != NULL) // See comment about this at a later FromHandlePermanent 00177 { 00178 // window has been created, invalidate 00179 UpdateBars(); 00180 Invalidate(TRUE); 00181 } 00182 } 00183 00184 const AFX_DATADEF SIZE CScrollZoomView::sizeDefault = {0,0}; 00185 00186 void CScrollZoomView::SetScrollSizes(int nMapMode, SIZE sizeTotal, int scalePercent, 00187 const SIZE& sizePage, const SIZE& sizeLine) 00188 { 00189 ASSERT(sizeTotal.cx >= 0 && sizeTotal.cy >= 0); 00190 ASSERT(nMapMode > 0); 00191 ASSERT(nMapMode != MM_ANISOTROPIC); 00192 00193 int nOldMapMode = m_nMapMode; 00194 m_nMapMode = nMapMode; 00195 m_totalLog = sizeTotal; 00196 m_scalePercent = scalePercent; 00197 00198 //BLOCK: convert logical coordinate space to device coordinates 00199 { 00200 CWindowDC dc(NULL); 00201 ASSERT(m_nMapMode > 0); 00202 dc.SetMapMode(m_nMapMode); 00203 if (m_nMapMode == MM_ISOTROPIC) { 00204 dc.SetWindowExt(100,100); 00205 dc.SetViewportExt(scalePercent, scalePercent); 00206 } 00207 00208 // total size 00209 m_totalDev = m_totalLog; 00210 dc.LPtoDP((LPPOINT)&m_totalDev); 00211 m_pageDev = sizePage; 00212 dc.LPtoDP((LPPOINT)&m_pageDev); 00213 m_lineDev = sizeLine; 00214 dc.LPtoDP((LPPOINT)&m_lineDev); 00215 if (m_totalDev.cy < 0) 00216 m_totalDev.cy = -m_totalDev.cy; 00217 if (m_pageDev.cy < 0) 00218 m_pageDev.cy = -m_pageDev.cy; 00219 if (m_lineDev.cy < 0) 00220 m_lineDev.cy = -m_lineDev.cy; 00221 } // release DC here 00222 00223 // now adjust device specific sizes 00224 ASSERT(m_totalDev.cx >= 0 && m_totalDev.cy >= 0); 00225 if (m_pageDev.cx == 0) 00226 m_pageDev.cx = m_totalDev.cx / 10; 00227 if (m_pageDev.cy == 0) 00228 m_pageDev.cy = m_totalDev.cy / 10; 00229 if (m_lineDev.cx == 0) 00230 m_lineDev.cx = m_pageDev.cx / 10; 00231 if (m_lineDev.cy == 0) 00232 m_lineDev.cy = m_pageDev.cy / 10; 00233 00234 if (m_hWnd != NULL) 00235 { 00236 // trick to overcome MFC9.0 AssertValid ASSERT (MFC9.0 became more strict, pickyer, probably this was present before also): 00237 // sometimes m_hWnd != NULL, but not valid, because HWND is missing from the permanent and the temporary map also, 00238 // so we basically query pMap->LookupPermanent(m_hWnd) here with the FromHandlePermanent call 00239 if (FromHandlePermanent(m_hWnd) != NULL) { 00240 // set scroll position after zoom 00241 // window has been created, invalidate now 00242 UpdateBars(); 00243 if (nOldMapMode != m_nMapMode) 00244 Invalidate(TRUE); 00245 } 00246 } 00247 } 00248 00250 // Getting information 00251 00252 CPoint CScrollZoomView::GetScrollPosition() const // logical coordinates 00253 { 00254 if (m_nMapMode == MM_SCALETOFIT) 00255 { 00256 return CPoint(0, 0); // must be 0,0 00257 } 00258 00259 CPoint pt = GetDeviceScrollPosition(); 00260 // pt may be negative if m_bCenter is set 00261 00262 if (m_nMapMode != MM_TEXT) 00263 { 00264 ASSERT(m_nMapMode > 0); // must be set 00265 CWindowDC dc(NULL); 00266 dc.SetMapMode(m_nMapMode); 00267 if (m_nMapMode == MM_ISOTROPIC) { 00268 dc.SetWindowExt(100,100); 00269 dc.SetViewportExt(m_scalePercent, m_scalePercent); 00270 } 00271 dc.DPtoLP((LPPOINT)&pt); 00272 } 00273 return pt; 00274 } 00275 00276 void CScrollZoomView::ScrollToPosition(POINT pt) // logical coordinates 00277 { 00278 ASSERT(m_nMapMode > 0); // not allowed for shrink to fit 00279 if (m_nMapMode != MM_TEXT) 00280 { 00281 CWindowDC dc(NULL); 00282 dc.SetMapMode(m_nMapMode); 00283 if (m_nMapMode == MM_ISOTROPIC) { 00284 dc.SetWindowExt(100,100); 00285 dc.SetViewportExt(m_scalePercent, m_scalePercent); 00286 } 00287 dc.LPtoDP((LPPOINT)&pt); 00288 } 00289 00290 // now in device coordinates - limit if out of range 00291 int xMax = GetScrollLimit(SB_HORZ); 00292 int yMax = GetScrollLimit(SB_VERT); 00293 // int xMin, xMax, yMin, yMax; 00294 // GetScrollRange(SB_HORZ, &xMin, &xMax); // it does not work correctly ?? !! 00295 // GetScrollRange(SB_VERT, &yMin, &yMax); 00296 if (m_noHscroll) // hack terge 00297 { 00298 xMax = 0; 00299 } 00300 if (m_noVscroll) // hack terge 00301 { 00302 yMax = 0; 00303 } 00304 00305 // terge ?? szar van 00306 00307 if (pt.x < 0) 00308 pt.x = 0; 00309 else if (pt.x > xMax) 00310 pt.x = xMax; 00311 if (pt.y < 0) 00312 pt.y = 0; 00313 else if (pt.y > yMax) 00314 pt.y = yMax; 00315 00316 ScrollToDevicePosition(pt); 00317 } 00318 00319 CPoint CScrollZoomView::GetDeviceScrollPosition() const 00320 { 00321 CPoint pt(GetScrollPos(SB_HORZ), GetScrollPos(SB_VERT)); 00322 ASSERT(pt.x >= 0 && pt.y >= 0); 00323 00324 if (m_bCenter) 00325 { 00326 CRect rect; 00327 GetClientRect(&rect); 00328 00329 // if client area is larger than total device size, 00330 // the scroll positions are overridden to place origin such that 00331 // output is centered in the window 00332 // GetDeviceScrollPosition() must reflect this 00333 00334 if (m_totalDev.cx < rect.Width()) 00335 pt.x = -((rect.Width() - m_totalDev.cx) / 2); 00336 if (m_totalDev.cy < rect.Height()) 00337 pt.y = -((rect.Height() - m_totalDev.cy) / 2); 00338 } 00339 00340 return pt; 00341 } 00342 00343 void CScrollZoomView::GetDeviceScrollSizes(int& nMapMode, SIZE& sizeTotal, 00344 SIZE& sizePage, SIZE& sizeLine) const 00345 { 00346 #ifdef DEBUG 00347 if (m_nMapMode <= 0) 00348 TRACE0("Warning: CScrollZoomView::GetDeviceScrollSizes returning invalid mapping mode.\n"); 00349 #endif 00350 nMapMode = m_nMapMode; 00351 sizeTotal = m_totalDev; 00352 sizePage = m_pageDev; 00353 sizeLine = m_lineDev; 00354 } 00355 00356 void CScrollZoomView::notifyPanning(CPoint pt) 00357 { 00358 // CMainFrame* main = (CMainFrame*)AfxGetMainWnd(); 00359 CMainFrame* main = (CMainFrame*)theApp.m_pMainWnd; 00360 00361 if (!main || !main->m_panningWindow.IsVisible()) 00362 return; 00363 CRect client; 00364 GetClientRect(&client); 00365 CWindowDC dc(NULL); 00366 dc.SetMapMode(MM_ISOTROPIC); 00367 dc.SetWindowExt(100,100); 00368 dc.SetViewportExt(m_scalePercent, m_scalePercent); 00369 dc.DPtoLP((LPPOINT)&pt); 00370 dc.DPtoLP(&client); 00371 CRect pannw(pt.x, pt.y, pt.x + client.Width(), pt.y + client.Height()); 00372 pannw.NormalizeRect(); 00373 00374 main->m_panningWindow.SetViewRect(pannw); 00375 } 00376 00377 void CScrollZoomView::ScrollToDevicePosition(POINT ptDev) 00378 { 00379 ASSERT(ptDev.x >= 0); 00380 ASSERT(ptDev.y >= 0); 00381 int maxh = GetScrollLimit(SB_HORZ); 00382 int maxv = GetScrollLimit(SB_VERT); 00383 // int xMin, yMin; 00384 // GetScrollRange(SB_HORZ, &xMin, &maxh); 00385 // GetScrollRange(SB_VERT, &yMin, &maxv); 00386 if (maxh == 0 && maxv == 0) 00387 { 00388 TRACE("notifyPanning from ScrollToDevicePosition - maxh == 0 && maxv == 0\n"); 00389 notifyPanning(ptDev); 00390 return; 00391 } 00392 00393 // Note: ScrollToDevicePosition can and is used to scroll out-of-range 00394 // areas as far as CScrollZoomView is concerned -- specifically in 00395 // the print-preview code. Since OnScrollBy makes sure the range is 00396 // valid, ScrollToDevicePosition does not vector through OnScrollBy. 00397 00398 int xOrig = GetScrollPos(SB_HORZ); 00399 SetScrollPos(SB_HORZ, ptDev.x); 00400 int yOrig = GetScrollPos(SB_VERT); 00401 SetScrollPos(SB_VERT, ptDev.y); 00402 ptDev.x = (maxh<ptDev.x)? maxh: ptDev.x; 00403 ptDev.y = (maxv<ptDev.y)? maxv: ptDev.y; 00404 TRACE("notifyPanning from ScrollToDevicePosition\n"); 00405 notifyPanning(ptDev); 00406 // ScrollWindow(xOrig - ptDev.x, yOrig - ptDev.y); 00407 ScrollWindow((ptDev.x - xOrig), (ptDev.y - yOrig) ); 00408 } 00409 00411 // Other helpers 00412 00413 void CScrollZoomView::FillOutsideRect(CDC* pDC, CBrush* pBrush) 00414 { 00415 ASSERT_VALID(pDC); 00416 ASSERT_VALID(pBrush); 00417 00418 // fill rect outside the image 00419 CRect rect; 00420 GetClientRect(rect); 00421 ASSERT(rect.left == 0 && rect.top == 0); 00422 rect.left = m_totalDev.cx; 00423 if (!rect.IsRectEmpty()) 00424 pDC->FillRect(rect, pBrush); // vertical strip along the side 00425 rect.left = 0; 00426 rect.right = m_totalDev.cx; 00427 rect.top = m_totalDev.cy; 00428 if (!rect.IsRectEmpty()) 00429 pDC->FillRect(rect, pBrush); // horizontal strip along the bottom 00430 } 00431 00432 void CScrollZoomView::ResizeParentToFit(BOOL bShrinkOnly) 00433 { 00434 // adjust parent rect so client rect is appropriate size 00435 ASSERT(m_nMapMode != MM_NONE); // mapping mode must be known 00436 00437 // determine current size of the client area as if no scrollbars present 00438 CRect rectClient; 00439 GetWindowRect(rectClient); 00440 CRect rect = rectClient; 00441 CalcWindowRect(rect); 00442 rectClient.left += rectClient.left - rect.left; 00443 rectClient.top += rectClient.top - rect.top; 00444 rectClient.right -= rect.right - rectClient.right; 00445 rectClient.bottom -= rect.bottom - rectClient.bottom; 00446 rectClient.OffsetRect(-rectClient.left, -rectClient.top); 00447 ASSERT(rectClient.left == 0 && rectClient.top == 0); 00448 00449 // determine desired size of the view 00450 CRect rectView(0, 0, m_totalDev.cx, m_totalDev.cy); 00451 if (bShrinkOnly) 00452 { 00453 if (rectClient.right <= m_totalDev.cx) 00454 rectView.right = rectClient.right; 00455 if (rectClient.bottom <= m_totalDev.cy) 00456 rectView.bottom = rectClient.bottom; 00457 } 00458 CalcWindowRect(rectView, CWnd::adjustOutside); 00459 rectView.OffsetRect(-rectView.left, -rectView.top); 00460 ASSERT(rectView.left == 0 && rectView.top == 0); 00461 if (bShrinkOnly) 00462 { 00463 if (rectClient.right <= m_totalDev.cx) 00464 rectView.right = rectClient.right; 00465 if (rectClient.bottom <= m_totalDev.cy) 00466 rectView.bottom = rectClient.bottom; 00467 } 00468 00469 // dermine and set size of frame based on desired size of view 00470 CRect rectFrame; 00471 CFrameWnd* pFrame = GetParentFrame(); 00472 ASSERT_VALID(pFrame); 00473 pFrame->GetWindowRect(rectFrame); 00474 CSize size = rectFrame.Size(); 00475 size.cx += rectView.right - rectClient.right; 00476 size.cy += rectView.bottom - rectClient.bottom; 00477 pFrame->SetWindowPos(NULL, 0, 0, size.cx, size.cy, 00478 SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE); 00479 } 00480 00482 00483 void CScrollZoomView::OnSize(UINT nType, int cx, int cy) 00484 { 00485 CView::OnSize(nType, cx, cy); 00486 if (m_nMapMode == MM_SCALETOFIT) 00487 { 00488 // force recalculation of scale to fit parameters 00489 SetScaleToFitSize(m_totalLog); 00490 } 00491 else 00492 { 00493 // UpdateBars() handles locking out recursion 00494 UpdateBars(); 00495 } 00496 } 00497 00499 // Scrolling Helpers 00500 00501 void CScrollZoomView::CenterOnPoint(CPoint ptCenter) // center in device coords 00502 { 00503 CRect rect; 00504 GetClientRect(&rect); // find size of client window 00505 00506 int xDesired = ptCenter.x - rect.Width() / 2; 00507 int yDesired = ptCenter.y - rect.Height() / 2; 00508 00509 DWORD dwStyle = GetStyle(); 00510 00511 if ((dwStyle & WS_HSCROLL) == 0 || xDesired < 0) 00512 { 00513 xDesired = 0; 00514 } 00515 else 00516 { 00517 // int xMin, xMax; 00518 // GetScrollRange(SB_HORZ, &xMin, &xMax); 00519 int xMax = GetScrollLimit(SB_HORZ); 00520 if (xDesired > xMax) 00521 xDesired = xMax; 00522 } 00523 00524 if ((dwStyle & WS_VSCROLL) == 0 || yDesired < 0) 00525 { 00526 yDesired = 0; 00527 } 00528 else 00529 { 00530 // int yMin, yMax; 00531 // GetScrollRange(SB_VERT, &yMin, &yMax); 00532 int yMax = GetScrollLimit(SB_VERT); 00533 if (yDesired > yMax) 00534 yDesired = yMax; 00535 } 00536 00537 ASSERT(xDesired >= 0); 00538 ASSERT(yDesired >= 0); 00539 00540 SetScrollPos(SB_HORZ, xDesired); 00541 SetScrollPos(SB_VERT, yDesired); 00542 } 00543 00545 // Tie to scrollbars and CWnd behaviour 00546 00547 void CScrollZoomView::GetScrollBarSizes(CSize& sizeSb) 00548 { 00549 sizeSb.cx = sizeSb.cy = 0; 00550 DWORD dwStyle = GetStyle(); 00551 00552 if (GetScrollBarCtrl(SB_VERT) == NULL) 00553 { 00554 // vert scrollbars will impact client area of this window 00555 sizeSb.cx = GetSystemMetrics(SM_CXVSCROLL) + CX_BORDER; 00556 if (dwStyle & WS_BORDER) 00557 sizeSb.cx -= CX_BORDER; 00558 } 00559 if (GetScrollBarCtrl(SB_HORZ) == NULL) 00560 { 00561 // horz scrollbars will impact client area of this window 00562 sizeSb.cy = GetSystemMetrics(SM_CYHSCROLL) + CY_BORDER; 00563 if (dwStyle & WS_BORDER) 00564 sizeSb.cy -= CY_BORDER; 00565 } 00566 } 00567 00568 BOOL CScrollZoomView::GetTrueClientSize(CSize& size, CSize& sizeSb) 00569 // return TRUE if enough room to add scrollbars if needed 00570 { 00571 CRect rect; 00572 GetClientRect(&rect); 00573 ASSERT(rect.top == 0 && rect.left == 0); 00574 size.cx = rect.right; 00575 size.cy = rect.bottom; 00576 DWORD dwStyle = GetStyle(); 00577 00578 // first get the size of the scrollbars for this window 00579 GetScrollBarSizes(sizeSb); 00580 00581 // first calculate the size of a potential scrollbar 00582 // (scroll bar controls do not get turned on/off) 00583 if (sizeSb.cx != 0 && (dwStyle & WS_VSCROLL)) 00584 { 00585 // vert scrollbars will impact client area of this window 00586 size.cx += sizeSb.cx; // currently on - adjust now 00587 } 00588 if (sizeSb.cy != 0 && (dwStyle & WS_HSCROLL)) 00589 { 00590 // horz scrollbars will impact client area of this window 00591 size.cy += sizeSb.cy; // currently on - adjust now 00592 } 00593 00594 // return TRUE if enough room 00595 return (size.cx > sizeSb.cx && size.cy > sizeSb.cy); 00596 } 00597 00598 // helper to return the state of the scrollbars without actually changing 00599 // the state of the scrollbars 00600 void CScrollZoomView::GetScrollBarState(CSize sizeClient, CSize& needSb, 00601 CSize& sizeRange, CPoint& ptMove, BOOL bInsideClient) 00602 { 00603 // get scroll bar sizes (the part that is in the client area) 00604 CSize sizeSb; 00605 GetScrollBarSizes(sizeSb); 00606 00607 // enough room to add scrollbars 00608 sizeRange = m_totalDev - sizeClient; 00609 // > 0 => need to scroll 00610 ptMove = GetDeviceScrollPosition(); 00611 // point to move to (start at current scroll pos) 00612 00613 BOOL bNeedH = sizeRange.cx > 0; 00614 if (!bNeedH) 00615 ptMove.x = 0; // jump back to origin 00616 else if (bInsideClient) 00617 sizeRange.cy += sizeSb.cy; // need room for a scroll bar 00618 00619 BOOL bNeedV = sizeRange.cy > 0; 00620 if (!bNeedV) 00621 ptMove.y = 0; // jump back to origin 00622 else if (bInsideClient) 00623 sizeRange.cx += sizeSb.cx; // need room for a scroll bar 00624 00625 if (bNeedV && !bNeedH && sizeRange.cx > 0) 00626 { 00627 ASSERT(bInsideClient); 00628 // need a horizontal scrollbar after all 00629 bNeedH = TRUE; 00630 sizeRange.cy += sizeSb.cy; 00631 } 00632 00633 // if current scroll position will be past the limit, scroll to limit 00634 if (sizeRange.cx > 0 && ptMove.x >= sizeRange.cx) 00635 ptMove.x = sizeRange.cx; 00636 if (sizeRange.cy > 0 && ptMove.y >= sizeRange.cy) 00637 ptMove.y = sizeRange.cy; 00638 00639 // now update the bars as appropriate 00640 needSb.cx = bNeedH; 00641 needSb.cy = bNeedV; 00642 00643 // needSb, sizeRange, and ptMove area now all updated 00644 } 00645 00646 void CScrollZoomView::UpdateBars() 00647 { 00648 // UpdateBars may cause window to be resized - ignore those resizings 00649 if (m_bInsideUpdate) 00650 return; // Do not allow recursive calls 00651 00652 // Lock out recursion 00653 m_bInsideUpdate = TRUE; 00654 00655 // update the horizontal to reflect reality 00656 // NOTE: turning on/off the scrollbars will cause 'OnSize' callbacks 00657 ASSERT(m_totalDev.cx >= 0 && m_totalDev.cy >= 0); 00658 00659 CRect rectClient; 00660 BOOL bCalcClient = TRUE; 00661 00662 // allow parent to do inside-out layout first 00663 CWnd* pParentWnd = GetParent(); 00664 if (pParentWnd != NULL) 00665 { 00666 // if parent window responds to this message, use just 00667 // client area for scroll bar calc -- not "true" client area 00668 if ((BOOL)pParentWnd->SendMessage(WM_RECALCPARENT, 0, 00669 (LPARAM)(LPCRECT)&rectClient) != 0) 00670 { 00671 // use rectClient instead of GetTrueClientSize for 00672 // client size calculation. 00673 bCalcClient = FALSE; 00674 } 00675 } 00676 00677 CSize sizeClient; 00678 CSize sizeSb; 00679 00680 if (bCalcClient) 00681 { 00682 // get client rect 00683 if (!GetTrueClientSize(sizeClient, sizeSb)) 00684 { 00685 // no room for scroll bars (common for zero sized elements) 00686 CRect rect; 00687 GetClientRect(&rect); 00688 if (rect.right > 0 && rect.bottom > 0) 00689 { 00690 // if entire client area is not invisible, assume we have 00691 // control over our scrollbars 00692 SetScrollPos(SB_HORZ, 0); 00693 SetScrollPos(SB_VERT, 0); 00694 EnableScrollBarCtrl(SB_BOTH, FALSE); 00695 m_noHscroll = true; // hack terge 00696 m_noVscroll = true; // hack terge 00697 SetScrollRange(SB_HORZ, 0, 0, TRUE); 00698 SetScrollRange(SB_VERT, 0, 0, TRUE); 00699 } 00700 m_bInsideUpdate = FALSE; 00701 // notifyPanning(CPoint(0,0)); // ?? 00702 return; 00703 } 00704 } 00705 else 00706 { 00707 // let parent window determine the "client" rect 00708 GetScrollBarSizes(sizeSb); 00709 sizeClient.cx = rectClient.right - rectClient.left; 00710 sizeClient.cy = rectClient.bottom - rectClient.top; 00711 } 00712 00713 // enough room to add scrollbars 00714 CSize sizeRange; 00715 CPoint ptMove; 00716 CSize needSb; 00717 00718 // get the current scroll bar state given the true client area 00719 GetScrollBarState(sizeClient, needSb, sizeRange, ptMove, bCalcClient); 00720 if (needSb.cx) 00721 sizeClient.cy -= sizeSb.cy; 00722 if (needSb.cy) 00723 sizeClient.cx -= sizeSb.cx; 00724 00725 // first scroll the window as needed 00726 if (!m_zoomScroll) 00727 { 00728 ScrollToDevicePosition(ptMove); // will set the scroll bar positions too 00729 } 00730 00731 // this structure needed to update the scrollbar page range 00732 SCROLLINFO info; 00733 info.fMask = SIF_PAGE|SIF_RANGE; 00734 info.nMin = 0; 00735 00736 // now update the bars as appropriate 00737 EnableScrollBarCtrl(SB_HORZ, needSb.cx); 00738 if (needSb.cx) 00739 { 00740 m_noHscroll = false; // hack terge 00741 info.nPage = sizeClient.cx; 00742 info.nMax = m_totalDev.cx-1; 00743 SetScrollInfo(SB_HORZ, &info, TRUE); 00744 } 00745 else 00746 { 00747 m_noHscroll = true; // hack terge 00748 // DWORD err = 0; 00749 // BOOL ret = TRUE; 00750 SetScrollPos(SB_HORZ, 0); 00751 SetScrollRange(SB_HORZ, 0, 0, TRUE); 00752 /* CScrollBar* pScrollBar; 00753 if ((pScrollBar = GetScrollBarCtrl(SB_HORZ)) != NULL) 00754 pScrollBar->SetScrollRange(0, 0, TRUE); 00755 else 00756 { 00757 ret = ::SetScrollRange(m_hWnd, SB_HORZ, 0, 0, TRUE); 00758 if (!ret) 00759 err = GetLastError(); 00760 }*/ 00761 // int lxMin, lxMax; 00762 // GetScrollRange(SB_HORZ, &lxMin, &lxMax); 00763 } 00764 EnableScrollBarCtrl(SB_VERT, needSb.cy); 00765 // int ixMin, ixMax; 00766 // GetScrollRange(SB_HORZ, &ixMin, &ixMax); 00767 if (needSb.cy) 00768 { 00769 m_noVscroll = false; // hack terge 00770 info.nPage = sizeClient.cy; 00771 info.nMax = m_totalDev.cy-1; 00772 SetScrollInfo(SB_VERT, &info, TRUE); 00773 //SetScrollRange(SB_VERT, 0, sizeRange.cy, TRUE); 00774 } 00775 else 00776 { 00777 m_noVscroll = true; // hack terge 00778 SetScrollPos(SB_VERT, 0); 00779 // int jxMin, jxMax; 00780 // GetScrollRange(SB_HORZ, &jxMin, &jxMax); 00781 SetScrollRange(SB_VERT, 0, 0, TRUE); 00782 } 00783 // int pxMin, pxMax, pyMin, pyMax; 00785 // GetScrollRange(SB_VERT, &pyMin, &pyMax); 00786 if (m_zoomScroll) 00787 { 00788 ScrollToPosition(m_zoomP); // logical coordinates 00789 m_zoomP.x = m_zoomP.y = 0; 00790 m_zoomScroll = false; 00791 } 00792 00793 // remove recursion lockout 00794 m_bInsideUpdate = FALSE; 00795 } 00796 00797 void CScrollZoomView::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType) 00798 { 00799 if (nAdjustType == adjustOutside) 00800 { 00801 // allow for special client-edge style 00802 ::AdjustWindowRectEx(lpClientRect, 0, FALSE, GetExStyle()); 00803 00804 if (m_nMapMode != MM_SCALETOFIT) 00805 { 00806 // if the view is being used in-place, add scrollbar sizes 00807 // (scollbars should appear on the outside when in-place editing) 00808 CSize sizeClient( 00809 lpClientRect->right - lpClientRect->left, 00810 lpClientRect->bottom - lpClientRect->top); 00811 00812 CSize sizeRange = m_totalDev - sizeClient; 00813 // > 0 => need to scroll 00814 00815 // get scroll bar sizes (used to adjust the window) 00816 CSize sizeSb; 00817 GetScrollBarSizes(sizeSb); 00818 00819 // adjust the window size based on the state 00820 if (sizeRange.cy > 0) 00821 { // vertical scroll bars take up horizontal space 00822 lpClientRect->right += sizeSb.cx; 00823 } 00824 if (sizeRange.cx > 0) 00825 { // horizontal scroll bars take up vertical space 00826 lpClientRect->bottom += sizeSb.cy; 00827 } 00828 } 00829 } 00830 else 00831 { 00832 // call default to handle other non-client areas 00833 ::AdjustWindowRectEx(lpClientRect, GetStyle(), FALSE, 00834 GetExStyle() & ~(WS_EX_CLIENTEDGE)); 00835 } 00836 } 00837 00839 // CScrollZoomView scrolling 00840 00841 void CScrollZoomView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 00842 { 00843 if (pScrollBar != NULL && pScrollBar->SendChildNotifyLastMsg()) 00844 return; // eat it 00845 00846 // ignore scroll bar msgs from other controls 00847 if (pScrollBar != NULL && pScrollBar != GetScrollBarCtrl(SB_HORZ)) 00848 return; 00849 // GetScrollInfo http://msdn.microsoft.com/en-us/library/bb787583%28VS.85%29.aspx 00850 // "The messages that indicate scroll bar position, WM_HSCROLL and WM_VSCROLL, provide only 16 bits of position data" 00851 if (nSBCode == SB_THUMBTRACK || nSBCode == SB_THUMBPOSITION) 00852 { 00853 SCROLLINFO si = {0}; 00854 if (!GetScrollInfo(SB_HORZ, &si, SIF_TRACKPOS)) 00855 { 00856 ASSERT(false); 00857 return; 00858 } 00859 nPos = si.nTrackPos; 00860 } 00861 00862 OnScroll(MAKEWORD(nSBCode, -1), nPos); 00863 } 00864 00865 void CScrollZoomView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 00866 { 00867 CView::OnVScroll(nSBCode, nPos, pScrollBar); 00868 if (pScrollBar != NULL && pScrollBar->SendChildNotifyLastMsg()) 00869 return; // eat it 00870 00871 // ignore scroll bar msgs from other controls 00872 if (pScrollBar != NULL && pScrollBar != GetScrollBarCtrl(SB_VERT)) 00873 return; 00874 // GetScrollInfo http://msdn.microsoft.com/en-us/library/bb787583%28VS.85%29.aspx 00875 // "The messages that indicate scroll bar position, WM_HSCROLL and WM_VSCROLL, provide only 16 bits of position data" 00876 if (nSBCode == SB_THUMBTRACK || nSBCode == SB_THUMBPOSITION) 00877 { 00878 SCROLLINFO si = {0}; 00879 if (!GetScrollInfo(SB_VERT, &si, SIF_TRACKPOS)) 00880 { 00881 ASSERT(false); 00882 return; 00883 } 00884 nPos = si.nTrackPos; 00885 } 00886 00887 OnScroll(MAKEWORD(-1, nSBCode), nPos); 00888 } 00889 00890 BOOL CScrollZoomView::OnMouseWheel(UINT fFlags, short zDelta, CPoint point) 00891 { 00892 // we don't handle anything but scrolling just now 00893 if (fFlags & MK_CONTROL) 00894 return FALSE; 00895 00896 // if the parent is a splitter, it will handle the message 00897 if (GetParentSplitter(this, TRUE)) 00898 return FALSE; 00899 00900 // we can't get out of it--perform the scroll ourselves 00901 return DoMouseWheel(fFlags, zDelta, point); 00902 } 00903 00904 // This function isn't virtual. If you need to override it, 00905 // you really need to override OnMouseWheel() here or in 00906 // CSplitterWnd. 00907 00908 BOOL CScrollZoomView::DoMouseWheel(UINT fFlags, short zDelta, CPoint point) 00909 { 00910 UNUSED_ALWAYS(point); 00911 UNUSED_ALWAYS(fFlags); 00912 00913 // if we have a vertical scroll bar, the wheel scrolls that 00914 // if we have _only_ a horizontal scroll bar, the wheel scrolls that 00915 // otherwise, don't do any work at all 00916 00917 DWORD dwStyle = GetStyle(); 00918 CScrollBar* pBar = GetScrollBarCtrl(SB_VERT); 00919 BOOL bHasVertBar = ((pBar != NULL) && pBar->IsWindowEnabled()) || 00920 (dwStyle & WS_VSCROLL); 00921 00922 pBar = GetScrollBarCtrl(SB_HORZ); 00923 BOOL bHasHorzBar = ((pBar != NULL) && pBar->IsWindowEnabled()) || 00924 (dwStyle & WS_HSCROLL); 00925 00926 if (!bHasVertBar && !bHasHorzBar) 00927 return FALSE; 00928 00929 bool preferHorizZoom = (fFlags & MK_SHIFT) != 0; 00930 00931 BOOL bResult = FALSE; 00932 UINT uWheelScrollLines = GetMouseScrollLines(); 00933 int nToScroll; 00934 int nDisplacement; 00935 00936 if (bHasVertBar && !(bHasHorzBar && preferHorizZoom)) 00937 { 00938 nToScroll = ::MulDiv(-zDelta, uWheelScrollLines, WHEEL_DELTA); 00939 if (nToScroll == -1 || uWheelScrollLines == WHEEL_PAGESCROLL) 00940 { 00941 nDisplacement = m_pageDev.cy; 00942 if (zDelta > 0) 00943 nDisplacement = -nDisplacement; 00944 } 00945 else 00946 { 00947 nDisplacement = nToScroll * m_lineDev.cy; 00948 nDisplacement = (nDisplacement<m_pageDev.cy)? nDisplacement: m_pageDev.cy; 00949 } 00950 bResult = OnScrollBy(CSize(0, nDisplacement), TRUE); 00951 } 00952 else if (bHasHorzBar) 00953 { 00954 nToScroll = ::MulDiv(-zDelta, uWheelScrollLines, WHEEL_DELTA); 00955 if (nToScroll == -1 || uWheelScrollLines == WHEEL_PAGESCROLL) 00956 { 00957 nDisplacement = m_pageDev.cx; 00958 if (zDelta > 0) 00959 nDisplacement = -nDisplacement; 00960 } 00961 else 00962 { 00963 nDisplacement = nToScroll * m_lineDev.cx; 00964 nDisplacement = (nDisplacement<m_pageDev.cx)? nDisplacement: m_pageDev.cx; 00965 } 00966 bResult = OnScrollBy(CSize(nDisplacement, 0), TRUE); 00967 } 00968 00969 if (bResult) 00970 UpdateWindow(); 00971 00972 return bResult; 00973 } 00974 00975 00976 BOOL CScrollZoomView::OnScroll(UINT nScrollCode, UINT nPos, BOOL bDoScroll) 00977 { 00978 // calc new x position 00979 int x = GetScrollPos(SB_HORZ); 00980 int xOrig = x; 00981 00982 switch (LOBYTE(nScrollCode)) 00983 { 00984 case SB_TOP: 00985 x = 0; 00986 break; 00987 case SB_BOTTOM: 00988 x = INT_MAX; 00989 break; 00990 case SB_LINEUP: 00991 x -= m_lineDev.cx; 00992 break; 00993 case SB_LINEDOWN: 00994 x += m_lineDev.cx; 00995 break; 00996 case SB_PAGEUP: 00997 x -= m_pageDev.cx; 00998 break; 00999 case SB_PAGEDOWN: 01000 x += m_pageDev.cx; 01001 break; 01002 case SB_THUMBTRACK: 01003 x = nPos; 01004 break; 01005 } 01006 01007 // calc new y position 01008 int y = GetScrollPos(SB_VERT); 01009 int yOrig = y; 01010 01011 switch (HIBYTE(nScrollCode)) 01012 { 01013 case SB_TOP: 01014 y = 0; 01015 break; 01016 case SB_BOTTOM: 01017 y = INT_MAX; 01018 break; 01019 case SB_LINEUP: 01020 y -= m_lineDev.cy; 01021 break; 01022 case SB_LINEDOWN: 01023 y += m_lineDev.cy; 01024 break; 01025 case SB_PAGEUP: 01026 y -= m_pageDev.cy; 01027 break; 01028 case SB_PAGEDOWN: 01029 y += m_pageDev.cy; 01030 break; 01031 case SB_THUMBTRACK: 01032 y = nPos; 01033 break; 01034 } 01035 01036 BOOL bResult = OnScrollBy(CSize(x - xOrig, y - yOrig), bDoScroll); 01037 if (bResult && bDoScroll) 01038 UpdateWindow(); 01039 01040 return bResult; 01041 } 01042 01043 BOOL CScrollZoomView::OnScrollBy(CSize sizeScroll, BOOL bDoScroll) 01044 { 01045 int xOrig, x; 01046 int yOrig, y; 01047 01048 // don't scroll if there is no valid scroll range (ie. no scroll bar) 01049 CScrollBar* pBar; 01050 DWORD dwStyle = GetStyle(); 01051 pBar = GetScrollBarCtrl(SB_VERT); 01052 if ((pBar != NULL && !pBar->IsWindowEnabled()) || 01053 (pBar == NULL && !(dwStyle & WS_VSCROLL))) 01054 { 01055 // vertical scroll bar not enabled 01056 sizeScroll.cy = 0; 01057 } 01058 pBar = GetScrollBarCtrl(SB_HORZ); 01059 if ((pBar != NULL && !pBar->IsWindowEnabled()) || 01060 (pBar == NULL && !(dwStyle & WS_HSCROLL))) 01061 { 01062 // horizontal scroll bar not enabled 01063 sizeScroll.cx = 0; 01064 } 01065 01066 // adjust current x position 01067 xOrig = x = GetScrollPos(SB_HORZ); 01068 // int xMax, xMin; 01069 // GetScrollRange(SB_HORZ, &xMin, &xMax); 01070 int xMax = GetScrollLimit(SB_HORZ); 01071 x += sizeScroll.cx; 01072 if (x < 0) 01073 x = 0; 01074 else if (x > xMax) 01075 x = xMax; 01076 01077 // adjust current y position 01078 yOrig = y = GetScrollPos(SB_VERT); 01079 // int yMin, yMax; 01080 // GetScrollRange(SB_VERT, &yMin, &yMax); 01081 int yMax = GetScrollLimit(SB_VERT); 01082 y += sizeScroll.cy; 01083 if (y < 0) 01084 y = 0; 01085 else if (y > yMax) 01086 y = yMax; 01087 01088 // did anything change? 01089 if (x == xOrig && y == yOrig) 01090 return FALSE; 01091 01092 if (bDoScroll) 01093 { 01094 // do scroll and update scroll positions 01095 ScrollWindow(-(x-xOrig), -(y-yOrig)); 01096 if (x != xOrig) 01097 SetScrollPos(SB_HORZ, x); 01098 if (y != yOrig) 01099 SetScrollPos(SB_VERT, y); 01100 } 01101 01102 // terge 01103 TRACE("notifyPanning from OnScrollBy\n"); 01104 notifyPanning(GetDeviceScrollPosition()); 01105 01106 return TRUE; 01107 } 01108 01110 // CScrollZoomView diagnostics 01111 01112 #ifdef _DEBUG 01113 void CScrollZoomView::Dump(CDumpContext& dc) const 01114 { 01115 CView::Dump(dc); 01116 01117 dc << "m_totalLog = " << m_totalLog; 01118 dc << "\nm_totalDev = " << m_totalDev; 01119 dc << "\nm_pageDev = " << m_pageDev; 01120 dc << "\nm_lineDev = " << m_lineDev; 01121 dc << "\nm_bCenter = " << m_bCenter; 01122 dc << "\nm_bInsideUpdate = " << m_bInsideUpdate; 01123 dc << "\nm_nMapMode = "; 01124 switch (m_nMapMode) 01125 { 01126 case MM_NONE: 01127 dc << "MM_NONE"; 01128 break; 01129 case MM_SCALETOFIT: 01130 dc << "MM_SCALETOFIT"; 01131 break; 01132 case MM_TEXT: 01133 dc << "MM_TEXT"; 01134 break; 01135 case MM_LOMETRIC: 01136 dc << "MM_LOMETRIC"; 01137 break; 01138 case MM_HIMETRIC: 01139 dc << "MM_HIMETRIC"; 01140 break; 01141 case MM_LOENGLISH: 01142 dc << "MM_LOENGLISH"; 01143 break; 01144 case MM_HIENGLISH: 01145 dc << "MM_HIENGLISH"; 01146 break; 01147 case MM_TWIPS: 01148 dc << "MM_TWIPS"; 01149 break; 01150 case MM_ISOTROPIC: 01151 dc << "MM_ISOTROPIC"; 01152 break; 01153 default: 01154 dc << "*unknown*"; 01155 break; 01156 } 01157 01158 dc << "\n"; 01159 } 01160 01161 void CScrollZoomView::AssertValid() const 01162 { 01163 CView::AssertValid(); 01164 01165 switch (m_nMapMode) 01166 { 01167 case MM_NONE: 01168 case MM_SCALETOFIT: 01169 case MM_TEXT: 01170 case MM_LOMETRIC: 01171 case MM_HIMETRIC: 01172 case MM_LOENGLISH: 01173 case MM_HIENGLISH: 01174 case MM_TWIPS: 01175 case MM_ISOTROPIC: 01176 break; 01177 case MM_ANISOTROPIC: 01178 ASSERT(FALSE); // illegal mapping mode 01179 default: 01180 ASSERT(FALSE); // unknown mapping mode 01181 } 01182 } 01183 #endif //_DEBUG 01184