Поделиться через


Добавление нескольких представлений в один документ

В приложении с одним документом (SDI), созданном с библиотекой классов Microsoft Foundation (MFC), каждый тип документа связан с одним типом представления. В некоторых случаях желательно переключить текущее представление документа с новым представлением.

Совет

Дополнительные процедуры реализации нескольких представлений для одного документа см. в разделе CDocument::AddView и образец COLLECT MFC.

Эту функцию можно реализовать, добавив новый CViewпроизводный класс и дополнительный код для динамического переключения представлений в существующее приложение MFC.

Для этого необходимо выполнить следующие шаги:

Оставшаяся часть этого раздела предполагает следующее:

  • Имя производного CWinAppобъекта — CMyWinAppи объявляется и CMyWinApp определяется в MYWINAPP. H и MYWINAPP. CPP.

  • CNewView — имя нового CViewпроизводного объекта и объявляется и CNewView определяется в NEWVIEW. H и NEWVIEW. CPP.

Изменение существующего класса приложения

Чтобы приложение переключалось между представлениями, необходимо изменить класс приложения, добавив переменные-члены для хранения представлений и метода для их переключения.

Добавьте следующий код в объявление CMyWinApp в MYWINAPP. H:

CView *m_pOldView;
CView *m_pNewView;
CView *SwitchView();

Новые переменные-члены m_pOldView и m_pNewViewуказатель на текущее представление и только что созданный. Новый метод (SwitchView) переключает представления при запросе пользователя. Текст метода рассматривается далее в этом разделе в разделе "Реализация функции переключения".

Для последнего изменения класса приложения требуется добавить новый файл заголовка, определяющий сообщение Windows (WM_INITIALUPDATE), которое используется в функции переключения.

Вставьте следующую строку в раздел включения MYWINAPP. CPP:

#include <AFXPRIV.H>

Сохраните изменения и перейдите к следующему шагу.

Создание и изменение нового класса представления

Создание нового класса представления упрощается с помощью команды New Class, доступной в представлении классов. Единственное требование для этого класса заключается в том, что он является производным от CView. Добавьте этот новый класс в приложение. Дополнительные сведения о добавлении нового класса в проект см. в разделе "Добавление класса".

После добавления класса в проект необходимо изменить специальные возможности некоторых членов класса представления.

Измените NEWVIEW. H путем изменения описателя доступа на public protected конструктор и деструктор. Это позволяет создавать и уничтожать класс динамически и изменять внешний вид представления перед его отображением.

Сохраните изменения и перейдите к следующему шагу.

Создание и присоединение нового представления

Чтобы создать и подключить новое представление, необходимо изменить InitInstance функцию класса приложения. Изменение добавляет новый код, который создает новый объект представления, а затем инициализирует оба m_pOldView m_pNewView и с двумя существующими объектами представления.

Так как новое представление создается в InitInstance функции, новые и существующие представления сохраняются в течение времени существования приложения. Однако приложение может так же легко создать новое представление динамически.

Вставьте этот код после вызова ProcessShellCommand:

CView *pActiveView = ((CFrameWnd *)m_pMainWnd)->GetActiveView();
m_pOldView = pActiveView;
m_pNewView = (CView *)new CNewView;
if (NULL == m_pNewView)
   return FALSE;

CDocument *pCurrentDoc = ((CFrameWnd *)m_pMainWnd)->GetActiveDocument();

// Initialize a CCreateContext to point to the active document.
// With this context, the new view is added to the document
// when the view is created in CView::OnCreate().
CCreateContext newContext;
newContext.m_pNewViewClass = NULL;
newContext.m_pNewDocTemplate = NULL;
newContext.m_pLastView = NULL;
newContext.m_pCurrentFrame = NULL;
newContext.m_pCurrentDoc = pCurrentDoc;

// The ID of the initial active view is AFX_IDW_PANE_FIRST.
// Incrementing this value by one for additional views works
// in the standard document/view case but the technique cannot
// be extended for the CSplitterWnd case.
UINT viewID = AFX_IDW_PANE_FIRST + 1;
CRect rect(0, 0, 0, 0); // Gets resized later.

// Create the new view. In this example, the view persists for
// the life of the application. The application automatically
// deletes the view when the application is closed.
m_pNewView->Create(NULL, _T("AnyWindowName"), WS_CHILD, rect, m_pMainWnd, viewID, &newContext);

// When a document template creates a view, the WM_INITIALUPDATE
// message is sent automatically. However, this code must
// explicitly send the message, as follows.
m_pNewView->SendMessage(WM_INITIALUPDATE, 0, 0);

Сохраните изменения и перейдите к следующему шагу.

Реализация функции переключения

На предыдущем шаге вы добавили код, который создал и инициализировал новый объект представления. Последний основной элемент заключается в реализации метода переключения. SwitchView

В конце файла реализации для класса приложения (MYWINAPP). CPP), добавьте следующее определение метода:

CView *CMyWinApp::SwitchView()
{
   CView *pActiveView = ((CFrameWnd *)m_pMainWnd)->GetActiveView();

   CView *pNewView = NULL;
   if (pActiveView == m_pOldView)
      pNewView = m_pNewView;
   else
      pNewView = m_pOldView;

      // Exchange view window IDs so RecalcLayout() works.
#ifndef _WIN32
   UINT temp = ::GetWindowWord(pActiveView->m_hWnd, GWW_ID);
   ::SetWindowWord(pActiveView->m_hWnd, GWW_ID, ::GetWindowWord(pNewView->m_hWnd, GWW_ID));
   ::SetWindowWord(pNewView->m_hWnd, GWW_ID, temp);
#else
   UINT temp = ::GetWindowLong(pActiveView->m_hWnd, GWL_ID);
   ::SetWindowLong(pActiveView->m_hWnd, GWL_ID, ::GetWindowLong(pNewView->m_hWnd, GWL_ID));
   ::SetWindowLong(pNewView->m_hWnd, GWL_ID, temp);
#endif

   pActiveView->ShowWindow(SW_HIDE);
   pNewView->ShowWindow(SW_SHOW);
   ((CFrameWnd *)m_pMainWnd)->SetActiveView(pNewView);
   ((CFrameWnd *)m_pMainWnd)->RecalcLayout();
   pNewView->Invalidate();
   return pActiveView;
}

Сохраните изменения и перейдите к следующему шагу.

Добавление поддержки переключения представления

Последний шаг включает добавление кода, вызывающего метод, SwitchView когда приложению необходимо переключиться между представлениями. Это можно сделать несколькими способами: добавив новый пункт меню для пользователя, чтобы выбрать или переключить представления внутри, когда выполняются определенные условия.

Дополнительные сведения о добавлении новых элементов меню и функций обработчика команд см. в разделе "Обработчики" для команд и уведомлений управления.

См. также

Архитектура документа и представления