// PrevView.cpp: implementation of the CPreviewViewEx class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "leocad.h" #include "PrevView.h" #include "CADView.h" #if _MFC_VER < 0x0710 #include <../src/afximpl.h> #else #include <../src/mfc/afximpl.h> #endif #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif BOOL CALLBACK _AfxPreviewCloseProcEx(CFrameWnd* pFrameWnd) { ASSERT_VALID(pFrameWnd); CPreviewViewEx* pView = (CPreviewViewEx*) pFrameWnd->GetDlgItem(AFX_IDW_PANE_FIRST); ASSERT_KINDOF(CPreviewViewEx, pView); pView->OnPreviewClose(); return FALSE; } ///////////////////////////////////////////////////////////////////////////// // Preview View BEGIN_MESSAGE_MAP(CPreviewViewEx, CScrollView) //{{AFX_MSG_MAP(CPreviewViewEx) ON_COMMAND(ID_PREVIEW_CLOSE, OnPreviewClose) ON_COMMAND(AFX_ID_PREVIEW_CLOSE, OnPreviewClose) ON_WM_CREATE() ON_WM_SIZE() // overriding CScrollView ON_WM_HSCROLL() ON_WM_VSCROLL() ON_WM_LBUTTONDOWN() ON_WM_ERASEBKGND() ON_COMMAND(ID_PREVIEW_ONEPAGE, OnPreviewOnepage) ON_COMMAND(ID_PREVIEW_TWOPAGES, OnPreviewTwopages) ON_COMMAND(ID_PREVIEW_NEXT, OnNextPage) ON_COMMAND(ID_PREVIEW_PREV, OnPrevPage) ON_COMMAND(ID_PREVIEW_PRINT, OnPreviewPrint) ON_COMMAND(ID_PREVIEW_ZOOMIN, OnZoomIn) ON_COMMAND(ID_PREVIEW_ZOOMOUT, OnZoomOut) ON_UPDATE_COMMAND_UI(ID_PREVIEW_ONEPAGE, OnUpdatePreviewOnepage) ON_UPDATE_COMMAND_UI(ID_PREVIEW_TWOPAGES, OnUpdatePreviewTwopages) ON_UPDATE_COMMAND_UI(ID_PREVIEW_NEXT, OnUpdateNextPage) ON_UPDATE_COMMAND_UI(ID_PREVIEW_PREV, OnUpdatePrevPage) ON_UPDATE_COMMAND_UI(ID_PREVIEW_ZOOMIN, OnUpdateZoomIn) ON_UPDATE_COMMAND_UI(ID_PREVIEW_ZOOMOUT, OnUpdateZoomOut) ON_WM_SETCURSOR() //}}AFX_MSG_MAP END_MESSAGE_MAP() CPreviewViewEx::CPreviewViewEx() { m_pPrintView = NULL; m_pOrigView = NULL; m_pPreviewInfo = NULL; m_pPreviewDC = NULL; m_pPreviewState = NULL; m_hMagnifyCursor = NULL; m_bPageNumDisplayed = FALSE; m_nZoomState = ZOOM_OUT; // default to pointing to embedded array. Allows for 2 pages m_pPageInfo = m_pageInfoArray; m_nMaxPages = 2; // initialize CScrollView members m_bCenter = TRUE; // Center Zoomed output in Scrollview m_nMapMode = MM_TEXT; } CPreviewViewEx::~CPreviewViewEx() { m_dcPrint.Detach(); // print DC is deleted by CPrintInfo destructor delete m_pPreviewInfo; // get rid of preview info delete m_pPreviewState; // Get rid of preview state delete m_pPreviewDC; // Get rid of preview DC object if (m_hMagnifyCursor != NULL) { // make sure that m_hMagnifyCursor isn't the current cursor when we destroy it ::SetCursor(::LoadCursor(NULL, IDC_ARROW)); DestroyCursor(m_hMagnifyCursor); } } int CPreviewViewEx::OnCreate(LPCREATESTRUCT lpCreateStruct) { int retVal = CView::OnCreate(lpCreateStruct); if (retVal == -1) return -1; // if -1 bag out CCreateContext* pContext = (CCreateContext*)lpCreateStruct->lpCreateParams; m_pOrigView = (CCADView*)pContext->m_pLastView; ASSERT(m_pOrigView != NULL); ASSERT_KINDOF(CView, m_pOrigView); return retVal; } #ifdef _MAC void CPreviewViewEx::CalcWindowRect(LPRECT lpClientRect) { CView::CalcWindowRect(lpClientRect); // The preview view is created with the WS_BORDER style, and when // the view is repositioned, these borders will by default be placed // outside the main monitor. If there are other monitors adjacent to // the main monitor, the border shows up on those monitors, which looks // sloppy. To prevent this we resize the window rect as necessary to // keep the borders inside the MDI parent frame window's client area. // Also note that we can't just get rid of the borders entirely because // this looks bad on a PowerBook where the edges of the screen are // white instead of black - if there aren't any borders, there's no // dividing line between the edge of the preview view's scrollbars // and the non-drawing areas of the screen. CWnd* pParent = GetParent(); if (pParent->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd))) { RECT rect; pParent->GetClientRect(&rect); if (lpClientRect->left < rect.left) lpClientRect->left = rect.left; if (lpClientRect->right > rect.right) lpClientRect->right = rect.right; if (lpClientRect->bottom > rect.bottom) lpClientRect->bottom = rect.bottom; // top not needed because it will be adjacent to the print // preview toolbar } } #endif BOOL CPreviewViewEx::SetPrintView(CCADView* pPrintView) { ASSERT_VALID(pPrintView); m_pPrintView = pPrintView; // allocate preview info m_pPreviewInfo = new CPrintInfo; m_pPreviewInfo->m_pPD->SetHelpID(AFX_IDD_PRINTSETUP); m_pPreviewInfo->m_pPD->m_pd.Flags |= PD_PRINTSETUP; m_pPreviewInfo->m_pPD->m_pd.Flags &= ~PD_RETURNDC; m_pPreviewInfo->m_bPreview = TRUE; // signal that this is preview ASSERT(m_pPreviewInfo->m_pPD != NULL); m_pPreviewDC = new CPreviewDC; // must be created before any // possible error returns if (!m_pPrintView->OnPreparePrinting(m_pPreviewInfo)) return FALSE; #ifdef _DEBUG if (m_pPreviewInfo->m_pPD->m_pd.hDC == NULL) { TRACE0("Error: hDC not set for printing --\n"); TRACE0("\tDid you remember to call DoPreparePrinting?\n"); ASSERT(FALSE); // common mistake gets trapped here } #endif //_DEBUG m_dcPrint.Attach(m_pPreviewInfo->m_pPD->m_pd.hDC); m_pPreviewDC->SetAttribDC(m_pPreviewInfo->m_pPD->m_pd.hDC); m_pPreviewDC->m_bPrinting = TRUE; m_dcPrint.m_bPrinting = TRUE; m_dcPrint.SaveDC(); // Save pristine state of DC HDC hDC = ::GetDC(m_hWnd); m_pPreviewDC->SetOutputDC(hDC); m_pPrintView->OnBeginPrinting(m_pPreviewDC, m_pPreviewInfo); m_pPreviewDC->ReleaseOutputDC(); ::ReleaseDC(m_hWnd, hDC); m_dcPrint.RestoreDC(-1); // restore to untouched state // Get Pixels per inch from Printer m_sizePrinterPPI.cx = m_dcPrint.GetDeviceCaps(LOGPIXELSX); m_sizePrinterPPI.cy = m_dcPrint.GetDeviceCaps(LOGPIXELSY); m_nPages = m_pPreviewInfo->m_nNumPreviewPages; if (m_nPages == 0) m_nPages = 1; else if (m_nPages > m_nMaxPages) m_nPages = m_nMaxPages; // Sanity Check! m_nZoomOutPages = m_nPages; SetScrollSizes(MM_TEXT, CSize(1, 1)); // initialize mapping mode only if (m_pPreviewInfo->GetMaxPage() < 0x8000 && m_pPreviewInfo->GetMaxPage() - m_pPreviewInfo->GetMinPage() <= 32767U) SetScrollRange(SB_VERT, m_pPreviewInfo->GetMinPage(), m_pPreviewInfo->GetMaxPage(), FALSE); else ShowScrollBar(SB_VERT, FALSE); // if no range specified, or too // large don't show SetCurrentPage(m_pPreviewInfo->m_nCurPage, TRUE); return TRUE; } void CPreviewViewEx::OnSize(UINT nType, int cx, int cy) { // CScrollView handles everything if zoomed in. if (m_nZoomState == ZOOM_OUT) { // Force recalc of scale ratios on next draw for (UINT i = 0; i < m_nMaxPages; i++) m_pPageInfo[i].sizeScaleRatio.cx = 0; // zero scale ratios CView::OnSize(nType, cx, cy); // No scroll functionality } else { // adjust scroll size to size of page m_pageDev.cx = cx; m_pageDev.cy = cy; m_lineDev.cx = cx / 10; m_lineDev.cy = cy / 10; CScrollView::OnSize(nType, cx, cy); } } void CPreviewViewEx::OnActivateView(BOOL bActivate, CView*, CView*) { if (bActivate) { CWnd* pFocusWnd = GetFocus(); if (pFocusWnd == NULL || (m_pToolBar != NULL && !m_pToolBar->IsChild(pFocusWnd))) { // focus is not already on a toolbar button - set it to one // m_pToolBar->GetDlgItem(AFX_ID_PREVIEW_PRINT)->SetFocus(); } } #ifdef _MAC // Make sure the preview frame's activation matches that of the frame // window so that scroll bars are drawn with the correct visibility. SendMessage(WM_NCACTIVATE, bActivate, 0); #endif } void CPreviewViewEx::OnPreviewClose() { m_pToolBar->DestroyWindow(); m_pToolBar = NULL; m_pPreviewInfo->m_nCurPage = m_nCurrentPage; m_pOrigView->OnEndPrintPreview(m_pPreviewDC, m_pPreviewInfo, CPoint(0, 0), this); } #define PREVIEW_MARGIN 8 #define PREVIEW_PAGEGAP 8 // Return is actually the fraction cx/cy. Simply using CSize for convenience CSize CPreviewViewEx::CalcScaleRatio(CSize screenSize, CSize actualSize) { // Test ratio based on vertical dimension to see if it is the one to use int nNum = screenSize.cy; int nDen = actualSize.cy; // If scaled width too large, choose width as primary dimension if (MulDiv(actualSize.cx, nNum, nDen) > screenSize.cx) { // wrong ratio--base on width nNum = screenSize.cx; nDen = actualSize.cx; } CSize ratio(nNum, nDen); return ratio; } // Position Page... // Generate a Screen MM_TEXT rectangle to enclose each page. Dimensions // of the rectangle must be 1 pixel Above and Left of the top/left corner // of the page and the rectangle width and height must be THREE pixels // larger than page in order to provide the correct placement of the // two pixel border. // // This routine is called once for each page with the preview DC set up for // that page void CPreviewViewEx::PositionPage(UINT nPage) { CSize windowSize = CalcPageDisplaySize(); VERIFY(m_dcPrint.Escape(GETPHYSPAGESIZE, 0, NULL, (LPVOID)&m_pPageInfo[nPage].sizeUnscaled)); CSize* pSize = &m_pPageInfo[nPage].sizeUnscaled; // Convert page size to screen coordinates pSize->cx = MulDiv(pSize->cx, afxData.cxPixelsPerInch, m_sizePrinterPPI.cx); pSize->cy = MulDiv(pSize->cy, afxData.cyPixelsPerInch, m_sizePrinterPPI.cy); m_pPageInfo[nPage].sizeZoomOutRatio = CalcScaleRatio(windowSize, *pSize); SetScaledSize(nPage); } CSize CPreviewViewEx::CalcPageDisplaySize() // calculate the current page size // set 'm_nSecondPageOffset' to start of second page // return size of current page less margins { CSize windowSize, scrollSize; GetTrueClientSize(windowSize, scrollSize); // subtract out vertical scrollbar if zoomed out and page range is known // and there is more than one page. if (m_nZoomState == ZOOM_OUT && (m_pPreviewInfo->GetMaxPage() != 0xffff) && (m_pPreviewInfo->GetMaxPage() - m_pPreviewInfo->GetMinPage() != 0)) windowSize.cx -= scrollSize.cx; m_nSecondPageOffset = (windowSize.cx - PREVIEW_MARGIN) / 2; windowSize.cx = (m_nPages == 2) ? (windowSize.cx - 3*PREVIEW_MARGIN) / 2 : windowSize.cx - 2*PREVIEW_MARGIN; windowSize.cy -= 2*PREVIEW_MARGIN; return windowSize; } void CPreviewViewEx::SetScaledSize(UINT nPage) { CSize* pSize = &m_pPageInfo[nPage].sizeUnscaled; CSize* pRatio = &m_pPageInfo[nPage].sizeScaleRatio; CSize* pZoomOutRatio = &m_pPageInfo[nPage].sizeZoomOutRatio; CSize windowSize = CalcPageDisplaySize(); BOOL bPaperLarger = pZoomOutRatio->cx < pZoomOutRatio->cy; // whether the paper is larger than the screen, or vice versa switch (m_nZoomState) { case ZOOM_OUT: *pRatio = *pZoomOutRatio; break; case ZOOM_MIDDLE: // the middle zoom state is a ratio between cx/cy and // 1/1 (or cy/cy). It is, therefore: // // (cx + cy)/2 // ----------- // cy // // if the paper is larger than the screen, or // // (3*cx - cy)/2 // ------------- // cy // // if the paper is smaller than the screen. if (bPaperLarger) { pRatio->cy = pZoomOutRatio->cy; pRatio->cx = (pZoomOutRatio->cx + pRatio->cy) / 2; } else { pRatio->cy = pZoomOutRatio->cy; pRatio->cx = (3*pZoomOutRatio->cx - pRatio->cy) / 2; } break; case ZOOM_IN: if (bPaperLarger) pRatio->cx = pRatio->cy = 1; else { // if the paper is smaller than the screen space we're displaying // it in, then using a ratio of 1/1 will result in a smaller image // on the screen, not a larger one. To get a larger image in this // case we double the zoom out ratio. pRatio->cy = pZoomOutRatio->cy; pRatio->cx = 2*pZoomOutRatio->cx - pZoomOutRatio->cy; } break; default: ASSERT(FALSE); } // Convert to scaled size CSize scaledSize; scaledSize.cx = MulDiv(pSize->cx, pRatio->cx, pRatio->cy); scaledSize.cy = MulDiv(pSize->cy, pRatio->cx, pRatio->cy); CRect* pRect = &m_pPageInfo[nPage].rectScreen; pRect->SetRect(PREVIEW_MARGIN, PREVIEW_MARGIN, scaledSize.cx + PREVIEW_MARGIN + 3, scaledSize.cy + PREVIEW_MARGIN + 3); if (m_nZoomState == ZOOM_OUT) { pRect->OffsetRect((windowSize.cx - pRect->Size().cx) / 2 - 1, (windowSize.cy - pRect->Size().cy) / 2 - 1); if (nPage == 1) pRect->OffsetRect(m_nSecondPageOffset, 0); } else { // set up scroll size SetScrollSizes(MM_TEXT, pRect->Size() + CSize(PREVIEW_MARGIN * 2, PREVIEW_MARGIN * 2), windowSize); } } // Only use the PrepareDC from CScrollView if we are zoomed in void CPreviewViewEx::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo) { ASSERT_VALID(pDC); if (m_nZoomState == ZOOM_OUT) CView::OnPrepareDC(pDC, pInfo); else if (m_pPageInfo[0].sizeScaleRatio.cx != 0) CScrollView::OnPrepareDC(pDC, pInfo); } BOOL CPreviewViewEx::OnEraseBkgnd(CDC* pDC) { ASSERT_VALID(pDC); // Fill background with APPWORKSPACE CBrush backBrush(GetSysColor(COLOR_APPWORKSPACE)); CBrush* pOldBrush = pDC->SelectObject(&backBrush); CRect rect; pDC->GetClipBox(&rect); // Erase the area needed pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY); pDC->SelectObject(pOldBrush); return TRUE; } void CPreviewViewEx::OnDraw(CDC* pDC) { ASSERT_VALID(pDC); // don't do anything if not fully initialized if (m_pPrintView == NULL || m_dcPrint.m_hDC == NULL) return; CPoint ViewportOrg = pDC->GetViewportOrg(); CPen rectPen; rectPen.CreatePen(PS_SOLID, 2, GetSysColor(COLOR_WINDOWFRAME)); CPen shadowPen; shadowPen.CreatePen(PS_SOLID, 3, GetSysColor(COLOR_BTNSHADOW)); m_pPreviewInfo->m_bContinuePrinting = TRUE; // do this once each paint for (UINT nPage = 0; nPage < m_nPages; nPage++) { int nSavedState = m_dcPrint.SaveDC(); // Save pristine state of DC // Use paint DC for print preview output m_pPreviewDC->SetOutputDC(pDC->GetSafeHdc()); m_pPreviewInfo->m_nCurPage = m_nCurrentPage + nPage; // Only call PrepareDC if within page range, otherwise use default // rect to draw page rectangle if (m_nCurrentPage + nPage <= m_pPreviewInfo->GetMaxPage()) m_pPrintView->OnPrepareDC(m_pPreviewDC, m_pPreviewInfo); // Set up drawing rect to entire page (in logical coordinates) m_pPreviewInfo->m_rectDraw.SetRect(0, 0, m_pPreviewDC->GetDeviceCaps(HORZRES), m_pPreviewDC->GetDeviceCaps(VERTRES)); m_pPreviewDC->DPtoLP(&m_pPreviewInfo->m_rectDraw); // Draw empty page on screen pDC->SaveDC(); // save the output dc state CSize* pRatio = &m_pPageInfo[nPage].sizeScaleRatio; CRect* pRect = &m_pPageInfo[nPage].rectScreen; if (pRatio->cx == 0) { // page position has not been determined PositionPage(nPage); // compute page position if (m_nZoomState != ZOOM_OUT) ViewportOrg = -GetDeviceScrollPosition(); } pDC->SetMapMode(MM_TEXT); // Page Rectangle is in screen device coords pDC->SetViewportOrg(ViewportOrg); pDC->SetWindowOrg(0, 0); pDC->SelectStockObject(HOLLOW_BRUSH); pDC->SelectObject(&rectPen); pDC->Rectangle(pRect); pDC->SelectObject(&shadowPen); pDC->MoveTo(pRect->right + 1, pRect->top + 3); pDC->LineTo(pRect->right + 1, pRect->bottom + 1); pDC->MoveTo(pRect->left + 3, pRect->bottom + 1); pDC->LineTo(pRect->right + 1, pRect->bottom + 1); // erase background to white (most paper is white) CRect rectFill = *pRect; rectFill.left += 1; rectFill.top += 1; rectFill.right -= 2; rectFill.bottom -= 2; ::FillRect(pDC->m_hDC, rectFill, (HBRUSH)GetStockObject(WHITE_BRUSH)); pDC->RestoreDC(-1); // restore to synchronized state if (!m_pPreviewInfo->m_bContinuePrinting || m_nCurrentPage + nPage > m_pPreviewInfo->GetMaxPage()) { m_pPreviewDC->ReleaseOutputDC(); m_dcPrint.RestoreDC(nSavedState); // restore to untouched state // if the first page is not displayable, back up one page // but never go below 1 if (nPage == 0 && m_nCurrentPage > 1) SetCurrentPage(m_nCurrentPage - 1, TRUE); break; } // Display page number OnDisplayPageNumber(m_nCurrentPage, nPage + 1); // Set scale ratio for this page m_pPreviewDC->SetScaleRatio(pRatio->cx, pRatio->cy); CSize PrintOffset; VERIFY(m_pPreviewDC->Escape(GETPRINTINGOFFSET, 0, NULL, (LPVOID)&PrintOffset)); m_pPreviewDC->PrinterDPtoScreenDP((LPPOINT)&PrintOffset); PrintOffset += (CSize)pRect->TopLeft(); PrintOffset += CSize(1, 1); PrintOffset += (CSize)ViewportOrg; // For Scrolling m_pPreviewDC->SetTopLeftOffset(PrintOffset); m_pPreviewDC->ClipToPage(); m_pPrintView->OnPrint(m_pPreviewDC, m_pPreviewInfo); m_pPreviewDC->ReleaseOutputDC(); m_dcPrint.RestoreDC(nSavedState); // restore to untouched state } rectPen.DeleteObject(); shadowPen.DeleteObject(); } void CPreviewViewEx::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { if (m_nZoomState != ZOOM_OUT) CScrollView::OnHScroll(nSBCode, nPos, pScrollBar); } void CPreviewViewEx::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { if (m_nZoomState != ZOOM_OUT) { CScrollView::OnVScroll(nSBCode, nPos, pScrollBar); return; } switch (nSBCode) { case SB_BOTTOM: SetCurrentPage(m_pPreviewInfo->GetMaxPage(), TRUE); break; case SB_TOP: SetCurrentPage(m_pPreviewInfo->GetMinPage(), TRUE); break; case SB_PAGEDOWN: SetCurrentPage(m_nCurrentPage + (m_pPreviewInfo->GetMaxPage() - m_pPreviewInfo->GetMinPage() + 9) / 10, TRUE); break; case SB_PAGEUP: SetCurrentPage(m_nCurrentPage - (m_pPreviewInfo->GetMaxPage() - m_pPreviewInfo->GetMinPage() + 9) / 10, TRUE); break; case SB_LINEDOWN: SetCurrentPage(m_nCurrentPage + 1, TRUE); break; case SB_LINEUP: SetCurrentPage(m_nCurrentPage - 1, TRUE); break; case SB_THUMBPOSITION: SetCurrentPage(nPos, TRUE); break; } } void CPreviewViewEx::OnNextPage() { SetCurrentPage(m_nCurrentPage + 1, TRUE); } void CPreviewViewEx::OnPrevPage() { SetCurrentPage(m_nCurrentPage - 1, TRUE); } void CPreviewViewEx::OnPreviewPrint() { CView* pOrigView = m_pOrigView; OnPreviewClose(); // force close of Preview // cause print (can be overridden by catching the command) CWnd* pMainWnd = AfxGetThread()->m_pMainWnd; ASSERT_VALID(pMainWnd); pMainWnd->SendMessage(WM_COMMAND, ID_FILE_PRINT); } // Finds page pointed to and convert to 1:1 screen device units BOOL CPreviewViewEx::FindPageRect(CPoint& point, UINT& nPage) { if (m_nZoomState != ZOOM_OUT) point += (CSize)GetDeviceScrollPosition(); for (nPage = 0; nPage < m_nPages; nPage++) { if (m_pPageInfo[nPage].rectScreen.PtInRect(point)) { // adjust point for page position point -= (CSize)m_pPageInfo[nPage].rectScreen.TopLeft(); // convert to 1:1 point.x = MulDiv(point.x, m_pPageInfo[nPage].sizeScaleRatio.cy, m_pPageInfo[nPage].sizeScaleRatio.cx); point.y = MulDiv(point.y, m_pPageInfo[nPage].sizeScaleRatio.cy, m_pPageInfo[nPage].sizeScaleRatio.cx); return TRUE; } } return FALSE; } void CPreviewViewEx::OnLButtonDown(UINT, CPoint point) { UINT nPage; if (!FindPageRect(point, nPage)) return; // Didn't click on a page // Set new zoom state SetZoomState((m_nZoomState == ZOOM_IN) ? ZOOM_OUT : m_nZoomState + 1, nPage, point); } void CPreviewViewEx::SetZoomState(UINT nNewState, UINT nPage, CPoint point) { if (m_nZoomState != nNewState) { m_nZoomState = nNewState; DoZoom(nPage, point); } } void CPreviewViewEx::OnZoomIn() { if (m_nZoomState != ZOOM_IN) SetZoomState(m_nZoomState + 1, 0, CPoint(0, 0)); } void CPreviewViewEx::OnZoomOut() { if (m_nZoomState != ZOOM_OUT) SetZoomState(m_nZoomState - 1, 0, CPoint(0, 0)); } // Actual zoom code. void CPreviewViewEx::DoZoom(UINT nPage, CPoint point) { if (m_nZoomState == ZOOM_OUT) { // taking over scroll bars m_nPages = m_nZoomOutPages; ShowScrollBar(SB_HORZ, FALSE); //hide the horizontal bar BOOL bShowBar = m_pPreviewInfo->GetMaxPage() < 0x8000 && m_pPreviewInfo->GetMaxPage() - m_pPreviewInfo->GetMinPage() <= 32767U; ShowScrollBar(SB_VERT, bShowBar); //Show the vertical bar if (bShowBar) { SetScrollRange(SB_VERT, m_pPreviewInfo->GetMinPage(), m_pPreviewInfo->GetMaxPage(), FALSE); SetScrollPos(SB_VERT, m_nCurrentPage, TRUE); } SetCurrentPage(m_nCurrentPage, TRUE); } else { m_nPages = 1; // only one page in zoomed states m_pPageInfo[0].sizeZoomOutRatio = m_pPageInfo[nPage].sizeZoomOutRatio; m_pPageInfo[0].sizeUnscaled = m_pPageInfo[nPage].sizeUnscaled; // Sets the printer page SetCurrentPage(m_nCurrentPage + nPage, FALSE); SetScaledSize(0); CSize* pRatio = &m_pPageInfo[nPage].sizeScaleRatio; // convert Hit Point from screen 1:1 point.x = MulDiv(point.x, pRatio->cx, pRatio->cy); point.y = MulDiv(point.y, pRatio->cx, pRatio->cy); // Adjust point for page position point += (CSize)m_pPageInfo[0].rectScreen.TopLeft(); // Scroll to center CenterOnPoint(point); } } void CPreviewViewEx::SetCurrentPage(UINT nPage, BOOL bClearRatios) { m_nCurrentPage = nPage; if (m_nCurrentPage > m_pPreviewInfo->GetMaxPage()) m_nCurrentPage = m_pPreviewInfo->GetMaxPage(); if (m_nCurrentPage < m_pPreviewInfo->GetMinPage()) m_nCurrentPage = m_pPreviewInfo->GetMinPage(); if (m_nZoomState == ZOOM_OUT) SetScrollPos(SB_VERT, m_nCurrentPage); if (bClearRatios) { // Force Recalc of layout for (UINT i = 0; i < m_nMaxPages; i++) m_pPageInfo[i].sizeScaleRatio.cx = 0; // zero scale ratios } Invalidate(TRUE); } void CPreviewViewEx::OnDisplayPageNumber(UINT nPage, UINT nPagesDisplayed) { UINT nEndPage = nPage + nPagesDisplayed - 1; CFrameWnd* pParent = (CFrameWnd*)AfxGetThread()->m_pMainWnd; ASSERT_VALID(pParent); ASSERT_KINDOF(CFrameWnd, pParent); int nSubString = (nPagesDisplayed == 1) ? 0 : 1; CString s; if (AfxExtractSubString(s, m_pPreviewInfo->m_strPageDesc, nSubString)) { TCHAR szBuf[80]; if (nSubString == 0) wsprintf(szBuf, s, nPage); else wsprintf(szBuf, s, nPage, nEndPage); pParent->SendMessage(WM_SETMESSAGESTRING, 0, (LPARAM)(LPVOID)szBuf); } else { TRACE1("Malformed Page Description string. Could not get string %d.\n", nSubString); } } void CPreviewViewEx::OnUpdateNextPage(CCmdUI* pCmdUI) { // enable if not showing last page pCmdUI->Enable(m_nCurrentPage+m_nPages-1 < m_pPreviewInfo->GetMaxPage()); } void CPreviewViewEx::OnUpdatePrevPage(CCmdUI* pCmdUI) { // enable if not showing First page pCmdUI->Enable(m_nCurrentPage > m_pPreviewInfo->GetMinPage()); } void CPreviewViewEx::OnUpdateZoomIn(CCmdUI* pCmdUI) { pCmdUI->Enable(m_nZoomState != ZOOM_IN); } void CPreviewViewEx::OnUpdateZoomOut(CCmdUI* pCmdUI) { pCmdUI->Enable(m_nZoomState != ZOOM_OUT); } BOOL CPreviewViewEx::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if (nHitTest != HTCLIENT) return CScrollView::OnSetCursor(pWnd, nHitTest, message); CPoint point; ::GetCursorPos(&point); ScreenToClient(&point); // client coordinates of mouse position UINT nPage; if (m_nZoomState != ZOOM_IN && FindPageRect(point, nPage)) { // On a page and not zoomed all the way in if (m_hMagnifyCursor == NULL) { HINSTANCE hInst = AfxFindResourceHandle( MAKEINTRESOURCE(AFX_IDC_MAGNIFY), RT_GROUP_CURSOR); m_hMagnifyCursor = ::LoadCursor(hInst, MAKEINTRESOURCE(AFX_IDC_MAGNIFY)); } ::SetCursor(m_hMagnifyCursor); } else { ::SetCursor(::LoadCursor(NULL, IDC_ARROW)); } return 0; } ///////////////////////////////////////////////////////////////////////////// // CPreviewViewEx diagnostics #ifdef _DEBUG void CPreviewViewEx::AssertValid() const { CView::AssertValid(); ASSERT_VALID(&m_dcPrint); if (m_pPreviewDC != NULL) ASSERT_VALID(m_pPreviewDC); switch (m_nZoomState) { case ZOOM_OUT: case ZOOM_IN: case ZOOM_MIDDLE: break; default: ASSERT(FALSE); // unknown zoom state } switch (m_nMapMode) { case MM_TEXT: case MM_LOMETRIC: case MM_HIMETRIC: case MM_LOENGLISH: case MM_HIENGLISH: case MM_TWIPS: case MM_ISOTROPIC: case MM_ANISOTROPIC: break; default: ASSERT(FALSE); // unknown mapping mode } } void CPreviewViewEx::Dump(CDumpContext& dc) const { CView::Dump(dc); dc << "m_pPrintView = " << m_pPrintView; dc << "\nm_pOrigView = " << m_pOrigView; dc << "\nm_bPageNumDisplayed = " << m_bPageNumDisplayed; dc << "\nm_bCenter = " << m_bCenter; dc << "\nm_nPages = " << m_nPages; dc << "\nm_nCurrentPage " << m_nCurrentPage; dc << "\nm_nSecondPageOffset " << m_nSecondPageOffset; dc << "\nm_nMaxPages = " << m_nMaxPages; dc << "\nm_sizePrinterPPI = " << m_sizePrinterPPI; dc << "\nm_ptCenterPoint = " << m_ptCenterPoint; dc << "\nm_nZoomState = "; switch (m_nZoomState) { case ZOOM_OUT: dc << "ZOOM_OUT"; break; case ZOOM_IN: dc << "ZOOM_IN"; break; case ZOOM_MIDDLE: dc << "ZOOM_MIDDLE"; break; default: dc << "*unknown*"; break; } dc << "\nm_nMapMode = "; switch (m_nMapMode) { case MM_TEXT: dc << "MM_TEXT"; break; case MM_LOMETRIC: dc << "MM_LOMETRIC"; break; case MM_HIMETRIC: dc << "MM_HIMETRIC"; break; case MM_LOENGLISH: dc << "MM_LOENGLISH"; break; case MM_HIENGLISH: dc << "MM_HIENGLISH"; break; case MM_TWIPS: dc << "MM_TWIPS"; break; case MM_ISOTROPIC: dc << "MM_ISOTROPIC"; break; case MM_ANISOTROPIC: dc << "MM_ANISOTROPIC"; break; default: dc << "*unknown*"; break; } dc << "\nm_dcPrint = " << &m_dcPrint; dc << "\nm_pPreviewDC = " << m_pPreviewDC; dc << "\n"; } #endif //_DEBUG #ifdef AFX_INIT_SEG #pragma code_seg(AFX_INIT_SEG) #endif IMPLEMENT_DYNCREATE(CPreviewViewEx, CScrollView) ///////////////////////////////////////////////////////////////////////////// void CPreviewViewEx::OnPreviewOnepage() { ASSERT(m_nPages == 1 || m_nPages == 2); m_nPages = 1; AfxGetApp()->m_nNumPreviewPages = m_nPages; m_nZoomOutPages = m_nPages; // Just do this to set the status correctly and invalidate SetCurrentPage(m_nCurrentPage, TRUE); } void CPreviewViewEx::OnUpdatePreviewOnepage(CCmdUI* pCmdUI) { // enable it only if valid to display another page and not zoomed pCmdUI->Enable(m_nZoomState == ZOOM_OUT && m_nMaxPages != 1 && (m_pPreviewInfo->GetMaxPage() > 1 || m_nPages > 1) && (m_nPages == 2)); } void CPreviewViewEx::OnPreviewTwopages() { ASSERT(m_nPages == 1 || m_nPages == 2); m_nPages = 2; AfxGetApp()->m_nNumPreviewPages = m_nPages; m_nZoomOutPages = m_nPages; // Just do this to set the status correctly and invalidate SetCurrentPage(m_nCurrentPage, TRUE); } void CPreviewViewEx::OnUpdatePreviewTwopages(CCmdUI* pCmdUI) { // enable it only if valid to display another page and not zoomed pCmdUI->Enable(m_nZoomState == ZOOM_OUT && m_nMaxPages != 1 && (m_pPreviewInfo->GetMaxPage() > 1 || m_nPages > 1) && (m_nPages == 1)); }