Udostępnij przez


Dodawanie wielu widoków do pojedynczego dokumentu

W aplikacji z interfejsem pojedynczego dokumentu (SDI) utworzonej za pomocą biblioteki klas Microsoft Foundation (MFC), każdy typ dokumentu jest skojarzony z jednym typem widoku. W niektórych przypadkach pożądane jest mieć możliwość przełączenia bieżącego widoku dokumentu na nowy widok.

Wskazówka

Aby uzyskać dodatkowe procedury implementowania wielu widoków dla pojedynczego dokumentu, zobacz CDocument::AddView i przykład COLLECT MFC.

Tę funkcję można zaimplementować, dodając nową CViewklasę pochodną i dodatkowy kod umożliwiający dynamiczne przełączanie widoków do istniejącej aplikacji MFC.

Kroki są następujące:

W pozostałej części tego tematu przyjęto następujące założenia:

  • Nazwa obiektu pochodnego CWinApp to CMyWinApp, a CMyWinApp jest zadeklarowana i zdefiniowana w MYWINAPP.H i MYWINAPP.CPP.

  • CNewView to nazwa nowego obiektu pochodnego CView, a CNewView jest zadeklarowana i zdefiniowana w NEWVIEW.H i NEWVIEW.CPP.

Modyfikowanie istniejącej klasy aplikacji

Aby aplikacja przełączała się między widokami, należy zmodyfikować klasę aplikacji, dodając zmienne składowe do przechowywania widoków i metody, aby je przełączyć.

Dodaj następujący kod do deklaracji CMyWinApp w aplikacji MYWINAPP. H:

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

Nowe zmienne składowe, m_pOldView i m_pNewView, wskazują na bieżący widok oraz nowo utworzony widok. Nowa metoda (SwitchView) przełącza widoki po zażądaniu przez użytkownika. Treść metody została omówiona w dalszej części tego tematu w temacie Implementowanie funkcji przełączania.

Ostatnia modyfikacja klasy aplikacji wymaga włączenia nowego pliku nagłówka definiującego komunikat systemu Windows (WM_INITIALUPDATE), który jest używany w funkcji przełączania.

Wstaw następujący wiersz w sekcji dołączania aplikacji MYWINAPP. CPP:

#include <AFXPRIV.H>

Zapisz zmiany i przejdź do następnego kroku.

Tworzenie i modyfikowanie nowej klasy widoku

Tworzenie nowej klasy widoku jest łatwe za pomocą polecenia Nowa klasa dostępnego w widoku klasy. Jedynym wymaganiem dla tej klasy jest to, że pochodzi z klasy CView. Dodaj tę nową klasę do aplikacji. Aby uzyskać szczegółowe informacje na temat dodawania nowej klasy do projektu, zobacz Dodawanie klasy.

Po dodaniu klasy do projektu należy zmienić dostępność niektórych składowych klas widoku.

Zmodyfikuj NEWVIEW.H przez zmianę specyfikatora dostępu z protected na public dla konstruktora i destruktora. Dzięki temu klasa może zostać utworzona i zniszczona dynamicznie oraz zmodyfikować wygląd widoku, zanim będzie widoczna.

Zapisz zmiany i przejdź do następnego kroku.

Tworzenie i dołączanie nowego widoku

Aby utworzyć i dołączyć nowy widok, należy zmodyfikować InitInstance funkcję klasy aplikacji. Modyfikacja dodaje nowy kod, który tworzy nowy obiekt widoku, a następnie inicjuje zarówno m_pOldView, jak i m_pNewView dwoma istniejącymi obiektami widoku.

Ponieważ nowy widok jest tworzony w InitInstance ramach funkcji, zarówno nowe, jak i istniejące widoki są utrwalane przez okres istnienia aplikacji. Jednak aplikacja może równie łatwo utworzyć nowy widok dynamicznie.

Wstaw ten kod po wywołaniu metody 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);

Zapisz zmiany i przejdź do następnego kroku.

Implementowanie funkcji przełączania

W poprzednim kroku dodano kod, który utworzył i zainicjował nowy obiekt widoku. Ostatnim głównym elementem jest zaimplementowanie metody przełączania , SwitchView.

Na końcu pliku implementacji dla klasy aplikacji (MYWINAPP). CPP), dodaj następującą definicję metody:

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

Zapisz zmiany i przejdź do następnego kroku.

Dodawanie obsługi przełączania widoku

Ostatnim krokiem jest dodanie kodu, który wywołuje metodę SwitchView , gdy aplikacja musi przełączać się między widokami. Można to zrobić na kilka sposobów: dodając nowy element menu dla użytkownika, aby wybrać lub przełączać widoki wewnętrznie po spełnieniu określonych warunków.

Aby uzyskać więcej informacji na temat dodawania nowych elementów menu i funkcji obsługi poleceń, zobacz Handlers for Commands and Control Notifications (Programy obsługi poleceń i powiadomień sterowania).

Zobacz także

Architektura dokumentu/widoku