switch view by clicking a push button

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..
b_harpalAsked:
Who is Participating?
 
RONSLOWConnect With a Mentor Commented:
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
 
ShaunWildeCommented:
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
 
ghimirenirajCommented:
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
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

 
b_harpalAuthor Commented:
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
 
SamHobbsCommented:
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
 
cypherljkCommented:
hey ghimireniraj,
how about posting that code
0
 
ghimirenirajCommented:



////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
 
SamHobbsCommented:
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
 
ghimirenirajCommented:
>>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
 
SamHobbsCommented:
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
 
ghimirenirajCommented:
Thanks a lot SamHobbs .I will try to find out more about that.

niraj
0
 
RONSLOWCommented:
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
 
RONSLOWCommented:
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
 
SamHobbsCommented:
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
 
RONSLOWCommented:
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
 
ShaunWildeCommented:
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
 
RONSLOWCommented:
I'll check that out .. might be nicer than the code I have now :-)
0
 
b_harpalAuthor Commented:
Adjusted points from 40 to 70
0
 
b_harpalAuthor Commented:
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
 
SamHobbsCommented:
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
 
RONSLOWCommented:
RONSLOW changed the proposed answer to a comment
0
 
ghimirenirajCommented:
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
 
b_harpalAuthor Commented:
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
 
SamHobbsCommented:
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
 
ghimirenirajCommented:
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
 
RONSLOWCommented:
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
 
b_harpalAuthor Commented:
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
 
RONSLOWCommented:
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
 
b_harpalAuthor Commented:
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
 
b_harpalAuthor Commented:
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
 
b_harpalAuthor Commented:
hello,
is there any probs with mu code ronslow..please let me know...
0
 
b_harpalAuthor Commented:
please help me someone....
0
 
RONSLOWCommented:
I have received it.

I'll have a look out of work hours ... our maybe during my lunch break.
0
 
SamHobbsCommented:
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
 
RONSLOWCommented:
eh? Sam .. is that comment related to this question.
0
 
RONSLOWCommented:
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
 
SamHobbsCommented:
RONSLOW: no, it is not. I am so confused.
0
 
b_harpalAuthor Commented:
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
 
RONSLOWCommented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.