home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / viewprev.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  31KB  |  1,091 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_PRINT_SEG
  14. #pragma code_seg(AFX_PRINT_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. BOOL CALLBACK _AfxPreviewCloseProc(CFrameWnd* pFrameWnd);
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CPrintPreviewState helper structure
  26.  
  27. CPrintPreviewState::CPrintPreviewState()
  28. {
  29.     // set defaults
  30.     nIDMainPane = AFX_IDW_PANE_FIRST;
  31.     dwStates = AFX_CONTROLBAR_MASK(AFX_IDW_STATUS_BAR);
  32.                         // status bar visible if available
  33.     lpfnCloseProc = _AfxPreviewCloseProc;
  34.                         // set frame hook so closing the frame window
  35.                         //  when in preview state will just end the mode
  36.     hMenu = NULL;
  37.     pViewActiveOld = NULL;
  38.     hAccelTable = NULL;
  39. }
  40.  
  41. /////////////////////////////////////////////////////////////////////////////
  42. // CView's OnPrintPreview.  Here to force linkage
  43.  
  44. void CView::OnFilePrintPreview()
  45. {
  46.     // In derived classes, implement special window handling here
  47.     // Be sure to Unhook Frame Window close if hooked.
  48.  
  49.     // must not create this on the frame.  Must outlive this function
  50.     CPrintPreviewState* pState = new CPrintPreviewState;
  51.  
  52.     // DoPrintPreview's return value does not necessarily indicate that
  53.     // Print preview succeeded or failed, but rather what actions are necessary
  54.     // at this point.  If DoPrintPreview returns TRUE, it means that
  55.     // OnEndPrintPreview will be (or has already been) called and the
  56.     // pState structure will be/has been deleted.
  57.     // If DoPrintPreview returns FALSE, it means that OnEndPrintPreview
  58.     // WILL NOT be called and that cleanup, including deleting pState
  59.     // must be done here.
  60.  
  61.     if (!DoPrintPreview(AFX_IDD_PREVIEW_TOOLBAR, this,
  62.                             RUNTIME_CLASS(CPreviewView), pState))
  63.     {
  64.         // In derived classes, reverse special window handling here for
  65.         // Preview failure case
  66.  
  67.         TRACE0("Error: DoPrintPreview failed.\n");
  68.         AfxMessageBox(AFX_IDP_COMMAND_FAILURE);
  69.         delete pState;      // preview failed to initialize, delete State now
  70.     }
  71. }
  72.  
  73. BOOL CView::DoPrintPreview(UINT nIDResource, CView* pPrintView,
  74.     CRuntimeClass* pPreviewViewClass, CPrintPreviewState* pState)
  75. {
  76.     ASSERT_VALID_IDR(nIDResource);
  77.     ASSERT_VALID(pPrintView);
  78.     ASSERT(pPreviewViewClass != NULL);
  79.     ASSERT(pPreviewViewClass->IsDerivedFrom(RUNTIME_CLASS(CPreviewView)));
  80.     ASSERT(pState != NULL);
  81.  
  82.     CFrameWnd* pParent = STATIC_DOWNCAST(CFrameWnd, AfxGetMainWnd());
  83.     ASSERT_VALID(pParent);
  84.  
  85.     CCreateContext context;
  86.     context.m_pCurrentFrame = pParent;
  87.     context.m_pCurrentDoc = GetDocument();
  88.     context.m_pLastView = this;
  89.  
  90.     // Create the preview view object
  91.     CPreviewView* pView = (CPreviewView*)pPreviewViewClass->CreateObject();
  92.     if (pView == NULL)
  93.     {
  94.         TRACE0("Error: Failed to create preview view.\n");
  95.         return FALSE;
  96.     }
  97.     ASSERT_KINDOF(CPreviewView, pView);
  98.     pView->m_pPreviewState = pState;        // save pointer
  99.  
  100.     pParent->OnSetPreviewMode(TRUE, pState);    // Take over Frame Window
  101.  
  102.     // Create the toolbar from the dialog resource
  103.     pView->m_pToolBar = new CDialogBar;
  104.     if (!pView->m_pToolBar->Create(pParent, MAKEINTRESOURCE(nIDResource),
  105.         CBRS_TOP, AFX_IDW_PREVIEW_BAR))
  106.     {
  107.         TRACE0("Error: Preview could not create toolbar dialog.\n");
  108.         pParent->OnSetPreviewMode(FALSE, pState);   // restore Frame Window
  109.         delete pView->m_pToolBar;       // not autodestruct yet
  110.         pView->m_pToolBar = NULL;
  111.         pView->m_pPreviewState = NULL;  // do not delete state structure
  112.         delete pView;
  113.         return FALSE;
  114.     }
  115.     pView->m_pToolBar->m_bAutoDelete = TRUE;    // automatic cleanup
  116.  
  117.     // Create the preview view as a child of the App Main Window.  This
  118.     // is a sibling of this view if this is an SDI app.  This is NOT a sibling
  119.     // if this is an MDI app.
  120.  
  121.     if (!pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
  122.         CRect(0,0,0,0), pParent, AFX_IDW_PANE_FIRST, &context))
  123.     {
  124.         TRACE0("Error: couldn't create preview view for frame.\n");
  125.         pParent->OnSetPreviewMode(FALSE, pState);   // restore Frame Window
  126.         pView->m_pPreviewState = NULL;  // do not delete state structure
  127.         delete pView;
  128.         return FALSE;
  129.     }
  130.  
  131.     // Preview window shown now
  132.  
  133.     pState->pViewActiveOld = pParent->GetActiveView();
  134.     CView* pActiveView = pParent->GetActiveFrame()->GetActiveView();
  135.     if (pActiveView != NULL)
  136.         pActiveView->OnActivateView(FALSE, pActiveView, pActiveView);
  137.  
  138.     if (!pView->SetPrintView(pPrintView))
  139.     {
  140.         pView->OnPreviewClose();
  141.         return TRUE;            // signal that OnEndPrintPreview was called
  142.     }
  143.  
  144.     pParent->SetActiveView(pView);  // set active view - even for MDI
  145.  
  146.     // update toolbar and redraw everything
  147.     pView->m_pToolBar->SendMessage(WM_IDLEUPDATECMDUI, (WPARAM)TRUE);
  148.     pParent->RecalcLayout();            // position and size everything
  149.     pParent->UpdateWindow();
  150.  
  151.     return TRUE;
  152. }
  153.  
  154. BOOL CALLBACK _AfxPreviewCloseProc(CFrameWnd* pFrameWnd)
  155. {
  156.     ASSERT_VALID(pFrameWnd);
  157.  
  158.     CPreviewView* pView = (CPreviewView*) pFrameWnd->GetDlgItem(AFX_IDW_PANE_FIRST);
  159.     ASSERT_KINDOF(CPreviewView, pView);
  160.  
  161.     pView->OnPreviewClose();
  162.     return FALSE;
  163. }
  164.  
  165. /////////////////////////////////////////////////////////////////////////////
  166. // Preview View
  167.  
  168. BEGIN_MESSAGE_MAP(CPreviewView, CScrollView)
  169.     //{{AFX_MSG_MAP(CPreviewView)
  170.     ON_WM_SIZE()        // overriding CScrollView
  171.     ON_WM_CREATE()
  172.  
  173.     ON_COMMAND(AFX_ID_PREVIEW_CLOSE, OnPreviewClose)
  174.     ON_COMMAND(AFX_ID_PREVIEW_NUMPAGE, OnNumPageChange)
  175.     ON_COMMAND(AFX_ID_PREVIEW_NEXT, OnNextPage)
  176.     ON_COMMAND(AFX_ID_PREVIEW_PREV, OnPrevPage)
  177.     ON_COMMAND(AFX_ID_PREVIEW_PRINT, OnPreviewPrint)
  178.     ON_COMMAND(AFX_ID_PREVIEW_ZOOMIN, OnZoomIn)
  179.     ON_COMMAND(AFX_ID_PREVIEW_ZOOMOUT, OnZoomOut)
  180.  
  181.     ON_UPDATE_COMMAND_UI(AFX_ID_PREVIEW_NUMPAGE, OnUpdateNumPageChange)
  182.     ON_UPDATE_COMMAND_UI(AFX_ID_PREVIEW_NEXT, OnUpdateNextPage)
  183.     ON_UPDATE_COMMAND_UI(AFX_ID_PREVIEW_PREV, OnUpdatePrevPage)
  184.     ON_UPDATE_COMMAND_UI(AFX_ID_PREVIEW_ZOOMIN, OnUpdateZoomIn)
  185.     ON_UPDATE_COMMAND_UI(AFX_ID_PREVIEW_ZOOMOUT, OnUpdateZoomOut)
  186.  
  187.     ON_WM_VSCROLL()
  188.     ON_WM_HSCROLL()
  189.     ON_WM_LBUTTONDOWN()
  190.     ON_WM_ERASEBKGND()
  191.     ON_WM_SETCURSOR()
  192.     //}}AFX_MSG_MAP
  193. END_MESSAGE_MAP()
  194.  
  195. CPreviewView::CPreviewView()
  196. {
  197.     m_pPrintView = NULL;
  198.     m_pOrigView = NULL;
  199.     m_pPreviewInfo = NULL;
  200.     m_pPreviewDC = NULL;
  201.     m_pPreviewState = NULL;
  202.     m_hMagnifyCursor = NULL;
  203.     m_bPageNumDisplayed = FALSE;
  204.     m_nZoomState = ZOOM_OUT;
  205.  
  206.     // default to pointing to embedded array.  Allows for 2 pages
  207.     m_pPageInfo = m_pageInfoArray;
  208.     m_nMaxPages = 2;
  209.  
  210.     // initialize CScrollView members
  211.     m_bCenter = TRUE;                   // Center Zoomed output in Scrollview
  212.     m_nMapMode = MM_TEXT;
  213. }
  214.  
  215. CPreviewView::PAGE_INFO::PAGE_INFO()
  216. {
  217. }
  218.  
  219. CPreviewView::~CPreviewView()
  220. {
  221.     m_dcPrint.Detach();         // print DC is deleted by CPrintInfo destructor
  222.  
  223.     delete m_pPreviewInfo;      // get rid of preview info
  224.     delete m_pPreviewState;     // Get rid of preview state
  225.     delete m_pPreviewDC;        // Get rid of preview DC object
  226.  
  227.     if (m_hMagnifyCursor != NULL)
  228.     {
  229.         // make sure that m_hMagnifyCursor isn't the current cursor when we destroy it
  230.         ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
  231.         DestroyCursor(m_hMagnifyCursor);
  232.     }
  233. }
  234.  
  235. int CPreviewView::OnCreate(LPCREATESTRUCT lpCreateStruct)
  236. {
  237.     int retVal = CView::OnCreate(lpCreateStruct);
  238.     if (retVal == -1)
  239.         return -1;      // if -1 bag out
  240.  
  241.     CCreateContext* pContext = (CCreateContext*)lpCreateStruct->lpCreateParams;
  242.  
  243.     m_pOrigView = pContext->m_pLastView;
  244.     ASSERT(m_pOrigView != NULL);
  245.     ASSERT_KINDOF(CView, m_pOrigView);
  246.  
  247.     return retVal;
  248. }
  249.  
  250. BOOL CPreviewView::SetPrintView(CView* pPrintView)
  251. {
  252.     ASSERT_VALID(pPrintView);
  253.  
  254.     m_pPrintView = pPrintView;
  255.  
  256.     // allocate preview info
  257.     m_pPreviewInfo = new CPrintInfo;
  258.     m_pPreviewInfo->m_pPD->SetHelpID(AFX_IDD_PRINTSETUP);
  259.     m_pPreviewInfo->m_pPD->m_pd.Flags |= PD_PRINTSETUP;
  260.     m_pPreviewInfo->m_pPD->m_pd.Flags &= ~PD_RETURNDC;
  261.  
  262.     m_pPreviewInfo->m_bPreview = TRUE;  // signal that this is preview
  263.     ASSERT(m_pPreviewInfo->m_pPD != NULL);
  264.  
  265.     m_pPreviewDC = new CPreviewDC;      // must be created before any
  266.                                         // possible error returns
  267.  
  268.     if (!m_pPrintView->OnPreparePrinting(m_pPreviewInfo))
  269.         return FALSE;
  270.  
  271. #ifdef _DEBUG
  272.     if (m_pPreviewInfo->m_pPD->m_pd.hDC == NULL)
  273.     {
  274.         TRACE0("Error: hDC not set for printing --\n");
  275.         TRACE0("\tDid you remember to call DoPreparePrinting?\n");
  276.         ASSERT(FALSE);      // common mistake gets trapped here
  277.     }
  278. #endif //_DEBUG
  279.  
  280.     m_dcPrint.Attach(m_pPreviewInfo->m_pPD->m_pd.hDC);
  281.     m_pPreviewDC->SetAttribDC(m_pPreviewInfo->m_pPD->m_pd.hDC);
  282.     m_pPreviewDC->m_bPrinting = TRUE;
  283.     m_dcPrint.m_bPrinting = TRUE;
  284.  
  285.     m_dcPrint.SaveDC();     // Save pristine state of DC
  286.  
  287.     HDC hDC = ::GetDC(m_hWnd);
  288.     m_pPreviewDC->SetOutputDC(hDC);
  289.     m_pPrintView->OnBeginPrinting(m_pPreviewDC, m_pPreviewInfo);
  290.     m_pPreviewDC->ReleaseOutputDC();
  291.     ::ReleaseDC(m_hWnd, hDC);
  292.  
  293.     m_dcPrint.RestoreDC(-1);    // restore to untouched state
  294.  
  295.     // Get Pixels per inch from Printer
  296.     m_sizePrinterPPI.cx = m_dcPrint.GetDeviceCaps(LOGPIXELSX);
  297.     m_sizePrinterPPI.cy = m_dcPrint.GetDeviceCaps(LOGPIXELSY);
  298.  
  299.     m_nPages = m_pPreviewInfo->m_nNumPreviewPages;
  300.     if (m_nPages == 0)
  301.         m_nPages = 1;
  302.     else if (m_nPages > m_nMaxPages)
  303.         m_nPages = m_nMaxPages;     // Sanity Check!
  304.  
  305.     m_nZoomOutPages = m_nPages;
  306.  
  307.     SetScrollSizes(MM_TEXT, CSize(1, 1));   // initialize mapping mode only
  308.  
  309.     if (m_pPreviewInfo->GetMaxPage() < 0x8000 &&
  310.         m_pPreviewInfo->GetMaxPage() - m_pPreviewInfo->GetMinPage() <= 32767U)
  311.     {
  312.         SCROLLINFO info;
  313.         info.fMask = SIF_PAGE|SIF_RANGE;
  314.         info.nMin = m_pPreviewInfo->GetMinPage();
  315.         info.nMax = m_pPreviewInfo->GetMaxPage();
  316.         info.nPage = 1;
  317.         if (!SetScrollInfo(SB_VERT, &info, FALSE))
  318.             SetScrollRange(SB_VERT, info.nMin, info.nMax, FALSE);
  319.     }
  320.     else
  321.         ShowScrollBar(SB_VERT, FALSE);      // if no range specified, or too
  322.                                             // large don't show
  323.  
  324.     SetCurrentPage(m_pPreviewInfo->m_nCurPage, TRUE);
  325.     return TRUE;
  326. }
  327.  
  328. void CPreviewView::OnSize(UINT nType, int cx, int cy)
  329. {
  330.     // CScrollView handles everything if zoomed in.
  331.     if (m_nZoomState == ZOOM_OUT)
  332.     {
  333.         // Force recalc of scale ratios on next draw
  334.         for (UINT i = 0; i < m_nMaxPages; i++)
  335.             m_pPageInfo[i].sizeScaleRatio.cx = 0;           // zero scale ratios
  336.  
  337.         CView::OnSize(nType, cx, cy);       // No scroll functionality
  338.     }
  339.     else
  340.     {
  341.         // adjust scroll size to size of page
  342.         m_pageDev.cx = cx;
  343.         m_pageDev.cy = cy;
  344.         m_lineDev.cx = cx / 10;
  345.         m_lineDev.cy = cy / 10;
  346.         CScrollView::OnSize(nType, cx, cy);
  347.     }
  348. }
  349.  
  350. void CPreviewView::OnActivateView(BOOL bActivate, CView*, CView*)
  351. {
  352.     if (bActivate)
  353.     {
  354.         CWnd* pFocusWnd = GetFocus();
  355.         if (pFocusWnd == NULL ||
  356.             (m_pToolBar != NULL && !m_pToolBar->IsChild(pFocusWnd)))
  357.         {
  358.             // focus is not already on a toolbar button - set it to one
  359.             m_pToolBar->GetDlgItem(AFX_ID_PREVIEW_PRINT)->SetFocus();
  360.         }
  361.     }
  362. }
  363.  
  364. void CPreviewView::OnPreviewClose()
  365. {
  366.     m_pToolBar->DestroyWindow();
  367.     m_pToolBar = NULL;
  368.  
  369.     m_pPreviewInfo->m_nCurPage = m_nCurrentPage;
  370.     m_pOrigView->OnEndPrintPreview(m_pPreviewDC, m_pPreviewInfo,
  371.                                     CPoint(0, 0), this);
  372. }
  373.  
  374. #define PREVIEW_MARGIN  8
  375. #define PREVIEW_PAGEGAP 8
  376.  
  377. // Return is actually the fraction cx/cy. Simply using CSize for convenience
  378. CSize CPreviewView::CalcScaleRatio(CSize screenSize, CSize actualSize)
  379. {
  380.     // Test ratio based on vertical dimension to see if it is the one to use
  381.     int nNum = screenSize.cy;
  382.     int nDen = actualSize.cy;
  383.  
  384.     // If scaled width too large, choose width as primary dimension
  385.     if (MulDiv(actualSize.cx, nNum, nDen) > screenSize.cx)
  386.     {
  387.         // wrong ratio--base on width
  388.         nNum = screenSize.cx;
  389.         nDen = actualSize.cx;
  390.     }
  391.     CSize ratio(nNum, nDen);
  392.     return ratio;
  393. }
  394.  
  395. // Position Page...
  396. // Generate a Screen MM_TEXT rectangle to enclose each page.  Dimensions
  397. // of the rectangle must be 1 pixel Above and Left of the top/left corner
  398. // of the page and the rectangle width and height must be THREE pixels
  399. // larger than page in order to provide the correct placement of the
  400. // two pixel border.
  401. //
  402. // This routine is called once for each page with the preview DC set up for
  403. // that page
  404.  
  405. void CPreviewView::PositionPage(UINT nPage)
  406. {
  407.     CSize windowSize = CalcPageDisplaySize();
  408.  
  409.     VERIFY(m_dcPrint.Escape(GETPHYSPAGESIZE, 0, NULL,
  410.             (LPVOID)&m_pPageInfo[nPage].sizeUnscaled));
  411.  
  412.     CSize* pSize = &m_pPageInfo[nPage].sizeUnscaled;
  413.  
  414.     // Convert page size to screen coordinates
  415.     pSize->cx = MulDiv(pSize->cx, afxData.cxPixelsPerInch, m_sizePrinterPPI.cx);
  416.     pSize->cy = MulDiv(pSize->cy, afxData.cyPixelsPerInch, m_sizePrinterPPI.cy);
  417.  
  418.     m_pPageInfo[nPage].sizeZoomOutRatio = CalcScaleRatio(windowSize, *pSize);
  419.  
  420.     SetScaledSize(nPage);
  421. }
  422.  
  423. CSize CPreviewView::CalcPageDisplaySize()
  424.     // calculate the current page size
  425.     //  set 'm_nSecondPageOffset' to start of second page
  426.     // return size of current page less margins
  427. {
  428.     CSize windowSize, scrollSize;
  429.     GetTrueClientSize(windowSize, scrollSize);
  430.  
  431.     // subtract out vertical scrollbar if zoomed out and page range is known
  432.     // and there is more than one page.
  433.     if (m_nZoomState == ZOOM_OUT && (m_pPreviewInfo->GetMaxPage() != 0xffff) &&
  434.         (m_pPreviewInfo->GetMaxPage() - m_pPreviewInfo->GetMinPage() != 0))
  435.         windowSize.cx -= scrollSize.cx;
  436.  
  437.     m_nSecondPageOffset = (windowSize.cx - PREVIEW_MARGIN) / 2;
  438.  
  439.     windowSize.cx = (m_nPages == 2) ? (windowSize.cx - 3*PREVIEW_MARGIN) / 2 :
  440.                                     windowSize.cx - 2*PREVIEW_MARGIN;
  441.  
  442.     windowSize.cy -= 2*PREVIEW_MARGIN;
  443.     return windowSize;
  444. }
  445.  
  446. void CPreviewView::SetScaledSize(UINT nPage)
  447. {
  448.     CSize* pSize = &m_pPageInfo[nPage].sizeUnscaled;
  449.     CSize* pRatio = &m_pPageInfo[nPage].sizeScaleRatio;
  450.     CSize* pZoomOutRatio = &m_pPageInfo[nPage].sizeZoomOutRatio;
  451.     CSize windowSize = CalcPageDisplaySize();
  452.     BOOL bPaperLarger = pZoomOutRatio->cx < pZoomOutRatio->cy;
  453.         // whether the paper is larger than the screen, or vice versa
  454.  
  455.     switch (m_nZoomState)
  456.     {
  457.     case ZOOM_OUT:
  458.         *pRatio = *pZoomOutRatio;
  459.         break;
  460.  
  461.     case ZOOM_MIDDLE:
  462.         // the middle zoom state is a ratio between cx/cy and
  463.         // 1/1 (or cy/cy).  It is, therefore:
  464.         //
  465.         // (cx + cy)/2
  466.         // -----------
  467.         //     cy
  468.         //
  469.         // if the paper is larger than the screen, or
  470.         //
  471.         // (3*cx - cy)/2
  472.         // -------------
  473.         //      cy
  474.         //
  475.         // if the paper is smaller than the screen.
  476.         if (bPaperLarger)
  477.         {
  478.             pRatio->cy = pZoomOutRatio->cy;
  479.             pRatio->cx = (pZoomOutRatio->cx + pRatio->cy) / 2;
  480.         }
  481.         else
  482.         {
  483.             pRatio->cy = pZoomOutRatio->cy;
  484.             pRatio->cx = (3*pZoomOutRatio->cx - pRatio->cy) / 2;
  485.         }
  486.         break;
  487.  
  488.     case ZOOM_IN:
  489.         if (bPaperLarger)
  490.             pRatio->cx = pRatio->cy = 1;
  491.         else
  492.         {
  493.             // if the paper is smaller than the screen space we're displaying
  494.             // it in, then using a ratio of 1/1 will result in a smaller image
  495.             // on the screen, not a larger one. To get a larger image in this
  496.             // case we double the zoom out ratio.
  497.             pRatio->cy = pZoomOutRatio->cy;
  498.             pRatio->cx = 2*pZoomOutRatio->cx - pZoomOutRatio->cy;
  499.         }
  500.         break;
  501.  
  502.     default:
  503.         ASSERT(FALSE);
  504.     }
  505.  
  506.     // Convert to scaled size
  507.     CSize scaledSize;
  508.     scaledSize.cx = MulDiv(pSize->cx, pRatio->cx, pRatio->cy);
  509.     scaledSize.cy = MulDiv(pSize->cy, pRatio->cx, pRatio->cy);
  510.  
  511.     CRect* pRect = &m_pPageInfo[nPage].rectScreen;
  512.     pRect->SetRect(PREVIEW_MARGIN, PREVIEW_MARGIN,
  513.                    scaledSize.cx + PREVIEW_MARGIN + 3,
  514.                    scaledSize.cy + PREVIEW_MARGIN + 3);
  515.  
  516.     if (m_nZoomState == ZOOM_OUT)
  517.     {
  518.         pRect->OffsetRect((windowSize.cx - pRect->Size().cx) / 2 - 1,
  519.                           (windowSize.cy - pRect->Size().cy) / 2 - 1);
  520.  
  521.         if (nPage == 1)
  522.             pRect->OffsetRect(m_nSecondPageOffset, 0);
  523.     }
  524.     else
  525.     {
  526.         // set up scroll size
  527.  
  528.         SetScrollSizes(MM_TEXT, pRect->Size() +
  529.                 CSize(PREVIEW_MARGIN * 2, PREVIEW_MARGIN * 2), windowSize);
  530.     }
  531. }
  532.  
  533. // Only use the PrepareDC from CScrollView if we are zoomed in
  534. void CPreviewView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
  535. {
  536.     ASSERT_VALID(pDC);
  537.  
  538.     if (m_nZoomState == ZOOM_OUT)
  539.         CView::OnPrepareDC(pDC, pInfo);
  540.     else if (m_pPageInfo[0].sizeScaleRatio.cx != 0)
  541.         CScrollView::OnPrepareDC(pDC, pInfo);
  542. }
  543.  
  544. BOOL CPreviewView::OnEraseBkgnd(CDC* pDC)
  545. {
  546.     ASSERT_VALID(pDC);
  547.  
  548.     // Fill background with APPWORKSPACE
  549.     CBrush backBrush(GetSysColor(COLOR_APPWORKSPACE));
  550.     CBrush* pOldBrush = pDC->SelectObject(&backBrush);
  551.     CRect rect;
  552.     pDC->GetClipBox(&rect);     // Erase the area needed
  553.  
  554.     pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
  555.     pDC->SelectObject(pOldBrush);
  556.     return TRUE;
  557. }
  558.  
  559. void CPreviewView::OnDraw(CDC* pDC)
  560. {
  561.     ASSERT_VALID(pDC);
  562.  
  563.     // don't do anything if not fully initialized
  564.     if (m_pPrintView == NULL || m_dcPrint.m_hDC == NULL)
  565.         return;
  566.  
  567.     CPoint ViewportOrg = pDC->GetViewportOrg();
  568.  
  569.     CPen rectPen;
  570.     rectPen.CreatePen(PS_SOLID, 2, GetSysColor(COLOR_WINDOWFRAME));
  571.     CPen shadowPen;
  572.     shadowPen.CreatePen(PS_SOLID, 3, GetSysColor(COLOR_BTNSHADOW));
  573.  
  574.     m_pPreviewInfo->m_bContinuePrinting = TRUE;     // do this once each paint
  575.  
  576.     for (UINT nPage = 0; nPage < m_nPages; nPage++)
  577.     {
  578.         int nSavedState = m_dcPrint.SaveDC();       // Save pristine state of DC
  579.  
  580.         // Use paint DC for print preview output
  581.         m_pPreviewDC->SetOutputDC(pDC->GetSafeHdc());
  582.  
  583.         m_pPreviewInfo->m_nCurPage = m_nCurrentPage + nPage;
  584.  
  585.         // Only call PrepareDC if within page range, otherwise use default
  586.         // rect to draw page rectangle
  587.         if (m_nCurrentPage + nPage <= m_pPreviewInfo->GetMaxPage())
  588.             m_pPrintView->OnPrepareDC(m_pPreviewDC, m_pPreviewInfo);
  589.  
  590.         // Set up drawing rect to entire page (in logical coordinates)
  591.         m_pPreviewInfo->m_rectDraw.SetRect(0, 0,
  592.             m_pPreviewDC->GetDeviceCaps(HORZRES),
  593.             m_pPreviewDC->GetDeviceCaps(VERTRES));
  594.         m_pPreviewDC->DPtoLP(&m_pPreviewInfo->m_rectDraw);
  595.  
  596.         // Draw empty page on screen
  597.  
  598.         pDC->SaveDC();          // save the output dc state
  599.  
  600.         CSize* pRatio = &m_pPageInfo[nPage].sizeScaleRatio;
  601.         CRect* pRect = &m_pPageInfo[nPage].rectScreen;
  602.  
  603.         if (pRatio->cx == 0)
  604.         {   // page position has not been determined
  605.             PositionPage(nPage);    // compute page position
  606.             if (m_nZoomState != ZOOM_OUT)
  607.                 ViewportOrg = -GetDeviceScrollPosition();
  608.         }
  609.  
  610.         pDC->SetMapMode(MM_TEXT);   // Page Rectangle is in screen device coords
  611.         pDC->SetViewportOrg(ViewportOrg);
  612.         pDC->SetWindowOrg(0, 0);
  613.  
  614.         pDC->SelectStockObject(HOLLOW_BRUSH);
  615.         pDC->SelectObject(&rectPen);
  616.         pDC->Rectangle(pRect);
  617.  
  618.         pDC->SelectObject(&shadowPen);
  619.  
  620.         pDC->MoveTo(pRect->right + 1, pRect->top + 3);
  621.         pDC->LineTo(pRect->right + 1, pRect->bottom + 1);
  622.         pDC->MoveTo(pRect->left + 3, pRect->bottom + 1);
  623.         pDC->LineTo(pRect->right + 1, pRect->bottom + 1);
  624.  
  625.         // erase background to white (most paper is white)
  626.         CRect rectFill = *pRect;
  627.         rectFill.left += 1;
  628.         rectFill.top += 1;
  629.         rectFill.right -= 2;
  630.         rectFill.bottom -= 2;
  631.         ::FillRect(pDC->m_hDC, rectFill, (HBRUSH)GetStockObject(WHITE_BRUSH));
  632.  
  633.         pDC->RestoreDC(-1);     // restore to synchronized state
  634.  
  635.         if (!m_pPreviewInfo->m_bContinuePrinting ||
  636.                 m_nCurrentPage + nPage > m_pPreviewInfo->GetMaxPage())
  637.         {
  638.             m_pPreviewDC->ReleaseOutputDC();
  639.             m_dcPrint.RestoreDC(nSavedState);   // restore to untouched state
  640.  
  641.             // if the first page is not displayable, back up one page
  642.             // but never go below 1
  643.             if (nPage == 0 && m_nCurrentPage > 1)
  644.                 SetCurrentPage(m_nCurrentPage - 1, TRUE);
  645.             break;
  646.         }
  647.  
  648.         // Display page number
  649.         OnDisplayPageNumber(m_nCurrentPage, nPage + 1);
  650.  
  651.         // Set scale ratio for this page
  652.         m_pPreviewDC->SetScaleRatio(pRatio->cx, pRatio->cy);
  653.  
  654.         CSize PrintOffset;
  655.         VERIFY(m_pPreviewDC->Escape(GETPRINTINGOFFSET, 0, NULL, (LPVOID)&PrintOffset));
  656.         m_pPreviewDC->PrinterDPtoScreenDP((LPPOINT)&PrintOffset);
  657.         PrintOffset += (CSize)pRect->TopLeft();
  658.         PrintOffset += CSize(1, 1);
  659.         PrintOffset += (CSize)ViewportOrg;  // For Scrolling
  660.  
  661.         m_pPreviewDC->SetTopLeftOffset(PrintOffset);
  662.  
  663.         m_pPreviewDC->ClipToPage();
  664.         m_pPrintView->OnPrint(m_pPreviewDC, m_pPreviewInfo);
  665.  
  666.         m_pPreviewDC->ReleaseOutputDC();
  667.  
  668.         m_dcPrint.RestoreDC(nSavedState);   // restore to untouched state
  669.  
  670.     }
  671.  
  672.     rectPen.DeleteObject();
  673.     shadowPen.DeleteObject();
  674. }
  675.  
  676. void CPreviewView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  677. {
  678.     if (m_nZoomState != ZOOM_OUT)
  679.         CScrollView::OnHScroll(nSBCode, nPos, pScrollBar);
  680. }
  681.  
  682. void CPreviewView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  683. {
  684.     if (m_nZoomState != ZOOM_OUT)
  685.     {
  686.         CScrollView::OnVScroll(nSBCode, nPos, pScrollBar);
  687.         return;
  688.     }
  689.  
  690.     switch (nSBCode)
  691.     {
  692.     case SB_BOTTOM:
  693.         SetCurrentPage(m_pPreviewInfo->GetMaxPage(), TRUE);
  694.         break;
  695.  
  696.     case SB_TOP:
  697.         SetCurrentPage(m_pPreviewInfo->GetMinPage(), TRUE);
  698.         break;
  699.  
  700.     case SB_PAGEDOWN:
  701.         SetCurrentPage(m_nCurrentPage +
  702.             (m_pPreviewInfo->GetMaxPage() - m_pPreviewInfo->GetMinPage() + 9) / 10, TRUE);
  703.         break;
  704.  
  705.     case SB_PAGEUP:
  706.         SetCurrentPage(m_nCurrentPage -
  707.             (m_pPreviewInfo->GetMaxPage() - m_pPreviewInfo->GetMinPage() + 9) / 10, TRUE);
  708.         break;
  709.  
  710.     case SB_LINEDOWN:
  711.         SetCurrentPage(m_nCurrentPage + 1, TRUE);
  712.         break;
  713.  
  714.     case SB_LINEUP:
  715.         SetCurrentPage(m_nCurrentPage - 1, TRUE);
  716.         break;
  717.  
  718.     case SB_THUMBPOSITION:
  719.         SetCurrentPage(nPos, TRUE);
  720.         break;
  721.     }
  722. }
  723.  
  724. void CPreviewView::OnNumPageChange()
  725. {
  726.     ASSERT(m_nPages == 1 || m_nPages == 2);
  727.     m_nPages = 3 - m_nPages;    // Toggle between 1 and 2
  728.     AfxGetApp()->m_nNumPreviewPages = m_nPages;
  729.     m_nZoomOutPages = m_nPages;
  730.  
  731.     // Just do this to set the status correctly and invalidate
  732.     SetCurrentPage(m_nCurrentPage, TRUE);
  733. }
  734.  
  735. void CPreviewView::OnNextPage()
  736. {
  737.     SetCurrentPage(m_nCurrentPage + 1, TRUE);
  738. }
  739.  
  740. void CPreviewView::OnPrevPage()
  741. {
  742.     SetCurrentPage(m_nCurrentPage - 1, TRUE);
  743. }
  744.  
  745. void CPreviewView::OnPreviewPrint()
  746. {
  747.     OnPreviewClose();               // force close of Preview
  748.  
  749.     // cause print (can be overridden by catching the command)
  750.     CWnd* pMainWnd = AfxGetThread()->m_pMainWnd;
  751.     ASSERT_VALID(pMainWnd);
  752.     pMainWnd->SendMessage(WM_COMMAND, ID_FILE_PRINT);
  753. }
  754.  
  755. // Finds page pointed to and convert to 1:1 screen device units
  756. BOOL CPreviewView::FindPageRect(CPoint& point, UINT& nPage)
  757. {
  758.     if (m_nZoomState != ZOOM_OUT)
  759.         point += (CSize)GetDeviceScrollPosition();
  760.  
  761.     for (nPage = 0; nPage < m_nPages; nPage++)
  762.     {
  763.         if (m_pPageInfo[nPage].rectScreen.PtInRect(point))
  764.         {
  765.             // adjust point for page position
  766.             point -= (CSize)m_pPageInfo[nPage].rectScreen.TopLeft();
  767.  
  768.             // convert to 1:1
  769.             point.x = MulDiv(point.x, m_pPageInfo[nPage].sizeScaleRatio.cy,
  770.                                     m_pPageInfo[nPage].sizeScaleRatio.cx);
  771.             point.y = MulDiv(point.y, m_pPageInfo[nPage].sizeScaleRatio.cy,
  772.                                     m_pPageInfo[nPage].sizeScaleRatio.cx);
  773.             return TRUE;
  774.         }
  775.     }
  776.     return FALSE;
  777. }
  778.  
  779.  
  780. void CPreviewView::OnLButtonDown(UINT, CPoint point)
  781. {
  782.     UINT nPage;
  783.     if (!FindPageRect(point, nPage))
  784.         return;                         // Didn't click on a page
  785.  
  786.     // Set new zoom state
  787.     SetZoomState((m_nZoomState == ZOOM_IN) ? ZOOM_OUT : m_nZoomState + 1,
  788.                                 nPage, point);
  789. }
  790.  
  791. void CPreviewView::SetZoomState(UINT nNewState, UINT nPage, CPoint point)
  792. {
  793.     if (m_nZoomState != nNewState)
  794.     {
  795.         m_nZoomState = nNewState;
  796.         DoZoom(nPage, point);
  797.     }
  798. }
  799.  
  800. void CPreviewView::OnZoomIn()
  801. {
  802.     if (m_nZoomState != ZOOM_IN)
  803.         SetZoomState(m_nZoomState + 1, 0, CPoint(0, 0));
  804. }
  805.  
  806. void CPreviewView::OnZoomOut()
  807. {
  808.     if (m_nZoomState != ZOOM_OUT)
  809.         SetZoomState(m_nZoomState - 1, 0, CPoint(0, 0));
  810. }
  811.  
  812. // Actual zoom code.
  813. void CPreviewView::DoZoom(UINT nPage, CPoint point)
  814. {
  815.     if (m_nZoomState == ZOOM_OUT)
  816.     {
  817.         // taking over scroll bars
  818.         m_nPages = m_nZoomOutPages;
  819.         ShowScrollBar(SB_HORZ, FALSE);      //hide the horizontal bar
  820.  
  821.         BOOL bShowBar = m_pPreviewInfo->GetMaxPage() < 0x8000 &&
  822.             m_pPreviewInfo->GetMaxPage() -
  823.             m_pPreviewInfo->GetMinPage() <= 32767U;
  824.  
  825.         ShowScrollBar(SB_VERT, bShowBar);       //Show the vertical bar
  826.  
  827.         if (bShowBar)
  828.         {
  829.             SCROLLINFO info;
  830.             info.fMask = SIF_PAGE|SIF_RANGE;
  831.             info.nMin = m_pPreviewInfo->GetMinPage();
  832.             info.nMax = m_pPreviewInfo->GetMaxPage();
  833.             info.nPage = 1;
  834.             if (!SetScrollInfo(SB_VERT, &info, FALSE))
  835.                 SetScrollRange(SB_VERT, info.nMin, info.nMax, FALSE);
  836.         }
  837.  
  838.         SetCurrentPage(m_nCurrentPage, TRUE);
  839.     }
  840.     else
  841.     {
  842.         m_nPages = 1;       // only one page in zoomed states
  843.  
  844.         m_pPageInfo[0].sizeZoomOutRatio = m_pPageInfo[nPage].sizeZoomOutRatio;
  845.         m_pPageInfo[0].sizeUnscaled = m_pPageInfo[nPage].sizeUnscaled;
  846.  
  847.         // Sets the printer page
  848.         SetCurrentPage(m_nCurrentPage + nPage, FALSE);
  849.  
  850.         SetScaledSize(0);
  851.  
  852.         CSize* pRatio = &m_pPageInfo[nPage].sizeScaleRatio;
  853.  
  854.         // convert Hit Point from screen 1:1
  855.         point.x = MulDiv(point.x, pRatio->cx, pRatio->cy);
  856.         point.y = MulDiv(point.y, pRatio->cx, pRatio->cy);
  857.  
  858.         // Adjust point for page position
  859.         point += (CSize)m_pPageInfo[0].rectScreen.TopLeft();
  860.  
  861.         // Scroll to center
  862.         CenterOnPoint(point);
  863.     }
  864. }
  865.  
  866. void CPreviewView::SetCurrentPage(UINT nPage, BOOL bClearRatios)
  867. {
  868.     m_nCurrentPage = nPage;
  869.     if (m_nCurrentPage > m_pPreviewInfo->GetMaxPage())
  870.         m_nCurrentPage = m_pPreviewInfo->GetMaxPage();
  871.     if (m_nCurrentPage < m_pPreviewInfo->GetMinPage())
  872.         m_nCurrentPage = m_pPreviewInfo->GetMinPage();
  873.  
  874.  
  875.     if (m_nZoomState == ZOOM_OUT)
  876.         SetScrollPos(SB_VERT, m_nCurrentPage);
  877.  
  878.     if (bClearRatios)
  879.     {
  880.         // Force Recalc of layout
  881.         for (UINT i = 0; i < m_nMaxPages; i++)
  882.             m_pPageInfo[i].sizeScaleRatio.cx = 0;           // zero scale ratios
  883.     }
  884.  
  885.     Invalidate(TRUE);
  886. }
  887.  
  888. void CPreviewView::OnDisplayPageNumber(UINT nPage, UINT nPagesDisplayed)
  889. {
  890.     UINT nEndPage = nPage + nPagesDisplayed - 1;
  891.  
  892.     CFrameWnd* pParent = (CFrameWnd*)AfxGetThread()->m_pMainWnd;
  893.     ASSERT_VALID(pParent);
  894.     ASSERT_KINDOF(CFrameWnd, pParent);
  895.  
  896.     int nSubString = (nPagesDisplayed == 1) ? 0 : 1;
  897.  
  898.     CString s;
  899.     if (AfxExtractSubString(s, m_pPreviewInfo->m_strPageDesc, nSubString))
  900.     {
  901.         TCHAR szBuf[80];
  902.         if (nSubString == 0)
  903.             wsprintf(szBuf, s, nPage);
  904.         else
  905.             wsprintf(szBuf, s, nPage, nEndPage);
  906.         pParent->SendMessage(WM_SETMESSAGESTRING, 0, (LPARAM)(LPVOID)szBuf);
  907.     }
  908.     else
  909.     {
  910.         TRACE1("Malformed Page Description string. Could not get string %d.\n",
  911.             nSubString);
  912.     }
  913. }
  914.  
  915.  
  916. void CPreviewView::OnUpdateNumPageChange(CCmdUI* pCmdUI)
  917. {
  918.     // set text of button to opposite of current state
  919.     CString text;
  920.     UINT nPages = m_nZoomState == ZOOM_OUT ? m_nPages : m_nZoomOutPages;
  921.     VERIFY(text.LoadString(nPages == 1 ? AFX_IDS_TWOPAGE : AFX_IDS_ONEPAGE));
  922.     pCmdUI->SetText(text);
  923.  
  924.     // enable it only if valid to display another page and not zoomed
  925.     pCmdUI->Enable(m_nZoomState == ZOOM_OUT && m_nMaxPages != 1 &&
  926.         (m_pPreviewInfo->GetMaxPage() > 1 || m_nPages > 1));
  927. }
  928.  
  929. void CPreviewView::OnUpdateNextPage(CCmdUI* pCmdUI)
  930. {
  931.     // enable if not showing last page
  932.     pCmdUI->Enable(m_nCurrentPage+m_nPages-1 < m_pPreviewInfo->GetMaxPage());
  933. }
  934.  
  935. void CPreviewView::OnUpdatePrevPage(CCmdUI* pCmdUI)
  936. {
  937.     // enable if not showing First page
  938.     pCmdUI->Enable(m_nCurrentPage > m_pPreviewInfo->GetMinPage());
  939. }
  940.  
  941. void CPreviewView::OnUpdateZoomIn(CCmdUI* pCmdUI)
  942. {
  943.     pCmdUI->Enable(m_nZoomState != ZOOM_IN);
  944. }
  945.  
  946. void CPreviewView::OnUpdateZoomOut(CCmdUI* pCmdUI)
  947. {
  948.     pCmdUI->Enable(m_nZoomState != ZOOM_OUT);
  949. }
  950.  
  951. BOOL CPreviewView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  952. {
  953.     if (nHitTest != HTCLIENT)
  954.         return CScrollView::OnSetCursor(pWnd, nHitTest, message);
  955.  
  956.     CPoint point;
  957.     ::GetCursorPos(&point);
  958.     ScreenToClient(&point);     // client coordinates of mouse position
  959.  
  960.     UINT nPage;
  961.     if (m_nZoomState != ZOOM_IN && FindPageRect(point, nPage))
  962.     {                       // On a page and not zoomed all the way in
  963.         if (m_hMagnifyCursor == NULL)
  964.         {
  965.             HINSTANCE hInst = AfxFindResourceHandle(
  966.                 MAKEINTRESOURCE(AFX_IDC_MAGNIFY), RT_GROUP_CURSOR);
  967.             m_hMagnifyCursor = ::LoadCursor(hInst,
  968.                 MAKEINTRESOURCE(AFX_IDC_MAGNIFY));
  969.         }
  970.         ::SetCursor(m_hMagnifyCursor);
  971.     }
  972.     else
  973.     {
  974.         ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
  975.     }
  976.     return 0;
  977. }
  978.  
  979. /////////////////////////////////////////////////////////////////////////////
  980. // CPreviewView diagnostics
  981.  
  982. #ifdef _DEBUG
  983. void CPreviewView::AssertValid() const
  984. {
  985.     CView::AssertValid();
  986.     ASSERT_VALID(&m_dcPrint);
  987.     if (m_pPreviewDC != NULL)
  988.         ASSERT_VALID(m_pPreviewDC);
  989.  
  990.     switch (m_nZoomState)
  991.     {
  992.     case ZOOM_OUT:
  993.     case ZOOM_IN:
  994.     case ZOOM_MIDDLE:
  995.         break;
  996.     default:
  997.         ASSERT(FALSE); // unknown zoom state
  998.     }
  999.  
  1000.     switch (m_nMapMode)
  1001.     {
  1002.     case MM_TEXT:
  1003.     case MM_LOMETRIC:
  1004.     case MM_HIMETRIC:
  1005.     case MM_LOENGLISH:
  1006.     case MM_HIENGLISH:
  1007.     case MM_TWIPS:
  1008.     case MM_ISOTROPIC:
  1009.     case MM_ANISOTROPIC:
  1010.         break;
  1011.     default:
  1012.         ASSERT(FALSE); // unknown mapping mode
  1013.     }
  1014. }
  1015.  
  1016. void CPreviewView::Dump(CDumpContext& dc) const
  1017. {
  1018.     CView::Dump(dc);
  1019.  
  1020.     dc << "m_pPrintView = " << m_pPrintView;
  1021.     dc << "\nm_pOrigView = " << m_pOrigView;
  1022.     dc << "\nm_bPageNumDisplayed = " << m_bPageNumDisplayed;
  1023.     dc << "\nm_bCenter = " << m_bCenter;
  1024.     dc << "\nm_nPages = " << m_nPages;
  1025.     dc << "\nm_nCurrentPage " << m_nCurrentPage;
  1026.     dc << "\nm_nSecondPageOffset " << m_nSecondPageOffset;
  1027.     dc << "\nm_nMaxPages = " << m_nMaxPages;
  1028.     dc << "\nm_sizePrinterPPI = " << m_sizePrinterPPI;
  1029.     dc << "\nm_ptCenterPoint = " << m_ptCenterPoint;
  1030.     dc << "\nm_nZoomState = ";
  1031.     switch (m_nZoomState)
  1032.     {
  1033.     case ZOOM_OUT:
  1034.         dc << "ZOOM_OUT";
  1035.         break;
  1036.     case ZOOM_IN:
  1037.         dc << "ZOOM_IN";
  1038.         break;
  1039.     case ZOOM_MIDDLE:
  1040.         dc << "ZOOM_MIDDLE";
  1041.         break;
  1042.     default:
  1043.         dc << "*unknown*";
  1044.         break;
  1045.     }
  1046.     dc << "\nm_nMapMode = ";
  1047.     switch (m_nMapMode)
  1048.     {
  1049.     case MM_TEXT:
  1050.         dc << "MM_TEXT";
  1051.         break;
  1052.     case MM_LOMETRIC:
  1053.         dc << "MM_LOMETRIC";
  1054.         break;
  1055.     case MM_HIMETRIC:
  1056.         dc << "MM_HIMETRIC";
  1057.         break;
  1058.     case MM_LOENGLISH:
  1059.         dc << "MM_LOENGLISH";
  1060.         break;
  1061.     case MM_HIENGLISH:
  1062.         dc << "MM_HIENGLISH";
  1063.         break;
  1064.     case MM_TWIPS:
  1065.         dc << "MM_TWIPS";
  1066.         break;
  1067.     case MM_ISOTROPIC:
  1068.         dc << "MM_ISOTROPIC";
  1069.         break;
  1070.     case MM_ANISOTROPIC:
  1071.         dc << "MM_ANISOTROPIC";
  1072.         break;
  1073.     default:
  1074.         dc << "*unknown*";
  1075.         break;
  1076.     }
  1077.     dc << "\nm_dcPrint = " << &m_dcPrint;
  1078.     dc << "\nm_pPreviewDC = " << m_pPreviewDC;
  1079.  
  1080.     dc << "\n";
  1081. }
  1082. #endif //_DEBUG
  1083.  
  1084. #ifdef AFX_INIT_SEG
  1085. #pragma code_seg(AFX_INIT_SEG)
  1086. #endif
  1087.  
  1088. IMPLEMENT_DYNCREATE(CPreviewView, CScrollView)
  1089.  
  1090. /////////////////////////////////////////////////////////////////////////////
  1091.