Agregar varias vistas a un solo documento
En una aplicación de interfaz de documento único (SDI) creada con la biblioteca MFC (Microsoft Foundation Class), cada tipo de documento está asociado a un tipo de vista único. En algunos casos, es conveniente tener la capacidad de cambiar la vista actual de un documento con una vista nueva.
Sugerencia
Para procedimientos adicionales sobre cómo implementar varias vistas para un documento único, consulte CDocument::AddView y el ejemplo COLLECT de MFC.
Para implementar esta funcionalidad, agregue una clase derivada de CView
nueva y código adicional para cambiar las vistas de manera dinámica a una aplicación MFC existente.
Los pasos son los siguientes:
En el resto de este tema, se presupone lo siguiente:
El nombre del objeto derivado de
CWinApp
esCMyWinApp
yCMyWinApp
se declara y define en MYWINAPP.H y MYWINAPP.CPP.CNewView
es el nombre del objeto derivado deCView
nuevo yCNewView
se declara y define en NEWVIEW.H y NEWVIEW.CPP.
Modificación de la clase de aplicación existente
Para que la aplicación cambie entre las vistas, debe modificar la clase de aplicación agregando variables miembro para almacenar las vistas y un método para cambiarlas.
Agregue el código siguiente a la declaración de CMyWinApp
en MYWINAPP.H:
CView *m_pOldView;
CView *m_pNewView;
CView *SwitchView();
Las variables miembro nuevas, m_pOldView
y m_pNewView
, apuntan a la vista actual y a la recién creada. El método nuevo (SwitchView
) cambia las vistas cuando lo solicita el usuario. El cuerpo del método se describe más adelante en este tema en Implementación de la función de cambio.
La última modificación de la clase de aplicación requiere incluir un archivo de encabezado nuevo que define un mensaje de Windows (WM_INITIALUPDATE) que se usa en la función de cambio.
Inserte la línea siguiente en la sección include de MYWINAPP.CPP:
#include <AFXPRIV.H>
Guarde los cambios y siga con el paso siguiente.
Creación y modificación de la clase de vista nueva
La creación de la clase de vista nueva se facilita con el comando New Class disponible en la Vista de clases. El único requisito para esta clase es que derive de CView
. Agregue esta clase nueva a la aplicación. Para información específica sobre cómo agregar una clase nueva al proyecto, consulte Agregar una clase.
Una vez que agregue la clase al proyecto, deberá cambiar la accesibilidad de algunos miembros de la clase de vista.
Modifique NEWVIEW.H cambiando el especificador de acceso de protected
a public
para el constructor y el destructor. Esto permite crear y destruir dinámicamente la clase y que modifique la apariencia de la vista antes de que sea visible.
Guarde los cambios y siga con el paso siguiente.
Creación y asociación de la vista nueva
Para crear y asociar la vista nueva, debe modificar la función InitInstance
de la clase de aplicación. La modificación agrega código nuevo que crea un objeto de vista nuevo y, luego, inicializa m_pOldView
y m_pNewView
con los dos objetos de vista existentes.
Como la vista nueva se crea dentro de la función InitInstance
, las vistas nueva y existente se conservan durante la vigencia de la aplicación. Sin embargo, la aplicación podría crear dinámicamente la vista nueva con la misma facilidad.
Inserte este código después de la llamada a 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);
Guarde los cambios y siga con el paso siguiente.
Implementación de la función de cambio
En el paso anterior, agregó código que creó e inicializó un objeto de vista nuevo. La última parte importante es implementar el método de cambio, SwitchView
.
Al final del archivo de implementación para la clase de aplicación (MYWINAPP.CPP), agregue la definición de método siguiente:
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;
}
Guarde los cambios y siga con el paso siguiente.
Incorporación de compatibilidad para cambiar la vista
El último paso implica agregar código que llama al método SwitchView
cuando la aplicación necesita cambiar entre las vistas. Esto se puede hacer de varias maneras: puede agregar un elemento de menú nuevo para que el usuario elija o cambiar las vistas internamente cuando se cumplan ciertas condiciones.
Para más información sobre cómo agregar elementos de menú nuevos y funciones de controlador de comandos, consulte Controladores de comandos y notificaciones de control.