⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 print.cpp

📁 英文版的 想要的话可以下载了 为大家服务
💻 CPP
字号:
/*
 * PRINT.CPP
 * Patron Chapter 1
 *
 * Implementation of printing functions for both CPatronDoc
 * and CPages classes.  These functions are here to keep clutter
 * down in document.cpp and pages.cpp.
 *
 * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
 *
 * Kraig Brockschmidt, Microsoft
 * Internet  :  kraigb@microsoft.com
 * Compuserve:  >INTERNET:kraigb@microsoft.com
 */

#include "patron.h"

static HWND g_hDlgPrint=NULL;
static BOOL g_fCancelPrint=FALSE;


/*
 * CPatronDoc::Print
 *
 * Purpose:
 *  Prints the current document.
 *
 * Parameters:
 *  hWndFrame       HWND of the frame to use for dialog parents.
 *
 * Return Value:
 *  BOOL            TRUE if printing happened, FALSE if it didn't
 *                  start or didn't complete.
 */

BOOL CPatronDoc::Print(HWND hWndFrame)
    {
    PRINTDLG        pd;
    BOOL            fSuccess;

    memset(&pd, 0, sizeof(PRINTDLG));
    pd.lStructSize=sizeof(PRINTDLG);
    pd.hwndOwner  =hWndFrame;
    pd.nCopies    =1;
    pd.nFromPage  =(USHORT)-1;
    pd.nToPage    =(USHORT)-1;
    pd.nMinPage   =1;
    pd.nMaxPage   =m_pPG->NumPagesGet();

    pd.lpfnPrintHook=PrintDlgHook;

    //Get the current document printer settings
    pd.hDevMode=m_pPG->DevModeGet();

    pd.Flags=PD_RETURNDC | PD_ALLPAGES | PD_COLLATE
        | PD_HIDEPRINTTOFILE | PD_NOSELECTION | PD_ENABLEPRINTHOOK;

    if (!PrintDlg(&pd))
        return FALSE;

    if (NULL!=pd.hDevMode)
        GlobalFree(pd.hDevMode);

    if (NULL!=pd.hDevNames)
        GlobalFree(pd.hDevNames);

    //Go do the actual printing.
    fSuccess=m_pPG->Print(pd.hDC, PSZ(IDS_DOCUMENTNAME), pd.Flags
        , pd.nFromPage, pd.nToPage, pd.nCopies);

    if (!fSuccess)
        {
        MessageBox(m_hWnd, PSZ(IDS_PRINTERROR)
            , PSZ(IDS_DOCUMENTCAPTION), MB_OK);
        }

    return fSuccess;
    }






/*
 * CPatronDoc::PrinterSetup
 *
 * Purpose:
 *  Selects a new printer and options for this document.
 *
 * Parameters:
 *  hWndFrame       HWND of the frame to use for dialog parents.
 *  fDefault        BOOL to avoid any dialog and just use the
 *                  default.
 *
 * Return Value:
 *  UINT            Undefined
 */

UINT CPatronDoc::PrinterSetup(HWND hWndFrame, BOOL fDefault)
    {
    PRINTDLG        pd;

    //Attempt to get printer metrics for the default printer.
    memset(&pd, 0, sizeof(PRINTDLG));
    pd.lStructSize=sizeof(PRINTDLG);

    if (fDefault)
        pd.Flags=PD_RETURNDEFAULT;
    else
        {
        pd.hwndOwner=hWndFrame;
        pd.Flags=PD_PRINTSETUP;

        //Get the current document printer settings
        pd.hDevMode=m_pPG->DevModeGet();
        }

    if (!PrintDlg(&pd))
        return FALSE;

    if (!m_pPG->DevModeSet(pd.hDevMode, pd.hDevNames))
        {
        GlobalFree(pd.hDevNames);
        GlobalFree(pd.hDevMode);
        return FALSE;
        }

    FDirtySet(TRUE);
    return 1;
    }



/*
 * PrintDlgHook
 *
 * Purpose:
 *  Callback hook for the Print Dialog so we can hide the Setup
 *  button.  Patron only allows Setup before anything exists on
 *  the page, and is not written to handle setup at Print time.
 */

UINT CALLBACK PrintDlgHook(HWND hDlg, UINT iMsg, WPARAM wParam
    , LPARAM lParam)
    {
    if (WM_INITDIALOG==iMsg)
        {
        HWND        hWnd;

        hWnd=GetDlgItem(hDlg, psh1);
        ShowWindow(hWnd, SW_HIDE);
        return TRUE;
        }

    return FALSE;
    }








/*
 * CPages::DevModeSet
 *
 * Purpose:
 *  Provides the Pages with the current printer information.
 *
 * Parameters:
 *  hDevMode        HGLOBAL to the memory containing the DEVMODE.
 *                  This function assumes responsibility for this
 *                  handle.
 *  hDevNames       HGLOBAL providing the driver name and device
 *                  name from which we can create a DC for
 *                  information.
 *
 * Return Value:
 *  BOOL            TRUE if we could accept this configuration,
 *                  FALSE otherwise.  If we return TRUE we also
 *                  delete the old memory we hold.
 */

BOOL CPages::DevModeSet(HGLOBAL hDevMode, HGLOBAL hDevNames)
    {
    LPDEVNAMES      pdn;
    LPTSTR          psz;

    if (NULL==hDevMode || NULL==hDevNames)
        return FALSE;

    psz=(LPTSTR)GlobalLock(hDevNames);

    if (NULL==psz)
        return FALSE;

    pdn=(LPDEVNAMES)psz;
    lstrcpy(m_szDriver, psz+pdn->wDriverOffset);
    lstrcpy(m_szDevice, psz+pdn->wDeviceOffset);
    lstrcpy(m_szPort,   psz+pdn->wOutputOffset);
    GlobalUnlock(hDevNames);
    GlobalFree(hDevNames);

    //Save this new memory and get rid of the old.
    if (NULL!=m_hDevMode)
        GlobalFree(m_hDevMode);

    m_hDevMode=hDevMode;

    return ConfigureForDevice();
    }







/*
 * CPages::DevModeGet
 *
 * Purpose:
 *  Retrieves a copy of the current DEVMODE structure for this
 *  Pages window.  The caller is responsible for this memory.
 *
 * Parameters:
 *  None
 *
 * Return Value:
 *  HGLOBAL         Handle to the memory containing the DEVMODE
 *                  structure.
 */

HGLOBAL CPages::DevModeGet(void)
    {
    HGLOBAL     hMem;
    DWORD       cb;
    DWORD       i;
    LPBYTE      pb1, pb2;

    cb=GlobalSize(m_hDevMode);

    if (0==cb)
        return NULL;

    hMem=GlobalAlloc(GHND, cb);

    if (NULL==hMem)
        return NULL;

    pb1=(LPBYTE)GlobalLock(hMem);
    pb2=(LPBYTE)GlobalLock(m_hDevMode);

    //Copy the existing DEVMODE structure
    for (i=0; i < cb; i++)
        *pb1++=*pb2++;

    GlobalUnlock(m_hDevMode);
    GlobalUnlock(hMem);

    return hMem;
    }




/*
 * CPages::ConfigureForDevice
 *
 * Purpose:
 *  Recalculates our drawing configuration based on the contents of
 *  an hDC.  If no HDC is given we use the contents of our DevMode
 *  stream.
 *
 * Parameters:
 *  None
 *
 * Return Value:
 *  BOOL            TRUE if successful, FALSE otherwise.
 */

BOOL CPages::ConfigureForDevice(void)
    {
    POINT           ptOffset, ptPaper;
    RECT            rc;
    HDC             hDC;
    LPDEVMODE       pdm;
    CHourglass      hg;     //Shows wait cursor, automatically destroyed

    pdm=(LPDEVMODE)GlobalLock(m_hDevMode);

    if (NULL==pdm)
        return FALSE;

    //Get the DC then configure
    hDC=CreateIC(m_szDriver, m_szDevice, m_szPort, pdm);

    GlobalUnlock(m_hDevMode);

    if (NULL==hDC)
        return FALSE;

    //Get usable page dimensions:  already sensitive to orientation
    m_cx=GetDeviceCaps(hDC, HORZSIZE)*10-16; //*10: mm to LOMETRIC
    m_cy=GetDeviceCaps(hDC, VERTSIZE)*10-16; //-16: for driver bugs.

    //Calculate the printer-limited margins on sides in LOMETRIC.
    Escape(hDC, GETPRINTINGOFFSET, NULL, NULL, &ptOffset);
    Escape(hDC, GETPHYSPAGESIZE,   NULL, NULL, &ptPaper);

    SetRect(&rc, ptOffset.x, ptOffset.y, ptPaper.x, ptPaper.y);
    SetMapMode(hDC, MM_LOMETRIC);
    RectConvertMappings(&rc, hDC, FALSE);

    //Left and top margins are the printing offset.
    m_xMarginLeft= rc.left+8;   //+8 to match -16 above
    m_yMarginTop =-rc.top+8;    //LOMETRIC makes this negative.

    //Right is (paper width)-(usable width)-(left margin)
    m_xMarginRight =rc.right-m_cx-m_xMarginLeft;

    //Bottom is (paper height)-(usable height)-(top margin)+1
    m_yMarginBottom=-rc.bottom-m_cy-m_yMarginTop+1;

    UpdateScrollRanges();

    DeleteDC(hDC);
    return TRUE;
    }




/*
 * CPages::Print
 *
 * Purpose:
 *  Prints a specified range of pages to a given hDC.  Repeats for
 *  a given number of copies.
 *
 * Parameters:
 *  hDC             HDC to which we print.
 *  pszDoc          LPTSTR providing the document name.
 *  dwFlags         DWORD flags from PrintDlg
 *  iPageStart      UINT starting page index (one based)
 *  iPageEnd        UINT ending page index (one based).  Includes
 *                  this page.
 *  cCopies         UINT number of copies to print.  If PD_COLLATE
 *                  in dwFlags is set, we print multiple copies of
 *                  each page as we cycle through.  Otherwise we
 *                  cycle multiple times.
 *
 * Return Value:
 *  None
 */

BOOL CPages::Print(HDC hDC, LPTSTR pszDoc, DWORD dwFlags
    , UINT iPageStart, UINT iPageEnd, UINT cCopies)
    {
    BOOL        fError=FALSE;
    int         iPage, iPageInc;
    int         iUserPage, cPages;
    UINT        iRepeat, cRepeat;
    UINT        iCycle, cCycles;
    UINT        iPageHold=m_iPageCur;
    HWND        hWndT, hWndTop=NULL;
    DOCINFO     di;
    PCDocument  pDoc;

    //Validate hDC and page ranges
    if (NULL==hDC)
        return FALSE;

    if ((PD_PAGENUMS & dwFlags))
        {
        if (-1==iPageStart)
            iPageStart=0;
        else
            iPageStart--;   //Switch to zero offset.

        if (-1==iPageEnd)
            iPageEnd=m_cPages-1;
        else
            iPageEnd--;     //Switch to zero offset.
        }
    else //Can't test PD_ALLPAGES with & since it's defined as 0L
        {
        iPageStart=0;
        iPageEnd=m_cPages-1;
        }

    //Arrange cycles and repeats depending on cCopies and collating
    if (PD_COLLATE & dwFlags)
        {
        cCycles=cCopies;
        cRepeat=1;
        }
    else
        {
        cCycles=1;
        cRepeat=cCopies;
        }

    //Disable the frame window to prevent reentrancy while printing.
    hWndT=GetParent(m_hWnd);
    pDoc=(PCDocument)SendMessage(hWndT, DOCM_PDOCUMENT, 0, 0L);

    if (NULL!=pDoc)
        {
        PCFrame pFR;

        pFR=pDoc->FrameGet();
        hWndTop=pFR->Window();
        EnableWindow(hWndTop, FALSE);
        }

    SetAbortProc(hDC, AbortProc);
    g_fCancelPrint=FALSE;

    //If these don't work then we'll just live without a dialog.
    g_hDlgPrint=CreateDialog(m_hInst, MAKEINTRESOURCE(IDD_PRINTING)
        , hWndTop, PrintDlgProc);

    //Increment for either direction.
    iPageInc=(iPageStart > iPageEnd) ? -1 : 1;

    //Initial entries in dialog box.
    cPages=1+((int)(iPageEnd-iPageStart)*iPageInc);

    SendMessage(g_hDlgPrint, PRINTM_PAGEUPDATE, 1, (LPARAM)cPages);
    SendMessage(g_hDlgPrint, PRINTM_COPYUPDATE, 1, (LPARAM)cRepeat);

    di.cbSize=sizeof(DOCINFO);
    di.lpszDocName=pszDoc;
    di.lpszOutput=NULL;

    if (StartDoc(hDC, &di) > 0)
        {
        /*
         * Iterate over the pages, repeating each page depending on
         * the copies we want and if we have collate enabled.
         */

        for (iCycle=1; iCycle <= cCycles; iCycle++)
            {
            if (PD_COLLATE & dwFlags)
                {
                SendMessage(g_hDlgPrint, PRINTM_COPYUPDATE, iCycle
                    , (LPARAM)cCycles);
                }

            //iPageInc controls direction
            for (iPage=iPageStart; ; iPage+=iPageInc)
                {
                iUserPage=1+((iPage-(int)iPageStart)*iPageInc);

                SendMessage(g_hDlgPrint, PRINTM_PAGEUPDATE
                    , iUserPage, (LPARAM)cPages);

                m_iPageCur=iPage;   //We restore this later.

                for (iRepeat=1; iRepeat <= cRepeat; iRepeat++)
                    {
                    if (!(PD_COLLATE & dwFlags))
                        {
                        SendMessage(g_hDlgPrint, PRINTM_COPYUPDATE
                            , iRepeat, (LPARAM)cRepeat);
                        }

                    StartPage(hDC);
                    Draw(hDC, TRUE, TRUE);

                    if (EndPage(hDC) < 0)
                        fError=TRUE;

                    if (fError || g_fCancelPrint)
                        break;
                    }

                if (fError || g_fCancelPrint)
                    break;

                //If we just printed the last page, time to quit.
                if (iPage==(int)iPageEnd)
                    break;
                }

            if (fError || g_fCancelPrint)
                break;
            }

        if (!fError)
            EndDoc(hDC);
        else
            AbortDoc(hDC);
        }
    else
        fError=TRUE;

    //Set the page back to what it was before all this started.
    m_iPageCur=iPageHold;

    EnableWindow(hWndTop, TRUE);
    SetFocus(hWndTop);
    DestroyWindow(g_hDlgPrint);
    DeleteDC(hDC);
    return !fError;
    }






/*
 * AbortProc
 *
 * Purpose:
 *  Abort procedure for printing the pages.
 *
 * Parameters:
 *  hDC             HDC on which printing is happening.
 *  iErr            int error code.
 *
 * Return Value:
 *  BOOL            TRUE to continue the print job, FALSE otherwise.
 */

BOOL APIENTRY AbortProc(HDC hDC, int iErr)
    {
    MSG     msg;

    while (!g_fCancelPrint
        && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
        if (NULL==g_hDlgPrint
            || !IsDialogMessage(g_hDlgPrint, &msg))
            {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
            }
        }

    return !g_fCancelPrint;
    }




/*
 * PrintDlgProc
 *
 * Purpose:
 *  Modeless dialog procedure for the dialog displayed while Patron
 *  is printing pages.
 */

BOOL APIENTRY PrintDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam
    , LPARAM lParam)
    {
    TCHAR           szFormat[40];
    TCHAR           szOutput[80];

    switch (iMsg)
        {
        case WM_INITDIALOG:
            EnableMenuItem(GetSystemMenu(hDlg, FALSE), SC_CLOSE
                , MF_GRAYED);
            return TRUE;

        case WM_COMMAND:
            //Cancel button was pressed.
            g_fCancelPrint=TRUE;
            ShowWindow(hDlg, SW_HIDE);
            return TRUE;

        case PRINTM_PAGEUPDATE:
            GetDlgItemText(hDlg, ID_PAGESTRING, szFormat
                , sizeof(szFormat));
            wsprintf(szOutput, szFormat, wParam, (UINT)lParam);
            SetDlgItemText(hDlg, ID_CURRENTPAGE, szOutput);
            return TRUE;

        case PRINTM_COPYUPDATE:
            GetDlgItemText(hDlg, ID_COPYSTRING, szFormat
                , sizeof(szFormat));
            wsprintf(szOutput, szFormat, wParam, (UINT)lParam);
            SetDlgItemText(hDlg, ID_CURRENTCOPY, szOutput);
            return TRUE;
        }

    return FALSE;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -