Visual C++ Programming Document/View Architecture Department of Digital Contents Sang Il Park
2 도큐먼트 / 뷰 구조 (1/3) 도큐먼트와 뷰 클래스의 역할 클래스역할 도큐먼트 데이터를 저장하거나 읽어들인다. 데이터의 변경 사항이 생기면 뷰의 화면을 갱신한다. 뷰 데이터를 화면에 표시한다. 사용자와의 상호 작용을 담당한다.
3 도큐먼트 / 뷰 구조 (2/3) 도큐먼트 / 뷰 구조의 장점 – 서로 다른 기능을 도큐먼트와 뷰 클래스로 분리해서 구현 하기 때문에 개념적으로 이해하기 쉽다. – 하나의 도큐먼트에 여러 개의 뷰가 존재하는 모델을 구현 하기가 쉽다. 예 ) 비주얼 C++ 편집창 –MFC 에서 도큐먼트 / 뷰 구조를 위해 제공하는 부가적인 서비스를 이용할 수 있다. 예 ) 직렬화
4 도큐먼트 / 뷰 구조 (3/3) SDI 와 MDI – 다룰 수 있는 문서의 개수에 따라 구분
5 SDI 응용 프로그램 구조 (1/11) SDI 응용 프로그램 구조 1 응용 프로그램 (CWinApp) 도큐먼트 템플릿 (CSingleDocTemplate) 도큐먼트 (CDocument) 뷰 (CView) 프레임 윈도우 (CFrameWnd)
6 SDI 응용 프로그램 구조 (2/11) SDI 응용 프로그램 구조 2 응용 프로그램 (CWinApp) 도큐먼트 템플릿 (CSingleDocTemplate) 도큐먼트 (CDocument) 뷰 (CView) 프레임 윈도우 (CFrameWnd) 뷰 (CView)
SDI 응용 프로그램 구조 (4/11) 주요 객체 사이의 참조 도큐먼트뷰 프레임 윈도우 GetFirstViewPosition & GetNextView GetDocument GetActiveDocumentGetActiveView 응용 프로그램 AfxGetMainWnd AfxGetApp m_pMainWnd GetParentFrame 도큐먼트 템플릿 GetFirstDocTemplatePosition & GetNextDocTemplate GetDocTemplate GetFirstDocPosition & GetNextDoc
8 SDI 응용 프로그램 구조 (5/11) 함수 요약 –CWinApp* AfxGetApp ( ); 응용 프로그램 객체의 주소를 리턴 –CWnd* AfxGetMainWnd ( ); 메인 윈도우 객체의 주소를 리턴 –CFrameWnd* CWnd::GetParentFrame ( ); 프레임 윈도우 객체의 주소를 리턴 –CView* CFrameWnd::GetActiveView ( ); 활성 뷰 객체의 주소를 리턴
9 SDI 응용 프로그램 구조 (6/11) 함수 요약 (cont'd) –CDocument* CFrameWnd::GetActiveDocument ( ); 활성 도큐먼트 객체의 주소를 리턴 –CDocument* CView::GetDocument ( ); 뷰 객체와 연결된 도큐먼트 객체의 주소를 리턴 –POSITION CDocument::GetFirstViewPosition ( ); CView* CDocument::GetNextView (POSITION& rPosition); 도큐먼트 객체와 연결된 모든 뷰 객체의 주소를 리턴 도큐먼트 객체 m_viewList 뷰 객체 #1 뷰 객체 #2 뷰 객체 #3 NULL
10 SDI 응용 프로그램 구조 (7/11) 함수 요약 (cont'd) –POSITION CWinApp::GetFirstDocTemplatePosition ( ); CDocTemplate* CWinApp::GetNextDocTemplate (POSITION& pos); 응용 프로그램 객체가 관리하는 모든 도큐먼트 템플릿 객체의 주 소를 리턴 응용 프로그램 객체 m_templateList 도큐먼트 템플릿 객체 #1 도큐먼트 템플릿 객체 #2 도큐먼트 템플릿 객체 #3 NULL
11 SDI 응용 프로그램 구조 (8/11) 함수 요약 (cont'd) –POSITION CDocTemplate::GetFirstDocPosition ( ); CDocument* CDocTemplate::GetNextDoc (POSITION& rPos); 도큐먼트 템플릿 객체가 관리하는 모든 도큐먼트 객체의 주소 를 리턴 –CDocTemplate* CDocument::GetDocTemplate ( ); 도큐먼트 객체와 연결된 도큐먼트 템플릿 객체의 주소를 리턴 도큐먼트 템플릿 객체 m_docList 도큐먼트 객체 #1 도큐먼트 객체 #2 도큐먼트 객체 #3 NULL
문서 / 뷰 구조 좀 더 자세히 보기 단일 문서를 다시 만든다. – 문서 템플릿 문자열을 편집
13 SDI 응용 프로그램 구조 (9/11) InitInstance() 함수 BOOL CExSDIApp::InitInstance() {... ① SetRegistryKey(_T(" Local AppWizard-Generated Applications ")); ② LoadStdProfileSettings(); CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CExSDIDoc), RUNTIME_CLASS(CMainFrame), RUNTIME_CLASS(CExSDIView)); AddDocTemplate(pDocTemplate);
14 SDI 응용 프로그램 구조 (10/11) InitInstance() 함수 (cont'd) ③ EnableShellOpen(); ④ RegisterShellFileTypes(TRUE); CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); if (!ProcessShellCommand(cmdInfo)) return FALSE; m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow(); ⑤ m_pMainWnd->DragAcceptFiles(); return TRUE; }
15 SDI 응용 프로그램 구조 (11/11) 도큐먼트 문자열 ExSDI\n\nExSDI\nExSDI 파일 (*.sdi)\n.sdi\nExSDI.Document ① ② ③ ④ ⑤ ⑥ \nExSDI Document ⑦
16 도큐먼트 클래스 (1/3) 주요 함수 –void SetModifiedFlag (BOOL bModified = TRUE); 도큐먼트 객체가 유지하는 데이터를 수정한 경우 호출 –void UpdateAllViews (CView* pSender, LPARAM lHint = 0L, CObject* pHint = NULL); 도큐먼트 객체와 연결된 모든 뷰의 화면을 갱신 CDocument::UpdateAllViews() CWnd::Invalidate() CView::OnUpdate() CWnd::OnPaint() CView::OnDraw() 도큐먼트 객체 뷰 객체
17 도큐먼트 클래스 (2/3) 주요 함수 (cont'd) –virtual BOOL OnNewDocument ( ); 새 문서를 생성할 때 자동으로 호출 –virtual BOOL OnOpenDocument (LPCTSTR lpszPathName); 파일을 열 때 자동으로 호출 –virtual void DeleteContents ( ); 새로운 문서를 생성하거나 파일을 열 때 자동으로 호출 –virtual void Serialize (CArchive& ar); 파일을 열거나 저장할 때 자동으로 호출
18 도큐먼트 클래스 (3/3) 가상 함수 호출 순서 –[ 파일 ]->[ 새 파일 ] 메뉴 항목을 선택할 때 –[ 파일 ]->[ 열기...] 메뉴 항목을 선택할 때 –[ 파일 ]->[ 저장 ] 또는 [ 파일 ]->[ 다른 이름으로 저장...] 메뉴 항목을 선택할 때 DeleteContents() OnNewDocument() DeleteContents() Serialize() OnOpenDocument() Serialize()
19 뷰 클래스 주요 함수 –virtual void OnDraw (CDC* pDC); 화면 출력, 인쇄, 인쇄 미리보기를 할 때 자동으로 호출 –virtual void OnInitialUpdate(); 뷰 객체가 도큐먼트 객체와 연결된 후 화면에 보이기 전에 자동으 로 호출 –virtual void OnUpdate (CView* pSender, LPARAM lHint, CObject* pHint); CDocument::UpdateAllViews() 함수와 CView::OnInitialUpdate() 함수에서 호출
코딩연습 Document/View 구조를 사용하여 원을 그리고, 저장 / 로드 하는 프로그램을 만들자. 고쳐야 하는 부분 CView:: OnDraw() CDocument:: OnNewDocument() Serialize() 고쳐야 하는 부분 CView:: OnDraw() CDocument:: OnNewDocument() Serialize()
Splitter Window
22 분할 윈도우 (1/4) 동적 분할 윈도우 – 같은 뷰 클래스를 기반으로 여러 개의 뷰를 생성 – 총 네 개의 구획 (Pane) 생성 가능
23 분할 윈도우 (2/4) 동적 분할 윈도우 구현
분할 윈도우 (2/4) 동적 분할 윈도우로 다양한 내용 출력하기 : 1. 현재의 뷰가 어떠한 어떤 pane 에 속하는지 판단 2. 각 pane 에 따라 출력한 내용을 달리한다. bool CSpliterWnd::IsChildPane ( CWnd * wnd, int * row, int * col ) if (col == 0) { … } Else if (col == 1) { …, } if (col == 0) { … } Else if (col == 1) { …, }
25 분할 윈도우 (3/4) 정적 분할 윈도우 – 서로 다른 뷰 클래스를 기반으로 여러 개의 뷰를 생성 – 총 256 개의 구획 생성 가능
26 분할 윈도우 (4/4) 정적 분할 윈도우 구현 BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext) { m_wndSplitter.CreateStatic(this, 2, 1); m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CFirstView), CSize(300, 200), pContext); m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CSecondView), CSize(300, 200), pContext); return TRUE; }
다양한 View Classes
다양한 View Class? View Class 에는 많은 종류가 있다
다양한 View Class? Project 생성 시 Setting:
FormView Dialog Box 와 비슷한 역할을 하는 View Class