Visual C++ Programming Dialog Box Department of Digital Contents Sang Il Park
모드형 대화상자 (1/4) 모드형 대화상자 작성 순서 ① 대화상자 리소스 작성 [Resource View] [insert dialog] ② CDialog (파생) 클래스 객체 생성 이 때 대화상자 리소스 ID를 생성자의 인자로 넘겨준다. [Project][add class] menu 이용 ③ 창 띄우기: CDialog::DoModal() 함수 호출
모드형 대화상자 (2/4) CDialog 클래스 가상 함수 호출 시점: WM_INITDIALOG 메시지 발생시 창을 준비하고 화면에 보이기 직전에 발생 속성의 Messages 항목에 없고, 수동으로 추가하여야 함 용도: 컨트롤을 초기화하거나 키보드 포커스를 변경 virtual BOOL CDialog::OnInitDialog ( );
모드형 대화상자 (3/4) CDialog 클래스 가상 함수 (cont'd) 호출 시점: IDOK 버튼을 누를 때 용도: 컨트롤의 값을 읽거나 값의 타당성 여부를 검사한 후 대화상자 종료 호출 시점: IDCANCEL 버튼을 누를 때 용도: 대화상자 종료 virtual void CDialog::OnOK ( ); virtual void CDialog::OnCancel ( );
DDX/DDV (4/8) DDX(Dialog Data eXchange) IDC_STR IDC_COLOR ① ② 대화상자 m_str m_color 대화상자 객체 뷰 객체 ③ ④ 자동화?
DDX/DDV (5/8) OnInitDialog(), OnOK() 함수 내부 구현 BOOL CDialog::OnInitDialog() { ... UpdateData(FALSE); } void CDialog::OnOK() UpdateData(TRUE);
DDX/DDV (7/8) DDX 구현 컨트롤의 값을 저장할 변수 선언 DoDataExchange() 함수를 자신의 프로그램에 맞게 재정의 DDX_* 매크로 사용 void CMyDialog::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CMyDialog) DDX_Text(pDX, IDC_STR, m_str); DDX_Text(pDX, IDC_COLOR, m_color); //}}AFX_DATA_MAP }
비 모드형 대화상자 차이점 객체를 View Class나 MainFrame Class에서 가지고 있어야 한다 (헤더파일에 객체추가) CDialog::DoModal() 함수 대신 CDialog::Create() 함수를 이용하여 생성한다. 화면에 보여줄 때는 CDialog::ShowWindow() 함수를 사용한다. 대화상자를 닫을 때 CDialog::EndDialog() 함수 대신 CWnd::DestroyWindow() 함수를 호출한다.
Dialog Box-based application/ MFC Dialog boxes
대화상자 기반 응용 프로그램 (1/2) 대화상자 기반 응용 프로그램 대화상자가 메인 윈도우 역할을 하는 응용 프로그램
대화상자 기반 응용 프로그램 (2/2) InitInstance() 함수 BOOL CSimpleCalcApp::InitInstance() { CSimpleCalcDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK) { } else if (nResponse == IDCANCEL) { return FALSE;
공통 대화상자 (1/10) MFC 클래스 계층도
공통 대화상자 (2/10) MFC 공통 대화상자 클래스 MFC 클래스 용도 API 함수 CColorDialog 색상 선택 ChooseColor CFileDialog 파일 열기 또는 저장 GetOpenFileName, GetSaveFileName CFindReplaceDialog 찾기 또는 바꾸기 FindText, ReplaceText CFontDialog 폰트 선택 ChooseFont CPageSetupDialog 페이지 설정(페이지 크기, 방향, 페이지 여백 등) PageSetupDlg CPrintDialog 인쇄 설정(프린터, 인쇄 범위 등) PrintDlg CPrintDialogEx (>MFC 7.0) PrintDlgEx (>윈도우 2000)
공통 대화상자 (3/10) CColorDialog CColorDialog dlg; dlg.DoModal(); COLORREF color = dlg.GetColor(); CColorDialog dlg(RGB(255, 0, 0), CC_FULLOPEN); dlg.DoModal(); COLORREF color = dlg.GetColor();
공통 대화상자 (4/10) CFileDialog CFileDialog dlg(TRUE); if(dlg.DoModal() == IDOK) MessageBox(dlg.GetPathName()); CFileDialog dlg(FALSE); if(dlg.DoModal() == IDOK) MessageBox(dlg.GetPathName());
공통 대화상자 (5/10) CFindReplaceDialog 사용 방법은 교재 참조
공통 대화상자 (6/10) CFontDialog Font의 색(GetColor)를 설정하거나, font의 세부 사항을 결정한다. Font의 세부 사항은 LOGFONT 구조체에 저장됨 GetCurrentFont
공통 대화상자 (6/10) CFontDialog CFontDialog dlg; if(dlg.DoModal() == IDOK){ CClientDC dc(this); // 화면을 지운다. CRect rect; GetClientRect(&rect); dc.SelectStockObject(WHITE_PEN); dc.SelectStockObject(WHITE_BRUSH); dc.Rectangle(&rect); // 선택된 색상을 알아낸다. COLORREF color = dlg.GetColor(); dc.SetTextColor(color);
공통 대화상자 (7/10) CFontDialog (cont'd) // 선택된 폰트를 알아낸다. LOGFONT lf; dlg.GetCurrentFont(&lf); CFont font; font.CreateFontIndirect(&lf); dc.SelectObject(&font); // 텍스트를 출력한다. dc.TextOut(10, 10, CString("한글 & English")); }
공통 대화상자 (8/10) CPageSetupDialog CPageSetupDialog dlg; dlg.DoModal();
공통 대화상자 (9/10) CPrintDialog CPrintDialog dlg(TRUE); dlg.DoModal(); CPrintDialog dlg(FALSE); dlg.DoModal();
공통 대화상자 (10/10) CPrintDialogEx // stdafx.h 파일에서 WINVER 상수값을 0x0500 이상으로 정의한다. // (예) #define WINVER 0x0500 CPrintDialogEx dlg; dlg.DoModal();
Document/View Architecture
도큐먼트/뷰 구조 (1/9) 도큐먼트와 뷰 디스크에 저장된 파일을 읽는 경우 도큐먼트 객체 뷰 객체 파일 사용자
도큐먼트/뷰 구조 (2/9) 도큐먼트와 뷰 사용자가 데이터를 입력하는 경우 도큐먼트 객체 뷰 객체 파일 사용자
도큐먼트/뷰 구조 (3/9) 도큐먼트와 뷰 입력된 문서를 디스크 파일로 저장하는 경우 도큐먼트 객체 뷰 객체 파일 사용자
도큐먼트/뷰 구조 (4/9) 도큐먼트와 뷰 클래스의 역할 클래스 역할 도큐먼트 데이터를 저장하거나 읽어들인다. 데이터의 변경 사항이 생기면 뷰의 화면을 갱신한다. 뷰 데이터를 화면에 표시한다. 사용자와의 상호 작용을 담당한다.
도큐먼트/뷰 구조 (5/9) 도큐먼트/뷰 구조의 장점 서로 다른 기능을 도큐먼트와 뷰 클래스로 분리해서 구현하기 때문에 개념적으로 이해하기 쉽다. 하나의 도큐먼트에 여러 개의 뷰가 존재하는 모델을 구현하기가 쉽다. 예) 비주얼 C++ 편집창 MFC에서 도큐먼트/뷰 구조를 위해 제공하는 부가적인 서비스를 이용할 수 있다. 예) 직렬화
도큐먼트/뷰 구조 (6/9) SDI와 MDI 다룰 수 있는 문서의 개수에 따라 구분
도큐먼트/뷰 구조 (7/9) 도큐먼트 템플릿 MFC 클래스 계층도 도큐먼트, 프레임 윈도우, 뷰 클래스 정보를 유지 필요에 따라 해당 객체를 동적으로 생성 MFC 클래스 계층도 SDI MDI
도큐먼트/뷰 구조 (8/9) InitInstance() 함수 BOOL CExFileApp::InitInstance() { ... CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CExFileDoc), RUNTIME_CLASS(CMainFrame), RUNTIME_CLASS(CExFileView)); AddDocTemplate(pDocTemplate); }
도큐먼트/뷰 구조 (9/9) 주요 객체의 관계 생성 주체 생성되는 것 ①응용 프로그램 객체 ②도큐먼트 템플릿 객체 ③도큐먼트 객체, ④프레임 윈도우 객체 프레임 윈도우 객체 ⑤뷰 객체
도큐먼트/뷰 구조 응용 프로그램 예제 작성 (1/5) 도큐먼트/뷰 구조 응용 프로그램 예제 작성 (1/5) 프로젝트 생성 (단일문서 + 문서/뷰 아키텍쳐)
도큐먼트/뷰 구조 응용 프로그램 예제 작성 (2/5) 도큐먼트/뷰 구조 응용 프로그램 예제 작성 (2/5) 고급기능 옵션 설정 ActiveX controls 선택 해제
도큐먼트/뷰 구조 응용 프로그램 예제 작성 (3/5) 도큐먼트/뷰 구조 응용 프로그램 예제 작성 (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) 도큐먼트/뷰 구조 응용 프로그램 예제 작성 (4/5) 실행 결과
도큐먼트/뷰 구조 응용 프로그램 예제 작성 (5/5) 도큐먼트/뷰 구조 응용 프로그램 예제 작성 (5/5) 실행 결과 (cont'd)
도큐먼트/뷰 구조 응용 프로그램 예제 분석 (1/10) 도큐먼트/뷰 구조 응용 프로그램 예제 분석 (1/10) 응용 프로그램 클래스 BEGIN_MESSAGE_MAP(CExFileApp, CWinApp) //{{AFX_MSG_MAP(CExFileApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) //}}AFX_MSG_MAP ① ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP() BOOL CExFileApp::InitInstance() { ② CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate(
도큐먼트/뷰 구조 응용 프로그램 예제 분석 (2/10) 도큐먼트/뷰 구조 응용 프로그램 예제 분석 (2/10) IDR_MAINFRAME, RUNTIME_CLASS(CExFileDoc), RUNTIME_CLASS(CMainFrame), RUNTIME_CLASS(CExFileView)); AddDocTemplate(pDocTemplate); ③ CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); ④ if (!ProcessShellCommand(cmdInfo)) return FALSE; ⑤ m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow(); return TRUE; }
도큐먼트/뷰 구조 응용 프로그램 예제 분석 (3/10) 도큐먼트/뷰 구조 응용 프로그램 예제 분석 (3/10) 프레임 윈도우 클래스 // 헤더 파일 class CMainFrame : public CFrameWnd { ... protected: ① DECLARE_DYNCREATE(CMainFrame) } // 구현 파일 ② IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
도큐먼트/뷰 구조 응용 프로그램 예제 분석 (4/10) 도큐먼트/뷰 구조 응용 프로그램 예제 분석 (4/10) 뷰 클래스 // 헤더 파일 class CExFileView : public CView { protected: CExFileView(); ① DECLARE_DYNCREATE(CExFileView) public: ② CExFileDoc* GetDocument(); ... } #ifndef _DEBUG ③ inline CExFileDoc* CExFileView::GetDocument() { return (CExFileDoc*)m_pDocument; } #endif
도큐먼트/뷰 구조 응용 프로그램 예제 분석 (5/10) 도큐먼트/뷰 구조 응용 프로그램 예제 분석 (5/10) // 구현 파일 ④ IMPLEMENT_DYNCREATE(CExFileView, CView) BEGIN_MESSAGE_MAP(CExFileView, CView) //{{AFX_MSG_MAP(CExFileView) //}}AFX_MSG_MAP ⑤ ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP() ... ⑥ void CExFileView::OnDraw(CDC* pDC) { CExFileDoc* pDoc = GetDocument();
도큐먼트/뷰 구조 응용 프로그램 예제 분석 (6/10) 도큐먼트/뷰 구조 응용 프로그램 예제 분석 (6/10) ASSERT_VALID(pDoc); pDC->SetMapMode(MM_LOMETRIC); pDC->Ellipse(100, -100, 600, -600); } ... ⑦ CExFileDoc* CExFileView::GetDocument() { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CExFileDoc))); return (CExFileDoc*)m_pDocument;
도큐먼트/뷰 구조 응용 프로그램 예제 분석 (7/10) 도큐먼트/뷰 구조 응용 프로그램 예제 분석 (7/10) 도큐먼트 클래스 // 헤더 파일 class CExFileDoc : public CDocument { protected: CExFileDoc(); ① DECLARE_DYNCREATE(CExFileDoc) // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CExFileDoc) public: ② virtual BOOL OnNewDocument(); ③ virtual void Serialize(CArchive& ar); //}}AFX_VIRTUAL
도큐먼트/뷰 구조 응용 프로그램 예제 분석 (8/10) 도큐먼트/뷰 구조 응용 프로그램 예제 분석 (8/10) public: virtual ~CExFileDoc(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif DECLARE_MESSAGE_MAP() }; // 구현 파일 ④ IMPLEMENT_DYNCREATE(CExFileDoc, CDocument) BEGIN_MESSAGE_MAP(CExFileDoc, CDocument) END_MESSAGE_MAP()
도큐먼트/뷰 구조 응용 프로그램 예제 분석 (9/10) 도큐먼트/뷰 구조 응용 프로그램 예제 분석 (9/10) CExFileDoc::CExFileDoc() { } CExFileDoc::~CExFileDoc() { } ⑤ BOOL CExFileDoc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; return TRUE; } ⑥ void CExFileDoc::Serialize(CArchive& ar) if (ar.IsStoring()) { }
도큐먼트/뷰 구조 응용 프로그램 예제 분석 (10/10) 도큐먼트/뷰 구조 응용 프로그램 예제 분석 (10/10) else { } } #ifdef _DEBUG void CExFileDoc::AssertValid() const { CDocument::AssertValid(); void CExFileDoc::Dump(CDumpContext& dc) const CDocument::Dump(dc); #endif //_DEBUG
(CSingleDocTemplate) SDI 응용 프로그램 구조 (1/11) SDI 응용 프로그램 구조 1 응용 프로그램 (CWinApp) 프레임 윈도우 (CFrameWnd) 도큐먼트 템플릿 (CSingleDocTemplate) 도큐먼트 (CDocument) 뷰 (CView)
(CSingleDocTemplate) SDI 응용 프로그램 구조 (2/11) SDI 응용 프로그램 구조 2 응용 프로그램 (CWinApp) 도큐먼트 템플릿 (CSingleDocTemplate) 도큐먼트 (CDocument) 뷰 (CView) 프레임 윈도우 (CFrameWnd)
SDI 응용 프로그램 구조 (3/11) 도큐먼트 프레임 윈도우 도큐먼트의 내용을 화면에 표시하는 역할을 하는 뷰를 자식으로 갖는 윈도우 = 뷰의 부모 윈도우 = 뷰를 감싸고 있는 윈도우 메인 윈도우 메인 윈도우 = 도큐먼트 프레임 윈도우 도큐먼트 프레임 윈도우
GetFirstViewPosition GetFirstDocTemplatePosition SDI 응용 프로그램 구조 (4/11) 주요 객체 사이의 참조 도큐먼트 뷰 프레임 윈도우 GetFirstViewPosition & GetNextView GetDocument GetActiveDocument GetActiveView 응용 프로그램 AfxGetMainWnd AfxGetApp m_pMainWnd GetParentFrame 템플릿 GetFirstDocTemplatePosition & GetNextDocTemplate GetDocTemplate GetFirstDocPosition & GetNextDoc
SDI 응용 프로그램 구조 (5/11) 함수 요약 CWinApp* AfxGetApp ( ); 응용 프로그램 객체의 주소를 리턴 CWnd* AfxGetMainWnd ( ); 메인 윈도우 객체의 주소를 리턴 CFrameWnd* CWnd::GetParentFrame ( ); 프레임 윈도우 객체의 주소를 리턴 CView* CFrameWnd::GetActiveView ( ); 활성 뷰 객체의 주소를 리턴
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
SDI 응용 프로그램 구조 (7/11) 함수 요약 (cont'd) POSITION CWinApp::GetFirstDocTemplatePosition ( ); CDocTemplate* CWinApp::GetNextDocTemplate (POSITION& pos); 응용 프로그램 객체가 관리하는 모든 도큐먼트 템플릿 객체의 주소를 리턴 응용 프로그램 객체 m_templateList 도큐먼트 템플릿 객체#1 객체#2 객체#3 NULL
SDI 응용 프로그램 구조 (8/11) 함수 요약 (cont'd) POSITION CDocTemplate::GetFirstDocPosition ( ); CDocument* CDocTemplate::GetNextDoc (POSITION& rPos); 도큐먼트 템플릿 객체가 관리하는 모든 도큐먼트 객체의 주소를 리턴 CDocTemplate* CDocument::GetDocTemplate ( ); 도큐먼트 객체와 연결된 도큐먼트 템플릿 객체의 주소를 리턴 도큐먼트 템플릿 객체 m_docList 도큐먼트 객체#1 객체#2 객체#3 NULL
문서/뷰 구조 좀 더 자세히 보기 단일 문서를 다시 만든다. 문서 템플릿 문자열을 편집
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() CView::OnUpdate() CWnd::Invalidate() 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() 함수에서 호출
명령 라우팅 (1/2) MFC 응용 프로그램에서 사용하는 메시지 종류
명령 라우팅 (2/2) 명령 라우팅 순서 ⑥ ::DefWindowProc() ⑤ 응용 프로그램 객체 명령 메시지 ④ 프레임 윈도우 명령 메시지 명령 갱신 메시지 ② 활성 도큐먼트 ① 활성 뷰 ③ 도큐먼트 템플릿 ⑤ 응용 프로그램 객체 ⑥ ::DefWindowProc()
분할 윈도우 (1/4) 동적 분할 윈도우 같은 뷰 클래스를 기반으로 여러 개의 뷰를 생성 총 네 개의 구획(Pane) 생성 가능
분할 윈도우 (2/4) 동적 분할 윈도우 구현
분할 윈도우 (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(CExSplitView), CSize(300, 200), pContext); m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CDrawView), SetActiveView((CView *)m_wndSplitter.GetPane(0, 0)); return TRUE; }