Print Preview in MDI Frame

Between Visual C++ 4.2 and 5.0 the behavior of displaying the print preview in MDI applications has changed.
This issue is covered by MSDN Article ID: Q166135

In 5.0 the preview is not longer displayed in the MDI-Frame, it’s in the MDI-Child.
This results in a small preview area which is even smaller, if there are docking toolbars, and the user interface is fully functioning during preview.
I think that this is unusable for many applications.

The reason is the following determination of the parent frame:


// VC 4.2
BOOL CView::DoPrintPreview(UINT nIDResource, CView* pPrintView,
CRuntimeClass* pPreviewViewClass, CPrintPreviewState* pState)
{

CFrameWnd* pParent = (CFrameWnd*)AfxGetThread()->m_pMainWnd;
ASSERT_VALID(pParent);
ASSERT_KINDOF(CFrameWnd, pParent);

}

// VC 5.0
BOOL CView::DoPrintPreview(UINT nIDResource, CView* pPrintView,
CRuntimeClass* pPreviewViewClass, CPrintPreviewState* pState)
{

CFrameWnd* pParent;
CWnd* pNaturalParent = pPrintView->GetParentFrame();
pParent = DYNAMIC_DOWNCAST(CFrameWnd, pNaturalParent);
if (pParent == NULL || pParent->IsIconic())
pParent = (CFrameWnd*)AfxGetThread()->m_pMainWnd;

}

To get back the old behavior the following this must be done:

1. Write your own DoPrintPreview() in your MDI View class

This function is mostly a copy of CView::DoPrintPreview() with 2 changes.


BOOL CMDIView::DoPrintPreview(UINT nIDResource, CView* pPrintView,
CRuntimeClass* pPreviewViewClass, CPrintPreviewState* pState)
{

// 1.) Use the MDI Frame as the parent
CFrameWnd* pParent = (CFrameWnd*)AfxGetThread()->m_pMainWnd;
ASSERT_VALID(pParent);
ASSERT_KINDOF(CFrameWnd, pParent);


// 2.) Deactivate the MDIChild and display the desired menu
CChildFrame *pChildFrame = DYNAMIC_DOWNCAST (CChildFrame, pParent->GetActiveFrame());

if (pChildFrame)
{
// Save the original shared menu
HMENU hMenuShared = pChildFrame->GetSharedMenu ();

// Set the displayed menu during preview to NULL or to the desired menu
pChildFrame->SetSharedMenu (NULL);

// Deactivate the MDIChild
pChildFrame->SendMessage (WM_MDIACTIVATE, 0, 0);

// Restore the shared menu
pChildFrame->SetSharedMenu (hMenuShared);
}

}

2. Make a derivation of CPreviewView

In CView::DoPrintPreview(), lots of protected members from CPreviewView are used.
This isn’t longer possible in your own DoPrintPreview().


The solution is to declare the CMDIView as a friend of CMyPreviewView.


class CMyPreviewView : public CPreviewView
{
protected:
CMyPreviewView();
DECLARE_DYNCREATE(CMyPreviewView)

friend class CMDIView;
};

3. Write menu access function in the MDI Child Frame


class CChildFrame : public CMDIChildWnd
{
DECLARE_DYNCREATE(CChildFrame)
public:
CChildFrame();

// Operations
public:
HMENU GetSharedMenu () const { return m_hMenuShared; }
void SetSharedMenu (HMENU hMenuShared) { m_hMenuShared = hMenuShared; }

};

Download demo project – 20 KB

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read