简体   繁体   中英

How to change MFC View by clicking a Button inside the MainFrame

I want to change the presented View by clicking a button inside the Window like this . My Project settings:

  1. I made an MFC Project (SDI) without Doc/View support.
  2. I made two more Views in the Designer and added Classes to them. The new View Classes are derived from CFormView . I changed the Constructor and Destructor of the new View Classes to public.

  3. Added them as pointers to MainFrm.h:

CMainView*        m_pMainView;
CSecondView*      m_pSecondView; 
  1. I changed the OnCreate() , OnSetFocus() and OnCmdMsg() Method of MainFrm.cpp like this: (That allows to present the FormView I made with the Designer)
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    // First, build the view context structure
    CCreateContext ccx;

    // Designate the class from which to build the view
    ccx.m_pNewViewClass = RUNTIME_CLASS(CMainView);

    // Using the structure, create a view
    m_pMainView = DYNAMIC_DOWNCAST(CMainView, this->CreateView(&ccx));


    if (!m_pMainView)
    {
        TRACE0("creation of view failed");
    }

    // Do layout recalc
    RecalcLayout();

    // Show the view and do an initial update

    m_pMainView->ShowWindow(SW_SHOW);
    m_pMainView->OnInitialUpdate();

    // Set this view active
    SetActiveView(m_pMainView);

    // Order it to resize the parent window to fit
    m_pMainView->ResizeParentToFit(FALSE);


    return 0;
}

...

void CMainFrame::OnSetFocus(CWnd* /*pOldWnd*/)
{

    m_pMainView->SetFocus();
}

BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{

    if (m_pMainView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
        return TRUE;

    return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

Now here comes my problem! I have a button on the First presented View and if you click on it, the view should change. I made the following function with the event handler in the Designer:

void CMainView::OnBnClickedButton1()
{
// What to do here? I want to change the current view to another View by clicking the button
}

If i handle it in the MainFrm.cpp class for example with menue buttons it is no problem... that works fine:

void CMainFrame::OnViewNextview()
{
    CCreateContext ccx2;
    ccx2.m_pNewViewClass = RUNTIME_CLASS(CSecondView);
    m_pSecondView = DYNAMIC_DOWNCAST(CSecondView, this->CreateView(&ccx2));

    RecalcLayout();

    m_pMainView->ShowWindow(SW_SHOW);
    m_pMainView->OnInitialUpdate();

    SetActiveView(m_pMainView);

    m_pMainView->ResizeParentToFit(FALSE);

}

I tried to write a function in CMainFrame and call this function in CMainView::OnBnClickedButton1() but I don't know how to get the current MainFrm Object. A pointer on MainFrm or a member of it in CMainView did not work.

I searched and red tutorials for days to solve my problem. I also tried it with Doc/View support like shown here: https://docs.microsoft.com/en-us/cpp/mfc/adding-multiple-views-to-a-single-document?view=vs-2019 but i dont know where to call switchView() correctly.

Maybe anyone can help...

First, you shouldn't really be overriding OnCmdMsg - instead, use DECLARE_MESSAGE_MAP in your header file and BEGIN_MESSAGE_MAP / END_MESSAGE_MAP in your implementation file, and insert handler messages between those two macros.

I see that you already have a handler in your CMainView class for the button click! From here, you should call the CMainFrame function to change to the next view - just as you do when the menu command is given (which you say works). Make that function public and give the MainView class access to a pointer to the main frame (or use AfxGetMainWnd() and cast it to a pointer of your class). Something like this:

void CMainView::OnBnClickedButton1()
{
    AfxGetMainWnd()->PostMessage(WM_COMMAND, menuID); // ID of menu command that works!
}

Big hugs for Adrian, i got it to work! I also added a third view successfully :)

It is very IMPORTANT , to HIDE the last shown Window if you want to implement more views. you can do it like:

void CMainFrame::OnView3()
{
    CCreateContext ccx3;
    ccx3.m_pNewViewClass = RUNTIME_CLASS(CThirdView);
    m_pThirdView = DYNAMIC_DOWNCAST(CThirdView, this->CreateView(&ccx3));

    RecalcLayout();

    m_pSecondView->ShowWindow(SW_HIDE); // Hide the last Window
    m_pThirdView->ShowWindow(SW_SHOW);  // Show the new Window

    m_pThirdView->OnInitialUpdate();
    SetActiveView(m_pThirdView);
    //m_pThirdView->ResizeParentToFit(FALSE); //if you call this, the size of the window is the same like in the Designer
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM