Link to home
Start Free TrialLog in
Avatar of FlorianJaeger
FlorianJaeger

asked on

SDI Application with split windows

This is what I want:

It's going to be a SDI application that will be split in the middle. On the left I will have a tree control that will basically show all configuration options in a tree (like general, sub options and such). If a user clicks on the particular item in the tree control then a particular dialog resource should be displayed in the right window.

So in the right window I will display the appropriate dialog resource, depending on what the user clicked in the left tree control.

The project will therefore consist of a tree control and several (about 6 or 7) dialogs.

The window should be resizable, so that users can make the left window wider or more narrow.

The big question is: What's the easiest (smartest?) way to do this? I don't have too much MFC experience, some code examples would be great.

I already looked at codeguru & codeproject but didn't see anything that really was what I was looking for.

Thanks - I'm willing to raise the points if necessary ...
Avatar of suganthkumar1
suganthkumar1

I the VC6 wizard itself there is an option to choose Explorer stye (which will enable the Left side tree control and a splitter window).

You can create as much as dilog templates as you require and create View class (derived from CFormView) for those forms instead of CDialog.

when ever you get a message to change the form, you can use the following code

void SwitchView(UINT nNew)
{
 // you have to use an array of view pointers
 // or a pointer for each view (form)
   
   CView *pViewOld, *pViewNew;

   *pViewOld = m_wndSplitterWnd.GetDlgItem(m_wndSplitterWnd.GetIdFromRowCol(0, 1)); // get the Current View

   swicth(nNew)
   {
   case XX:
      if (m_pXView == NULL )
      {
         m_pXView = RUNTIME_CLASS(CXForm)->CreateObject();
         m_pXView->Create(AfxRegisterWndClass(CS_DBLCLKS), "", WS_CHILD, CRect(0, 0, 425, 278),
          &m_wndSplitterWnd, IDD_X_FORM, NULL);
      }

      *pViewNew = m_pXView;
   }

   pViewOld->SetDlgCtrlID(pViewNew->GetDlgCtrlID());
   pViewNew->SetDlgCtrlID(m_wndSplitterWnd.GetIdFromrowCol(0,1);

   pViewNew->MoveWindow( <size to fit your parent window > );

   if ( pViewOld == pViewNew )
       return;


   pViewNew->ShowWindow(SW_SHOW);
   pViewOld->ShowWindow(SW_HIDE);
   
}

You can use this function in your program to swith between different forms.

Avatar of FlorianJaeger

ASKER

Gee, I had no idea VC came with that feature!! I should probably pay more attention to the wizard I use all the time.

I'll give it a try and let you know!

Thanks so far!
Maybe you can help me out a little more. I have only used a SDI application once, all the other times only dialog based apps.

Now the code you gave me only works in the CMainFrame class - however I was thinking about handling OnLButtonDblClk in the CLeftView class to determine what item was actually selected when the user clicked in the tree view.

So I assume that best way to do that is send a message to the CMainFrame class? Would you agree? I have not really done that yet - send custom messages - can you help?

Also it is a little more complicated. When somebody clicks in the tree then I need to pass some informations to that particular view class (after creating the view / displaying it). For example if it will be an empty form or if the form will load some data.

Well, then I have developed a class that is supposed to be used by the whole app - it's a class that stores and manipulates the configuration of the app. In which class should I store this class to make it accessible to all the view classes (and the LeftView class)?

Sorry I hope that's not too much :(

Thanks ..
Well I am doing some reading now ... it seems as if I should put my configuration class that stores all configuration values into the document view ...

.. but I'm not sure about the rest - just wanted to keep you updated ...

thanks
better you do one thing, Manage all your operations through the CMainFrame Class. Send custom messages when th e user does clicks. through CMainFrame class you will get the current View pointer and do the needed with the current view. (In this case better not to talk with the view directly from the list control).

Enjoy..
Now that I have the messages working between the classes I would like to try the code you gave me but it doesn't work.

First I realized that the var is m_wndSplitter and not m_wndSplitterWnd, the function is called IdFromRowCol() and not GetIdFromRowCol().

The line:

*pViewOld = m_wndSplitter.GetDlgItem(m_wndSplitter.IdFromRowCol(0, 1));

causes the following error:

error C2582: 'CView' : 'operator =' function is unavailable

Any ideas?

Thanks.
GetDlgItem Function returns only CWnd* you type cast it to CView* and use it.
I don't know, I found the following sample code (split32) on MSDN and it works. Of course I'll have to adapt it a little but still. Your code also has a lot of typos which is inconvenient.

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

CCreateContext context;
BOOL bSetActive;

if ((m_wndSplitter.GetPane(0, 1)->IsKindOf(RUNTIME_CLASS(CViewDialog2)))==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   = RUNTIME_CLASS(CViewDialog2);
context.m_pCurrentDoc     = pDoc;
context.m_pNewDocTemplate = NULL;
context.m_pLastView       = NULL;
context.m_pCurrentFrame   = NULL;
   
m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CViewDialog2), size, &context);
   
CView * pNewView= (CView *) m_wndSplitter.GetPane(0,1);
   
if (bSetActive == TRUE)
     m_wndSplitter.GetParentFrame(->SetActiveView(pNewView);
   
m_wndSplitter.RecalcLayout();
m_wndSplitter.GetPane(0, 1)->SendMessage(WM_PAINT);
ASKER CERTIFIED SOLUTION
Avatar of modulo
modulo

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