Switch persistent views in MDI app
Hi,
I am trying to switch between views in a MDI app but I can't.
I found some examples but I am not satisfied with them because they put
it in CDocument. To me it should be in CWinApp or even better in
CmainFrame for a SDI and ChildFrame for a MDI.
Anyway here is the code I use for my MDI app, but the line
pDoc->AddView(pNewView); in the SwitchToView gives me an exception with
the following line from debugger:
if (!AfxIsValidAddress(pOb, pOb->GetRuntimeClass()->m_nObjectSize, FALSE))
__vfptr 0xfeeefeee
I don't understand, all my views are declare DYNAMIC, ...
Does someone has a clean SwitchToView implementation, I am not
interested by code using CDocument like the ones found on CodeGuru or
CodeProject
// Our different Views
enum EViews
{
eContextView,
eTmpView,
N_VIEWS,
};
BOOL CMyApp::InitInstance()
{
...
// Init all our views
InitViews();
return TRUE;
}
void CMyApp::InitViews()
{
m_nCurView = 0; // Save index of the currently active view class
CMDIFrameWnd* pMainWnd = (CMDIFrameWnd*) AfxGetMainWnd();
CMDIChildWnd* pChild = (CMDIChildWnd*) pMainWnd->MDIGetActive();
CView* pActiveView = pChild->GetActiveView();
m_pViews[0] = pActiveView;
m_pViews[1] = (CView*) new CSmartTokenTesterView;
CDocument* pCurrentDoc = pChild->GetActiveDocument();
CRect rect(0, 0, 0, 0); // gets resized later
// Need to cast pointers to have correct Create functions called
// CForm2 is CFormView::Create
for ( int nView=1; nView < N_VIEWS; nView++ )
{
m_pViews[nView]->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, rect,
pChild, AFX_IDW_PANE_FIRST + 1, NULL);
}
}
CView* CMyApp::SwitchToView( UINT nIndex )
{
ASSERT( nIndex >=0 && nIndex < N_VIEWS );
CMDIFrameWnd* pMainWnd = (CMDIFrameWnd*) AfxGetMainWnd();
CMDIChildWnd* pChild = (CMDIChildWnd*) pMainWnd->MDIGetActive();
CView* pActiveView = pChild->GetActiveView();
CDocument* pDoc = pChild->GetActiveDocument();
if ( !pActiveView ) // No currently active view
return NULL;
CView* pNewView = m_pViews[ nIndex ];
if ( pNewView == pActiveView ) // Already there
return pActiveView;
// Set flag so that document will not be deleted when view is dettached.
BOOL bAutoDelete = m_bAutoDelete;
m_bAutoDelete = FALSE;
// Dettach existing view
pDoc->RemoveView(pActiveView);
// restore flag
m_bAutoDelete = bAutoDelete;
m_nCurView = nIndex; // Store the new current view's index
// exchange view window ID's so RecalcLayout() works
UINT temp = ::GetWindowLong(pActiveView->m_hWnd, GWL_ID);
::SetWindowLong(pActiveView->m_hWnd, GWL_ID,
::GetWindowLong(pNewView->m_hWnd, GWL_ID));
::SetWindowLong(pNewView->m_hWnd, GWL_ID, temp);
// Display and update the new current view - hide the old one
pActiveView->ShowWindow(SW_HIDE);
pNewView->ShowWindow(SW_SHOW);
//((CMDIFrameWnd*) m_pMainWnd)->SetActiveView(pNewView);
//((CMDIFrameWnd*) m_pMainWnd)->RecalcLayout();
//pNewView->Invalidate();
// Attach new view
pDoc->AddView(pNewView);
pChild->RecalcLayout();
pNewView->UpdateWindow();
pChild->SetActiveView(pNewView);
return pActiveView;
}