Nice Post. ---------- I love http://youtube.com
ReplyAfter messing arround with the code supplied and some other code i found from microsoft i came up with this. don't forget this implementation is for MDI applications i recommend moving this function to the CMDIChildWnd subclass for a few reasons: 1. A document should not be controling it's views (that's the job of the parent * (ie : CMDIChildWnd) 2. it just plain makes more sense *a view should not manage it's document, as this is also the job of the parent. because the view is not destroyed i found it more suitable in my code to maintain the references to the views elsewhere and pass a reference to the new view rather then the CRuntimeClass. if you manage the references in the same class that controls switching views and each View (class) has only one instance (one to one relationship) then you could pass the runtime class and iterate over your collection of views to find the coresponding view void CMDIChildWndSubclass::SwitchToView(CView * pNewView) { //get main wnd CMDIFrameWnd* pMainWnd = (CMDIFrameWnd*)AfxGetMainWnd(); // Get the active MDI child window. CMDIChildWnd* pChild = (CMDIChildWnd*)pMainWnd->MDIGetActive(); // Get the active view attached to the active MDI child window. CView* pOldActiveView = pChild->GetActiveView(); //Get the coresponding document CDocument * doc = pChild->GetActiveDocument(); // If we're already displaying this kind of view, no need to go further. if (pOldActiveView == pNewView) return; //this ensures proper client area it used for RecalcLayout int oldID = pNewView->GetDlgCtrlID(); pNewView->SetDlgCtrlID(AFX_IDW_PANE_FIRST); pOldActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST + 1); //don't show the old view pOldActiveView->ShowWindow(SW_HIDE); //disconnect all views (the old view) doc->DisconnectViews(); //add the new view doc->AddView(pNewView); //show the new view pNewView->ShowWindow(SW_SHOW); //recalc the layout pChild->RecalcLayout(); //invalidate the new view to ensure it is repainted in UpdateWindow (in case the document was changed while it wasn't active) pNewView->Invalidate(); //Update the view pNewView->UpdateWindow(); //set the active view pChild->SetActiveView(pNewView); } if you're wondering about how to create the view... it really doesn't matter as long as the view is valid and has been created (view->Create(...)) i can only assume this works (i had to remove a few things unique to my application) and so i leave no guarantee whatsoever to this code, use at your own risk. Bugs? Questions? Comments? email me: ark_schuck@hotmail.com Mark
ReplyWorked great however, for VC++.NET(7) I had to
substitute:
ASSERT(pSplitter->IsChildPane(pOldActiveView, &row, &col));
for
ASSERT(pSplitter->IsChildPane(pOldActiveView, row, col));
I'm not sure if this is a change in IsChildPane, a typo, or my mistake but passing the address works for me.
Additionally, I had a similar problem with initializing various controls in the OnInitialUpdate function. It seems
as though it was not getting called for the non-default View. Anyway, it was fixed by performing the following:
CRuntimeClass* pNewViewClass = RUNTIME_CLASS(CForm);
if (!SwitchToView(pNewViewClass))
TRACE ("Didn't Do CForm\n");
else
{
CMDIFrameWnd* pMainWnd = (CMDIFrameWnd*)AfxGetMainWnd();
// Get the active MDI child window.
CMDIChildWnd* pChild = (CMDIChildWnd*)pMainWnd->MDIGetActive();
// Get the active view attached to the active MDI child window.
CView* pActiveView = pChild->GetActiveView();
pActiveView->OnInitialUpdate();
TRACE ("CForm Worked \n");
}
Reply
Originally posted by: Heiko Kortlang
I have a problem with the InitialUpdate Function in my FormView class, cause i initialize my ComboBoxes in the InitialUpdate(). In release version the program crashes because the ComboBoxes are not created.
In my FormView class i added the
ON_MESSAGE(WMU_INITIALUPDATE, OnInitialUpdate)
How can i delay the event to trigger the InitialUpdate()
Originally posted by: Filip Rak
Thanks for a piece of great work, ive found it after sleepless night when trying to do it alone !!
Agan - thank You !!
Originally posted by: Lie Gu
First let us take a look at the source code of ChtmlView in MFC:
/////////////////////////////////////////////////////////////////////////////
void CHtmlView::OnDestroy()
The amazing happens here, it seems it dose not call the CView.OnDestory function before release m_pAPP. Let's go on to look CView::OnDestroy() function:
void CView::OnDestroy()
When you destroy a ChtmlView, the "ActiveView" remains unchanged. That's where the exception comes from. So the solution is very simple, inherited from CHtmlView and rewrite the OnDestroy function.
class CHtmlView2 : public CHtmlView
/////////////////////////////////////////////////////////////////////////////
void CHtmlView2::OnDestroy()
You cannot simplly switch to CHtmlView from other views. I found this problem when I was trying to write an outlook style interface. Here is the solution.
// CHtmlView message handlers
{
RELEASE(m_pBrowserApp);
}
{
CFrameWnd* pFrame = GetParentFrame();
if (pFrame != NULL && pFrame->GetActiveView() == this)
pFrame->SetActiveView(NULL); // deactivate during death
~~~~~~~~~~~~~~~~~~~~~~~~~
CWnd::OnDestroy();
}
{
protected:
CHtmlView2(); // protected constructor used by dynamic creation
DECLARE_DYNCREATE(CHtmlView2)
…………………..
…………………..
// Generated message map functions
//{{AFX_MSG(CHtmlView2)
afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
// CHtmlView2 message handlers
{
CHtmlView::OnDestroy();
CView::OnDestroy();
// TODO: Add your message handler code here
}
I was searching for this problem and suddenly found it from your post. So can't stop myself to thank you.
ReplyOriginally posted by: Oliver
I use your code and I'm very satisfied with it. But I have one problem. If I maximize a view and the change to another view, this next view is not maximized but the system menu (minimize, normal and close button) are located at the position of a maximized view. This means these buttons are at the right hand side of the programs menu.
How to solve this problem? How can I ensure that a maximize view is shown as maximized (using the whole area) or how to force the new view to be shown in a normal size?
Oliver
ReplyOriginally posted by: DGK
Is it possible to create a second and third recordview, each with its own recordset and how does one switch between these views?
ReplyOriginally posted by: Freudi
if i have a usercontrol on one of the forms you cant create the pane. Any idea.
I use vc60 under XP/2000
Originally posted by: Dark
works not, perhaps because CRecordView is from CFormView?
Reply