MFC

SDI 단일 문서에 다중 뷰 추가 - MSDN 표준방식

디버그정 2008. 9. 4. 18:07
Visual C++
MFC
 단일 문서에 다중 뷰 추가

MFC(Microsoft Foundation Class) 라이브러리로 만든 SDI(단일 문서 인터페이스) 응용 프로그램에서 각 문서 형식은 단일 뷰 형식과 연결되어 있습니다. 일부 경우 문서의 현재 뷰를 새 뷰로 전환하는 기능을 설정하는 것이 좋습니다.

   단일 문서의 다중 뷰 구현에 대한 추가 절차는 CDocument::AddView와 MFC 샘플 ENROLLCOLLECT를 참조하십시오.

이 기능은 CView에서 파생된 새 클래스와 뷰를 동적으로 전환하는 추가 코드를 기존 MFC 응용 프로그램에 추가하여 구현할 수 있습니다.

이 기능을 구현하는 단계는 다음과 같습니다.

이 항목의 나머지 부분에서는 다음과 같이 가정합니다.

  • CWinApp에서 파생된 개체 이름은 CMyWinApp이고 CMyWinApp는 MYWINAPP.H와 MYWINAPP.CPP에서 선언 및 정의합니다.
  • CNewViewCView에서 파생된 새 개체의 이름이고 CNewView는 NEWVIEW.H 및 NEWVIEW.CPP에서 선언 및 정의합니다.

기존 응용 프로그램 클래스 수정

뷰 간에 전환하는 응용 프로그램에서 뷰와 뷰 전환 메서드를 저장하려면 멤버 변수를 추가하여 응용 프로그램 클래스를 수정해야 합니다.

MYWINAPP.H의 CMyWinApp 선언에 다음 코드를 추가합니다.

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

새 멤버 변수 m_pOldViewm_pNewView는 현재 뷰와 새로 만든 뷰를 가리킵니다. 새 메서드(SwitchView)는 사용자가 요청할 때 뷰를 전환합니다. 메서드 본문은 이 항목 뒤 부분에 나오는 전환 함수 구현에서 설명합니다.

응용 프로그램을 마지막으로 수정할 때 전환 함수에 사용된 Windows 메시지(WM_INITIALUPDATE)를 정의하는 새 헤더 파일이 포함되어야 합니다.

MYWINAPP.CPP의 include 섹션에 다음 줄을 삽입합니다.

#include <AFXPRIV.H>

변경 내용을 저장하고 다음 단계를 계속합니다.

새 뷰 클래스 만들기 및 수정

클래스 뷰의 New Class 명령을 사용하면 편리하게 새 뷰 클래스를 만들 수 있습니다. 이 클래스에 대한 유일한 요구 사항은 CView에서 파생되어야 한다는 것입니다. 이 새로운 클래스를 응용 프로그램에 추가합니다. 프로젝트에 새 클래스를 추가하는 방법에 대한 자세한 내용은 클래스 추가를 참조하십시오.

프로젝트에 클래스를 추가한 후 일부 뷰 클래스 멤버의 액세스 가능성을 변경해야 합니다.

생성자와 소멸자에 대한 액세스 지정자를 protected에서 public로 변경하여 NEWVIEW.H를 수정합니다. 이렇게 하면 클래스가 동적으로 생성 및 소멸되고 뷰가 표시되기 전에 뷰의 모양을 수정할 수 있습니다.

변경 내용을 저장하고 다음 단계를 계속합니다.

새 뷰 만들기 및 연결

새 뷰를 만들고 연결하려면 응용 프로그램 클래스의 InitInstance 함수를 수정해야 합니다. 이 함수를 수정하면 새 뷰 개체를 만드는 새 코드를 추가한 다음 두 개의 기존 뷰 개체를 사용하여 m_pOldViewm_pNewView 모두를 초기화합니다.

새 뷰는 InitInstance 함수 내에 만들어지므로 새 뷰와 기존 뷰는 응용 프로그램이 소멸될 때까지 지속됩니다. 그러나, 응용 프로그램에서는 간단하게 새 뷰를 동적으로 만들 수 있습니다.

ProcessShellCommand를 호출한 후 다음 코드를 삽입합니다.

...
CView* pActiveView = ((CFrameWnd*) m_pMainWnd)->GetActiveView();
m_pOldView = pActiveView;
m_pNewView = (CView*) new CNewView;

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, "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 메서드를 호출하는 코드를 추가합니다. 뷰 간의 전환은 여러 가지 방법으로 수행할 수 있습니다. 사용자가 선택하는 새 메뉴 항목을 추가할 수도 있고 일정한 조건을 만족하는 경우 내부적으로 뷰를 전환할 수도 있습니다.

새 메뉴 항목과 명령 처리기 함수 추가에 대한 자세한 내용은 명령 및 컨트롤 알림에 대한 처리기를 참조하십시오.

참고 항목

문서/뷰 아키텍처