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