?
Solved

SDI App with different views - access to document object

Posted on 2003-03-21
3
Medium Priority
?
388 Views
Last Modified: 2013-11-20
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 ...
0
Comment
Question by:FlorianJaeger
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
3 Comments
 
LVL 9

Accepted Solution

by:
Priyesh earned 2000 total points
ID: 8187312
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
pApp->configClass...

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.

Regards,
PGP
0
 

Author Comment

by:FlorianJaeger
ID: 8187471
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.
0
 

Author Comment

by:FlorianJaeger
ID: 8187473
Oops, pressed the wrong button. Questions solved - MANY many thanks.
0

Featured Post

New benefit for Premium Members - Upgrade now!

Ready to get started with anonymous questions today? It's easy! Learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
Suggested Courses

800 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question