PRINT.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:14k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*
  2.  * PRINT.CPP
  3.  * Patron Chapter 1
  4.  *
  5.  * Implementation of printing functions for both CPatronDoc
  6.  * and CPages classes.  These functions are here to keep clutter
  7.  * down in document.cpp and pages.cpp.
  8.  *
  9.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  10.  *
  11.  * Kraig Brockschmidt, Microsoft
  12.  * Internet  :  kraigb@microsoft.com
  13.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  14.  */
  15. #include "patron.h"
  16. static HWND g_hDlgPrint=NULL;
  17. static BOOL g_fCancelPrint=FALSE;
  18. /*
  19.  * CPatronDoc::Print
  20.  *
  21.  * Purpose:
  22.  *  Prints the current document.
  23.  *
  24.  * Parameters:
  25.  *  hWndFrame       HWND of the frame to use for dialog parents.
  26.  *
  27.  * Return Value:
  28.  *  BOOL            TRUE if printing happened, FALSE if it didn't
  29.  *                  start or didn't complete.
  30.  */
  31. BOOL CPatronDoc::Print(HWND hWndFrame)
  32.     {
  33.     PRINTDLG        pd;
  34.     BOOL            fSuccess;
  35.     memset(&pd, 0, sizeof(PRINTDLG));
  36.     pd.lStructSize=sizeof(PRINTDLG);
  37.     pd.hwndOwner  =hWndFrame;
  38.     pd.nCopies    =1;
  39.     pd.nFromPage  =(USHORT)-1;
  40.     pd.nToPage    =(USHORT)-1;
  41.     pd.nMinPage   =1;
  42.     pd.nMaxPage   =m_pPG->NumPagesGet();
  43.     pd.lpfnPrintHook=PrintDlgHook;
  44.     //Get the current document printer settings
  45.     pd.hDevMode=m_pPG->DevModeGet();
  46.     pd.Flags=PD_RETURNDC | PD_ALLPAGES | PD_COLLATE
  47.         | PD_HIDEPRINTTOFILE | PD_NOSELECTION | PD_ENABLEPRINTHOOK;
  48.     if (!PrintDlg(&pd))
  49.         return FALSE;
  50.     if (NULL!=pd.hDevMode)
  51.         GlobalFree(pd.hDevMode);
  52.     if (NULL!=pd.hDevNames)
  53.         GlobalFree(pd.hDevNames);
  54.     //Go do the actual printing.
  55.     fSuccess=m_pPG->Print(pd.hDC, PSZ(IDS_DOCUMENTNAME), pd.Flags
  56.         , pd.nFromPage, pd.nToPage, pd.nCopies);
  57.     if (!fSuccess)
  58.         {
  59.         MessageBox(m_hWnd, PSZ(IDS_PRINTERROR)
  60.             , PSZ(IDS_DOCUMENTCAPTION), MB_OK);
  61.         }
  62.     return fSuccess;
  63.     }
  64. /*
  65.  * CPatronDoc::PrinterSetup
  66.  *
  67.  * Purpose:
  68.  *  Selects a new printer and options for this document.
  69.  *
  70.  * Parameters:
  71.  *  hWndFrame       HWND of the frame to use for dialog parents.
  72.  *  fDefault        BOOL to avoid any dialog and just use the
  73.  *                  default.
  74.  *
  75.  * Return Value:
  76.  *  UINT            Undefined
  77.  */
  78. UINT CPatronDoc::PrinterSetup(HWND hWndFrame, BOOL fDefault)
  79.     {
  80.     PRINTDLG        pd;
  81.     //Attempt to get printer metrics for the default printer.
  82.     memset(&pd, 0, sizeof(PRINTDLG));
  83.     pd.lStructSize=sizeof(PRINTDLG);
  84.     if (fDefault)
  85.         pd.Flags=PD_RETURNDEFAULT;
  86.     else
  87.         {
  88.         pd.hwndOwner=hWndFrame;
  89.         pd.Flags=PD_PRINTSETUP;
  90.         //Get the current document printer settings
  91.         pd.hDevMode=m_pPG->DevModeGet();
  92.         }
  93.     if (!PrintDlg(&pd))
  94.         return FALSE;
  95.     if (!m_pPG->DevModeSet(pd.hDevMode, pd.hDevNames))
  96.         {
  97.         GlobalFree(pd.hDevNames);
  98.         GlobalFree(pd.hDevMode);
  99.         return FALSE;
  100.         }
  101.     FDirtySet(TRUE);
  102.     return 1;
  103.     }
  104. /*
  105.  * PrintDlgHook
  106.  *
  107.  * Purpose:
  108.  *  Callback hook for the Print Dialog so we can hide the Setup
  109.  *  button.  Patron only allows Setup before anything exists on
  110.  *  the page, and is not written to handle setup at Print time.
  111.  */
  112. UINT CALLBACK PrintDlgHook(HWND hDlg, UINT iMsg, WPARAM wParam
  113.     , LPARAM lParam)
  114.     {
  115.     if (WM_INITDIALOG==iMsg)
  116.         {
  117.         HWND        hWnd;
  118.         hWnd=GetDlgItem(hDlg, psh1);
  119.         ShowWindow(hWnd, SW_HIDE);
  120.         return TRUE;
  121.         }
  122.     return FALSE;
  123.     }
  124. /*
  125.  * CPages::DevModeSet
  126.  *
  127.  * Purpose:
  128.  *  Provides the Pages with the current printer information.
  129.  *
  130.  * Parameters:
  131.  *  hDevMode        HGLOBAL to the memory containing the DEVMODE.
  132.  *                  This function assumes responsibility for this
  133.  *                  handle.
  134.  *  hDevNames       HGLOBAL providing the driver name and device
  135.  *                  name from which we can create a DC for
  136.  *                  information.
  137.  *
  138.  * Return Value:
  139.  *  BOOL            TRUE if we could accept this configuration,
  140.  *                  FALSE otherwise.  If we return TRUE we also
  141.  *                  delete the old memory we hold.
  142.  */
  143. BOOL CPages::DevModeSet(HGLOBAL hDevMode, HGLOBAL hDevNames)
  144.     {
  145.     LPDEVNAMES      pdn;
  146.     LPTSTR          psz;
  147.     if (NULL==hDevMode || NULL==hDevNames)
  148.         return FALSE;
  149.     psz=(LPTSTR)GlobalLock(hDevNames);
  150.     if (NULL==psz)
  151.         return FALSE;
  152.     pdn=(LPDEVNAMES)psz;
  153.     lstrcpy(m_szDriver, psz+pdn->wDriverOffset);
  154.     lstrcpy(m_szDevice, psz+pdn->wDeviceOffset);
  155.     lstrcpy(m_szPort,   psz+pdn->wOutputOffset);
  156.     GlobalUnlock(hDevNames);
  157.     GlobalFree(hDevNames);
  158.     //Save this new memory and get rid of the old.
  159.     if (NULL!=m_hDevMode)
  160.         GlobalFree(m_hDevMode);
  161.     m_hDevMode=hDevMode;
  162.     return ConfigureForDevice();
  163.     }
  164. /*
  165.  * CPages::DevModeGet
  166.  *
  167.  * Purpose:
  168.  *  Retrieves a copy of the current DEVMODE structure for this
  169.  *  Pages window.  The caller is responsible for this memory.
  170.  *
  171.  * Parameters:
  172.  *  None
  173.  *
  174.  * Return Value:
  175.  *  HGLOBAL         Handle to the memory containing the DEVMODE
  176.  *                  structure.
  177.  */
  178. HGLOBAL CPages::DevModeGet(void)
  179.     {
  180.     HGLOBAL     hMem;
  181.     DWORD       cb;
  182.     DWORD       i;
  183.     LPBYTE      pb1, pb2;
  184.     cb=GlobalSize(m_hDevMode);
  185.     if (0==cb)
  186.         return NULL;
  187.     hMem=GlobalAlloc(GHND, cb);
  188.     if (NULL==hMem)
  189.         return NULL;
  190.     pb1=(LPBYTE)GlobalLock(hMem);
  191.     pb2=(LPBYTE)GlobalLock(m_hDevMode);
  192.     //Copy the existing DEVMODE structure
  193.     for (i=0; i < cb; i++)
  194.         *pb1++=*pb2++;
  195.     GlobalUnlock(m_hDevMode);
  196.     GlobalUnlock(hMem);
  197.     return hMem;
  198.     }
  199. /*
  200.  * CPages::ConfigureForDevice
  201.  *
  202.  * Purpose:
  203.  *  Recalculates our drawing configuration based on the contents of
  204.  *  an hDC.  If no HDC is given we use the contents of our DevMode
  205.  *  stream.
  206.  *
  207.  * Parameters:
  208.  *  None
  209.  *
  210.  * Return Value:
  211.  *  BOOL            TRUE if successful, FALSE otherwise.
  212.  */
  213. BOOL CPages::ConfigureForDevice(void)
  214.     {
  215.     POINT           ptOffset, ptPaper;
  216.     RECT            rc;
  217.     HDC             hDC;
  218.     LPDEVMODE       pdm;
  219.     CHourglass      hg;     //Shows wait cursor, automatically destroyed
  220.     pdm=(LPDEVMODE)GlobalLock(m_hDevMode);
  221.     if (NULL==pdm)
  222.         return FALSE;
  223.     //Get the DC then configure
  224.     hDC=CreateIC(m_szDriver, m_szDevice, m_szPort, pdm);
  225.     GlobalUnlock(m_hDevMode);
  226.     if (NULL==hDC)
  227.         return FALSE;
  228.     //Get usable page dimensions:  already sensitive to orientation
  229.     m_cx=GetDeviceCaps(hDC, HORZSIZE)*10-16; //*10: mm to LOMETRIC
  230.     m_cy=GetDeviceCaps(hDC, VERTSIZE)*10-16; //-16: for driver bugs.
  231.     //Calculate the printer-limited margins on sides in LOMETRIC.
  232.     Escape(hDC, GETPRINTINGOFFSET, NULL, NULL, &ptOffset);
  233.     Escape(hDC, GETPHYSPAGESIZE,   NULL, NULL, &ptPaper);
  234.     SetRect(&rc, ptOffset.x, ptOffset.y, ptPaper.x, ptPaper.y);
  235.     SetMapMode(hDC, MM_LOMETRIC);
  236.     RectConvertMappings(&rc, hDC, FALSE);
  237.     //Left and top margins are the printing offset.
  238.     m_xMarginLeft= rc.left+8;   //+8 to match -16 above
  239.     m_yMarginTop =-rc.top+8;    //LOMETRIC makes this negative.
  240.     //Right is (paper width)-(usable width)-(left margin)
  241.     m_xMarginRight =rc.right-m_cx-m_xMarginLeft;
  242.     //Bottom is (paper height)-(usable height)-(top margin)+1
  243.     m_yMarginBottom=-rc.bottom-m_cy-m_yMarginTop+1;
  244.     UpdateScrollRanges();
  245.     DeleteDC(hDC);
  246.     return TRUE;
  247.     }
  248. /*
  249.  * CPages::Print
  250.  *
  251.  * Purpose:
  252.  *  Prints a specified range of pages to a given hDC.  Repeats for
  253.  *  a given number of copies.
  254.  *
  255.  * Parameters:
  256.  *  hDC             HDC to which we print.
  257.  *  pszDoc          LPTSTR providing the document name.
  258.  *  dwFlags         DWORD flags from PrintDlg
  259.  *  iPageStart      UINT starting page index (one based)
  260.  *  iPageEnd        UINT ending page index (one based).  Includes
  261.  *                  this page.
  262.  *  cCopies         UINT number of copies to print.  If PD_COLLATE
  263.  *                  in dwFlags is set, we print multiple copies of
  264.  *                  each page as we cycle through.  Otherwise we
  265.  *                  cycle multiple times.
  266.  *
  267.  * Return Value:
  268.  *  None
  269.  */
  270. BOOL CPages::Print(HDC hDC, LPTSTR pszDoc, DWORD dwFlags
  271.     , UINT iPageStart, UINT iPageEnd, UINT cCopies)
  272.     {
  273.     BOOL        fError=FALSE;
  274.     int         iPage, iPageInc;
  275.     int         iUserPage, cPages;
  276.     UINT        iRepeat, cRepeat;
  277.     UINT        iCycle, cCycles;
  278.     UINT        iPageHold=m_iPageCur;
  279.     HWND        hWndT, hWndTop=NULL;
  280.     DOCINFO     di;
  281.     PCDocument  pDoc;
  282.     //Validate hDC and page ranges
  283.     if (NULL==hDC)
  284.         return FALSE;
  285.     if ((PD_PAGENUMS & dwFlags))
  286.         {
  287.         if (-1==iPageStart)
  288.             iPageStart=0;
  289.         else
  290.             iPageStart--;   //Switch to zero offset.
  291.         if (-1==iPageEnd)
  292.             iPageEnd=m_cPages-1;
  293.         else
  294.             iPageEnd--;     //Switch to zero offset.
  295.         }
  296.     else //Can't test PD_ALLPAGES with & since it's defined as 0L
  297.         {
  298.         iPageStart=0;
  299.         iPageEnd=m_cPages-1;
  300.         }
  301.     //Arrange cycles and repeats depending on cCopies and collating
  302.     if (PD_COLLATE & dwFlags)
  303.         {
  304.         cCycles=cCopies;
  305.         cRepeat=1;
  306.         }
  307.     else
  308.         {
  309.         cCycles=1;
  310.         cRepeat=cCopies;
  311.         }
  312.     //Disable the frame window to prevent reentrancy while printing.
  313.     hWndT=GetParent(m_hWnd);
  314.     pDoc=(PCDocument)SendMessage(hWndT, DOCM_PDOCUMENT, 0, 0L);
  315.     if (NULL!=pDoc)
  316.         {
  317.         PCFrame pFR;
  318.         pFR=pDoc->FrameGet();
  319.         hWndTop=pFR->Window();
  320.         EnableWindow(hWndTop, FALSE);
  321.         }
  322.     SetAbortProc(hDC, AbortProc);
  323.     g_fCancelPrint=FALSE;
  324.     //If these don't work then we'll just live without a dialog.
  325.     g_hDlgPrint=CreateDialog(m_hInst, MAKEINTRESOURCE(IDD_PRINTING)
  326.         , hWndTop, PrintDlgProc);
  327.     //Increment for either direction.
  328.     iPageInc=(iPageStart > iPageEnd) ? -1 : 1;
  329.     //Initial entries in dialog box.
  330.     cPages=1+((int)(iPageEnd-iPageStart)*iPageInc);
  331.     SendMessage(g_hDlgPrint, PRINTM_PAGEUPDATE, 1, (LPARAM)cPages);
  332.     SendMessage(g_hDlgPrint, PRINTM_COPYUPDATE, 1, (LPARAM)cRepeat);
  333.     di.cbSize=sizeof(DOCINFO);
  334.     di.lpszDocName=pszDoc;
  335.     di.lpszOutput=NULL;
  336.     if (StartDoc(hDC, &di) > 0)
  337.         {
  338.         /*
  339.          * Iterate over the pages, repeating each page depending on
  340.          * the copies we want and if we have collate enabled.
  341.          */
  342.         for (iCycle=1; iCycle <= cCycles; iCycle++)
  343.             {
  344.             if (PD_COLLATE & dwFlags)
  345.                 {
  346.                 SendMessage(g_hDlgPrint, PRINTM_COPYUPDATE, iCycle
  347.                     , (LPARAM)cCycles);
  348.                 }
  349.             //iPageInc controls direction
  350.             for (iPage=iPageStart; ; iPage+=iPageInc)
  351.                 {
  352.                 iUserPage=1+((iPage-(int)iPageStart)*iPageInc);
  353.                 SendMessage(g_hDlgPrint, PRINTM_PAGEUPDATE
  354.                     , iUserPage, (LPARAM)cPages);
  355.                 m_iPageCur=iPage;   //We restore this later.
  356.                 for (iRepeat=1; iRepeat <= cRepeat; iRepeat++)
  357.                     {
  358.                     if (!(PD_COLLATE & dwFlags))
  359.                         {
  360.                         SendMessage(g_hDlgPrint, PRINTM_COPYUPDATE
  361.                             , iRepeat, (LPARAM)cRepeat);
  362.                         }
  363.                     StartPage(hDC);
  364.                     Draw(hDC, TRUE, TRUE);
  365.                     if (EndPage(hDC) < 0)
  366.                         fError=TRUE;
  367.                     if (fError || g_fCancelPrint)
  368.                         break;
  369.                     }
  370.                 if (fError || g_fCancelPrint)
  371.                     break;
  372.                 //If we just printed the last page, time to quit.
  373.                 if (iPage==(int)iPageEnd)
  374.                     break;
  375.                 }
  376.             if (fError || g_fCancelPrint)
  377.                 break;
  378.             }
  379.         if (!fError)
  380.             EndDoc(hDC);
  381.         else
  382.             AbortDoc(hDC);
  383.         }
  384.     else
  385.         fError=TRUE;
  386.     //Set the page back to what it was before all this started.
  387.     m_iPageCur=iPageHold;
  388.     EnableWindow(hWndTop, TRUE);
  389.     SetFocus(hWndTop);
  390.     DestroyWindow(g_hDlgPrint);
  391.     DeleteDC(hDC);
  392.     return !fError;
  393.     }
  394. /*
  395.  * AbortProc
  396.  *
  397.  * Purpose:
  398.  *  Abort procedure for printing the pages.
  399.  *
  400.  * Parameters:
  401.  *  hDC             HDC on which printing is happening.
  402.  *  iErr            int error code.
  403.  *
  404.  * Return Value:
  405.  *  BOOL            TRUE to continue the print job, FALSE otherwise.
  406.  */
  407. BOOL APIENTRY AbortProc(HDC hDC, int iErr)
  408.     {
  409.     MSG     msg;
  410.     while (!g_fCancelPrint
  411.         && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  412.         {
  413.         if (NULL==g_hDlgPrint
  414.             || !IsDialogMessage(g_hDlgPrint, &msg))
  415.             {
  416.             TranslateMessage(&msg);
  417.             DispatchMessage(&msg);
  418.             }
  419.         }
  420.     return !g_fCancelPrint;
  421.     }
  422. /*
  423.  * PrintDlgProc
  424.  *
  425.  * Purpose:
  426.  *  Modeless dialog procedure for the dialog displayed while Patron
  427.  *  is printing pages.
  428.  */
  429. BOOL APIENTRY PrintDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam
  430.     , LPARAM lParam)
  431.     {
  432.     TCHAR           szFormat[40];
  433.     TCHAR           szOutput[80];
  434.     switch (iMsg)
  435.         {
  436.         case WM_INITDIALOG:
  437.             EnableMenuItem(GetSystemMenu(hDlg, FALSE), SC_CLOSE
  438.                 , MF_GRAYED);
  439.             return TRUE;
  440.         case WM_COMMAND:
  441.             //Cancel button was pressed.
  442.             g_fCancelPrint=TRUE;
  443.             ShowWindow(hDlg, SW_HIDE);
  444.             return TRUE;
  445.         case PRINTM_PAGEUPDATE:
  446.             GetDlgItemText(hDlg, ID_PAGESTRING, szFormat
  447.                 , sizeof(szFormat));
  448.             wsprintf(szOutput, szFormat, wParam, (UINT)lParam);
  449.             SetDlgItemText(hDlg, ID_CURRENTPAGE, szOutput);
  450.             return TRUE;
  451.         case PRINTM_COPYUPDATE:
  452.             GetDlgItemText(hDlg, ID_COPYSTRING, szFormat
  453.                 , sizeof(szFormat));
  454.             wsprintf(szOutput, szFormat, wParam, (UINT)lParam);
  455.             SetDlgItemText(hDlg, ID_CURRENTCOPY, szOutput);
  456.             return TRUE;
  457.         }
  458.     return FALSE;
  459.     }