[Webinar] Streamline your web hosting managementRegister Today

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 396
  • Last Modified:

SDI App with different views - access to document object

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))
            return FALSE;

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)
      CRuntimeClass* prcNew;
      CCreateContext context;
      SIZE size;

      size.cx = 100;
      size.cy = 100;

      BOOL bSetActive;
      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)
            return FALSE;

// 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)



      return (1);

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
      return (CGuiExplorerDoc*)m_pDocument;

that returns the m_pDocument. I realized that this works only (I think?) because in "Gui Explorer.cpp" the following is run:

      CSingleDocTemplate *pDocTemplate;
      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 ...
  • 2
1 Solution
your global config class can be stored as a public member of CWinApp derived class in your sdi app. all the views will have the #include "yourapp.h" so, they can access the app object with code like

CMyApp* pApp = (CMyApp*)AfxGetApp() ;
//you could access the public member of config class from the pApp pointer

or in your app header, after the class declaration, add the line, extern CMyApp theApp ;

then you could access CMyApp from all the cpp files that include app.h

like theApp.configClass.

VisualStudio.net generates code in the second method.

how many document classes do you have? if each of your view class have separate document classes, you should add the corresponding documents runtime class into the CCreateContext's m_pCurrentDoc as RUNTIME_CLASS(YOUR_DOCCLASS), then the view's GetDocument code will work for you to give the correct doc.

if you plan to add one document and access it from all the views, you could do a
GetActiveFrame() to get the frame ptr, GetActiveDocument() to get the document ptr from the frame and cast it to the explorerdoc ptr, use it.

FlorianJaegerAuthor Commented:
Thank you VERY much. This works just right. I just always thought that I would *have* to use the document class for the configuration when it technically, I suppose, doesn't matter.

You saved me lots of time. It was in the back of my head but I just thought that had to be a way with the document class. Well there might still be with your last sentences but that works just fine.

And yes, I only have one "document" - this one class that holds the entire configuration data.

Thanks a LOT.
FlorianJaegerAuthor Commented:
Oops, pressed the wrong button. Questions solved - MANY many thanks.

Featured Post

Receive 1:1 tech help

Solve your biggest tech problems alongside global tech experts with 1:1 help.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now