Добавление нескольких представлений в один документ
В приложении с одним документом (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
когда приложению необходимо переключиться между представлениями. Это можно сделать несколькими способами: добавив новый пункт меню для пользователя, чтобы выбрать или переключить представления внутри, когда выполняются определенные условия.
Дополнительные сведения о добавлении новых элементов меню и функций обработчика команд см. в разделе "Обработчики" для команд и уведомлений управления.