| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090 |
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
- #include "stdafx.h"
- #ifdef AFX_PRINT_SEG
- #pragma code_seg(AFX_PRINT_SEG)
- #endif
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- BOOL CALLBACK _AfxPreviewCloseProc(CFrameWnd* pFrameWnd);
- /////////////////////////////////////////////////////////////////////////////
- // CPrintPreviewState helper structure
- CPrintPreviewState::CPrintPreviewState()
- {
- // set defaults
- nIDMainPane = AFX_IDW_PANE_FIRST;
- dwStates = AFX_CONTROLBAR_MASK(AFX_IDW_STATUS_BAR);
- // status bar visible if available
- lpfnCloseProc = _AfxPreviewCloseProc;
- // set frame hook so closing the frame window
- // when in preview state will just end the mode
- hMenu = NULL;
- pViewActiveOld = NULL;
- hAccelTable = NULL;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CView's OnPrintPreview. Here to force linkage
- void CView::OnFilePrintPreview()
- {
- // In derived classes, implement special window handling here
- // Be sure to Unhook Frame Window close if hooked.
- // must not create this on the frame. Must outlive this function
- CPrintPreviewState* pState = new CPrintPreviewState;
- // DoPrintPreview's return value does not necessarily indicate that
- // Print preview succeeded or failed, but rather what actions are necessary
- // at this point. If DoPrintPreview returns TRUE, it means that
- // OnEndPrintPreview will be (or has already been) called and the
- // pState structure will be/has been deleted.
- // If DoPrintPreview returns FALSE, it means that OnEndPrintPreview
- // WILL NOT be called and that cleanup, including deleting pState
- // must be done here.
- if (!DoPrintPreview(AFX_IDD_PREVIEW_TOOLBAR, this,
- RUNTIME_CLASS(CPreviewView), pState))
- {
- // In derived classes, reverse special window handling here for
- // Preview failure case
- TRACE0("Error: DoPrintPreview failed.\n");
- AfxMessageBox(AFX_IDP_COMMAND_FAILURE);
- delete pState; // preview failed to initialize, delete State now
- }
- }
- BOOL CView::DoPrintPreview(UINT nIDResource, CView* pPrintView,
- CRuntimeClass* pPreviewViewClass, CPrintPreviewState* pState)
- {
- ASSERT_VALID_IDR(nIDResource);
- ASSERT_VALID(pPrintView);
- ASSERT(pPreviewViewClass != NULL);
- ASSERT(pPreviewViewClass->IsDerivedFrom(RUNTIME_CLASS(CPreviewView)));
- ASSERT(pState != NULL);
- CFrameWnd* pParent = STATIC_DOWNCAST(CFrameWnd, AfxGetMainWnd());
- ASSERT_VALID(pParent);
- CCreateContext context;
- context.m_pCurrentFrame = pParent;
- context.m_pCurrentDoc = GetDocument();
- context.m_pLastView = this;
- // Create the preview view object
- CPreviewView* pView = (CPreviewView*)pPreviewViewClass->CreateObject();
- if (pView == NULL)
- {
- TRACE0("Error: Failed to create preview view.\n");
- return FALSE;
- }
- ASSERT_KINDOF(CPreviewView, pView);
- pView->m_pPreviewState = pState; // save pointer
- pParent->OnSetPreviewMode(TRUE, pState); // Take over Frame Window
- // Create the toolbar from the dialog resource
- pView->m_pToolBar = new CDialogBar;
- if (!pView->m_pToolBar->Create(pParent, MAKEINTRESOURCE(nIDResource),
- CBRS_TOP, AFX_IDW_PREVIEW_BAR))
- {
- TRACE0("Error: Preview could not create toolbar dialog.\n");
- pParent->OnSetPreviewMode(FALSE, pState); // restore Frame Window
- delete pView->m_pToolBar; // not autodestruct yet
- pView->m_pToolBar = NULL;
- pView->m_pPreviewState = NULL; // do not delete state structure
- delete pView;
- return FALSE;
- }
- pView->m_pToolBar->m_bAutoDelete = TRUE; // automatic cleanup
- // Create the preview view as a child of the App Main Window. This
- // is a sibling of this view if this is an SDI app. This is NOT a sibling
- // if this is an MDI app.
- if (!pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
- CRect(0,0,0,0), pParent, AFX_IDW_PANE_FIRST, &context))
- {
- TRACE0("Error: couldn't create preview view for frame.\n");
- pParent->OnSetPreviewMode(FALSE, pState); // restore Frame Window
- pView->m_pPreviewState = NULL; // do not delete state structure
- delete pView;
- return FALSE;
- }
- // Preview window shown now
- pState->pViewActiveOld = pParent->GetActiveView();
- CView* pActiveView = pParent->GetActiveFrame()->GetActiveView();
- if (pActiveView != NULL)
- pActiveView->OnActivateView(FALSE, pActiveView, pActiveView);
- if (!pView->SetPrintView(pPrintView))
- {
- pView->OnPreviewClose();
- return TRUE; // signal that OnEndPrintPreview was called
- }
- pParent->SetActiveView(pView); // set active view - even for MDI
- // update toolbar and redraw everything
- pView->m_pToolBar->SendMessage(WM_IDLEUPDATECMDUI, (WPARAM)TRUE);
- pParent->RecalcLayout(); // position and size everything
- pParent->UpdateWindow();
- return TRUE;
- }
- BOOL CALLBACK _AfxPreviewCloseProc(CFrameWnd* pFrameWnd)
- {
- ASSERT_VALID(pFrameWnd);
- CPreviewView* pView = (CPreviewView*) pFrameWnd->GetDlgItem(AFX_IDW_PANE_FIRST);
- ASSERT_KINDOF(CPreviewView, pView);
- pView->OnPreviewClose();
- return FALSE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Preview View
- BEGIN_MESSAGE_MAP(CPreviewView, CScrollView)
- //{{AFX_MSG_MAP(CPreviewView)
- ON_WM_SIZE() // overriding CScrollView
- ON_WM_CREATE()
- ON_COMMAND(AFX_ID_PREVIEW_CLOSE, OnPreviewClose)
- ON_COMMAND(AFX_ID_PREVIEW_NUMPAGE, OnNumPageChange)
- ON_COMMAND(AFX_ID_PREVIEW_NEXT, OnNextPage)
- ON_COMMAND(AFX_ID_PREVIEW_PREV, OnPrevPage)
- ON_COMMAND(AFX_ID_PREVIEW_PRINT, OnPreviewPrint)
- ON_COMMAND(AFX_ID_PREVIEW_ZOOMIN, OnZoomIn)
- ON_COMMAND(AFX_ID_PREVIEW_ZOOMOUT, OnZoomOut)
- ON_UPDATE_COMMAND_UI(AFX_ID_PREVIEW_NUMPAGE, OnUpdateNumPageChange)
- ON_UPDATE_COMMAND_UI(AFX_ID_PREVIEW_NEXT, OnUpdateNextPage)
- ON_UPDATE_COMMAND_UI(AFX_ID_PREVIEW_PREV, OnUpdatePrevPage)
- ON_UPDATE_COMMAND_UI(AFX_ID_PREVIEW_ZOOMIN, OnUpdateZoomIn)
- ON_UPDATE_COMMAND_UI(AFX_ID_PREVIEW_ZOOMOUT, OnUpdateZoomOut)
- ON_WM_VSCROLL()
- ON_WM_HSCROLL()
- ON_WM_LBUTTONDOWN()
- ON_WM_ERASEBKGND()
- ON_WM_SETCURSOR()
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- CPreviewView::CPreviewView()
- {
- 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;
- }
- CPreviewView::PAGE_INFO::PAGE_INFO()
- {
- }
- CPreviewView::~CPreviewView()
- {
- 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 CPreviewView::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- int retVal = CView::OnCreate(lpCreateStruct);
- if (retVal == -1)
- return -1; // if -1 bag out
- CCreateContext* pContext = (CCreateContext*)lpCreateStruct->lpCreateParams;
- m_pOrigView = pContext->m_pLastView;
- ASSERT(m_pOrigView != NULL);
- ASSERT_KINDOF(CView, m_pOrigView);
- return retVal;
- }
- BOOL CPreviewView::SetPrintView(CView* 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)
- {
- SCROLLINFO info;
- info.fMask = SIF_PAGE|SIF_RANGE;
- info.nMin = m_pPreviewInfo->GetMinPage();
- info.nMax = m_pPreviewInfo->GetMaxPage();
- info.nPage = 1;
- if (!SetScrollInfo(SB_VERT, &info, FALSE))
- SetScrollRange(SB_VERT, info.nMin, info.nMax, 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 CPreviewView::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 CPreviewView::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();
- }
- }
- }
- void CPreviewView::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 CPreviewView::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 CPreviewView::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 CPreviewView::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 CPreviewView::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 CPreviewView::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 CPreviewView::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 CPreviewView::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 CPreviewView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
- {
- if (m_nZoomState != ZOOM_OUT)
- CScrollView::OnHScroll(nSBCode, nPos, pScrollBar);
- }
- void CPreviewView::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 CPreviewView::OnNumPageChange()
- {
- ASSERT(m_nPages == 1 || m_nPages == 2);
- m_nPages = 3 - m_nPages; // Toggle between 1 and 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 CPreviewView::OnNextPage()
- {
- SetCurrentPage(m_nCurrentPage + 1, TRUE);
- }
- void CPreviewView::OnPrevPage()
- {
- SetCurrentPage(m_nCurrentPage - 1, TRUE);
- }
- void CPreviewView::OnPreviewPrint()
- {
- 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 CPreviewView::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 CPreviewView::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 CPreviewView::SetZoomState(UINT nNewState, UINT nPage, CPoint point)
- {
- if (m_nZoomState != nNewState)
- {
- m_nZoomState = nNewState;
- DoZoom(nPage, point);
- }
- }
- void CPreviewView::OnZoomIn()
- {
- if (m_nZoomState != ZOOM_IN)
- SetZoomState(m_nZoomState + 1, 0, CPoint(0, 0));
- }
- void CPreviewView::OnZoomOut()
- {
- if (m_nZoomState != ZOOM_OUT)
- SetZoomState(m_nZoomState - 1, 0, CPoint(0, 0));
- }
- // Actual zoom code.
- void CPreviewView::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)
- {
- SCROLLINFO info;
- info.fMask = SIF_PAGE|SIF_RANGE;
- info.nMin = m_pPreviewInfo->GetMinPage();
- info.nMax = m_pPreviewInfo->GetMaxPage();
- info.nPage = 1;
- if (!SetScrollInfo(SB_VERT, &info, FALSE))
- SetScrollRange(SB_VERT, info.nMin, info.nMax, FALSE);
- }
- 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 CPreviewView::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 CPreviewView::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 CPreviewView::OnUpdateNumPageChange(CCmdUI* pCmdUI)
- {
- // set text of button to opposite of current state
- CString text;
- UINT nPages = m_nZoomState == ZOOM_OUT ? m_nPages : m_nZoomOutPages;
- VERIFY(text.LoadString(nPages == 1 ? AFX_IDS_TWOPAGE : AFX_IDS_ONEPAGE));
- pCmdUI->SetText(text);
- // 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));
- }
- void CPreviewView::OnUpdateNextPage(CCmdUI* pCmdUI)
- {
- // enable if not showing last page
- pCmdUI->Enable(m_nCurrentPage+m_nPages-1 < m_pPreviewInfo->GetMaxPage());
- }
- void CPreviewView::OnUpdatePrevPage(CCmdUI* pCmdUI)
- {
- // enable if not showing First page
- pCmdUI->Enable(m_nCurrentPage > m_pPreviewInfo->GetMinPage());
- }
- void CPreviewView::OnUpdateZoomIn(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable(m_nZoomState != ZOOM_IN);
- }
- void CPreviewView::OnUpdateZoomOut(CCmdUI* pCmdUI)
- {
- pCmdUI->Enable(m_nZoomState != ZOOM_OUT);
- }
- BOOL CPreviewView::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;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CPreviewView diagnostics
- #ifdef _DEBUG
- void CPreviewView::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 CPreviewView::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(CPreviewView, CScrollView)
- /////////////////////////////////////////////////////////////////////////////
|