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; }
…
};