Compartir por


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 es CMyWinApp y CMyWinApp se declara y define en MYWINAPP.H y MYWINAPP.CPP.

  • CNewView es el nombre del objeto derivado de CView nuevo y CNewView 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.

Consulte también

Arquitectura de vistas y documentos