400 likes | 540 Views
Visual C++ Programming Dialog. Department of Digital Contents Sang Il Park. Document/View Architecture. 도큐먼트 / 뷰 구조 (1/9). 도큐먼트와 뷰 디스크에 저장된 파일을 읽는 경우. 도큐먼트 객체. 뷰 객체. 파일. 사용자. 도큐먼트 / 뷰 구조 (2/9). 도큐먼트와 뷰 사용자가 데이터를 입력하는 경우. 도큐먼트 객체. 뷰 객체. 파일. 사용자. 도큐먼트 / 뷰 구조 (3/9). 도큐먼트와 뷰
E N D
Visual C++ Programming Dialog Department of Digital Contents Sang Il Park
도큐먼트/뷰 구조 (1/9) • 도큐먼트와 뷰 • 디스크에 저장된 파일을 읽는 경우 도큐먼트 객체 뷰 객체 파일 사용자
도큐먼트/뷰 구조 (2/9) • 도큐먼트와 뷰 • 사용자가 데이터를 입력하는 경우 도큐먼트 객체 뷰 객체 파일 사용자
도큐먼트/뷰 구조 (3/9) • 도큐먼트와 뷰 • 입력된 문서를 디스크 파일로 저장하는 경우 도큐먼트 객체 뷰 객체 파일 사용자
도큐먼트/뷰 구조 (4/9) • 도큐먼트와 뷰 클래스의 역할
도큐먼트/뷰 구조 (2/6) • 도큐먼트/뷰 구조의 장점 • 서로 다른 기능을 도큐먼트와 뷰 클래스로 분리해서 구현하기 때문에 개념적으로 이해하기 쉽다. • 하나의 도큐먼트에 여러 개의 뷰가 존재하는 모델을 구현하기가 쉽다. • 예) 비주얼 C++ 편집창 • MFC에서 도큐먼트/뷰 구조를 위해 제공하는 부가적인 서비스를 이용할 수 있다. • 예) 직렬화
도큐먼트/뷰 구조 (3/6) • SDI와 MDI • 다룰 수 있는 문서의 개수에 따라 구분
SDI MDI 도큐먼트/뷰 구조 (4/6) • 도큐먼트 템플릿 • 도큐먼트, 프레임 윈도우, 뷰 클래스 정보를 유지 • 필요에 따라 해당 객체를 동적으로 생성 • MFC 클래스 계층도
도큐먼트/뷰 구조 (5/6) • InitInstance() 함수 BOOL CExFileApp::InitInstance() { ... CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CExFileDoc), RUNTIME_CLASS(CMainFrame), RUNTIME_CLASS(CExFileView)); AddDocTemplate(pDocTemplate); ... }
도큐먼트/뷰 구조 (6/6) • 주요 객체의 관계
도큐먼트/뷰 구조 응용 프로그램 예제 작성 (1/5) • 프로젝트 생성 (단일문서 + 문서/뷰 아키텍쳐)
도큐먼트/뷰 구조 응용 프로그램 예제 작성 (2/5) • 고급기능 옵션 설정 • ActiveX controls 선택해제
도큐먼트/뷰 구조 응용 프로그램 예제 작성 (3/5) • 코드 추가 void CExFileView::OnDraw(CDC* pDC) { CExFileDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); pDC->SetMapMode(MM_LOMETRIC); pDC->Ellipse(100, -100, 600, -600); }
도큐먼트/뷰 구조 응용 프로그램 예제 작성 (4/5) • 실행 결과
도큐먼트/뷰 구조 응용 프로그램 예제 작성 (5/5) • 실행 결과 (cont'd)
SDI 응용 프로그램 구조 (1/11) • SDI 응용 프로그램 구조 1 프레임 윈도우 (CFrameWnd) 응용 프로그램 (CWinApp) 도큐먼트 템플릿 (CSingleDocTemplate) 도큐먼트 (CDocument) 뷰 (CView)
프레임 윈도우 (CFrameWnd) 응용 프로그램 (CWinApp) 뷰 (CView) 도큐먼트 템플릿 (CSingleDocTemplate) 도큐먼트 (CDocument) 뷰 (CView) SDI 응용 프로그램 구조 (2/11) • SDI 응용 프로그램 구조 2
SDI 응용 프로그램 구조 (3/11) • 도큐먼트 프레임 윈도우 • 도큐먼트의 내용을 화면에 표시하는 역할을 하는 뷰를 자식으로 갖는 윈도우 =뷰의 부모 윈도우 = 뷰를 감싸고 있는 윈도우 메인 윈도우 메인 윈도우 = 도큐먼트 프레임 윈도우 도큐먼트 프레임 윈도우
GetFirstViewPosition & GetNextView 도큐먼트 뷰 GetDocument GetActiveDocument GetActiveView GetParentFrame GetDocTemplate 도큐먼트 프레임 윈도우 AfxGetMainWnd GetFirstDocPosition & GetNextDoc m_pMainWnd 도큐먼트 템플릿 응용 프로그램 AfxGetApp GetFirstDocTemplatePosition & GetNextDocTemplate SDI 응용 프로그램 구조 (4/11) • 주요 객체 사이의 참조
SDI 응용 프로그램 구조 (5/11) • 함수 요약 • CWinApp* AfxGetApp ( ); • 응용 프로그램 객체의 주소를 리턴 • CWnd* AfxGetMainWnd ( ); • 메인 윈도우 객체의 주소를 리턴 • CFrameWnd* CWnd::GetParentFrame ( ); • 프레임 윈도우 객체의 주소를 리턴 • CView* CFrameWnd::GetActiveView ( ); • 활성 뷰 객체의 주소를 리턴
뷰 객체#1 뷰 객체#2 뷰 객체#3 도큐먼트 객체 m_viewList NULL SDI 응용 프로그램 구조 (6/11) • 함수 요약 (cont'd) • CDocument* CFrameWnd::GetActiveDocument ( ); • 활성 도큐먼트 객체의 주소를 리턴 • CDocument* CView::GetDocument ( ); • 뷰 객체와 연결된 도큐먼트 객체의 주소를 리턴 • POSITION CDocument::GetFirstViewPosition ( );CView* CDocument::GetNextView (POSITION& rPosition); • 도큐먼트 객체와 연결된 모든 뷰 객체의 주소를 리턴
도큐먼트 템플릿 객체#1 도큐먼트 템플릿 객체#2 도큐먼트 템플릿 객체#3 응용 프로그램 객체 m_templateList NULL SDI 응용 프로그램 구조 (7/11) • 함수 요약 (cont'd) • POSITION CWinApp::GetFirstDocTemplatePosition ( );CDocTemplate* CWinApp::GetNextDocTemplate (POSITION& pos); • 응용 프로그램 객체가 관리하는 모든 도큐먼트 템플릿 객체의 주소를 리턴
도큐먼트 객체#1 도큐먼트 객체#2 도큐먼트 객체#3 도큐먼트 템플릿 객체 m_docList NULL SDI 응용 프로그램 구조 (8/11) • 함수 요약 (cont'd) • POSITION CDocTemplate::GetFirstDocPosition ( );CDocument* CDocTemplate::GetNextDoc (POSITION& rPos); • 도큐먼트 템플릿 객체가 관리하는 모든 도큐먼트 객체의 주소를 리턴 • CDocTemplate* CDocument::GetDocTemplate ( ); • 도큐먼트 객체와 연결된 도큐먼트 템플릿 객체의 주소를 리턴
문서/뷰 구조 좀 더 자세히 보기 • 단일 문서를 다시 만든다. • 문서템플릿 문자열을 편집
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);
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; }
SDI 응용 프로그램 구조 (11/11) • 도큐먼트 문자열 ExSDI\n\nExSDI\nExSDI 파일 (*.sdi)\n.sdi\nExSDI.Document ① ② ③ ④ ⑤ ⑥ \nExSDI Document ⑦
도큐먼트 클래스 (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() 도큐먼트 객체 뷰 객체
도큐먼트 클래스 (2/3) • 주요 함수 (cont'd) • virtual BOOL OnNewDocument ( ); • 새 문서를 생성할 때 자동으로 호출 • virtual BOOL OnOpenDocument (LPCTSTR lpszPathName); • 파일을 열 때 자동으로 호출 • virtual void DeleteContents ( ); • 새로운 문서를 생성하거나 파일을 열 때 자동으로 호출 • virtual void Serialize (CArchive& ar); • 파일을 열거나 저장할 때 자동으로 호출
도큐먼트 클래스 (3/3) • 가상 함수 호출 순서 • [파일]->[새 파일] 메뉴 항목을 선택할 때 • [파일]->[열기...] 메뉴 항목을 선택할 때 • [파일]->[저장] 또는 [파일]->[다른 이름으로 저장...] 메뉴 항목을 선택할 때 DeleteContents() OnNewDocument() DeleteContents() Serialize() OnOpenDocument() Serialize()
뷰 클래스 • 주요 함수 • 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()
명령 라우팅 (1/2) • MFC 응용 프로그램에서 사용하는 메시지 종류
⑥ ::DefWindowProc() ⑤ 응용 프로그램 객체 명령 메시지 명령 갱신 메시지 ④ 프레임 윈도우 ③ 도큐먼트 템플릿 ② 활성 도큐먼트 ① 활성 뷰 명령 라우팅 (2/2) • 명령 라우팅 순서
분할 윈도우 (1/4) • 동적 분할 윈도우 • 같은 뷰 클래스를 기반으로 여러 개의 뷰를 생성 • 총 네 개의 구획(Pane) 생성 가능
분할 윈도우 (2/4) • 동적 분할 윈도우 구현
분할 윈도우 (2/4) • 동적 분할 윈도우로 다양한 내용 출력하기: • 현재의 뷰가 어떠한 어떤 pane에 속하는지 판단 • 각 pane에 따라 출력한 내용을 달리한다. bool CSpliterWnd::IsChildPane ( CWnd * wnd, int * row, int * col ) if (col == 0) { … } Else if (col == 1) { …, }
분할 윈도우 (3/4) • 정적 분할 윈도우 • 서로 다른 뷰 클래스를 기반으로 여러 개의 뷰를 생성 • 총 256개의 구획 생성 가능
분할 윈도우 (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); SetActiveView((CView *)m_wndSplitter.GetPane(0, 0)); return TRUE; }