Link to home
Start Free TrialLog in
Avatar of dcooper080498
dcooper080498

asked on

MDI Grandchild Windows?

I am porting a C Windows application to MFC.  This application uses an interface where each MDI child window has several child windows of it's own.  I'm looking for way to port this arrangement over to MFC, leveraging the most amount of MFC's functionality that I can.  I'm aware that Windows does not support nested MDI Windows. I've experimented with creating CWnds inside an CMDIChildWnd's CView. This almost works Ok, except that the "grandchild" windows don't act like normal windows.  They don't paint their title bars as the active window when they receive the focus and they don't pop to the front when activated by a mouse click down, only when the click is lifted.  

My question:  Should I continue with this approach and try to work around these problems or are there other options I should pursue to get this functionality. Any ideas on how to work around the problems with grandchild CWnd?  I would like to avoid managing the focus and painting in my own code if possible, that is where the C program is getting into trouble.

Splitter windows have already been rejected, there would be too many panes and would be too cumbersome for the user to drag the borders around when they wanted to enlarge a particular pane of information.  Movable, resizable windows are necessary.

Thanks in advance
Avatar of psdavis
psdavis
Flag of United States of America image

Hmmm... Nested MDI windows isn't absolutely impossible. (depends on the definition).  I'm doing a MDI window and when you click on the toolbar inside of the MDI window, then another MDI window pops up.  I'm doing it down three levels and everything seems well.

Here's a little snipplet from my mainfrm class.  The key to it is the last line "pApp->m_pSignatureTemplate->OpenDocumentFile( NULL );" that will open up the new MDI child if it doesn't already exist.  When creating your templates, keep a pointer to them in your main application's header file.  Then when you want to open it, check it against the current open classes to eliminate duplicates.

I hope this helps you.

Phillip


void CMainFrame::OnViewSignature()
{
   CVisaApp* pApp = CVisaApp::GetApp( );

// If the view is already opened, then just go to it!

   CCountryView* pCountryView = NULL;

   POSITION posTemplate = pApp->GetFirstDocTemplatePosition( );
   
   while( posTemplate )
   {
      CDocTemplate* pTemplate = (CDocTemplate*) pApp->GetNextDocTemplate( posTemplate );

      POSITION posDocument = pTemplate->GetFirstDocPosition( );
     
      while( posDocument )
      {
      // If we found a document of this type, then we're already done.  Just activate it!

         CDocument* pDocument = pTemplate->GetNextDoc( posDocument );

         if( pDocument->IsKindOf( RUNTIME_CLASS( CSignatureDoc )))
         {
         // Now iterate all of the windows and activate the first one!

            POSITION posView = pDocument->GetFirstViewPosition( );

            if( posView )
            {
               CView* pView = pDocument->GetNextView( posView );

               ((CMDIChildWnd*) pView->GetParentFrame( ))->MDIActivate( );
            }

            return;
         }
         else if( pDocument->IsKindOf( RUNTIME_CLASS( CCountryDoc )))
         {
         // Now iterate all of the windows and activate the first one!

            POSITION posView = pDocument->GetFirstViewPosition( );

            if( posView )
            {
               pCountryView = (CCountryView*) pDocument->GetNextView( posView );
            }
         }

      }
   }
   
// If the signature list is empty, but the country view is already opened, then limit the signatures to only that one country!

   BOOL GetCurrCountry( CString& strCurrCountry );

   if( pCountryView )
      pApp->m_pSignatureSet->m_strFilter.Format( "[Country Code] = \"%s\"", pCountryView->GetCurrCountry( ));
   else
      pApp->m_pSignatureSet->m_strFilter.Empty( );

   pApp->m_pSignatureSet->Requery( );

   pApp->m_pSignatureTemplate->OpenDocumentFile( NULL );      
}


Avatar of dcooper080498
dcooper080498

ASKER

Thanks for you answer Phillip, but I don't think it is what I am looking for.  It appears that your app is opening MDI siblings when it responds to the toolbar command.  What I am looking for is an MDI child window that itself is the parent of and contains child windows:

CMDIFrameWnd <- MDI parent frame
     CMDIChildWnd <- MDI child frame
        CView
          CWnd <- Window contained in MDI child view or frame
          CWnd <- more of these
          ...  

Let me know if I am mistaken about how your app works.

Dan

No you're not mistaken, but it's the only way that I know to do 'simulated' children.  I do put the toolbars within the MDI windows so at least it seems more sibling like.

Phillip
How about adding your own information to the window classes?  Each window could have it's own member variables for remembering it's parent and children.  You could then add functions like

GetRealParent
GetFirstRealChild
GetNextRealChild
EnumerateRealChildren
etc. etc.

Where the "Real" parents and children used your internal member variables to keep track of who was who.  You could even override the "GetParent" etc CWnd functions, although I wouldn't recommend it.

This might give you the functionality you need without having to get too far away from the built in functionality provided by the MDI API.
Thanks for you comment jstolan.  The problem seems to lie in the message passing up and down the chain of Windows.  While I can create and display windows that are children of an MDI child they don't respond like they should. I'm trying to work as much within the MFC framework as possible.  I guess the kind of answer I am looking for is an "oh yeah, just handle such and such message and everything will work" type of thing that a MFC guru might know about.  Such an answer may not exist, but I would like to put the question out there.

I'm currently trying out a solution using docking toolbar panes like DevStudio debug mode uses.  This doesn't duplicate the look of the program I'm duplicating, but it does work functionally so it really is an aesthetic decision.
Another thing to look at -- A splitter frame does something simmilar to what you are talking about (it contains two sub-windows in one).  You might look at it's implementation for hints on how to imbed CFrameWnd classes in a second CFrameWnd class.  CSplitterWnd does message passing, window selection, etc -- it should be easy to see what you have to override in a e.g. CContainerWnd.
ASKER CERTIFIED SOLUTION
Avatar of psdavis
psdavis
Flag of United States of America image

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
Ding ding ding, we have a winner!  Actually, I'm working on using similar docking CDialogBars extended using the fine examples available from www.codeguru.com.  Without having code in hand, Stingray's description of being able to dock to frames is pretty much what the doctor ordered.  I'm interested in how their focus management works etc.  A bit pricey, but it looks like something to look into.

Thanks, Phillip, for pointing this out.

Best regards,

Dan Cooper
dcooper@fvt.com