dcsimg

Print Preview in MDI Frame

WEBINAR:
On-Demand

Desktop-as-a-Service Designed for Any Cloud ? Nutanix 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



This article was originally published on January 15th, 1999

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date