Link to home
Start Free TrialLog in
Avatar of FlorianJaeger
FlorianJaeger

asked on

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))
      {
            m_wndSplitter.DestroyWindow();
            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 );
                                                break;
            case DIALOG_FILTER:            prcNew = RUNTIME_CLASS( CViewFilter );
                                                break;
            case DIALOG_TARGET:            prcNew = RUNTIME_CLASS( CViewTarget );
                                                break;
            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;
      else
            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)
            m_wndSplitter.GetParentFrame()->SetActiveView(pNewView);

      m_wndSplitter.RecalcLayout();

pNewView->OnInitialUpdate();
      pNewView->SendMessage(WM_PAINT);

      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
{
      ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CGuiExplorerDoc)));
      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(
            IDR_MAINFRAME,
            RUNTIME_CLASS(CGuiExplorerDoc),
            RUNTIME_CLASS(CMainFrame),       // main SDI frame window
            RUNTIME_CLASS(CLeftView));
      AddDocTemplate(pDocTemplate);

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:

      pDoc->RemoveView(pActiveView);
      pDoc->AddView(pNewView);      

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 ...
ASKER CERTIFIED SOLUTION
Avatar of Priyesh
Priyesh

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of FlorianJaeger
FlorianJaeger

ASKER

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.
Oops, pressed the wrong button. Questions solved - MANY many thanks.