Daily Archives: June 23, 2006

Getting the real view under a CPreviewView (MFC)

I had an interesting problem at work the other day. In this MFC application, there are a number of views that can be printed and we support the Print Preview function.

However, in one of these views we rely on getting the view from the frame window in order to handle command updates. This is accomplished with code like this:

 pWnd = reinterpret_cast< CBaseView*>(GetActiveView());

However, when you’re in print preview mode, GetActiveView() returns a CPreviewView, not the underlying view (CBaseView). If you look in the source of CPreviewView, you’ll notice that it has a protected member m_pOrigView, which is indeed the one I want. However, there is no way of accessing that value. (I briefly toyed with the idea of directly accessing the memory via its offset from the beginning of the object, but as this software has to run in unpredictable environments, and it’s a horrible idea anyway, I let that go…)

 If you try this:

pWnd=(CBaseView*)pWnd->GetDescendantWindow(MAP_WINDOW);

Where MAP_WINDOW is the ID of the real view that I want, it won’t work (it may work in the general case, but it doesn’t work in my case).

I had two options, just return NULL and tell the higher-level functions to not do those certain command updates when the returned view is NULL. This should be done anyway, so I implemented those checks.

However, it still bugged me that I couldn’t get access to the real view. At last I hit on the idea of going through the document (this uses the Doc/View framework).

 I used this code and it did exactly what I needed:

CDocument* pDoc = GetActiveDocument();
if (pDoc!=NULL) {
    
POSITION pos = pDoc->GetFirstViewPosition();
    
CView* pView = NULL;
    
do {
            
pView = pDoc->GetNextView(pos);
            
if (pView != NULL && pView->IsKindOf(RUNTIME_CLASS(CBaseView)))
                        
return (CBaseView*)pView;     } while (pos!=NULL);
}