Solved

switch view by clicking a push button

Posted on 2000-04-01
39
507 Views
Last Modified: 2013-11-20
hi,

how can I switch view by clicking a push button
 I want to create push button at the top of each screen that says '>> Next' so that when the user clicks it, the screen switches to the next view.
How can I switch views when the user presses this push button? I am spent hours trying to figure this out. I am absolutely stuck. Any response you can give me will be greatly appreciated.

cheers..
0
Comment
Question by:b_harpal
  • 12
  • 10
  • 8
  • +3
39 Comments
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 2675988
are you trying to replace one CView derived class for another within a document?

if so then you could probably try this

1) set CDocument::m_bAutoDelete to FALSE
2) delete the current view
3) set CDocument::m_bAutoDelete to TRUE
4) create the new view and set that up in your document.
0
 
LVL 3

Expert Comment

by:ghimireniraj
ID: 2676140
DO you have multiple Views  derived from CView and its derived classes.

The best way.

Write a public view switching code in the mainfrane class that takes in an int value say that represents the view.
Place a button each in each view and    call this member function when ever you press buttons this button in your view class like.

(CMainFrame*)AfxGetMainWnd()->SwitchToView(5);

////include your mainframe class in all view classes
 ////SwitchToView(5) is your view switching code

If you cant write the view switching code i will provide the view switching function.

NIRAJ


0
 

Author Comment

by:b_harpal
ID: 2677186
hi ,
   well i have a bitmap(full screen) on which i have a button ,means i have to load the bitmap also..on it the button.one bitmap can have back as well as forward button..and so on..
hope u think on this..
cheers
 

0
 
LVL 3

Expert Comment

by:SamHobbs
ID: 2677209
The sample code in CDocument::AddView can be used as one sample of switching views.

If it is possible to use just one view and give the user the impression of switching by just switching the data shown in the view, then that would probably be easier for you and the computer.
0
 
LVL 3

Expert Comment

by:cypherljk
ID: 2677624
hey ghimireniraj,
how about posting that code
0
 
LVL 3

Expert Comment

by:ghimireniraj
ID: 2678142



////Add this to your CMainFrame  class

public:
void  SwitchToView(int vn);

////Add this function to your mainfrm.cpp file ie the implementation for the  SwitchToView


void CMainFrame::SwitchToView(int vn)
{
CView * oview=GetActiveView();
CView * nview=(CView *)GetDlgItem(vn);
if(nview==NULL)
{
switch(vn)
{
case 1:
nview=(CView*)new (CSwitchView);
break;
case 2:
nview=(CView*)new (DescView);
break;
case 3:
nview=(CView*)new (DetailView);
break;
case 4:
nview=(CView*)new (BriefView);
break;
}
CCreateContext context;
                  context.m_pCurrentDoc=oview->GetDocument();
nview->Create(NULL,NULL,WS_BORDER,CFrameWnd::rectDefault,
this,vn,&context);
nview->OnInitialUpdate();
}
SetActiveView(nview);
nview->ShowWindow(SW_SHOW);
oview->ShowWindow(SW_HIDE);
            
if(oview->GetRuntimeClass()==RUNTIME_CLASS(CSwitchView))
oview->SetDlgCtrlID(1);
if(oview->GetRuntimeClass()==RUNTIME_CLASS(DescView))
oview->SetDlgCtrlID(2);
if(oview->GetRuntimeClass()==RUNTIME_CLASS(DetailView))
oview->SetDlgCtrlID(3);
if(oview->GetRuntimeClass()==RUNTIME_CLASS(BriefView))
oview->SetDlgCtrlID(4);

nview->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
RecalcLayout();
}

///////////////////////////////////
///V V IMP
//note that you are using all the constructors of different view class so change all the constructors that are protected to public
///////////////////////

Add to all your view

GetDocument()
implementation like the class wizard adds to the first view it  creates..


/////////////////

There will be many places that you have to include the view header files to the mainframe and the mainframe header to all the views

/////////////////

My main frame class is

CMainFrame

and i have switched between 4 views
that are
1)CSwitchView
2)DescView
3)DetailView
4)BriefView

Now to cll this function just write this to the handler of your buttons at different views

((CMainFrame*)AfxGetMainWnd())->SwitchToView(3);

//here 3 means i want to go to the third view (refer to the Switch to view class

I have tested all the code above .
If you have further problems contact me at

niraj_ghimire@hotmail.com

Niraj


0
 
LVL 3

Expert Comment

by:SamHobbs
ID: 2678234
That should work, ghimireniraj, assuming it satisfies b_harpal's requirements. It is similar to the sample in CDocument::AddView.

Is it necessary to delete each of the four views that get allocated or does MFC handle that?
0
 
LVL 3

Expert Comment

by:ghimireniraj
ID: 2678322
>>Is it necessary to delete each of the four views that get allocated or does MFC handle that?



Because the views are created on the heap local to a function , they are deleted when they go out of scope ie out of the function.C++ handles rather than saying MFC handles it.

Comment if i am wrong.

niraj

0
 
LVL 3

Expert Comment

by:SamHobbs
ID: 2678444
I tried to find something in the Microsoft documentation that clearly explained this but Microsoft documentation can be very frustrating at times.

There are two very distinct methods of allocating storage for items in C and C++; stack and heap. Items allocated "local to a function" are allocated on the stack. The term stack refers to the area used to store information about a caller of a function so that the function can return to the caller. The caller also "pushes" onto the stack the parameters being passed. There is a processor register (the Stack Pointer or SP register) that stores a pointer to where the beginning of a function's area in the stack is. Upon return everything for the function gets "poped" off the stack by restoring the SP register to the value it was prior to calling the function. Therefore memory allocated for the called function gets automatically deallocated in a single machine instruction. Of course, C++ would handle calling destructors as needed.

The heap is a separate area of storage. It is like a big pile of memory that everyone (all C and C++ functions etc.) allocates memory from and deallocates memory to.

In the case of a statement such as:

CView * nview=(CView *)GetDlgItem(vn);

it is true that the pointer nview gets allocated on the stack and automatically deallocated. Unfortunately using the new operator such as in the following:

nview=(CView*)new (CSwitchView);

will allocate the view on the heap and items on the heap are not automatically deleted. MFC might have some special method of unallocating views but unless it does there would be memory leaks caused by not unallocating the view (with delete).
0
 
LVL 3

Expert Comment

by:ghimireniraj
ID: 2680064
Thanks a lot SamHobbs .I will try to find out more about that.

niraj
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2682572
From what you said you have a (big)bitmap button that has a given bitmap on it and you want to go forward/back in the list of bitmaps to display on that button

This doesn't require view switching.

Instead, you just load respond to the buttons by getting the next/preb bitmap from the list and replacing the bitmap in the button with the new one and redraing (invalidating) the button (if required).

Switching views is a lot of overhead for such a simple operation.
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2682579
or do you mean that you havea ful-screen bitmap, and over that one (or two) buttons to take you to next/prev image.

Again, no need for view switching.  Just create both buttons, hide the one(s) that aren't applicable (eg. prev when on the first image).

In response to the button push, load in the appropriate bitmap and redraw the screen (invalidate), and update the prev/next button visibility.

Again, no need for view switching.

If you do want to switch views, then the code given earlier (by ghimireniraj) is the sort of thing to do - although I'm not sure about his creating new views all the time without deleting.  I have a similar routine in my app (switches between multiple views in a splitter), and there are MFC examples you can download that show this as well.


0
 
LVL 3

Expert Comment

by:SamHobbs
ID: 2682594
What you are saying, RONSLOW, is essentially what I was saying except I was rather brief about it.

Also ghimireniraj's code does not create a view more than once. Look at the code again. Yes, the reason why it will create each view only once is somewhat obscure, but I am sure you can figure it out.

0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2682632
yeup .. sneaky.

This is what I do to switch views (in a mainframe with a splitter .. simpler if there is no splitter of course)

static struct {
    int id;
    CRuntimeClass* pViewClass;
} map = {
    { ID_VIEW_1, RUNTIME_CLASS(CView1) },
    { ID_VIEW_2, RUNTIME_CLASS(CView2) },
    { ID_VIEW_3, RUNTIME_CLASS(CView3) },
    //.. etc
};

BOOL CMainFrame::OnViewPlanGL3D(UINT id) {
    // which view class do we want
    CRuntimeClass* pViewClass = NULL;
    for (int i = 0; i < sizeof(map)/sizeof(*map); i++) {
        if (map.id == id) {
            pViewClass = map.pViewClass;
            break;
        }
    }
    // don't know what class to create
    if (! pViewClass) return FALSE;
    // get pointer to CDocument object so that it
    // can be used in the creation process of the new view
    CDocument* pDoc = GetActiveDocument();
    if (! pDoc) return FALSE;
    // get old view
    CView* pOldView = GetActiveView();
    if (! pOldView) return FALSE;
    // get pointer to splitter (parent)
    CSplitterWnd* pSplitter = static_cast<CSplitterWnd*>(pOldView->GetParent());
    if (! pSplitter || ! pSplitter->IsKindOf(RUNTIME_CLASS(CSplitterWnd))) return FALSE;
    // find which pane
    int row,col;
    if (! pSplitter->IsChildPane(pOldView,&row,&col)) return FALSE;
    // get the size of the pane
    int w,h,minw,minh;
    pSplitter->GetColumnInfo(col,w,minw);
    pSplitter->GetRowInfo(row,h,minh);
    // set flag so that document will not be deleted when view is destroyed
    BOOL was = pDoc->m_bAutoDelete;
    pDoc->m_bAutoDelete=false;    
    pOldView->DestroyWindow();
    pDoc->m_bAutoDelete=was;    
    // Create new view                      
    CCreateContext context;
    context.m_pNewViewClass=pViewClass;
    context.m_pCurrentDoc=pDoc;
    context.m_pNewDocTemplate=NULL;
    context.m_pLastView=NULL;
    context.m_pCurrentFrame=NULL;
    if (! pSplitter->CreateView(row,col,pViewClass,CSize(w,h),&context)) return FALSE;
    // make this view the active one
    CView* pNewView = static_cast<CView*>(pSplitter->GetPane(row,col));
    SetActiveView(pNewView);
    // set it up
    pNewView->SendMessage(WM_INITIALUPDATE,0,0);
    // tell the splitter about it
    pSplitter->SetColumnInfo(col,w,minw);
    pSplitter->SetRowInfo(row,h,minh);
    pSplitter->RecalcLayout();
    // and update the view
    pNewView->UpdateWindow();
}
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 2682930
well if we are talking splitters then have a look at the following

http://www.codetools.com/splitter/usefulsplitter.asp

that has a method replaceview(...)
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2683345
I'll check that out .. might be nicer than the code I have now :-)
0
 

Author Comment

by:b_harpal
ID: 2686216
Adjusted points from 40 to 70
0
 

Author Comment

by:b_harpal
ID: 2686217
hello everyone,
         well there seems to b too much comments going on here..it has confused me lot..its very urgent for me ..and above that im really confused..i want my it to work  anyhow..either by using sreenview or something else..let me define my problem ..on a fullscreen bitmap i had to place a small button(buttons) which can take me to next bitmap or the previous bitmap..really im stucked in here..you people out there seems to TOO good..so please help me..first try the code and and let me know..it would b greatly appreciated..if u can try it out and then give the full code..please..and for this im INCREASING the POINTS from 40 TO  70.so please help me as early as possible  or u can mail me at bharpal@yahoo.com.

cheers

 
0
 
LVL 3

Expert Comment

by:SamHobbs
ID: 2686262
Probably the important thing is that you probably do not need to switch views. It sounds like you only need to switch bitmaps in the view.

0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 10

Expert Comment

by:RONSLOW
ID: 2686295
RONSLOW changed the proposed answer to a comment
0
 
LVL 10

Accepted Solution

by:
RONSLOW earned 70 total points
ID: 2686296
OK .. if you are doing a dialog based app (or a form view), then you'd simply have button controls on your dialog and paint the appropriate bitmap as the dialog background.  There is good smaple code on how to do this in MS KB.

If you are using a CView, then I assume you are already able to display the image, and that you know how to change what image is displayed.  All that remains is adding some child buttons to the view, which you can create with the Create function (do it in the OnCreate of the view, say).  Then respond to the click messages by changing the view appropriately.  Use ShowWindow to show or hide the buttons as required.
0
 
LVL 3

Expert Comment

by:ghimireniraj
ID: 2687291
Do not use view switching if you just want to changebitmaps.
Load a bit map, screenbilt on your screen.

then show your programatically created
button over the bitmap.

I guess you need to show your button after drawing your bitmap so that it remains on the top.(in your OnDraw)

Make an index to your array of bit maps
Make this index a document data.Simply decrease or increase your index and invalidate(to Execute your ONDRAW AGAIN) when you want to show Prev or next BMP.

Just write code to load and display one BMP  pointed by the index on the ONDraw .







0
 

Author Comment

by:b_harpal
ID: 2704177
hi everyone,
        when i load a bitmap..on it i place a button.by clicking i goto next bitmap..on next bitmap when i click the pre buton..i get only bitmap but no button on it..tell me how to hide and show the button..please help as early as possible..

cheers..
0
 
LVL 3

Expert Comment

by:SamHobbs
ID: 2705502
In order for us to help you, you must tell us more. You must at least explain what you mean by "place a button". It is impossible for us to tell you how to hide and show the button without guessing and by guessing we are likely to be as confusing as we have been in prior attempts to help you.

Did RONSLOW's answer solve the problem you asked for a solution to? If not, then why not?
0
 
LVL 3

Expert Comment

by:ghimireniraj
ID: 2705672
show button as


do this at the very end of your OnDraw function

CButton * but1=(CButton *)GetDlgItem(ID_but1);
but1->ShowWindow(SW_SHOW);

hide it as
but1->ShowWindow(SW_HIDE);


0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2705916
show us some code if you are still having problems.

you could send me code at roger.onslow@compsys.com.au if there is too much to post here
0
 

Author Comment

by:b_harpal
ID: 2711851
hi everyone ,

all u great gurus out there..i need ur urgent help.once again my prob..i have 10 bitmaps..on bitmap1 i have one button[but1].on clicking but1 it should take me to bitmap2..on bitmap2 i have 2 buttons .one takes me to next bitmap3..and other to previ bitmap1..simple thats it.how to do this ..im not an expert like u people..so please tell me each and every details...please.it would b very kind of u ,if u could take some time out or this one..thanx

cheers..
bharpal
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2712150
show us what you have so far so we know what to work with.  Asking us to write the entire application is a bit much.
0
 

Author Comment

by:b_harpal
ID: 2714591
hi everyone..
im just making a computer based tutor..
for that i need to switch between bitmaps..if u have any links..for animations..and how to use sound in application please tell me..it would be greatly appreciated...
0
 

Author Comment

by:b_harpal
ID: 2718975
hi ronslow,
 i mailed u the code..please have a look and help me please..it would b very kind of u..u can mail me at bharpal@yahoo.com

thanx..

bharpal
0
 

Author Comment

by:b_harpal
ID: 2720038
hello,
is there any probs with mu code ronslow..please let me know...
0
 

Author Comment

by:b_harpal
ID: 2720039
please help me someone....
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2721247
I have received it.

I'll have a look out of work hours ... our maybe during my lunch break.
0
 
LVL 3

Expert Comment

by:SamHobbs
ID: 2721566
RONSLOW: Do you agree that a system-wide hook should be able to access the Outlook Express Inbox to query such things as which item is selected?

0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2721617
eh? Sam .. is that comment related to this question.
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2721628
b_harpal:

The ASSERT is becuase you are loading the a bitmap more than one into the one CBitmap object without first doing a DeleteObject on it to clear out the old bitmap.

But my advice is to throw this code away!! .. there is some very dubious and not-at-all nice things going on here.

Instead, Start with AppWizard.

Generate either a dialog app, or an SDI app (with no Doc/View suport if you like).

Dialog app will let you add your bitmap ara and the buttons for prev/next using the resource editor.

SDI app will let you do things a bit more like your current code.

Either way, add your code to that working framework, rather that the mess you have here.  All sort of strange things going on .. too many to really deal with here individually.

Roger

>>> source code sent...

#include <afxwin.h>
#include <afxext.h>
#include"resource.h"
#define IDB_BUTTON1 100
#define IDB_BUTTON2 200
// Declare the application class
class CButtonApp : public CWinApp
{
public:
      virtual BOOL InitInstance();
      afx_msg void HandleButton1();
      afx_msg void HandleButton2();
};
// Create an instance of the a
CButtonApp ButtonApp;
// Declare the main window cpplication class
class CButtonWindow : public CFrameWnd
{
      CButton *button1,*button2;
      CBitmap b,c;
      CDC s,v;
            HBITMAP hbitmap;
public:

      CButtonWindow()

      {
            Create
(0,"HCL",WS_OVERLAPPEDWINDOW|WS_SYSMENU|WS_MAXIMIZEBOX);

            // Create a button
      button1 = new CButton();
      button1->Create("Push me",
            WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
            CRect(348,436,464,466),
            this,
            IDB_BUTTON1);
      }


      void OnPaint()
      {


CPaintDC dc(this);
int width = 795;
int hieght = 575;
int width1 = 0;
int hieght1 = 0;
HDC hMemDC = ::CreateCompatibleDC(NULL);
SelectObject(hMemDC, hbitmap);
::StretchBlt(dc.m_hDC, 0, 0, width, hieght, hMemDC,
width1, hieght1, 660,537, SRCCOPY);
::DeleteDC(hMemDC);
::DeleteObject(hbitmap);


            //SetTimer(1,0,NULL);




      }



      void CButtonWindow::OnCreate()
      {

static int i =1;
if(i == 1)
{
   hbitmap = ::LoadBitmap
(::AfxGetInstanceHandle(),MAKEINTRESOURCE(IDB_BITMAP1));

}



this->InvalidateRect(NULL);
      }
      void CButtonWindow::HandleButton1()
      {
      delete button1;UpdateWindow();
      CClientDC d(this);// change this first and see.

      b.LoadBitmap(IDB_BITMAP2);
            s.CreateCompatibleDC(&d);
            s.SelectObject(b);

         // d.BitBlt(10,10,48,48,&s,0,0,SRCCOPY);

            d.StretchBlt(0,
                           0,
                               795,
                               575,
                               &s,
                               0,
                               0,
                               689,
                               518,
                               SRCCOPY);
            // Create a button2
      button2 = new CButton();
      button2->Create("Push me too",
            WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
            CRect(666,530,753,561),
            this,
            IDB_BUTTON2);

}
      void CButtonWindow::HandleButton2()

      {
      delete button2;UpdateWindow();

      CClientDC d(this);// change this first and see.

      c.LoadBitmap(IDB_BITMAP1);
            v.CreateCompatibleDC(&d);
            v.SelectObject(c);

         // d.BitBlt(10,10,48,48,&s,0,0,SRCCOPY);

            d.StretchBlt(0,
                           0,
                               795,
                               575,
                               &v,
                               0,
                               0,
                               660,
                               537,
                               SRCCOPY);

            // Create a button
      button1 = new CButton();
      button1->Create("Push me",
            WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
            CRect(348,436,464,466),
            this,
            IDB_BUTTON1);

      }
  DECLARE_MESSAGE_MAP()
};




BEGIN_MESSAGE_MAP(CButtonWindow,CFrameWnd)
ON_WM_CREATE()
//ON_WM_TIMER()


ON_WM_PAINT()
ON_BN_CLICKED(IDB_BUTTON1, HandleButton1)
ON_BN_CLICKED(IDB_BUTTON2, HandleButton2)

END_MESSAGE_MAP()
// The InitInstance function is called once
// when the application first executes
BOOL CButtonApp::InitInstance()
{
      m_pMainWnd = new CButtonWindow();
      m_pMainWnd->ShowWindow(3);
      m_pMainWnd->UpdateWindow();
      return TRUE;
}

>>>>

0
 
LVL 3

Expert Comment

by:SamHobbs
ID: 2721676
RONSLOW: no, it is not. I am so confused.
0
 

Author Comment

by:b_harpal
ID: 2737453
hi ronslow,
 u have solved 90% of my problem..
but when i click on button1,it dispalys full screen bitmap,with no previos buttons visible..but they r still active..how to deactivate them..also if i want to make a new button on new bitmap by deactivating all the previous buttons..How to do this..plz help..
im waiting for ur kind reply..

cheers

harpal
0
 
LVL 10

Expert Comment

by:RONSLOW
ID: 2743220
please re-email your code to me so I can see what is happening.

Have you considered starting with an Appwizard Dialog or SDI app instead?
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

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: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
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.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

708 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now