【问题标题】:How to change MFC View by clicking a Button inside the MainFrame如何通过单击 MainFrame 内的按钮来更改 MFC 视图
【发布时间】:2019-12-23 23:12:25
【问题描述】:

我想通过单击窗口内的按钮来更改显示的视图 like this。 我的项目设置:

  1. 我创建了一个不支持 Doc/View 的 MFC 项目 (SDI)。
  2. 我在设计器中又制作了两个视图并向它们添加了类。新的视图类派生自CFormView。我将新视图类的构造函数和析构函数更改为公开的。

  3. 将它们作为指向 MainFrm.h 的指针添加:

CMainView*        m_pMainView;
CSecondView*      m_pSecondView; 
  1. 我更改了 MainFrm.cpp 的 OnCreate(),OnSetFocus()OnCmdMsg() 方法,如下所示: (这样可以展示我用 Designer 制作的 FormView)
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);
}

现在我的问题来了!我在第一个呈现的视图上有一个按钮,如果你点击它,视图应该会改变。我在 Designer 中使用事件处理程序创建了以下函数:

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

如果我在 MainFrm.cpp 类中处理它,例如使用菜单按钮,那没问题...工作正常:

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);

}

我尝试在CMainFrame 中编写一个函数并在CMainView::OnBnClickedButton1() 中调用此函数,但我不知道如何获取当前的 MainFrm 对象。 CMainView 中 MainFrm 或其成员的指针不起作用。

我搜索了几天的红色教程来解决我的问题。我还尝试使用 Doc/View 支持,如下所示: https://docs.microsoft.com/en-us/cpp/mfc/adding-multiple-views-to-a-single-document?view=vs-2019 但我不知道在哪里正确调用 switchView()。

也许任何人都可以提供帮助......

【问题讨论】:

    标签: c++ visual-c++ view mfc sdi


    【解决方案1】:

    首先,您实际上不应该覆盖OnCmdMsg - 相反,在您的头文件中使用DECLARE_MESSAGE_MAP,在您的实现文件中使用BEGIN_MESSAGE_MAP/END_MESSAGE_MAP,并在这两个宏之间插入处理程序消息。

    我看到您的CMainView 类中已经有一个处理程序,用于单击按钮!从这里,你应该调用CMainFrame 函数来切换到下一个视图——就像你在给出菜单命令时所做的那样(你说它有效)。将该函数公开,并让 MainView 类访问指向主框架的指针(或使用 AfxGetMainWnd() 并将其转换为您的类的指针)。像这样的:

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

    【讨论】:

    • PS:CMainFrame 和 MainView 混淆了抱歉!
    • 我会试试这个,让你知道它是否有用!谢谢
    【解决方案2】:

    给阿德里安一个大大的拥抱,我开始工作了! 我还成功添加了第三个视图:)

    如果您想实现更多视图,隐藏最后显示的窗口非常重要。你可以这样做:

    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
    }
    

    【讨论】:

    • 很高兴它成功了!但我要再次强调,您应该取消对 OnCmdMsg 的覆盖!据我所知,它没有任何用处,但可能会导致很多很多问题!用于 MainView 窗口的消息将由框架发送到那里;发送到 MainFrame(并由 MainFrame 接收)的消息是给它的,而且是它自己的!
    • 我做了,我的 void CMainFrame::OnSetFocus() 方法有问题。我试图从 view2 切换到 View3,但焦点没有正确改变。也许你可以在这里给我小费。
    • 测试 GetActiveView(),如果不为 NULL,则使用 GetActiveView()->SetFocus()
    • if (GetActiveView() != NULL) { GetActiveView()->SetFocus();我在 OnSetFocus() 中试过这个,但似乎没有效果
    • 也许在你的框架窗口类中放置一个“CFormView *current”成员,将它设置为 NULL 或任何你想要的(当你制作和显示每个表单时)并使用它:current- >设置焦点()。不确定 SDI,但 MDI 应用程序使用 MDIGetActive() 返回活动窗口的“框架”。
    猜你喜欢
    • 1970-01-01
    • 2019-12-03
    • 1970-01-01
    • 2012-08-18
    • 1970-01-01
    • 2012-11-09
    • 2020-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多