0
votes

I am migrating an old MFC MDI (multi document interface) application from Visual Studio 6 to Visual Studio 2013. The process was pretty much straight forward, but now I'm stuck with a problem concerning print preview.

When I compile the program with Visual Studio 6, print preview looks like this :

enter image description here

The preview window takes over the main frame window, removing the menu and the tool bar.

But the same program compiled with Visual Studio 2013 looks like this:

enter image description here

The print preview takes place within the view’s frame window and this behavior is not acceptable for various reasons. While stepping through the MFC sourcecode on both VS6 and VS2013 I have found out that the difference boils down to how MFC's CView::DoPrintPreview method obtains the frame window for the print preview.

The relevant parts of CView::DoPrintPreview (in viewprev.cpp) are here:

Visual Studio 6

BOOL CView::DoPrintPreview(UINT nIDResource, CView* pPrintView,
    CRuntimeClass* pPreviewViewClass, CPrintPreviewState* pState)
{
    ASSERT_VALID_IDR(nIDResource);
    ASSERT_VALID(pPrintView);
    ASSERT(pPreviewViewClass != NULL);
    ASSERT(pPreviewViewClass->IsDerivedFrom(RUNTIME_CLASS(CPreviewView)));
    ASSERT(pState != NULL);

    CFrameWnd* pParent = STATIC_DOWNCAST(CFrameWnd, AfxGetMainWnd());
    ...

Here pParent will simply contain the main frame window.

Visual Studio 2013

BOOL CView::DoPrintPreview(UINT nIDResource, CView* pPrintView,
    CRuntimeClass* pPreviewViewClass, CPrintPreviewState* pState)
{
    ASSERT_VALID_IDR(nIDResource);
    ASSERT_VALID(pPrintView);
    ASSERT(pPreviewViewClass != NULL);
    ASSERT(pPreviewViewClass->IsDerivedFrom(RUNTIME_CLASS(CPreviewView)));
    ASSERT(pState != NULL);

    CWnd* pMainWnd = GetParentFrame();
    if (DYNAMIC_DOWNCAST(CFrameWnd, pMainWnd) == NULL)
    {
        // if it's not a frame, we'll try the main window
        pMainWnd = AfxGetMainWnd();
    }

    CFrameWnd* pParent = STATIC_DOWNCAST(CFrameWnd, pMainWnd);
    ...

Here pParent will contain the view’s frame window (obtained via GetParentFrame()) instead of the main frame window.

Notes

  • This behaviour occurs on most if not all Visual Studio versions above Visual Studio 6.
  • This is only an issue with MDI programs, the behaviour with SDI programs remains the same, which BTW is normal as with SDI, the view's frame window is actually the main frame window.

Does anybody know how I can obtain the same beaviour with Visual Studio that with Visual Studio 6 without the need of reimplementing half of MFC's CView and CPreviewView classes ?

1
I had somewhat related issue but not the same when I was converting VC6 project to VS10, my print preview would crash. I had to derive my own print preview class from CView - if that's give you a pointer.The new model is more accurate though because it is more true MDI like. Try to make case if you can stick with it.zar
What about creating your own CFrameWnd to act as a temporary parent to the CView?user1793036
@user1793036: could you provide some more details ?Jabberwocky

1 Answers

0
votes

I am not sure if it works, but you can try to use SetParent.

  • Saddly CView::DoPrintPreview isn't virtual. So overwrite CView::OnFilePrintPreview. The implementation is simple and just calls DoPrintPreview.
  • Now use GetParent and save the old Parent of the view. Save it.
  • Use SetParent and attach the view to the AfxGetMainWnd
  • Call DoPrintPreview
  • After DoPrintPreview returns use SetParent and set the old saved parent handle again.

Should work, because the structure of Frame and view is than identical to the SDI form of the application.