Re: Single Document MDI-like interface questions
 
On 23 jul, 20:31, Joseph M. Newcomer <newco...@flounder.com> wrote:
See below...
On Thu, 23 Jul 2009 14:10:43 +0200, "Mikel" <mikel.luri_NOSPAM@gmail_NOSP=
AM.com> wrote:
Hi all:
I'm creating a single-document MDI-like application. You know, several
different views on a single document, in an MDI framework.
I'd like it to have a CFormView as a main view, where the user can set s=
ome
"Project" settings and from which the user can open the other views.
So far, I've created the CFormView MDI app, and changed the "new documen=
t"
handling mechanism to close the current document and open a new one, so =
that
only one document (and one FormView) is open at any time. I've also adde=
d
two views, and by following Joe's example in
http://groups.google.es/group/microsoft.public.vc.mfc/browse_thread/t...=
, I
can open them via a menu handler:
void CMainFrame::OnOpenGreenView()
{
   OpenGreenView();
}
void CMainFrame::OpenGreenView()
{
   if (pGreenViewTemplate == NULL)
   {
       pGreenViewTemplate = new CMultiDocTemplate(IDR_GreeVie=
wTYPE,
           RUNTIME_CLASS(CMyDoc),
           RUNTIME_CLASS(CGreenChildFrm),
           RUNTIME_CLASS(CGreeView));
       CMyDoc* doc = (CMyDoc*)GetCurrentDocument();
       CFrameWnd* frame = pGreenViewTemplate->CreateNewFrame(=
doc, NULL);
       if (frame != NULL)
       {
           frame->InitialUpdateFrame(doc, TRUE);
       }
   }
}
I have the same for the other view, say RedView.
Now, how can I handle the situation where the user closes the view and l=
ater
tries to open it?
****
Closes which view?
****>Right now it doesn't open, because the MultiDocTemplate is not destr=
oyed.
****
The point of the code is that the MultiDocTemplate is not *supposed* to b=
e destroyed, at
least not until the CMainFrame::OnDestroy or CMainFrame::~CMainFrame hand=
ler.  THe whole
point of the code is that it may or may not already exist, but if it does=
n't it is created
at the point where it is first needed, and retained until the program ter=
minates.  So you
can't say "it doesn't open because the MultiDocTemplate is not destroyed"=
..  It may not
open for some OTHER reason (that's why single-stepping was invented in th=
e debugger) but
it is *not* because the template is not destroyed!  The template should=
 be created ONCE. I
just chose to not bother to create it until it was needed.
****>I've thought of posting a message to the MainFrame when the ChildFra=
me is
destroyed, so it can destroy the CMultidocTemplate and set it to NULL.
****
That would be a mistake.  There is no REASON to destroy the template, a=
nd in any case, you
must not.destroy it because it must exist!
****>Other
idea I've come across is to hide or minimize the ChildFrame instead of
destroying it and when the user tries to open it again, restore it, but =
I'm
not really sure how to do this.
****
No, this would be wrong.  When you destroy the view, you *want* the chi=
ld frame to be
destroyed!
****
Another problem is I don't know how to switch to an open view. For examp=
le,
the three views are open and maximized, the active one is the FormView, =
and
the user clicks on "open the GreenView". I'd like it to switch to the on=
e
that's already open.
****
That case is simple.  You just get the current active document, and cal=
l its method
ActivateView(RUNTIME_CLASS(CGreenView)).  Since you have made sure you =
have only one
instance of each view, you define this as
BOOL CMyDocument::ActivateView(CRuntimeClass * act)
    { /* scan views */
     POSITION pos = GetFirstViewPosition();
     while(pos != NULL)
        {
         CView * view = GetNextViewPosition(pos);
         if(IsKindOf(view, act))
            { /* found it */
             CMDIChildWnd * wnd = (CMDIChildWnd *)view->G=
etParentFrame();
             wnd->MDIActivate();
             return TRUE;
           } /* found it */
        } /* scan views */
     return FALSE;
   }
Now when you come in to the CreateGreenView handler in the main frame, yo=
u first call
GetActiveDocument().  If this returns NULL, you are in trouble, since t=
he menu item should
not have been activated and you shouldn't be here.  If it is non-NULL, =
you would call the
ActivateView(RUNTIME_CLASS(GreenView)); if it returns TRUE, the view exis=
ts and has been
activated; if it returns FALSE, you create the view.
****
I guess I have to get the ChildFrame from the
CMultiDocTemplate and activate it, but I don't know how to do it, as thi=
s is
my first incursion in the MDI world.
****
I wouldn't deal with the template; I'd have the document worry about it.
****
And the last, for now: I'd like to open the "Green" and "Red" views in
response to button clicks in the form view, instead of (or in adition to=
)
menu commands. How should I do this? Send a message to the MainFrame in =
the
button handler, maybe?
****
In this case, I would have the CFormView do as you describe; send a user-=
defined message,
such as UWM_ACTIVATE_VIEW, which contains the RUNTIME_CLASS of the view i=
n its WPARAM or
LPARAM.  Then some simple if-tests and call the appropriate OnXXXXView =
handler.
****
Thanks in advance for your patience. As I said, I'm new to MDI.
Mikel
Joseph M. Newcomer [MVP]
email: newco...@flounder.com
Web:http://www.flounder.com
MVP Tips:http://www.flounder.com/mvp_tips.htm- Ocultar texto de la cita -
- Mostrar texto de la cita -
Thanks, Joe. What you suggest is, more or less, what I ended up doing,
and it is working fine.
Now I have a solution, I see that what I was trying to do was quite
silly. Anyway, thanks
Mikel