Solved

How to switch to MyView2 by clicking on Button in MyView1?

Posted on 2001-09-13
13
376 Views
Last Modified: 2013-11-20
Hello, I have 2 Views.  I have been trying, unsuccessfully, to switch to
MyView2 by clicking on a button in MyView1.


void MyView1::OnButton7()
{
CChildFrame  pChildFrame;
 pChildFrame.GuiRv(RUNTIME_CLASS(MyView2));
}


This is the Switch View code:

BOOL CChildFrame::ReplaceView(CRuntimeClass * pViewClass)
{
  CCreateContext context;
  CView * pCurrentView;
 if ((pCurrentView=GetActiveView())==NULL)
   return FALSE;
if ((pCurrentView->IsKindOf(pViewClass))==TRUE)
     return TRUE;
   CDocument * pDoc= pCurrentView->GetDocument();
    BOOL bAutoDelete=pDoc->m_bAutoDelete;
   pDoc->m_bAutoDelete=FALSE;
   pCurrentView->DestroyWindow();
    pDoc->m_bAutoDelete=bAutoDelete;
   context.m_pNewViewClass=pViewClass;
   context.m_pCurrentDoc=pDoc;
   context.m_pNewDocTemplate=NULL;
   context.m_pLastView=NULL;
   context.m_pCurrentFrame=this;
   CView * pNewView = (CView *) pViewClass->CreateObject();
   if (pNewView == NULL)
 {
     TRACE1("Warning: Dynamic create of view type %Fs failed\n",
    pViewClass->m_lpszClassName);
  return FALSE;
 }
    if (!pNewView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
  CRect(0,0,0,0), this, AFX_IDW_PANE_FIRST, &context))
  {
      TRACE0("Warning: couldn't create view for frame\n");
   return FALSE;
  }
 pNewView->SendMessage(WM_INITIALUPDATE, 0, 0);
   RecalcLayout();
   pNewView->UpdateWindow();
   SetActiveView(pNewView);
   return TRUE;
}

I hope someone can help.  Thanks!



0
Comment
Question by:binstar
  • 4
  • 3
  • 3
  • +2
13 Comments
 
LVL 49

Expert Comment

by:DanRollins
ID: 6481334
What does
   GuiRv( RUNTIME_CLASS(MyView2) );
do?
What is the current behavior? (crash, not show the view, ASSERT, show msg in the trace window... ???

-- Dan

0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6481900
this is a replace view I use in my splitters with success

BOOL CUsefulSplitterWnd::ReplaceView(int row, int col,CRuntimeClass * pViewClass,SIZE size)
{
  CCreateContext context;
  BOOL bSetActive;
           
   
  if ((GetPane(row,col)->IsKindOf(pViewClass))==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 *)GetPane(row,col))->GetDocument();
   CView * pActiveView=GetParentFrame()->GetActiveView();
   if (pActiveView==NULL || pActiveView==GetPane(row,col))
      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 *) GetPane(row,col))->DestroyWindow();
    // set flag back to default
    pDoc->m_bAutoDelete=TRUE;
 
    // Create new view                      
   
   context.m_pNewViewClass=pViewClass;
   context.m_pCurrentDoc=pDoc;
   context.m_pNewDocTemplate=NULL;
   context.m_pLastView=NULL;
   context.m_pCurrentFrame=NULL;
   
   CreateView(row,col,pViewClass,size, &context);
   
   CView * pNewView= (CView *)GetPane(row,col);
   
   if (bSetActive==TRUE)
      GetParentFrame()->SetActiveView(pNewView);
   
   RecalcLayout();
   GetPane(row,col)->SendMessage(WM_PAINT);
   
   return TRUE;
}
0
 
LVL 9

Expert Comment

by:Pacman
ID: 6482076
binstar,

your function for replacing the view is not the problem.
I'm using exactly the same function in an application (it's from MSDN, right?).

So there's going something wrong outside the function.
It would help to see the code which calls the replace function.

I don't understand this lines of code:

CChildFrame  pChildFrame;
pChildFrame.GuiRv(RUNTIME_CLASS(MyView2));

is it only a snippet and should pChildFrame be a POINTER which is somewhere else assigned by something like pChildFrame = GetChildFrame()
???


0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 2

Expert Comment

by:shilpa_Jb
ID: 6482268
Hi
here i have mentioned the steps to swtich betwn two views OnClick of toolbar button.
It would be better if u go for splitter windows.
Say u have two view  CFirtsView and CSecondView ;
CCreateContext *m_pcContext; //in header file

Assume that pViewClass = CFirstView;
BOOL CChildFrame::ReplaceView(CRuntimeClass * pViewClass)
{
      CView *pCurrentView =GetActiveView();
     CSecondView *pSecondView = (CSecondView *) pViewClass->CreateObject();
     CDocument *pDocument = pCurrentView->GetDocument();
      m_pcContext = new CCreateContext;
     if((pViewClass == NULL )|| (m_pcContext == NULL))
          return;
     if(pViewClass->IsKindOf( RUNTIME_CLASS(CFirstView) ) )
          m_pcContext->m_pNewViewClass = RUNTIME_CLASS(CSecondView);
     m_pcMainSplitter = new CSplitterWnd;    
     m_pcContext->m_pCurrentDoc = ;
     m_pcContext->m_pNewDocTemplate = NULL;
     m_pcContext->m_pLastView = NULL;
     m_pcContext->m_pCurrentFrame = NULL;
     this->CreateView(m_pcContex, AFX_IDW_PANE_FIRST );
     pSecondView->OnInitialUpdate();
     pDocument->UpdateAllViews();
     SetActiveView( pSecondView);
     return TRUE;

}
And one more suggestion if u use splitter windows switching would be more easier. Try out.
Hope it helps u.
-Shilpa    

0
 

Author Comment

by:binstar
ID: 6482517
The ReplaceView code works fine if I select the View I want to switch to from the Menu bar, but the same code does not work if I am calling it from the Button in the View (which is what I want to do).

The pChildFrame.GuiRv(RUNTIME_CLASS(MyView2));
calls
BOOL CChildFrame::GuiRV(CRuntimeClass * pViewClass)
which is identical to
BOOL CChildFrame::ReplaceView(CRuntimeClass * pViewClass)
the only difference is GuiRV is called from a button in the view:

void MyView1::OnButton7()
{
CChildFrame  pChildFrame;
pChildFrame.GuiRv(RUNTIME_CLASS(MyView2));
}

while ReplaceView is called from the Menu bar. The ReplaceView works GuiRV called from the button does not.  When I trace both I notice that the this value is different in the ReplaceView (menu bar where it works)from
the GuiRV (button in View the value is 0x12f7e0 {CChildFrame hWnd=0x000000}.

It jumps to the end of the fuction in GuiRv after:
if ((pCurrentView=GetActiveView())==NULL.

Thanks
 


0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6482538
is it because you are deleting the class/window that is handling the message - try posting a message from your button handler to the other handler in a different window to switch the views
0
 
LVL 9

Expert Comment

by:Pacman
ID: 6482628
Sorry, but I'm really confused now ...

1. why do you have two functions for switching the view ??
2. I still don't understand these lines:

CChildFrame  pChildFrame;
pChildFrame.GuiRv(RUNTIME_CLASS(MyView2));

You make a new local CChildFrame-object on the stack.
Then you call GuiRv() to switch the view. But the child-frame window is never CREATED (means there is no phyisical window there) !!??!!

I expected code like this:

CChildFrame *pChildFrame;
pChildFrame = (CChildFrame*)GetParent();
pChildFrame->GuiRv(RUNTIME_CLASS(MyView2));

0
 
LVL 9

Expert Comment

by:Pacman
ID: 6482651
... a better way would be to place the handler in CChildFrame and store the view-type:

void CChildFrame::OnButton7()
{
    GuiRv(RUNTIME_CLASS(MyView2));
}
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 200 total points
ID: 6483245
I think Shaun is on the right track.  Even without knowing the details of exactly what convolutes steps MFC invokes,  it seems dangerous for a piece of code (a member fn of a window object) to start a cascade of operations that eventually ends up deleting itself.

You have a menu handler that switches views right?  And it works correctly, right?  So just use it!  

In the outgoing view, post a WM_COMMAND message to the frame window.  It will be something like:

void MyView1::OnButton7()
{
   AfxGetMainWnd()->PostMessage( WM_COMMAND, IDM_SwitchToView2, 0,0);
}

-- Dan
0
 

Author Comment

by:binstar
ID: 6483871
Thank You DanRollins. That is exactly what I needed.

AfxGetMainWnd()->PostMessage(WM_COMMAND,IDM_SwitchToView2, 0);  (you added one extra zero).

binstar
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6484124
What's one little NULL between friends... lol
Thanks.

-- Dan
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6485001
so shaun was on the right track - humph
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6485141
... but Dan derailed him...

0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
iSeries FTP Exit Program 8 163
Smart Camera scanning and reading information 3 122
sum13 challenge 24 135
moto 4g phone enable finger print 4 48
Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
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.
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

726 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