PAGEWIN.CPP
/* 
 * PAGEWIN.CPP 
 * Patron Chapter 7 
 * 
 * Window procedure for the Pages window and support functions. 
 * This window manages its own scrollbars and viewport and provides 
 * printing capabilities as well.  The public CPages::Print 
 * function lives here. 
 * 
 * Copyright (c)1993-1996 Microsoft Corporation, All Rights Reserved 
 * 
 * Kraig Brockschmidt, Software Design Engineer 
 * Microsoft Systems Developer Relations 
 * 
 * Internet  :  kraigb@microsoft.com 
 * Compuserve:  >INTERNET:kraigb@microsoft.com 
 */ 
 
 
 
#include "patron.h" 
 
static HWND g_hDlgPrint=NULL; 
static BOOL g_fCancelPrint=FALSE; 
 
 
/* 
 * PagesWndProc 
 * 
 * Purpose: 
 *  Window procedure for the Pages window. 
 */ 
 
LRESULT APIENTRY PagesWndProc(HWND hWnd, UINT iMsg, WPARAM wParam 
    , LPARAM lParam) 
    { 
    PCPages         ppg; 
    PAINTSTRUCT     ps; 
    HDC             hDC; 
    int             iPos, iTmp; 
    int             iMin, iMax; 
    UINT            idScroll; 
    //CHAPTER7MOD 
    BOOL            fDirty=FALSE; 
    //End CHAPTER7MOD 
 
    ppg=(PCPages)GetWindowLong(hWnd, PAGEWL_STRUCTURE); 
 
    switch (iMsg) 
        { 
        case WM_CREATE: 
            ppg=(PCPages)((LPCREATESTRUCT)lParam)->lpCreateParams; 
            SetWindowLong(hWnd, PAGEWL_STRUCTURE, (LONG)ppg); 
 
            ppg->m_hWnd=hWnd; 
            break; 
 
 
        case WM_PAINT: 
            hDC=BeginPaint(hWnd, &ps); 
 
            //Draw only if we have a page to show. 
            if (0!=ppg->m_cPages) 
                ppg->Draw(hDC, FALSE, FALSE); 
 
            EndPaint(hWnd, &ps); 
            break; 
 
 
        case WM_HSCROLL: 
        case WM_VSCROLL: 
            idScroll=(WM_HSCROLL==iMsg) ? SB_HORZ : SB_VERT; 
 
            iPos=GetScrollPos(hWnd, idScroll); 
            iTmp=iPos; 
            GetScrollRange(hWnd, idScroll, &iMin, &iMax); 
 
            switch (LOWORD(wParam)) 
                { 
                case SB_LINEUP:     iPos -= 20;  break; 
                case SB_PAGEUP:     iPos -=100;  break; 
                case SB_LINEDOWN:   iPos += 20;  break; 
                case SB_PAGEDOWN:   iPos +=100;  break; 
 
                case SB_THUMBPOSITION: 
                    iPos=ScrollThumbPosition(wParam, lParam); 
                    break; 
 
                //We don't want scrolling on this message. 
                case SB_THUMBTRACK: 
                    return 0L; 
                } 
 
            iPos=max(iMin, min(iPos, iMax)); 
 
            if (iPos!=iTmp) 
                { 
                //Set the new position and scroll the window 
                SetScrollPos(hWnd, idScroll, iPos, TRUE); 
 
                if (SB_HORZ==idScroll) 
                    { 
                    ppg->m_xPos=iPos; 
                    ScrollWindow(hWnd, iTmp-iPos, 0, NULL, NULL); 
                    } 
                else 
                    { 
                    ppg->m_yPos=iPos; 
                    ScrollWindow(hWnd, 0, iTmp-iPos, NULL, NULL); 
                    } 
                } 
 
            break; 
 
        //CHAPTER7MOD 
        case WM_LBUTTONDOWN: 
            if (NULL==ppg->m_pPageCur) 
                break; 
 
            fDirty=ppg->m_pPageCur->OnLeftDown(wParam 
                , LOWORD(lParam), HIWORD(lParam)); 
            break; 
 
        case WM_LBUTTONUP: 
            if (NULL==ppg->m_pPageCur) 
                break; 
 
            fDirty=ppg->m_pPageCur->OnLeftUp(wParam 
                , LOWORD(lParam), HIWORD(lParam)); 
            break; 
 
        case WM_LBUTTONDBLCLK: 
            if (NULL==ppg->m_pPageCur) 
                break; 
 
            fDirty=ppg->m_pPageCur->OnLeftDoubleClick(wParam, LOWORD(lParam) 
                , HIWORD(lParam)); 
            break; 
 
        case WM_MOUSEMOVE: 
            if (NULL==ppg->m_pPageCur) 
                break; 
 
            ppg->m_pPageCur->OnMouseMove(wParam, LOWORD(lParam) 
                , HIWORD(lParam)); 
            break; 
 
        case WM_TIMER: 
            if (NULL==ppg->m_pPageCur) 
                break; 
 
            ppg->m_pPageCur->OnTimer(wParam); 
            break; 
 
        case WM_NCHITTEST: 
            if (NULL!=ppg->m_pPageCur) 
                { 
                /* 
                 * This just saves information in the page for 
                 * OnSetCursor 
                 */ 
                ppg->m_pPageCur->OnNCHitTest(LOWORD(lParam) 
                    , HIWORD(lParam)); 
                } 
 
            return DefWindowProc(hWnd, iMsg, wParam, lParam); 
 
        case WM_SETCURSOR: 
            if (NULL!=ppg->m_pPageCur) 
                { 
                if (ppg->m_pPageCur->OnSetCursor(LOWORD(lParam))) 
                    break; 
                } 
 
            return DefWindowProc(hWnd, iMsg, wParam, lParam); 
 
        //End CHAPTER7MOD 
 
        default: 
            return DefWindowProc(hWnd, iMsg, wParam, lParam); 
        } 
 
    //CHAPTER7MOD 
    ppg->m_fDirty |= fDirty; 
    //End CHAPTER7MOD 
    return 0L; 
    } 
 
 
 
 
 
/* 
 * RectConvertMappings 
 * 
 * Purpose: 
 *  Converts the contents of a rectangle from device to logical 
 *  coordinates where the hDC defines the logical coordinates. 
 * 
 * Parameters: 
 *  pRect           LPRECT containing the rectangle to convert. 
 *  hDC             HDC describing the logical coordinate system. 
 *                  if NULL, uses a screen DC in MM_LOMETRIC. 
 *  fToDevice       BOOL TRUE to convert from uConv to device, 
 *                  FALSE to convert device to uConv. 
 * 
 * Return Value: 
 *  None 
 */ 
 
void RectConvertMappings(LPRECT pRect, HDC hDC, BOOL fToDevice) 
    { 
    POINT   rgpt[2]; 
    BOOL    fSysDC=FALSE; 
 
    if (NULL==pRect) 
        return; 
 
    rgpt[0].x=pRect->left; 
    rgpt[0].y=pRect->top; 
    rgpt[1].x=pRect->right; 
    rgpt[1].y=pRect->bottom; 
 
    if (NULL==hDC) 
        { 
        hDC=GetDC(NULL); 
        SetMapMode(hDC, MM_LOMETRIC); 
        fSysDC=TRUE; 
        } 
 
    if (fToDevice) 
        LPtoDP(hDC, rgpt, 2); 
    else 
        DPtoLP(hDC, rgpt, 2); 
 
    if (fSysDC) 
        ReleaseDC(NULL, hDC); 
 
    pRect->left=rgpt[0].x; 
    pRect->top=rgpt[0].y; 
    pRect->right=rgpt[1].x; 
    pRect->bottom=rgpt[1].y; 
 
    return; 
    } 
 
 
 
 
 
 
/* 
 * CPages::Draw 
 * 
 * Purpose: 
 *  Paints the current page in the pages window. 
 * 
 * Parameters: 
 *  hDC             HDC to draw on, could be a metafile or printer 
 *                  DC or any other type of DC. 
 *  fNoColor        BOOL indicating if we should use screen colors 
 *                  or printer colors (B&W).  Objects are printed 
 *                  as-is, however.  This is TRUE for printer DCs 
 *                  or print preview. 
 *  fPrinter        BOOL indicating if this is a printer DC in which 
 *                  case we eliminate some of the fancy drawing, 
 *                  like shadows on the page and so forth. 
 * 
 * Return Value: 
 *  None 
 */ 
 
void CPages::Draw(HDC hDC, BOOL fNoColor, BOOL fPrinter) 
    { 
    RECT            rc, rcT; 
    UINT            uMM; 
    HPEN            hPen; 
    HBRUSH          hBrush; 
    HGDIOBJ         hObj1, hObj2; 
    COLORREF        cr; 
    TCHAR           szTemp[20]; 
    UINT            cch; 
    SIZE            sz; 
    //CHAPTER7MOD 
    PCPage          pPage; 
    RECT            rcPos; 
    //End CHAPTER7MOD 
 
    //Make sure the DC is in LOMETRIC 
    uMM=SetMapMode(hDC, MM_LOMETRIC); 
 
    if (!fPrinter) 
        { 
        /* 
         * We maintain a 6mm border around the page on the screen 
         * besides 12.7mm margins.  We also have to account for 
         * the scroll position with m_*Pos which are in pixels so 
         * we have to convert them. 
         */ 
 
        //CHAPTER7MOD 
        SetRect(&rcPos, m_xPos, m_yPos, 0, 0); 
        RectConvertMappings(&rcPos, hDC, FALSE); 
 
        rc.left  = LOMETRIC_BORDER-rcPos.left; 
        rc.top   =-LOMETRIC_BORDER-rcPos.top; 
        //End CHAPTER7MOD 
        } 
    else 
        { 
        /* 
         * We define the corner of the printed paper at a negative 
         * offset so rc.right and rc.bottom come out right below. 
         */ 
        SetRect(&rc, -(int)m_xMarginLeft, m_yMarginTop, 0, 0); 
        } 
 
    rc.right=rc.left+m_cx+(m_xMarginLeft+m_xMarginRight); 
    rc.bottom=rc.top-m_cy-(m_yMarginTop+m_yMarginBottom); 
 
    //Draw a rect filled with the window color to show the page. 
    if (!fPrinter) 
        { 
        if (fNoColor) 
            { 
            //Black frame, white box for printed colors. 
            hPen  =CreatePen(PS_SOLID, 0, RGB(0,0,0)); 
            hBrush=CreateSolidBrush(RGB(255, 255, 255)); 
            } 
        else 
            { 
            //Normal colors on display 
            hPen=CreatePen(PS_SOLID, 0 
                , GetSysColor(COLOR_WINDOWFRAME)); 
            hBrush=CreateSolidBrush(GetSysColor(COLOR_WINDOW)); 
            } 
 
        hObj1=SelectObject(hDC, hPen); 
        hObj2=SelectObject(hDC, hBrush); 
 
        //Paper boundary 
        Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom+1); 
 
        /* 
         * Draw a shadow on the *visual* bottom and right edges 
         * .5mm wide.  If the button shadow color and workspace 
         * colors match, then use black.  We always use black 
         * when printing as well. 
         */ 
        if (fNoColor) 
            cr=RGB(0,0,0); 
        else 
            { 
            cr=GetSysColor(COLOR_BTNSHADOW); 
 
            if (GetSysColor(COLOR_APPWORKSPACE)==cr) 
                cr=RGB(0,0,0); 
            } 
 
        cr=SetBkColor(hDC, cr); 
        SetRect(&rcT, rc.left+5, rc.bottom, rc.right+5,rc.bottom-5); 
        ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rcT, NULL, 0, NULL); 
 
        SetRect(&rcT, rc.right, rc.top-5, rc.right+5, rc.bottom-5); 
        ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rcT, NULL, 0, NULL); 
        SetBkColor(hDC, cr); 
 
        SelectObject(hDC, hObj1); 
        SelectObject(hDC, hObj2); 
        DeleteObject(hBrush); 
        DeleteObject(hPen); 
        } 
 
    //Write the page number in the lower left corner 
    if (!fNoColor) 
        { 
        SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); 
        SetBkColor(hDC, GetSysColor(COLOR_WINDOW)); 
        } 
 
    //Write the page number in our page font. 
    cch=wsprintf(szTemp, TEXT("Page %d"), m_iPageCur+1); 
 
    hObj1=SelectObject(hDC, m_hFont); 
    GetTextExtentPoint(hDC, szTemp, cch, &sz); 
 
    TextOut(hDC, rc.left+m_xMarginLeft 
        , rc.bottom+m_yMarginBottom+sz.cy, szTemp, cch); 
 
    SelectObject(hDC, hObj1); 
 
    //Rectangle to show border. 
    MoveToEx(hDC, rc.left+m_xMarginLeft, rc.top-m_yMarginTop, NULL); 
    LineTo(hDC, rc.left+m_xMarginLeft,   rc.bottom+m_yMarginBottom); 
    LineTo(hDC, rc.right-m_xMarginRight, rc.bottom+m_yMarginBottom); 
    LineTo(hDC, rc.right-m_xMarginRight, rc.top-m_yMarginTop); 
    LineTo(hDC, rc.left+m_xMarginLeft,   rc.top-m_yMarginTop); 
 
    //CHAPTER7MOD 
    /* 
     * Go draw the objects on this page.  If the page is not open, 
     * we open it anyway.  If it is already open, then opening again 
     * will bump it's reference count, so the Close in ineffectual. 
     */ 
    if (FPageGet(m_iPageCur, &pPage, TRUE)) 
        { 
        if (!fPrinter) 
            { 
            pPage->Draw(hDC, rcPos.left, rcPos.top, fNoColor 
                , fPrinter); 
            } 
        else 
            pPage->Draw(hDC, 0, 0, fNoColor, fPrinter); 
 
        pPage->Close(FALSE); 
        } 
    //End CHAPTER7MOD 
 
    SetMapMode(hDC, uMM); 
    return; 
    } 
 
 
 
 
 
/* 
 * CPages::UpdateScrollRanges 
 * 
 * Purpose: 
 *  Reset scrollbar ranges (horizontal and vertical) depending on 
 *  the window size and the page size.  This function may remove 
 *  the scrollbars altogether. 
 * 
 * Parameters: 
 *  None, but set m_cx, m_cy and size m_hWnd before calling. 
 * 
 * Return Value: 
 *  None 
 */ 
 
void CPages::UpdateScrollRanges(void) 
    { 
    UINT        cxSB;   //Scrollbar width and height. 
    UINT        cySB; 
    UINT        cx, cy; 
    UINT        dx, dy; 
    UINT        u; 
    int         iMin, iMax; 
    RECT        rc; 
    BOOL        fHScroll; 
    BOOL        fVScroll; 
    BOOL        fWasThere; 
 
    GetClientRect(m_hWnd, &rc); 
 
    cx=rc.right-rc.left; 
    cy=rc.bottom-rc.top; 
 
    //Convert dimensions of the image in LOMETRIC to pixels. 
    SetRect(&rc, (m_cx+m_xMarginLeft+m_xMarginRight 
        +LOMETRIC_BORDER*2), (m_cy+m_yMarginTop 
        +m_yMarginBottom+LOMETRIC_BORDER*2), 0, 0); 
 
    RectConvertMappings(&rc, NULL, TRUE); 
 
    dx=rc.left; 
    dy=-rc.top; 
 
    //Assume that both scrollbars will be visible. 
    fHScroll=TRUE; 
    fVScroll=TRUE; 
 
    /* 
     * Determine: 
     *  1)  Which scrollbars are needed. 
     *  2)  How many divisions to give scrollbars so as to 
     *      only scroll as little as necessary. 
     */ 
 
    //Scrollbar dimensions in our units. 
    cxSB=GetSystemMetrics(SM_CXVSCROLL); 
    cySB=GetSystemMetrics(SM_CYHSCROLL); 
 
    //Remove horizontal scroll if window >= cxPage+borders 
    if (cx >= dx) 
        fHScroll=FALSE; 
 
 
    /* 
     * If we still need a horizontal scroll, see if we need a 
     * vertical taking the height of the horizontal scroll into 
     * account. 
     */ 
 
    u=fHScroll ? cySB : 0; 
 
    if ((cy-u) >= dy) 
        fVScroll=FALSE; 
 
    //Check if adding vert scrollbar necessitates a horz now. 
    u=fVScroll ? cxSB : 0; 
    fHScroll=((cx-u) < dx); 
 
    /* 
     * Modify cx,cy to reflect the new client area before scaling 
     * scrollbars.  We only affect the client size if there is a 
     * *change* in scrollbar status:  if the scrollbar was there 
     * but is no longer, then add to the client size; if it was 
     * not there but now is, then subtract. 
     */ 
 
    //Change cx depending on vertical scrollbar change 
    GetScrollRange(m_hWnd, SB_VERT, &iMin, &iMax); 
    fWasThere=(0!=iMin || 0!=iMax); 
 
    if (fWasThere && !fVScroll) 
        cx+=cxSB; 
 
    if (!fWasThere && fVScroll) 
        cx-=cxSB; 
 
    //Change cy depending on horizontal scrollbar change 
    GetScrollRange(m_hWnd, SB_HORZ, &iMin, &iMax); 
    fWasThere=(0!=iMin || 0!=iMax); 
 
    if (fWasThere && !fHScroll) 
        cy+=cySB; 
 
    if (!fWasThere && fHScroll) 
        cy-=cySB; 
 
 
    /* 
     * Show/Hide the scrollbars if necessary and set the ranges. 
     * The range is the number of units of the page we cannot see. 
     */ 
    if (fHScroll) 
        { 
        //Convert current scroll position to new range. 
        u=GetScrollPos(m_hWnd, SB_HORZ); 
 
        if (0!=u) 
            { 
            GetScrollRange(m_hWnd, SB_HORZ, &iMin, &iMax); 
            u=MulDiv(u, (dx-cx), (iMax-iMin)); 
            } 
 
        SetScrollRange(m_hWnd, SB_HORZ, 0, dx-cx, FALSE); 
        SetScrollPos(m_hWnd, SB_HORZ, u, TRUE); 
        m_xPos=u; 
        } 
    else 
        { 
        SetScrollRange(m_hWnd, SB_HORZ, 0, 0, TRUE); 
        m_xPos=0; 
        } 
 
    if (fVScroll) 
        { 
        //Convert current scroll position to new range. 
        u=GetScrollPos(m_hWnd, SB_VERT); 
 
        if (0!=u) 
            { 
            GetScrollRange(m_hWnd, SB_VERT, &iMin, &iMax); 
            u=MulDiv(u, (dy-cy), (iMax-iMin)); 
            } 
 
        SetScrollRange(m_hWnd, SB_VERT, 0, dy-cy, FALSE); 
        SetScrollPos(m_hWnd, SB_VERT, u, TRUE); 
 
        m_yPos=u; 
        } 
    else 
        { 
        SetScrollRange(m_hWnd, SB_VERT, 0, 0, TRUE); 
        m_yPos=0; 
        } 
 
    //Repaint to insure that changes to m_x/yPos are reflected 
    InvalidateRect(m_hWnd, NULL, TRUE); 
 
    return; 
    } 
 
 
 
 
 
/* 
 * 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; 
    }