SDI App with different views - access to document object
Posted on 2003-03-21
I have created an SDI app in explorer-style. The left window shows the explorer bar with configuration categories for the software, the right pane should display various dialogs with various settings.
Now I created the framework but I am having big troubles accessing the document object from views.
This is how I have it currently setup. I have a function in the MainFrame class that switches view, I took the code of MSDN I believe (it's shown down there).
If the users selects a tree item in the LeftView (=explorer) class then I send a message to the MainFrame class using PostMessage, the parameters wParam & lParam contain information of which dialog to display.
The Mainframe class then switches the view, works.
Previously, when this app was dialog based (not good, that's why I changed it), I had developed a custom configuration class. This class stores the complete configuration of the application. Now all views need to access this class, so I put this class into the MyAppDoc class. Good. I can access this class just fine from the LeftView class so the tree gets displayed correctly.
The AppWizard also created a default View class, note that I am not using this class at all, I am using a different dialog that I derived from the FormView class:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext)
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftView), CSize(200, 100), pContext) ||
!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CWelcomeDlg), CSize(100, 100), pContext))
So I created several dialogs whose classes are derived from the CFormView class. The contain tab dialogs within them and that works fine. Since those dialogs contain a dozen edit boxes and such they need direct access to the configuration class that is stored in the document object. Frankly I don't care where the configuration class is stored as long as every view has access to it. Right now it doesn't have access to it.
The code to switch views is, as stated before, located in the MainFrame class and is called after a message is received from the LeftView class (I removed custom code that's non relevant):
LRESULT CMainFrame::OnChangeView(WPARAM wParam, LPARAM lParam)
size.cx = 100;
size.cy = 100;
BOOL bEdit = FALSE;
if (wParam & ACTION_EDIT)
bEdit = TRUE;
// Determine dialog to display
switch (wParam & 0xFF)
case DIALOG_GENERAL: prcNew = RUNTIME_CLASS( CGeneralOptionsDlg );
case DIALOG_FILTER: prcNew = RUNTIME_CLASS( CViewFilter );
case DIALOG_TARGET: prcNew = RUNTIME_CLASS( CViewTarget );
default: return FALSE;
if ((m_wndSplitter.GetPane(0, 1)->IsKindOf( prcNew ))==TRUE)
// Get pointer to CDocument object so that it can be used in the creation
// process of the new view
CDocument * pDoc= ((CView *) m_wndSplitter.GetPane(0, 1))->GetDocument();
CView * pActiveView = m_wndSplitter.GetParentFrame()->GetActiveView();
if (pActiveView == NULL || pActiveView == m_wndSplitter.GetPane(0, 1))
bSetActive = TRUE;
bSetActive = FALSE;
// set flag so that document will not be deleted when view is destroyed
pDoc->m_bAutoDelete = FALSE;
// Delete existing view
((CView *) m_wndSplitter.GetPane(0, 1))->DestroyWindow();
// set flag back to default
pDoc->m_bAutoDelete = TRUE;
// Create new view
context.m_pNewViewClass = prcNew;
context.m_pCurrentDoc = pDoc;
context.m_pNewDocTemplate = NULL;
context.m_pLastView = NULL;
context.m_pCurrentFrame = NULL;
m_wndSplitter.CreateView(0, 1, prcNew, size, &context);
CView * pNewView = (CView *) m_wndSplitter.GetPane(0, 1);
if (bSetActive == TRUE)
As I said this works very well except for the document problem. Let's take the CViewFilter class for example. In the LeftView class I can just say
CGuiExplorerDoc *pDocObj = GetDocument();
and I have access to the document class. The LeftView class has the code
CGuiExplorerDoc* CLeftView::GetDocument() // non-debug version is inline
that returns the m_pDocument. I realized that this works only (I think?) because in "Gui Explorer.cpp" the following is run:
pDocTemplate = new CSingleDocTemplate(
RUNTIME_CLASS(CMainFrame), // main SDI frame window
Good. So I thought I'd be smart and just add the same function (GetDocument()) to the CViewFilter class and I would get the document object. Of course the ASSERTIOn fails because it never gets the document object.
Allright, then I thought I'd just add the following lines (after reading more through MSDN) to the ChangeView function at the end:
so the document tells the view about it. Unfortunately that doesn't work either, the same problem persists.
So frankly I don't know what to do here - how can I access the document object from dynamically switched views or where should I store my configuration class?
I will always only have this one configuration class, so right now there is no need to add new document templates and such - I just decided to use the SDI model since I would like the menu bar, explorer style display.
Thanks for any insights ...