Print Preview without the Doc/View Architecture

Environment: VC6 SP3, NT4 SP5, Windows 2000 Beta 3

This code allows you to make use of the MFC print preview architecture without
using the document/ view architecture. This is accomplished by overriding some
key functions from the MFC CView class and CPreview class. I have introduced two
new classes with the required overrides called CWrapperView and CMyPrintPreview.
I will explain how to integrate these classes into a new MFC project created without
the use of the document/ view architecture.

Create a new MFC project without the document view architecture. Add WrapperView.cpp,
WrapperView.h, and MyPreview.h to your project.

Open the ChildView.h file and include the header file WrapperView.h. Now change the parent
class to CWrapperView and add the DECLARE_DYNCREATE macro to the class.


	class CChildView : public CWrapperView
	{
		DECLARE_DYNCREATE(CChildView)
		:
		:
		:
	}

Open MainFrm.h and change


	ChildView m_wndView;

To


	CChildView  *m_pView;

Open MainFrm.cpp and remove the following code from the OnCreate function


	if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
	CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
	{
		TRACE0("Failed to create view windown");
		return -1;
	}

And replace it with


	CCreateContext context;
	context.m_pNewViewClass = RUNTIME_CLASS(CChildView);
	context.m_pCurrentFrame = this;
	context.m_pCurrentDoc = NULL;
	context.m_pLastView = NULL;

	m_pView = STATIC_DOWNCAST(CChildView, CreateView(&context));
	if(m_pView != NULL)
	{
		m_pView->ShowWindow(SW_SHOW);
		SetActiveView(m_pView);
	}

Use the class wizard to add command handlers for ID_FILE_PRINT and ID_FILE_PRINT_PREVIEW
to CMainFrame and edit the new functions to…


	void CMainFrame::OnFilePrint()
	{
		m_pView->OnFilePrint();
	}

	void CMainFrame::OnFilePrintPreview()
	{
		m_pView->OnFilePrintPreview(this);
	}

OnFilePrintPreview has been overriden to take a pointer to the owner frame (in this case
CMainFrame) as this is needed in the overriden DoPrintPreview function. The defualt
implementation uses AfxGetMainWnd() but sometimes we don’t want to use the main window
we want to use another frame window derived from CFrameWnd

Open ChildView.cpp and add the following code


	void CChildView::OnFilePrint()
	{
		CView::OnFilePrint();
	}

	IMPLEMENT_DYNCREATE(CChildView, CWrapperView)

Now add a command handler to the CChildView message map


	ON_COMMAND(ID_FILE_PRINT, OnFilePrint)

Open ChildView.h and add


	public:
		void OnFilePrint();

We have to add this overide for the OnFilePrint function because the default implementation
in CView is protected and seeing as we need to invoke it from our frame window (CMainFrame,
in the File Print Command Handler) we have to make it public in our derived view and then
call the default implementation.

Now use the class wizard to add an OnDraw function to your view class and add code to call
OnDraw from OnPaint.


	void CChildView::OnPaint()
	{
		CPaintDC dc(this); // device context for painting

		OnDraw(&dc);

		// Do not call CWnd::OnPaint() for painting messages
	}

Now all that remains is to add some code to your OnDraw function.


	OnDraw(CDC *pDC)
	{
		CRect client;
		GetClientRect(&client);
		client.DeflateRect(50, 50);
		CBrush brush(RGB(255, 0, 0));
		pDC->FillRect(&client, &brush);
	}

The same process needs to take place if you have derived a class from CFrameWnd and
want to add MFC print preview support to it. The only difference is that you have to
do a bit more work by creating the view class yourself.

Downloads

Download demo – 8 Kb
Download source – 21 Kb

More by Author

Must Read