Replacing a view in an in-place activated server

To fully understand what follows some previous knowledge is required, namely how MFC creates documents, frame windows and views using document templates and how their relationship is maintained in the program. A previous article showing how to replace views in non-OLE applications is a recommended reading.

First of all lets understand how the framework creates OLE frames. When a server object is inserted in a container, a document, a frame window and a view contained within it (or multiple views, if it is a splitter) are first constructed, following common document-template procedures. After that, in response to the OLEIVERB_SHOW OLE verb the COleServerDoc::ActivateInPlace function is called. If there is no previous OLE frame (i.e. it is the first time it will be activated) the OLE frame is created, calling the COleServerDoc::CreateInPlaceFrame function. Here not only the OLE frame is created (using the CDocTemplate::CreateOleFrame function), but also the view in the previously constructed frame window is "connected" to the newly created OLE frame. If the original frame was a splitter, then the view in the first pane is used. The "connection" process consists on changing the view's parent window to the new frame. It is performed calling the COleServerDoc::ConnectView function. The active view on the original frame window is kept (using the m_pActiveView member), because some controls continue to send notification messages to their original parent window. These notification messages should be handled in the original frame window. Once the OLE frame is created and a view is "connected" to it then it is activated.

Now, if we want to replace a view in an OLE frame, we have to replace it in 2 frame windows: the OLE frame and the original frame. The current active view should be destroyed, a new view should be created within the original frame and be later connected to the OLE frame. The active views should be set to NULL first, so no windows message could be sent by the framework to a non-valid view stored in the m_pActiveView member of the frame windows.

To perform this we need a method in our document class, which should receive the new view type as a parameter and return a success flag. The advantage of having this method in the document class becomes obvious when there are several document types each of which can have different view types. Note that the document should be a COleServerDoc descendant. This is how it is done:


BOOL CMyDoc::InPlaceSwitchToView(CRuntimeClass *pNewViewClass)
{
 // The original parent window is saved in m_pOrigParent.
 CFrameWnd* pFrame = (CFrameWnd *)m_pOrigParent;
 // Get the active view.
 CView* pOldActiveView = m_pInPlaceFrame->GetActiveView();
	
 // If we're already displaying this kind of view, no need to go further.
 if (pOldActiveView->IsKindOf(pNewViewClass))
  return TRUE;	

 // No currently active views in either frame
 pFrame->SetActiveView(NULL);
 m_pInPlaceFrame->SetActiveView(NULL);

 // Set flag so that document will not be deleted when view is destroyed.
 BOOL bAutoDelete = m_bAutoDelete;
 m_bAutoDelete = FALSE;
 // Delete existing view	
 pOldActiveView->DestroyWindow();
 // restore flag
 m_bAutoDelete = bAutoDelete;
 // Create new view.
 CView* pNewView = (CView *)pNewViewClass->CreateObject();
 if (pNewView == NULL)
 {
  TRACE1("Warning: Dynamic create of view type %Fs failed\n", pNewViewClass->m_lpszClassName);
  return FALSE;
 }

 // Draw new view.
 CCreateContext context;
 context.m_pNewViewClass = pNewViewClass;
 context.m_pCurrentDoc = this;
 context.m_pNewDocTemplate = NULL;	
 context.m_pLastView = NULL;
 context.m_pCurrentFrame = pFrame;
 if (!pNewView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0, 0, 0, 0), 
  pFrame, AFX_IDW_PANE_FIRST, &context))	
 {
  TRACE0("Warning: couldn't create view for frame\n");		
  delete pNewView;
  return FALSE; 	
 }	

 // Keep the view active in the original frame
 pFrame->SetActiveView(pNewView);

 // Connect the view to the OLE frame
 ConnectView(m_pInPlaceFrame, pNewView);
 pNewView->ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_DRAWFRAME);
 pNewView->SendMessage(WM_INITIALUPDATE, 0, 0);
 // WM_INITIALUPDATE is defined in afxpriv.h
 pNewView->UpdateWindow();
		
 return TRUE;
}

Now that we have a method in our document class that will replace the current view in an OLE frame, lets use it. The new view type should be decided (in response to a menu selection, for instance), and the function must be called as follows:


 CRuntimeClass* pNewViewClass = RUNTIME_CLASS(CMyView);
 if (!InPlaceSwitchToView(pNewViewClass))
  // failed
 else
  // succeeded

Date Last Updated: March 3, 1999



Comments

  • Thanks a lot

    Posted by Legacy on 03/20/2001 12:00am

    Originally posted by: Nyrup

    Thank you - I battled this for hours until I came across you example.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Do you spend a lot of time thinking about your enemies? Attacker attribution - figuring out who's out to get you - is one of the most important things an organization can do to protect itself.  Because you have no hope of defending yourself if you don't understand who the attackers are. Good news? Every organization isn't targeted by all the attackers. Bad news? No one can identify your potential attackers as well as you. Read this graphics-rich threat summary for 2014 to determine who might be your next …

  • Cloud computing isn't new, but it's still a hot topic in technology circles. Moving to the cloud has done great things for many businesses. When it comes to handling a basic business necessity, cloud computing has brought many improvements to overall business continuity. Using the cloud for DR makes a lot of sense for many, but it's not exactly the most simple concept. Read this eBook to find answers to all the key questions IT professionals have about cloud-based disaster recovery, and helpful info around the …

Most Popular Programming Stories

More for Developers

RSS Feeds

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