Я хочу изменить представленный вид, нажав кнопку внутри окна вот так. Настройки моего проекта:

  1. Я сделал проект MFC (SDI) без поддержки Doc / View.
  2. Я сделал еще два представления в конструкторе и добавил к ним классы. Новые классы представления получены из CFormView. Я изменил Конструктор и Деструктор новых Классов Представления на public.

  3. Добавил их как указатели в MainFrm.h:

CMainView*        m_pMainView;
CSecondView*      m_pSecondView; 
  1. Я изменил OnCreate(), OnSetFocus() и OnCmdMsg() метод MainFrm.cpp следующим образом: (Это позволяет представить FormView, который я сделал с помощью 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);
}

Теперь вот моя проблема! У меня есть кнопка «Первый представленный вид», и если вы нажмете на нее, вид должен измениться. Я сделал следующую функцию с помощью обработчика событий в 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. Указатель на MainFrm или его член в CMainView не работал.

Я искал и готовил уроки в течение нескольких дней, чтобы решить мою проблему. Я также попробовал это с поддержкой Doc / View, как показано здесь: https://docs.microsoft.com/en-us/cpp/mfc/adding-multiple-views-to-a-single-document?view=vs-2019 но я не знаю, где вызвать switchView ( ) правильно.

Может быть, кто-нибудь может помочь ...

3
Xe Li 18 Авг 2019 в 15:55

2 ответа

Лучший ответ

Во-первых, вам не следует переопределять 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!
}
3
Andrew Truckle 18 Авг 2019 в 19:02

Большие объятия для Адриана, я заставил его работать! Я также успешно добавил третий вид :)

Это очень важно, чтобы скрыть последнее показанное окно, если вы хотите реализовать больше видов. Вы можете сделать это как:

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
}
1
Xe Li 19 Авг 2019 в 09:07