Adicionando várias exibições a um único documento

Em um aplicativo de SDI (interface de documento único) criado com a Biblioteca de Classe MFC (Microsoft Foundation), cada tipo de documento está associado a um único tipo de exibição. Em alguns casos, é desejável ter a capacidade de alternar o modo de exibição atual de um documento com um novo modo de exibição.

Dica

Para obter procedimentos adicionais sobre como implementar vários modos de exibição para um único documento, consulte CDocument::AddView e o exemplo COLLECT do MFC.

Você pode implementar essa funcionalidade adicionando uma nova classe derivada de CView e um código adicional para alternar os modos de exibição dinamicamente para um aplicativo MFC existente.

As etapas são as seguintes:

O restante deste tópico presume o seguinte:

  • O nome do objeto derivado de CWinApp é CMyWinApp, e CMyWinApp é declarado e definido em MYWINAPP. H e MYWINAPP. CPP.

  • CNewView é o nome do novo objeto derivado de CView e CNewView é declarado e definido em NEWVIEW. H e NEWVIEW. CPP.

Modificar a classe de aplicativo existente

Para que o aplicativo alterne entre exibições, você precisa modificar a classe de aplicativo adicionando variáveis de membro para armazenar as exibições e um método para alterná-las.

Adicione o seguinte código à declaração de CMyWinApp em MYWINAPP.H:

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

As novas variáveis de membro m_pOldView e m_pNewView apontam para o modo de exibição atual e o recém-criado. O novo método (SwitchView) alterna as exibições quando solicitado pelo usuário. O corpo do método é discutido posteriormente neste tópico em Implementar a Função de Alternância.

A última modificação na classe de aplicativo requer a inclusão de um novo arquivo de cabeçalho que define uma mensagem do Windows (WM_INITIALUPDATE) usada na função de alternância.

Insira a linha a seguir na seção incluir de MYWINAPP. CPP:

#include <AFXPRIV.H>

Salve suas alterações e continue para a próxima etapa.

Criar e modificar a nova classe de exibição

A criação da nova classe de exibição é facilitada usando o comando New Class disponível no Modo de Exibição de Classe. O único requisito para essa classe é que ela derive de CView. Adicione essa nova classe ao aplicativo. Para obter informações específicas sobre como adicionar uma nova classe ao projeto, consulte Adicionar uma classe.

Depois de adicionar a classe ao projeto, você precisará alterar a acessibilidade de alguns membros da classe de exibição.

Modifique NEWVIEW. H alterando o especificador de acesso de protected para public para o construtor e o destruidor. Isso permite que a classe seja criada e destruída dinamicamente e modifique a aparência da exibição antes de ela ficar visível.

Salve suas alterações e continue para a próxima etapa.

Criar e anexar o novo modo de exibição

Para criar e anexar o novo modo de exibição, você precisa modificar a função InitInstance da classe de aplicativo. A modificação adiciona um novo código que cria um novo objeto de exibição e, em seguida, inicializa ambos, m_pOldView e m_pNewView, com os dois objetos de exibição existentes.

Como o novo modo de exibição é criado dentro da função InitInstance, as exibições novas e existentes persistem durante o tempo de vida do aplicativo. No entanto, o aplicativo poderia facilmente criar o novo modo de exibição dinamicamente.

Insira esse código após a chamada para 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);

Salve suas alterações e continue para a próxima etapa.

Implementar a Função de Alternância

Na etapa anterior, você adicionou código que criou e inicializou um novo objeto de exibição. A última parte principal é implementar o método de alternância SwitchView.

No final do arquivo de implementação para sua classe de aplicativo (MYWINAPP. CPP), adicione a seguinte definição de método:

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;
}

Salve suas alterações e continue para a próxima etapa.

Adicionar suporte para alternar o modo de exibição

A etapa final envolve a adição de código que chama o método SwitchView quando o aplicativo precisa alternar entre exibições. Isso pode ser feito de várias maneiras: adicionando um novo item de menu para o usuário escolher ou alternando as exibições internamente quando determinadas condições forem atendidas.

Para obter mais informações sobre como adicionar novos itens de menu e funções do manipulador de comandos, consulte Manipuladores para Comandos e Notificações de Controle.

Confira também

Arquitetura de documento/exibição