Switching views : season 2
Hi,
In my SDI application I have defined a CBaseFrame deriving from
CFrameWnd and that allow me to switch between view dynamically
created.Here is the code I suse
//CREATE_ONCE means view is create once and never deleted when switching
//CREATE_AND_DESTROY means views are deleted/recreated on switch
CBaseFrame::stViewInfo CBaseFrame::m_ViewInfo[] =
{
{ IDD_MAIN_FORM, CBaseFrame::CREATE_ONCE, AFX_IDW_PANE_FIRST + 0, NULL },
{ IDD_WELCOME_DLG, CBaseFrame::CREATE_AND_DESTROY,
AFX_IDW_PANE_FIRST + 1, NULL },
{ IDD_WIZZARD_DLG, CBaseFrame::CREATE_AND_DESTROY, AFX_IDW_PANE_FIRST
+ 2, NULL },
{ IDD_OPTIONS_DLG, CBaseFrame::CREATE_AND_DESTROY, AFX_IDW_PANE_FIRST
+ 3, NULL },
{ IDD_CNX_DLG, CBaseFrame::CREATE_AND_DESTROY, AFX_IDW_PANE_FIRST +
4, NULL },
{ IDD_SCHEDULE_DLG, CBaseFrame::CREATE_AND_DESTROY, AFX_IDW_PANE_FIRST
+ 5, NULL },
{ IDD_HISTORY_DLG, CBaseFrame::CREATE_AND_DESTROY, AFX_IDW_PANE_FIRST
+ 6, NULL },
{ IDD_ABOUT_DLG, CBaseFrame::CREATE_AND_DESTROY, AFX_IDW_PANE_FIRST +
7, NULL },
};
LRESULT CBaseFrame::OnSwitchView( WPARAM wParam, LPARAM lParam )
//CView* CBaseFrame::SwitchView( UINT a_ViewId )
{
int iCurViewIdx = 0;
int iNewViewIdx = 0;
CView* pCurView = NULL;
CView* pNewView = NULL;
BOOL bDestroyOldView = FALSE;
UINT ViewId = (UINT) wParam;
//Get current active view
pCurView = m_pFrame->GetActiveView();
TRACE( _T("CViewMgr::SwitchView : pCurView = 0x%x\r\n"), pCurView );
if ( pCurView == NULL)
return 0L;
//Get Curview and NextView index
iCurViewIdx = GetIndexFromView( pCurView );
iNewViewIdx = GetIndexFromId( wParam );
if ((iCurViewIdx == -1) || (iNewViewIdx == -1))
return 0L;
pNewView = m_ViewInfo[iNewViewIdx].pView;
// View is already displayed
if ( pNewView == pCurView ){
return 0L/*pCurView*/;
}
// New view is NULL - we must create it
if ( pNewView == NULL ){
pNewView = CreateView( ViewId, iNewViewIdx);
TRACE( _T("pNewView = 0x%x\r\n"), pNewView );
if (pNewView != NULL){
// Save new created view
m_ViewInfo[iNewViewIdx].pView = pNewView;
}
}//pView == NULL
//Make sure that the document won't be destroyed when the view is
destroyed.
//m_bAutoDelete is a public, but non-documented member of CDocument.
CDocument* pCurrentDoc = m_pFrame->GetActiveDocument();
pCurrentDoc->m_bAutoDelete = FALSE;
// exchange view window ID's so RecalcLayout() works
UINT temp = ::GetWindowLong(pCurView->m_hWnd, GWL_ID);
::SetWindowLong(pCurView->m_hWnd, GWL_ID,
::GetWindowLong(pNewView->m_hWnd, GWL_ID));
::SetWindowLong(pNewView->m_hWnd, GWL_ID, temp);
// Hide Old view
pCurView->ShowWindow(SW_HIDE);
//OnInitialUpdate() is not called as a result of calling CreateView()
above.
//It is not always called by the framework, so it is called here:
pNewView->OnInitialUpdate();
// Now show the new view
pNewView->ShowWindow(SW_SHOW);
m_pFrame->SetActiveView(pNewView);
m_pFrame->RecalcLayout();
pNewView->Invalidate();
// try to destroy old view
if ( m_ViewInfo[iCurViewIdx].eCreationMode == CREATE_AND_DESTROY){
pCurView->DestroyWindow();
m_ViewInfo[iCurViewIdx].pView = NULL;
}
return 0L/*pNewView*/;
}
The problem happens when I try to destroy the old view :
// try to destroy old view
if ( m_ViewInfo[iCurViewIdx].eCreationMode == CREATE_AND_DESTROY){
pCurView->DestroyWindow();
m_ViewInfo[iCurViewIdx].pView = NULL;
}
I have the following assert :
Assert wincore.cpp(windows CE) 442
LRESULT CALLBACK
AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
// special message which identifies the window as using AfxWndProc
if (nMsg == WM_QUERYAFXWNDPROC)
return 1;
// all other messages route through message map
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
ASSERT(pWnd != NULL && pWnd->m_hWnd == hWnd);
....
}