Click here to Skip to main content
15,867,704 members
Articles / Desktop Programming / MFC

MultiPage PrintPreview Enhancements for MFC Doc/View Applications

Rate me:
Please Sign up or sign in to vote.
4.73/5 (13 votes)
27 Apr 2002CPOL3 min read 165.1K   5.2K   34   30
How to improve the standard MFC print preview options to allow preview from 1 to 9 pages at a time

Sample Image - 9pages.gif

Acknowledgements

First, I would like to acknowledge some articles which I used as a reference when putting this project together.

Overview

The standard Print Preview mechanism supplied by MFC is a little understood phenomenon. There are few enhancements currently published for it, and none for showing more than 2 pages at a time in preview mode. I set out to solve this! It turned out to be reasonably easy to do, working from the examples supplied by Robin and Yasuhiko. In my solution, I used small parts of both examples (Robins onwner drawn buttons, and Yasuhiko's extra zoom levels).

The enhancement are:

  • From 1 to 9 pages viewed at a time - selectable by a popup menu
  • The scrollbar will not allow blank pages to be scrolled into view
  • You can switch dynamically between portrait and landscape mode using the toolbar command

So how do you go about using these enhancements?

Adding the Required Resources

To use this enhanced preview mode, you need to include the following resources into your project.

These should be copied and pasted into your project. You can do this from the VC IDE, or by manually editing the .rc file (not really recommended):

  • The replacement toolbar resource
  • The popup menu resource
  • The button bitmaps

Add the Source Files

The enhanced preview uses the following source files:

  • MappedBitmapButton.cpp/h - Robin J. Leatherbarrow
  • MultiPagePreview.cpp/h - Myself with some code from Yasuhiko
  • An additional function in your CWinApp derived class - see later

Replacing the Standard Print Preview

To replace the standard PrintPreview supplied by the MFC Doc/View architecture, you have to write a handler in your projects CView class to handle the ID_FILE_PRINT_PREVIEW command. You put the following code in that handler to supplant the MFC preview with the new one:

C++
// replace the default print preview with ours!

// In derived classes, implement special window handling here
// Be sure to Unhook Frame Window close if hooked.
    
// must not create this on the frame.  Must outlive this function
CPrintPreviewState* pState = new CPrintPreviewState;
    
// DoPrintPreview's return value does not necessarily indicate that
// Print preview succeeded or failed, but rather what actions are necessary
// at this point.  If DoPrintPreview returns TRUE, it means that
// OnEndPrintPreview will be (or has already been) called and the
// pState structure will be/has been deleted.
// If DoPrintPreview returns FALSE, it means that OnEndPrintPreview
// WILL NOT be called and that cleanup, including deleting pState
// must be done here.
    
if (!DoPrintPreview(IDD_PREVIEW, this, RUNTIME_CLASS(CMultiPagePreviewView),
                    pState)) // note, put your class name in here
{
    // In derived classes, reverse special window handling here for
    // Preview failure case
        
    TRACE0("Error: DoPrintPreview failed.\n");
    AfxMessageBox(AFX_IDP_COMMAND_FAILURE);
    delete pState;      // preview failed to initialize, delete State now
    pState = NULL;
}

Update Your CWinApp Derived Class

The additional functionality to switch dynamically between portrait and landscape mode in print preview requires support of an additional function in your CWinApp derived class. This is because the m_hDevMode object is a protected member and cannot be accessed directly by the preview class. The prototype of this function and the code for it is as follows:

C++
// prototype for CWinApp derived class
void        SetPrintOrientation(int mode) ;

void CYourApp::SetPrintOrientation(int mode)
{
    switch (mode)
        {
        case DMORIENT_PORTRAIT :
                {
                // portrait mode
                PRINTDLG pd;
                pd.lStructSize = (DWORD)sizeof(PRINTDLG) ;
                BOOL bRet = GetPrinterDeviceDefaults(&pd) ;
                if (bRet)
                    {
                    // protect memory handle with ::GlobalLock and ::GlobalUnlock
                    DEVMODE *pDevMode = (DEVMODE*)::GlobalLock(m_hDevMode) ;
                    // set orientation to portrait
                    pDevMode->dmOrientation = DMORIENT_PORTRAIT ;
                    ::GlobalUnlock(m_hDevMode) ;
                    }
                }
                break ;
        case DMORIENT_LANDSCAPE :
                {
                // landscape mode
                PRINTDLG pd;
                pd.lStructSize = (DWORD)sizeof(PRINTDLG) ;
                BOOL bRet = GetPrinterDeviceDefaults(&pd) ;
                if (bRet)
                    {
                    // protect memory handle with ::GlobalLock and ::GlobalUnlock
                    DEVMODE *pDevMode = (DEVMODE*)::GlobalLock(m_hDevMode) ;
                    // set orientation to landscape
                    pDevMode->dmOrientation = DMORIENT_LANDSCAPE ;
                    ::GlobalUnlock(m_hDevMode) ;
                    }
                }
                break ;
        default :    ASSERT(FALSE) ;        // invalid parameter
        }
}

If you are adding this to your application, you will also have to mod the code so it uses your CWinApp derived class name and not that of the demo project. If you insert the code and compile. The errors generated will get you to the lines you will need to update.

Once all of this is in, the preview mode should work automatically. You should now be able to preview upto a maximum of 9 pages simultaneously. This can be expanded for more by enhancing the options in the popup menu, and modifying the function CMultiPagePreviewView::OnPreviewPages() to handle the new layout. Just make sure that you increase the size of the m_pageInfoArray2 array in the .h file to avoid overwriting memory. So if you wanted to support a 4 * 4 preview, the array size needs to be increased from 9 to 16.

Changes Made

  • 24-4-2002 Release 1
  • 28-4-2002 Release 2 - Added portrait/landscale switching and updated the scrollbar control code

Future Enhancements

I would like to add the following features in the future:

  • Make the pages flicker free

Or you could always add them yourselves.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Sirius Analytical Instruments
United Kingdom United Kingdom
A research and development programmer working for a pharmaceutical instrument company for the past 17 years.

I am one of those lucky people who enjoys his work and spends more time than he should either doing work or reseaching new stuff. I can also be found on playing DDO on the Cannith server (Send a tell to "Maetrim" who is my current main)

I am also a keep fit fanatic, doing cross country running and am seriously into [url]http://www.ryushinkan.co.uk/[/url] Karate at this time of my life, training from 4-6 times a week and recently achieved my 1st Dan after 6 years.

Comments and Discussions

 
QuestionMemory leak in OnPrinSetup Pin
mrsilver7-Aug-16 9:04
mrsilver7-Aug-16 9:04 
QuestionWhat piece of code should I change to get rid of the spacing.. Pin
Frosty mtl4-Mar-13 8:01
Frosty mtl4-Mar-13 8:01 
GeneralHello Pin
Mark Jefferson27-Apr-08 4:41
Mark Jefferson27-Apr-08 4:41 
GeneralDon't need to modify you CWinApp class Pin
Wolfram Rösler21-Jan-07 21:59
Wolfram Rösler21-Jan-07 21:59 
Generalprinting Pin
AlexDa1-Dec-05 23:25
AlexDa1-Dec-05 23:25 
GeneralCombine pages with portrait and landscape Pin
Stoil24-Sep-04 4:47
Stoil24-Sep-04 4:47 
GeneralRe: Combine pages with portrait and landscape Pin
Stoil16-Oct-04 0:26
Stoil16-Oct-04 0:26 
QuestionFont Bug ? Pin
mroy_10016-Feb-04 5:44
mroy_10016-Feb-04 5:44 
GeneralFrom landscape to full setup Pin
asconaga3-Dec-03 3:08
asconaga3-Dec-03 3:08 
GeneralProblem with hiding the view Pin
wolfbert17-Oct-03 2:27
wolfbert17-Oct-03 2:27 
Hello,
first very nice job, seems to be very helpfull

But before i could even think using this new Print Preview, maybe somebody could help me with following problem.

I use Visual STudio .Net (VC++7.0), migrated a middlesized Application from VC++6.0, But experiences hangups when I try to switch into Print preview.
I debugged the project and found out that so far everything seems right, Until in
CFrameWnd::OnSetPreviewMode,
following code is executed
HWND hWnd = ::GetDlgItem(m_hWnd, pState->nIDMainPane);
ASSERT(hWnd != NULL); // must be one that we are hiding!
::ShowWindow(hWnd, SW_HIDE);
where
pState->nIDMainPane==AFX_IDW_PANE_FIRST
which should be correct, and the retrieved hWnd seems to be ok too (Its not NULL) but then on the ::ShowWindow command, somehow the application went into an endless loop...

Did anybody had the same Problems and could solve this?

THanks in Advance
Wolfbert

Generalvery useful Pin
Marco Walle25-Sep-03 5:45
Marco Walle25-Sep-03 5:45 
GeneralJust a little improvement... Pin
Kickaha19-Sep-03 13:29
Kickaha19-Sep-03 13:29 
Generali want to send u my Projectzip Pin
Balaji20001-Jun-03 20:57
Balaji20001-Jun-03 20:57 
GeneralAny body Know !..Help Me!.. Pin
Balaji200029-May-03 2:07
Balaji200029-May-03 2:07 
General...I need help on overwriting CWinApp Pin
vanjaESS7-May-03 10:25
vanjaESS7-May-03 10:25 
GeneralProblems with VC++ 7 Pin
Paul Steane7-Mar-03 22:19
Paul Steane7-Mar-03 22:19 
GeneralRe: Problems with VC++ 7 Pin
Paul Steane6-Nov-04 9:12
Paul Steane6-Nov-04 9:12 
GeneralAnother Bug/Oversite found Pin
Eldon Zacek1-Jan-03 18:30
Eldon Zacek1-Jan-03 18:30 
QuestionHow to realize multipage printpreview in a D/V whose parent class is CStrollView? Pin
william_shen1-Jan-03 2:26
william_shen1-Jan-03 2:26 
AnswerRe: How to realize multipage printpreview in a D/V whose parent class is CStrollView? Pin
Roger Allen2-Jan-03 0:41
Roger Allen2-Jan-03 0:41 
Generalquestion about CPrintDialog and DEVMODE Structure Pin
lavocat2-Dec-02 0:21
lavocat2-Dec-02 0:21 
GeneralGreat, but one more question Pin
lubin25-Oct-02 15:33
lubin25-Oct-02 15:33 
GeneralRe: Great, but one more question Pin
Roger Allen21-May-04 1:58
Roger Allen21-May-04 1:58 
GeneralBug... Pin
Mulot16-Sep-02 10:36
Mulot16-Sep-02 10:36 
GeneralTool bar buttons are slow?! Pin
Mulot16-Sep-02 10:27
Mulot16-Sep-02 10:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.