Presentation is loading. Please wait.

Presentation is loading. Please wait.

Chap. 6 Dialog and Control Classes. Contents  CDialog class  Common Dialogs  Property Sheets  Control classes.

Similar presentations


Presentation on theme: "Chap. 6 Dialog and Control Classes. Contents  CDialog class  Common Dialogs  Property Sheets  Control classes."— Presentation transcript:

1 Chap. 6 Dialog and Control Classes

2 Contents  CDialog class  Common Dialogs  Property Sheets  Control classes

3 CDialog Class  Dialog 의 종류  Modal dialog Close 될 때 까지 다른 부분을 사용할 수 없음 Close 될 때 까지 다른 부분을 사용할 수 없음 DoModal() 함수를 이용 DoModal() 함수를 이용 예 : common dialog box 예 : common dialog box  Modeless dialog Close 되기 전에 다른 부분을 사용할 수 있음 Close 되기 전에 다른 부분을 사용할 수 있음 Create() 함수를 이용 Create() 함수를 이용 DestroyWindow() 함수를 이용하여 명시적으로 종료함 DestroyWindow() 함수를 이용하여 명시적으로 종료함 예 : find and replace dialog box 예 : find and replace dialog box

4 CDialog Class (cont’d)  History  MFC 1.0 Modal dialog : CModalDialog Modal dialog : CModalDialog Modeless dialog : CDialog Modeless dialog : CDialog  Current version Modal dialog : CDialog Modal dialog : CDialog Modeless dialog : Cdialog Modeless dialog : Cdialog  AFXWIN.H // all CModalDialog functionality is now in CDialog #define CModalDialog CDialog

5 CDialog Class (cont’d) void CMyView::DisplayOrderDialog() { CMyDialog myDialog(ID_DLG_MYDIALOG); if ( myDialog.DoModal() == IDOK ) { // Do OK processing } else { // Do Calnel processing } m_pDlgMyDlgPtr = new CMyDialog; m_pDlgMyDlgPtr->Create(ID_DLG_MYDIALOG); // Do something m_pDlgMyDlgPtr->DestroyWindow(); m_pDlgMyDlgPtr = NULL;

6 Win32 APIs  Dialog 생성을 위한 Win32 APIs  CreateDialog() Modeless dialog 생성, template resource 이용 Modeless dialog 생성, template resource 이용  CreateDialogIndirect() Modeless dialog 생성, template pointer 이용 Modeless dialog 생성, template pointer 이용  DialogBox() Modal dialog 생성, template resource 이용 Modal dialog 생성, template resource 이용  DialogBoxIndirect() Modal dialog 생성, template pointer 이용 Modal dialog 생성, template pointer 이용

7 Win32 APIs (cont’d)  CDialog Class  오직 CreateDialogIndirect() API 을 이용  Modality 를 내부적으로 구현  AFXWIN.H  DLGCORE.CPP, AFXWIN2.INL

8 CDialog class CDialog : public CWnd { DECLARE_DYNAMIC(CDialog) BOOL Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL); BOOL Create(UINT nIDTemplate, CWnd* pParentWnd = NULL); BOOL CreateIndirect(LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd = NULL, void* lpDialogInit = NULL); BOOL CreateIndirect(HGLOBAL hDialogTemplate, CWnd* pParentWnd = NULL); // Modal construct public: CDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL); CDialog(UINT nIDTemplate, CWnd* pParentWnd = NULL); BOOL InitModalIndirect(LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd = NULL, void* lpDialogInit = NULL); BOOL InitModalIndirect(HGLOBAL hDialogTemplate, CWnd* pParentWnd = NULL); // Operations public: // modal processing virtual int DoModal();

9 CDialog (cont’d) void NextDlgCtrl() const; void PrevDlgCtrl() const; void GotoDlgCtrl(CWnd* pWndCtrl); // termination void EndDialog(int nResult); // Overridables (special message map entries) virtual BOOL OnInitDialog(); virtual void OnSetFont(CFont* pFont); protected: virtual void OnOK(); virtual void OnCancel(); // Implementation public: virtual ~CDialog(); virtual BOOL PreTranslateMessage(MSG* pMsg); virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); virtual BOOL CheckAutoCenter();

10 protected: // parameters for 'DoModal' LPCTSTR m_lpszTemplateName; // name or MAKEINTRESOURCE HGLOBAL m_hDialogTemplate; // indirect (m_lpDialogTemplate == NULL) LPCDLGTEMPLATE m_lpDialogTemplate; void* m_lpDialogInit; // DLGINIT resource data CWnd* m_pParentWnd; // parent/owner window HWND m_hWndTop; // top level parent window (may be disabled) virtual void PreInitDialog(); // implementation helpers HWND PreModal(); void PostModal(); BOOL CreateIndirect(LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd, void* lpDialogInit, HINSTANCE hInst); BOOL CreateIndirect(HGLOBAL hDialogTemplate, CWnd* pParentWnd, HINSTANCE hInst); protected: DECLARE_MESSAGE_MAP() }; CDialog (cont’d)

11  Declaration(AFXWIN.H)  멤버 변수 m_nIDHelp m_nIDHelp  Button 을 위한 help ID m_lpszTemplateName m_lpszTemplateName  Resource template 의 이름 m_hDialogTemplate m_hDialogTemplate  일단 load 된 후의 resource template 의 handle m_lpDialogInit m_lpDialogInit  초기화에 관련된 data 에 대한 pointer CDialog (cont’d)

12 m_pParentWnd m_pParentWnd  Parent window 에 대한 pointer m_hWndTop m_hWndTop  Top-level parent window m_pOccDialogInfo m_pOccDialogInfo  OLE controls 을 위한 stored information  멤버 함수 virtual PreTranslateMessage() virtual PreTranslateMessage()  특별한 message(tool tips, context-sensitive help) 에 대한 filtering CDialog (cont’d)

13 virtual OnCmdMsg() virtual OnCmdMsg()  Command message 처리작업 virtual CheckAutoCenter() virtual CheckAutoCenter()  Auto-center 옵션이 체크되었는지 확인 virtual SetOccDialogInfo() virtual SetOccDialogInfo()  M_pOccDialogInfo 변수에 데이터를 setting virtual PreInitDialog() virtual PreInitDialog()  WM_INITDIALOG message 이전에 불리워지는 함수 PreModal() PreModal()  DoModal() 함수 실행을 위한 준비작업 PostModal() PostModal()  DoModal() 함수가 끝난후의 뒤처리 CDialog (cont’d)

14  일반적으로 두가지의 과정을 거침  CDialog construction  DoModal() 함수의 호출  CDialog construction  DLGCORE.CPP 에 있음  두가지 버전이 있으며 CDialog class 의 필요한 변수에 값을 입력하는 역할을 함 Modal Dialog Creation

15 Modal Dialog Creation (cont’d) “ DlgCore.cpp ” CDialog::CDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd) { m_pParentWnd = pParentWnd; m_lpszTemplateName = lpszTemplateName; if (HIWORD(m_lpszTemplateName) == 0) m_nIDHelp = LOWORD((DWORD)m_lpszTemplateName); } CDialog::CDialog(UINT nIDTemplate, CWnd* pParentWnd) { m_pParentWnd = pParentWnd; m_lpszTemplateName = MAKEINTRESOURCE(nIDTemplate); m_nIDHelp = nIDTemplate; }

16 Modal Dialog Creation (cont’d) int CDialog::DoModal() { // STEP 1 : load resource as necessary LPCDLGTEMPLATE lpDialogTemplate = m_lpDialogTemplate; HGLOBAL hDialogTemplate = m_hDialogTemplate; HINSTANCE hInst = AfxGetResourceHandle(); if (m_lpszTemplateName != NULL) { hInst = AfxFindResourceHandle(m_lpszTemplateName, RT_DIALOG); HRSRC hResource = ::FindResource(hInst, m_lpszTemplateName, RT_DIALOG); hDialogTemplate = LoadResource(hInst, hResource); } if (hDialogTemplate != NULL) lpDialogTemplate = (LPCDLGTEMPLATE)LockResource (hDialogTemplate); // return -1 in case of failure to load the dialog template resource if (lpDialogTemplate == NULL) return -1;

17 Modal Dialog Creation (cont’d) // STEP 2 : Preparing to create the dialog HWND hWndParent = PreModal(); AfxUnhookWindowCreate(); BOOL bEnableParent = FALSE; if (hWndParent != NULL && ::IsWindowEnabled(hWndParent)){ ::EnableWindow(hWndParent, FALSE); bEnableParent = TRUE; } // STEP 3 : create modeless dialog AfxHookWindowCreate(this); if (CreateDlgIndirect(lpDialogTemplate, CWnd::FromHandle(hWndParent), hInst)) { if (m_nFlags & WF_CONTINUEMODAL) { // enter modal loop DWORD dwFlags = MLF_SHOWONIDLE; if (GetStyle() & DS_NOIDLEMSG) dwFlags |= MLF_NOIDLEMSG; VERIFY(RunModalLoop(dwFlags) == m_nModalResult); }

18 Modal Dialog Creation (cont’d) // hide the window before enabling the parent, etc. if (m_hWnd != NULL) SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW| SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); } if (bEnableParent) ::EnableWindow(hWndParent, TRUE); if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd) ::SetActiveWindow(hWndParent); // STEP 4 : destroy modal window DestroyWindow(); PostModal(); }

19 Modal Dialog Creation (cont’d) HWND CDialog::PreModal() { // cannot call DoModal on a dialog already constructed as modeless ASSERT(m_hWnd == NULL); // allow OLE servers to disable themselves CWinApp* pApp = AfxGetApp(); if (pApp != NULL) pApp->EnableModeless(FALSE); // find parent HWND HWND hWnd = CWnd::GetSafeOwner_ (m_pParentWnd->GetSafeHwnd(), &m_hWndTop); // hook for creation of dialog AfxHookWindowCreate(this); // return window to use as parent for dialog return hWnd; }

20 Modal Dialog Creation (cont’d) int CWnd::RunModalLoop(DWORD dwFlags) { BOOL bIdle = TRUE; LONG lIdleCount = 0; BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE); HWND hWndParent = ::GetParent(m_hWnd); // acquire and dispatch messages until the modal state is done for (;;) { // phase1: check to see if we can do idle work while(bIdle&&!::PeekMessage(pMsg,NULL,NULL,NULL,PM_NOREMOVE)) { } // phase2: pump messages while available do { // pump message, but quit on WM_QUIT !AfxGetThread()->PumpMessage(); } while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE)); }

21  DoModal()(DLGCORE.CPP)  Dialog resource 의 loading Dialog template name 을 가지고 dialog template 을 찾아서 load 함 Dialog template name 을 가지고 dialog template 을 찾아서 load 함  Dialog 를 생성하기 위한 준비 PreModal() 함수를 호출함 PreModal() 함수를 호출함  Safety checks Parent window handle 을 찾음 Parent window handle 을 찾음  m_hWndTop 에 저장 EnableWindow(FALSE) 를 호출 EnableWindow(FALSE) 를 호출  Parent window 를 disable 시킴 Modal Dialog Creation (cont’d)

22  Dialog 를 생성하고 보여줌 CWnd::CreateDlgIndirect() 함수 호출 CWnd::CreateDlgIndirect() 함수 호출 내부적으로 Win32API 인 CreateDialogIndirect() 를 호출 내부적으로 Win32API 인 CreateDialogIndirect() 를 호출 CWnd::RunModalLoop() 함수 호출 CWnd::RunModalLoop() 함수 호출 Dialog 가 끝날때 까지 일을 수행 Dialog 가 끝날때 까지 일을 수행 사용자가 ok 나 cancel 버튼을 누르면 CWnd::EndModalLoop() 함수가 호출됨 사용자가 ok 나 cancel 버튼을 누르면 CWnd::EndModalLoop() 함수가 호출됨 Dialog 를 화면에서 보이지 않게 함 Dialog 를 화면에서 보이지 않게 함 Dialog 가 종료하면 EnableWindow(TRUE) 를 호출 Dialog 가 종료하면 EnableWindow(TRUE) 를 호출 Parent window 를 enable 시킴 Parent window 를 enable 시킴  마지막 단계 DestroyWindow() 함수 호출 DestroyWindow() 함수 호출 PostModal() 함수 호출 PostModal() 함수 호출 Modal Dialog Creation (cont’d)

23  Modeless dialog creation  두가지 과정을 거침 New operator 를 사용하여 변수 생성 New operator 를 사용하여 변수 생성 CDialog::Create() 함수 호출 CDialog::Create() 함수 호출 Modeless Dialog Creation

24 Modeless Dialog Creation (cont’d) BOOL CDialog::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd) { m_lpszTemplateName = lpszTemplateName; // used for help if (HIWORD(m_lpszTemplateName) == 0 && m_nIDHelp == 0) m_nIDHelp = LOWORD((DWORD)m_lpszTemplateName); if (!_AfxCheckDialogTemplate(lpszTemplateName, FALSE)) { PostNcDestroy(); // cleanup if Create fails too soon return FALSE; } HINSTANCE hInst = AfxFindResourceHandle(lpszTemplateName, RT_DIALOG); HRSRC hResource = ::FindResource(hInst, lpszTemplateName, RT_DIALOG); HGLOBAL hTemplate = LoadResource(hInst, hResource); BOOL bResult = CreateIndirect(hTemplate, pParentWnd, hInst); FreeResource(hTemplate); return bResult; }

25 Modeless Dialog Creation (cont’d) BOOL CDialog::CreateIndirect (LPCDLGTEMPLATE lpDialogTemplate, CWnd* pParentWnd, void* lpDialogInit, HINSTANCE hInst) { ASSERT(lpDialogTemplate != NULL); if (pParentWnd == NULL) pParentWnd = AfxGetMainWnd(); m_lpDialogInit = lpDialogInit; return CreateDlgIndirect(lpDialogTemplate, pParentWnd, hInst); }

26  CDialog::Create()(DLGCORE.CPP)  Template name 과 help ID 를 내부 변수에 저장  Dialog resource 를 찾고 load 함  CDialog::CreateIndirect() 함수 호출 내부적으로 Win32 API 인 CreateDialogIndirect() 함수 호출 내부적으로 Win32 API 인 CreateDialogIndirect() 함수 호출  사용자가 ok 나 cancel 버튼을 누르면 EndDialog() 가 호출되어 dialog 가 사라짐 Modeless Dialog Creation (cont’d)

27 Dialog Terminator void CDialog::EndDialog(int nResult) { ASSERT(::IsWindow(m_hWnd)); if (m_nFlags & (WF_MODALLOOP|WF_CONTINUEMODAL)) EndModalLoop(nResult); ::EndDialog(m_hWnd, nResult); }

28 CDialog Control Initialization  Dialog 에 있는 control 의 초기화 작업  Resource 에 의한 초기화  Combo box 를 예로 살펴봄 Data 는 “one”, “two”, “three” 라 가정 Data 는 “one”, “two”, “three” 라 가정  다음과 같은 코드가 생성되지 않는다. m_pCombo->AddString( “ one ” ); m_pCombo->AddString( “ two ” ); m_pCombo->AddString( “ three ” );

29  WM_INITDIALOG  Dialog 가 화면에 보이기 전에 발생하는 message  Application 으로 하여금 dialog 에 있는 control 들을 초기화 할 수 있도록 함  CDialog::HandleInitDialog() 함수에 mapping 되어 있음  CDialog::HandleInitDialog()  OLE control 관련 초기화 작업을 하고 CDialog::OnInitDialog() 를 호출  CDialog::OnInitDialog()  CWnd::ExecuteDlgInit() 를 호출 CDialog Control Initialization (cont’d)

30  Resource file CDialog Control Initialization (cont’d) IDD_ABOUTBOX DLGINIT BEGIN IDC_COMBO1, 0x403, 4, 0 0x6e6f, 0x0065, IDC_COMBO1, 0x403, 4, 0 0x7774, 0x006f, IDC_COMBO1, 0x403, 6, 0 0x6874, 0x6572, 0x0065, 0 END

31  CWnd::ExecuteDlgInit()(WINCORE.CPP)  두가지 버전이 존재 Argument 로 dialog template name Argument 로 dialog template name Argument 로 dialog data 에 대한 pointer Argument 로 dialog data 에 대한 pointer  일단 첫번째 버전의 함수가 dialog template name 을 가지고 resource 파일에서 control 의 data 를 load 함  이 후 pointer 를 얻어서 두번째 버전의 함수를 호출  why CWnd class member function? CDialog Control Initialization (cont’d)

32 CWnd::ExecuteDlgInit(LPVOID) CWnd::ExecuteDlgInit(LPVOID)  Resource file 의 raw data(DLGINIT) 를 parsing 함 BOOL CWnd::ExecuteDlgInit(LPVOID lpResource) { BOOL bSuccess = TRUE; UNALIGNED WORD* lpnRes = (WORD*)lpResource; while(bSuccess && *lpnRes != 0) { WORD nIDC = *lpnRes++; WORD nMsg = *lpnRes++; DWORD dwLen = *((UNALIGNED DWORD*&)lpnRes)++; if (nMsg == LB_ADDSTRING || nMsg == CB_ADDSTRING) { if (::SendDlgItemMessageA(m_hWnd, nIDC, nMsg, 0, (LONG)lpnRes) == -1) bSuccess = FALSE; } return bSuccess; } CDialog Control Initialization (cont’d)

33 DDX/DDV  DDX/DDV  DDX(Dynamic Data eXchange)  DDV(Dynamic Data Validation)  Data members  Controls  활용 사례 void CMyDlg::DoDataExchange(CDataExchange * pDX) { CDialog::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT1, m_strEdit1); DDV_MaxChars(pDX, IDC_EDIT1, 20); DDX_Text(pDX, IDC_EDIT2, m_uEdit2); DDV_MinMaxChars(pDX, IDC_EDIT2, 1, 234); DDX_Check(pDX, IDC_CHECK, m_bCheckState); DDX_Radio(pDX, IDC_RADIO, m_nRadioState); }

34 DDX/DDV (cont’d)  Question  CDataExchange class 의 역할  Control 들과 멤버 변수들간의 정보 교환은 언제, 어디에서, 어떻게 이루어지는가  DDX/DDV 함수는 무슨 일들을 하는가

35 DDX/DDV (cont’d)  Helper class  CDataExchange(AFXWIN.H) class CDataExchange { // Attributes public: BOOL m_bSaveAndValidate; // TRUE => save and validate data CWnd* m_pDlgWnd; // container usually a dialog // Operations (for implementors of DDX and DDV procs) HWND PrepareCtrl(int nIDC); // return HWND of control HWND PrepareEditCtrl(int nIDC); // return HWND of control void Fail(); // will throw exception CWnd* PrepareOleCtrl(int nIDC); // for OLE controls in dialog // Implementation CDataExchange(CWnd* pDlgWnd, BOOL bSaveAndValidate); HWND m_hWndLastControl; // last control used (for validation) BOOL m_bEditLastControl; // last control was an edit item };

36 DDX/DDV (cont’d)  멤버 변수  m_bSaveAndValidate TRUE  data 가 control 에서 변수로 감 TRUE  data 가 control 에서 변수로 감 FALSE  data 가 변수에서 control 로 감 FALSE  data 가 변수에서 control 로 감 Validation 은 TRUE 일때만 일어남 Validation 은 TRUE 일때만 일어남  m_pDlgWnd Dialog 에 대한 CWnd pointer Dialog 에 대한 CWnd pointer  m_hWndLastControl Previous control 에 대한 handle 을 저장 Previous control 에 대한 handle 을 저장  m_bEditLastControl Previous control 이 수정되었는지를 저장 Previous control 이 수정되었는지를 저장

37  멤버 함수  Constructor  PrepareCtrl() Non-edit control 을 위한 준비 Non-edit control 을 위한 준비  PrepareEditCtrl() Edit control 을 위한 준비 Edit control 을 위한 준비  Fail() Validation 이 실패하면 호출됨 Validation 이 실패하면 호출됨 Focus 를 previous control 로 보내고 CUserException 예외를 발생시킴 Focus 를 previous control 로 보내고 CUserException 예외를 발생시킴  PrepareOleCtrl() OLE control 을 위한 준비 OLE control 을 위한 준비 DDX/DDV (cont’d)

38  특징  DDX/DDV 는 Serialize 과정과 유사  CDataExchange 는 CArchive 와 비슷  DoDataExchange() 는 Serialize() 와 비슷  Save/load tag 를 가짐 DDX/DDV (cont’d)

39  DDX/DDV 함수들  DDX_Text()(DLGDATA.CPP) m_bSaveAndValidate 의 값을 기준으로 data 이동 m_bSaveAndValidate 의 값을 기준으로 data 이동  DDV_MaxChars()(DLGDATA.CPP) m_bSaveAndValidate 값이 TRUE 인경우 validation 코드 수행 m_bSaveAndValidate 값이 TRUE 인경우 validation 코드 수행  DDX_TextWithFormat()(DLGDATA.CPP) String 과 int 사이의 conversion String 과 int 사이의 conversion DDX/DDV (cont’d)

40 void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, CString& value) { HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC); if (pDX->m_bSaveAndValidate) { int nLen = ::GetWindowTextLength(hWndCtrl); ::GetWindowText(hWndCtrl, value.GetBufferSetLength(nLen), nLen+1); value.ReleaseBuffer(); } else { AfxSetWindowText(hWndCtrl, value); }

41 DDX/DDV (cont’d) void AFXAPI DDV_MaxChars(CDataExchange* pDX, CString const& value, int nChars) { ASSERT(nChars >= 1); // allow them something if (pDX->m_bSaveAndValidate && value.GetLength() > nChars) { TCHAR szT[32]; wsprintf(szT, _T("%d"), nChars); CString prompt; AfxFormatString1(prompt, AFX_IDP_PARSE_STRING_SIZE, szT); AfxMessageBox(prompt, MB_ICONEXCLAMATION, AFX_IDP_PARSE_STRING_SIZE); prompt.Empty(); // exception prep pDX->Fail(); } else if (pDX->m_hWndLastControl != NULL && pDX->m_bEditLastControl) { // limit the control max-chars automatically ::SendMessage(pDX->m_hWndLastControl, EM_LIMITTEXT, nChars, 0); }

42  언제 DoDataExchange() 가 호출되는가 ?  필요할 때 마다 UpdateData() 함수 호출  위 함수 내부에서 DoDataExchange() 를 호출함  UpdateData()(WINCORE.CPP) DDX/DDV (cont’d)

43 BOOL CWnd::UpdateData(BOOL bSaveAndValidate) { CDataExchange dx(this, bSaveAndValidate); _AFX_THREAD_STATE* pThreadState = AfxGetThreadState(); HWND hWndOldLockout = pThreadState->m_hLockoutNotifyWindow; ASSERT(hWndOldLockout != m_hWnd); // must not recurse pThreadState->m_hLockoutNotifyWindow = m_hWnd; BOOL bOK = FALSE; // assume failure TRY { DoDataExchange(&dx); bOK = TRUE; // it worked } CATCH(CUserException, e) { // validation failed - user already alerted, fall through ASSERT(!bOK); }

44 DDX/DDV (cont’d) void CDialog::OnOK() { if (!UpdateData(TRUE)){ TRACE0("UpdateData failed during dialog termination.\n"); // the UpdateData routine will set focus to correct item return; } EndDialog(IDOK); } BOOL CDialog::OnInitDialog() { BOOL bDlgInit; if (m_lpDialogInit != NULL) bDlgInit = ExecuteDlgInit(m_lpDialogInit); else bDlgInit = ExecuteDlgInit(m_lpszTemplateName); UpdateData(FALSE); return TRUE; // set focus to first one }

45 Common Dialogs  Common Dialogs  표준 interface 제공을 위하여  종류 CColorDialog CColorDialog CFileDialog CFileDialog CFindReplaceDialog CFindReplaceDialog CFontDialog CFontDialog CPrintDialog CPrintDialog CPageSetupDialog ( MFC 4.0 ) CPageSetupDialog ( MFC 4.0 )

46  Steps  생성자 호출  DoModal() 호출  IDOK 가 리턴될 때 적절한 처리 Common Dialogs (cont’d) CFileDialog myDialog(TRUE, NULL, NULL, OFN_FILEMUSTEXIST); if ( myDialog.DoModal() == IDOK ) { Cstring strPath = myDialog.GetPathName(); CString strFile = myDialog.GetFileName(); } else // User selected Cancel …

47  Win32 API 관점에서  모든 common dialog 는 대응되는 structure 를 가지고 있다. 대응되는 structure 를 가지고 있다. 대응되는 API 를 가지고 있다. 대응되는 API 를 가지고 있다. 예 ) Open File common dialog 예 ) Open File common dialog  Structure – OPENFILENAME  API – GetOpenFileName(LP OPENFILENAME)  모든 common dialog 의 base class  CCommonDialog(AFXDLGS.H)  OnOK() 와 OnCancel() 추가 Common Dialogs (cont’d)

48  예제 dialog  CFileDialog(AFXDLGS.H) Common Dialogs (cont’d) class CFileDialog : public CCommonDialog { public: OPENFILENAME m_ofn; // open file parameter block virtual int DoModal(); CString GetPathName() const; // return full path and filename CString GetFileName() const; // return only filename CString GetFileExt() const; // return only ext CString GetFileTitle() const; // return file title BOOL GetReadOnlyPref() const; // return TRUE if readonly checked // Enumerating multiple file selections POSITION GetStartPosition() const; CString GetNextPathName(POSITION& pos) const;

49 Common Dialogs (cont’d) protected: friend UINT CALLBACK _AfxCommDlgProc(HWND, UINT, WPARAM, LPARAM); virtual UINT OnShareViolation(LPCTSTR lpszPathName); virtual BOOL OnFileNameOK(); virtual void OnLBSelChangedNotify(UINT nIDBox, UINT iCurSel, UINT nCode); // only called back if OFN_EXPLORER is set virtual void OnInitDone(); virtual void OnFileNameChange(); virtual void OnFolderChange(); virtual void OnTypeChange(); // Implementation BOOL m_bOpenFileDialog; // TRUE for file open, FALSE for file save CString m_strFilter; // filter string TCHAR m_szFileTitle[64]; // contains file title after return TCHAR m_szFileName[_MAX_PATH]; // contains full path name after return OPENFILENAME* m_pofnTemp; virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); };

50  예제 dialog  CFileDialog(AFXDLGS.H) OPENFILENAME structure OPENFILENAME structure 여러 개의 virtual protected 함수 여러 개의 virtual protected 함수 기타 여러 정보 저장을 위한 변수 기타 여러 정보 저장을 위한 변수  CFileDialog 의 생성 (DLGFILE.CPP) 생성자의 argument 들을 OPENFILENAME structure 의 멤버에 setting 함 (m_ofn) 생성자의 argument 들을 OPENFILENAME structure 의 멤버에 setting 함 (m_ofn) Window95 이상일 경우에는 OFN_EXPLORER 와 OFN_ENABLEHOOK flag 를 set 함 Window95 이상일 경우에는 OFN_EXPLORER 와 OFN_ENABLEHOOK flag 를 set 함  OFN_ENABLEHOOK  Hook routine 을 제공 (_AfxCommDlgProc() 를 m_ofn 의 hook field 에 set) Common Dialogs (cont’d)

51  CFileDialog::DoModal()(DLGFILE.CPP) M_bOpenFileDialog 변수의 값을 보고 Win32 API 인 GetOpenFileName() 을 호출할건지 GetSaveFileName() 을 호출할건지를 결정 M_bOpenFileDialog 변수의 값을 보고 Win32 API 인 GetOpenFileName() 을 호출할건지 GetSaveFileName() 을 호출할건지를 결정 Common Dialogs (cont’d)

52 int CFileDialog::DoModal() { int nResult; BOOL bEnableParent = FALSE; m_ofn.hwndOwner = PreModal(); AfxUnhookWindowCreate(); if (m_ofn.hwndOwner != NULL && ::IsWindowEnabled(m_ofn.hwndOwner)) { bEnableParent = TRUE; ::EnableWindow(m_ofn.hwndOwner, FALSE); } if (m_bOpenFileDialog) nResult = ::GetOpenFileName(&m_ofn); else nResult = ::GetSaveFileName(&m_ofn); if (bEnableParent) ::EnableWindow(m_ofn.hwndOwner, TRUE); PostModal(); return nResult ? nResult : IDCANCEL; }

53 Property Sheets  Tabbed dialogs  MFC 3.0 때부터 제공  하나의 dialog 에서 사용자로부터 많은 입력을 받을 수 있는 인터페이스

54 Property Sheets (cont’d)  두개의 class  CPropertySheet Tabbed dialog 를 위한 class Tabbed dialog 를 위한 class  CPropertyPage Tabbed dialog 의 각각의 tab(page) 을 위한 class Tabbed dialog 의 각각의 tab(page) 을 위한 class  일반 dialog 와의 차이점  Apply 버튼 제공 Page 별로 update 하는 기능을 제공 Page 별로 update 하는 기능을 제공

55 Property Sheets (cont’d)  STEP  1. Dialog template 생성 및 property sheet 의 layout 설정  2. 각 template 에 대응하는 CPropertyPage 파생 클래스들을 생성  3-1. (modal property sheet) CPropertySheet 의 instance 를 생성하고 AddPage() 멤버 함수를 통해 추가한 뒤 DoModal() 호출 CPropertySheet 의 instance 를 생성하고 AddPage() 멤버 함수를 통해 추가한 뒤 DoModal() 호출 OK/Apply/Cancel 버튼이 자동적으로 추가 OK/Apply/Cancel 버튼이 자동적으로 추가  3-2. (modeless property sheet) CPropertySheet 의 파생클래스 생성한 뒤 인스턴스를 생성하고 Create() 함수 호출 CPropertySheet 의 파생클래스 생성한 뒤 인스턴스를 생성하고 Create() 함수 호출 OK/Apply/Cancel 버튼이 자동적으로 추가되지 않음 OK/Apply/Cancel 버튼이 자동적으로 추가되지 않음

56 Property Sheets (cont’d) CPropertySheet mySheet( “ My Property Sheet! ”, this); CPageOne myPage1; CPageTwo myPage2; CPageThree myPage3; mySheet.AddPage(&myPage1); mySheet.AddPage(&myPage2); mySheet.AddPage(&myPage3); mySheet.DoModal(); …

57 CPropertySheet Class  Declaration of CPropertySheet  AFXDLGS.H class CPropertySheet : public CWnd { // Attributes public: AFX_OLDPROPSHEETHEADER m_psh; int GetPageCount() const; CPropertyPage* GetActivePage() const; int GetActiveIndex() const; CPropertyPage* GetPage(int nPage) const; int GetPageIndex(CPropertyPage* pPage); BOOL SetActivePage(int nPage); BOOL SetActivePage(CPropertyPage* pPage); void SetTitle(LPCTSTR lpszText, UINT nStyle = 0); void EnableStackedTabs(BOOL bStacked);

58 CPropertySheet Class (cont’d) // Operations public: virtual int DoModal(); void AddPage(CPropertyPage* pPage); void RemovePage(CPropertyPage* pPage); void RemovePage(int nPage); void EndDialog(int nEndID); // used to terminate a modal dialog BOOL PressButton(int nButton); // Implementation public: virtual ~CPropertySheet(); void CommonConstruct(CWnd* pParentWnd, UINT iSelectPage); virtual BOOL PreTranslateMessage(MSG* pMsg); virtual void BuildPropPageArray(); virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); virtual BOOL OnInitDialog(); virtual BOOL ContinueModal();

59 CPropertySheet Class (cont’d) protected: CPtrArray m_pages; // array of CPropertyPage pointers CString m_strCaption; // caption of the pseudo-dialog CWnd* m_pParentWnd; // parent window of property sheet BOOL m_bStacked; // EnableStackedTabs sets this BOOL m_bModeless; // TRUE when Create called instead of DoModal // Generated message map functions //{{AFX_MSG(CPropertySheet) afx_msg BOOL OnNcCreate(LPCREATESTRUCT); afx_msg LRESULT HandleInitDialog(WPARAM, LPARAM); afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); afx_msg LRESULT OnCommandHelp(WPARAM, LPARAM); afx_msg void OnClose(); afx_msg void OnSysCommand(UINT nID, LPARAM); afx_msg LRESULT OnSetDefID(WPARAM, LPARAM); //}}AFX_MSG friend class CPropertyPage; };

60  Declaration of CPropertySheet  AFXDLGS.H  CWnd 에서 상속받음 (why?)  멤버 CommonConstruct() CommonConstruct()  수많은 constructor 들이 호출하는 공통 함수 m_pages m_pages  CPtrArray 형의 pointer 로 CPropertyPage class 의 pointer 의 배열 CPropertySheet Class (cont’d)

61 m_strCaption m_strCaption  Property sheet 의 caption m_pParentWnd m_pParentWnd  Parent window 에 대한 pointer m_bStacked m_bStacked  Tab 을 stacked mode 로 할건지 scrolled mode 로 할 건지를 결정 m_bModeless m_bModeless  Property sheet 를 modal 로 할건지 modeless 로 할건지 CPropertySheet Class (cont’d)

62  CPropertySheet::DoModal()  DLGPROP.CPP  내부 수행 AfxDeferRegisterClass() 호출 AfxDeferRegisterClass() 호출  내부적으로 InitCommonControls() 함수 호출 (Windows common controls DLL 을 초기화 ) BuildPropPageArray() 호출 BuildPropPageArray() 호출 Main window 를 disable 하고 ::PropertySheet() 함수를 호출 ( 이후는 CDialog::DoModal() 과 동일 ) Main window 를 disable 하고 ::PropertySheet() 함수를 호출 ( 이후는 CDialog::DoModal() 과 동일 ) CPropertySheet Class (cont’d)

63  CPropertySheet::AddPage()  DLGPROP.CPP  m_pages 멤버 변수에 page 추가  CPropertySheet::BuildPropPageArray()  DLGPROP.CPP  각 page 에 있는 PROPSHEETPAGE structure 정보를 저장함 CPropertySheet Class (cont’d)

64 int CPropertySheet::DoModal() { VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG)); BuildPropPageArray(); HWND hWndParent = CWnd::GetSafeOwner_(); ::EnableWindow(hWndParent, FALSE); HWND hWnd = (HWND)::PropertySheet((PROPSHEETHEADER*)psh); nResult = RunModalLoop(dwFlags); DestroyWindow(); ::EnableWindow(hWndTop, TRUE); return nResult; }

65 CPropertySheet Class (cont’d) void CPropertySheet::AddPage(CPropertyPage* pPage) { m_pages.Add(pPage); if (m_hWnd != NULL){ HPROPSHEETPAGE hPSP = CreatePropertySheetPage((PROPSHEETPAGE*)ppsp); if (hPSP == NULL) AfxThrowMemoryException(); if (!SendMessage(PSM_ADDPAGE, 0, (LPARAM)hPSP)) { DestroyPropertySheetPage(hPSP); AfxThrowMemoryException(); }

66 CPropertySheet Class (cont’d) void CPropertySheet::BuildPropPageArray() { delete[] (PROPSHEETPAGE*)m_psh.ppsp; m_psh.ppsp = NULL; AFX_OLDPROPSHEETPAGE* ppsp = new AFX_OLDPROPSHEETPAGE[m_pages.GetSize()]; m_psh.ppsp = (LPPROPSHEETPAGE)ppsp; for (int i = 0; i < m_pages.GetSize(); i++){ CPropertyPage* pPage = GetPage(i); memcpy(&ppsp[i], &pPage->m_psp, sizeof(pPage->m_psp)); pPage->PreProcessPageTemplate ((PROPSHEETPAGE&)ppsp[i], bWizard); } m_psh.nPages = m_pages.GetSize(); }

67 Control Classes  Control class 의 세가지 group  Old fashioned (6) Button, combo box, edit, list box, scroll bar, static Button, combo box, edit, list box, scroll bar, static  New fangled Window common controls Window common controls  OLE controls

68 Old-Fashioned  특징  모두 CWnd 에서 상속받음  Cbitmap, CBitmapButton, CComboBox, CEdit, CListBox, CDragListBox, CCheckListBox, CScrollBar, CStatic  Declaration 은 AFXWIN.H  Implementation AFXWIN2.INL AFXWIN2.INL WINCTRL1.CPP WINCTRL1.CPP WINCTRL2.CPP WINCTRL2.CPP WINCTRL3.CPP WINCTRL3.CPP WINBTN.CPP WINBTN.CPP

69 Old-Fashioned (cont’d) Cbutton* pButton = (Cbutton *)pDialog->GetDlgItem(IDC_CHECK1); ASSERT(pButton != NULL); pButton->SetCheck(m_bShowState); //// Crect rectButton(10, 10, 50, 50); Cbutton* pButton = new Cbutton; pButton->Create( “ Text ”, WS_CHILD|BS_PUSHBUTTON, rectButton, pView, ID_BUTTON); … pBtton->DestroyWindow(); delete pButton;

70 New-fangled  특징  모두 CWnd 에서 상속받음  CAnimateCtrl, CDragListBox, CHotKeyCtrl, CImageList, CProgressCtrl, CRichEditCtrl, CSliderCtrl, CSpinButtonCtrl, …  Declaration 은 AFXCMN.H  Implementation AFXCMN.INL AFXCMN.INL WINCTRL2.CPP WINCTRL2.CPP WINCTRL4.CPP WINCTRL4.CPP

71 Chap. 7 Document/View Architecture

72 Contents  Introduction  Architecture  Inside document/view architecture  Document/view internals

73 Introduction  Application 의 data 관리  Data 를 분리하여 관리하자.  중요한 이슈 누가 data 를 관리할 것인가 누가 data 를 관리할 것인가 누가 data 를 update 할 것인가 누가 data 를 update 할 것인가 data 의 rendering 어떻게 다르게 할 것인가 data 의 rendering 어떻게 다르게 할 것인가 …  Print 와 print preview 의 지원  두 부분 Data management Data management User-interface management User-interface management

74 Introduction (cont’d)  기존의 방법  분리하지 않고 하나의 클래스에서 처리  대단히 복잡  중요성  Multiple ways to represent your data Rendering & Updating Rendering & Updating  Multiple types of data User interface User interface

75 Architecture  Document 와 view  Document Application 의 data 를 의미 Application 의 data 를 의미  View Application 의 data 의 표현을 의미 Application 의 data 의 표현을 의미

76 Document/View Components  MFC document/view architecture 를 위한 4 개의 components  Documents  Views  Document/view frames  Document templates

77  Documents  CDocument class Managing file I/O Managing file I/O Updating renderings of the data Updating renderings of the data CCmdTarget(CObject) 로 부터 상속 받음 CCmdTarget(CObject) 로 부터 상속 받음  CObject  Run-time type information, dynamic creation, serialization  CCmdTarget  Command message (WM_COMMAND) 를 받을 수 있음 Document/View Components (cont’d)

78  Views  CView class CWnd(CCmdTarget, CObject) 로 부터 상속 받음 CWnd(CCmdTarget, CObject) 로 부터 상속 받음  CCmdTarget  Command message (WM_COMMAND) 를 받을 수 있음  CWnd  Window message(WM_PAINT) 를 받을 수 있음 View 는 border 가 없는 window 임 View 는 border 가 없는 window 임 View 를 둘러싸고 있는 border 있는 window 를 frame window 라고 함 View 를 둘러싸고 있는 border 있는 window 를 frame window 라고 함 Document/View Components (cont’d)

79  Document/View Frames  각각의 view 에 서로 다른 user-interface 를 적용할 수 있게 함 View Frame Document/View Components (cont’d)

80  SDI  CFrameWnd class Single Document Interface Single Document Interface 워드패드 워드패드  MDI  CMDIChildWnd class Multiple Document Inteface Multiple Document Inteface MS Word MS Word Document/View Components (cont’d)

81  Document templates  CDocTemplate class  Document, view, frame 을 묶어서 하나의 unit 으로 관리  각각의 서로 다른 document type 에 대하여 하나씩의 template 을 가질 수 있다.  실제 사용시 한 type 의 document  CSingleDocTemplate class 한 type 의 document  CSingleDocTemplate class 여러 type 의 document  CMultiDocTemplate class 여러 type 의 document  CMultiDocTemplate class Document/View Components (cont’d)

82  CSingleDocTemplate  생성자의 인자 Resource ID Resource ID Documet/View/Frame 의 Run-time class Documet/View/Frame 의 Run-time class  CMultiDocTemplate  CSingleDocTemplate 와 생성자의 인자가 동일  차이점 : linked list 를 통해 다수의 정보 유지 Document/View Components (cont’d)

83  Resource ID  application 의 string table  window title, document name  새 document 생성 시 description  파일 open 시 파일 type 에 대한 description  file extension filter, … Document/View Components (cont’d)

84 CWinApp 의 역할  CWinApp 의 역할은 ?  Document template 을 관리함  CWinApp::InitInstance() 함수 Document template 을 생성함 Document template 을 생성함 생성이 끝나면 CWinApp::AddDocTemplate() 호출 생성이 끝나면 CWinApp::AddDocTemplate() 호출  CWinApp 의 document template list 에 추가함

85 CWinApp 의 역할 (cont’d) BOOL CTestApp::InitInstance() { … CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_TESTTYPE, RUNTIME_CLASS(CTestDoc), RUNTIME_CLASS(CChildFrame), // custom MDI child frame RUNTIME_CLASS(CTestView)); AddDocTemplate(pDocTemplate); … }

86 Document/View Arch. Internals  Document/View arch. 의 기본  CWinApp Document template 의 관리 Document template 의 관리  Document template Frames/Views/Documents 의 관리 Frames/Views/Documents 의 관리

87 CDocManager Class  CDocManager  CWinApp 와 CDocTemplate 사이의 interface 역할  CWinApp 가 필요한 document template 의 list 를 관리하는 역할  CWinApp 의 declaration(AFXWIN.H) CDocManager * m_pDocManager; CDocManager * m_pDocManager;

88 CDocManager Class(contd.) class CDocManager : public CObject { DECLARE_DYNAMIC(CDocManager) CDocManager(); virtual void AddDocTemplate(CDocTemplate* pTemplate); virtual POSITION GetFirstDocTemplatePosition() const; virtual CDocTemplate* GetNextDocTemplate(POSITION& pos) const; virtual void RegisterShellFileTypes(BOOL bCompat); void UnregisterShellFileTypes(); virtual CDocument* OpenDocumentFile(LPCTSTR lpszFileName); virtual BOOL SaveAllModified(); // save before exit virtual void CloseAllDocuments(BOOL bEndSession); virtual int GetOpenDocumentCount(); CPtrList m_templateList; int GetDocumentCount(); };

89 CDocManager Class(contd.)  Declaration(AFXWIN.H)  멤버 변수 m_templateList m_templateList  CPtrList type  실제 document template 의 list  멤버 함수 대부분의 함수가 m_templateList 에 대한 조작과 CWinApp 와의 interface 를 위해서 존재 대부분의 함수가 m_templateList 에 대한 조작과 CWinApp 와의 interface 를 위해서 존재

90 CDocManager Class(contd.) 대부분의 CWinApp 의 document template 관련 함수는 CDocManager 의 함수를 그대로 호출함 대부분의 CWinApp 의 document template 관련 함수는 CDocManager 의 함수를 그대로 호출함  CWinApp::AddDocTemplate()  CWinApp::CloseAllDocument()  CWinApp::DoPromptFileName()  CWinApp::GetFirstDocTemplatePosition()  CWinApp::GetNextDocTemplate()  CWinApp::GetOpenDocumentCount()  CWinApp::OnFileNew()  CWinApp::OnFileOpen()  …

91 CDocManager Class(contd.) void CWinApp::AddDocTemplate(CDocTemplate* pTemplate) { if (m_pDocManager == NULL) m_pDocManager = new CDocManager; m_pDocManager->AddDocTemplate(pTemplate); } void CWinApp::OnFileNew() { if (m_pDocManager != NULL) m_pDocManager->OnFileNew(); }

92 CDocManager Class(contd.)  CDocManager::OnFileNew()  새로운 document template 을 생성하는 역할  하나 이상의 document template 가 있을때는 CNewTypeDlg dialog class 를 이용 (DOCMGR.CPP) 사용자가 document template 을 선택하게 함 사용자가 document template 을 선택하게 함 사용자에게 document template list 로 보여주는 좋은 예가 됨 사용자에게 document template list 로 보여주는 좋은 예가 됨

93 CDocManager Class(contd.) “ DocMgr.cpp ” void CDocManager::OnFileNew() { CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead(); if (m_templateList.GetCount() > 1) { CNewTypeDlg dlg(&m_templateList); int nID = dlg.DoModal(); if (nID == IDOK) pTemplate = dlg.m_pSelectedTemplate; else return; // none - cancel operation } pTemplate->OpenDocumentFile(NULL); }

94 CDocManager Class(contd.) class CNewTypeDlg : public CDialog { protected: CPtrList* m_pList; // actually a list of doc templates public: CDocTemplate* m_pSelectedTemplate; enum { IDD = AFX_IDD_NEWTYPEDLG }; CNewTypeDlg(CPtrList* pList) : CDialog(CNewTypeDlg::IDD) { m_pList = pList; m_pSelectedTemplate = NULL; } protected: BOOL OnInitDialog(); void OnOK(); };  CNewTypeDlg class  DOCMGR.CPP

95 CDocManager Class(contd.)  CNewTypeDlg resource  AFXRES.RC

96 CDocManager Class(contd.) BOOL CNewTypeDlg::OnInitDialog() { CListBox* pListBox = (CListBox*)GetDlgItem(AFX_IDC_LISTBOX); POSITION pos = m_pList->GetHeadPosition(); while (pos != NULL){ CDocTemplate* pTemplate = (CDocTemplate*)m_pList->GetNext(pos); CString strTypeName; if (pTemplate->GetDocString(strTypeName, CDocTemplate::fileNewName) && !strTypeName.IsEmpty()) { int nIndex = pListBox->AddString(strTypeName); pListBox->SetItemDataPtr(nIndex, pTemplate); } return CDialog::OnInitDialog(); }

97 CDocTemplate class  CDocTemplate  Document/View/Frame 을 관리  Base class  실제 사용시에는 CSingleDocTemplate CSingleDocTemplate  DOCSINGL.CPP CMultiDocTemplate CMultiDocTemplate  DOCMULTI.CPP

98 CDocTemplate class(contd.)  Declaration(AFXWIN.H) class CDocTemplate : public CCmdTarget { DECLARE_DYNAMIC(CDocTemplate) protected: CDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass, CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass); // Attributes public: virtual POSITION GetFirstDocPosition() const = 0; virtual CDocument* GetNextDoc(POSITION& rPos) const = 0; virtual void AddDocument(CDocument* pDoc); // must override virtual void RemoveDocument(CDocument* pDoc); // must override virtual BOOL GetDocString(CString& rString, enum DocStringIndex index) const; // get one of the info strings CFrameWnd* CreateOleFrame(CWnd* pParentWnd, CDocument* pDoc, BOOL bCreateView); virtual CDocument* CreateNewDocument(); virtual CFrameWnd* CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther);

99 CDocTemplate class(contd.) virtual void InitialUpdateFrame(CFrameWnd* pFrame, CDocument* pDoc, BOOL bMakeVisible = TRUE); virtual BOOL SaveAllModified(); // for all documents virtual void CloseAllDocuments(BOOL bEndSession); virtual CDocument* OpenDocumentFile( LPCTSTR lpszPathName, BOOL bMakeVisible = TRUE) = 0; virtual void SetDefaultTitle(CDocument* pDocument) = 0; public: BOOL m_bAutoDelete; virtual ~CDocTemplate(); protected: UINT m_nIDResource; CRuntimeClass* m_pDocClass; // class for creating new documents CRuntimeClass* m_pFrameClass; // class for creating new frames CRuntimeClass* m_pViewClass; // class for creating new views CString m_strDocStrings; // '\n' separated names };

100 CDocTemplate class(contd.)  Declaration(AFXWIN.H)  멤버 변수 m_nIDResource m_nIDResource  Document template 에 대한 resource ID m_pDocClass m_pDocClass  CDocument 에 대한 CRuntimeClass structure 의 pointer m_pFrameClass m_pFrameClass  CFrameWnd 에 대한 CRuntimeClass structure 의 pointer

101 CDocTemplate class(contd.) m_pViewClass m_pViewClass  CView 에 대한 CRuntimeClass structure 의 pointer m_strDocStrings m_strDocStrings  Document template 의 string resource  Implementation(DOCTEMPL.CPP)  Document/View/Frame 을 생성하는 함수 CDocTemplate::CreateNewDocument() CDocTemplate::CreateNewDocument() CDocTemplate::CreateNewFrame() CDocTemplate::CreateNewFrame() View 에 관한 명시적인 함수는 없음 View 에 관한 명시적인 함수는 없음

102 CDocTemplate class(contd.) CDocument* CDocTemplate::CreateNewDocument() { CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject(); AddDocument(pDocument); return pDocument; }

103 CDocTemplate class(contd.) CFrameWnd* CDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther) { CCreateContext context; context.m_pCurrentFrame = pOther; context.m_pCurrentDoc = pDoc; context.m_pNewViewClass = m_pViewClass; context.m_pNewDocTemplate = this; CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject(); pFrame->LoadFrame(m_nIDResource, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, &context)) return pFrame; }

104 CDocTemplate class(contd.)  CDocTemplate::CreateNewDocument() m_pDocClass->CreateObject() 를 이용해 document 생성 m_pDocClass->CreateObject() 를 이용해 document 생성 생성된 document 를 open 된 document list 에 추가 생성된 document 를 open 된 document list 에 추가  CDocTemplate::CreateNewFrame() CCreateContext 에 필요한 정보를 채움 CCreateContext 에 필요한 정보를 채움 m_pFrameClass->CreateObject() 를 이용해 frame 생성 m_pFrameClass->CreateObject() 를 이용해 frame 생성 Frame 에 필요한 resource 를 load Frame 에 필요한 resource 를 load

105 CDocTemplate class(contd.)  CCreateContext structure Declaration(AFXEXT.H) Declaration(AFXEXT.H) struct CCreateContext // Creation information structure // All fields are optional and may be NULL { CRuntimeClass* m_pNewViewClass; CDocument* m_pCurrentDoc; // for creating MDI children (CMDIChildWnd::LoadFrame) CDocTemplate* m_pNewDocTemplate; // for sharing view/frame state from the original view/frame CView* m_pLastView; CFrameWnd* m_pCurrentFrame; // Implementation CCreateContext(); };

106 CDocTemplate class(contd.)  CCreateContext structure Declaration(AFXEXT.H) Declaration(AFXEXT.H)  m_pNewViewClass  View 생성을 위한 CRuntimeClass pointer  m_pCurrentDoc  Current document  m_pCurrentFrame  Current frame  m_pNewDocTemplate  Multiple document 일 때 마지막 document 를 가리킴  m_pLastView  Multiple view 일 때 마지막 view 를 가리킴

107 CDocTemplate class(contd.)  Open 된 document 의 관리는 ?  CSingleDocTemplate 와 CMultiDocTemplate 가 담당  CSingleDocTemplate  CDocument* m_pOnlyDoc;  CMultiDocTemplate  CPtrList m_docList;  int m_nUntitledCount;  Untitled document 의 수를 저장함 (Untitled[X])

108 CDocTemplate class(contd.)  CMultiDocTemplate::OpenDocumentFile() DOCMULTI.CPP DOCMULTI.CPP Document 와 frame 의 생성 Document 와 frame 의 생성 CFrameWnd::InitialUpdateFrame() 호출 CFrameWnd::InitialUpdateFrame() 호출

109 CDocTemplate class(contd.) “ DocMulti.cpp ” CDocument* CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible) { CDocument* pDocument = CreateNewDocument(); CFrameWnd* pFrame = CreateNewFrame(pDocument, NULL); if (lpszPathName == NULL){ // create a new document - with default document name SetDefaultTitle(pDocument); pDocument->OnNewDocument(); } else { // open an existing document CWaitCursor wait; pDocument->OnOpenDocument(lpszPathName); pDocument->SetPathName(lpszPathName); } return pDocument; }

110 CFrameWnd class  CFrameWnd  CView 의 생성 !  m_pViewActive 현재 atcive 한 view 에 대한 pointer 현재 atcive 한 view 에 대한 pointer CFrameWnd::GetActiveView() CFrameWnd::GetActiveView() CFrameWnd::SetActiveView() CFrameWnd::SetActiveView()  InitialUpdateFrame() 함수 모든 view 의 OnInitialUpdate() 함수를 호출함 모든 view 의 OnInitialUpdate() 함수를 호출함

111 CFrameWnd class(contd.)  Implementation(WINFRM.CPP)  CFrameWnd::CreateView() 진정한 view 의 생성 진정한 view 의 생성 CWnd* CFrameWnd::CreateView(CCreateContext* pContext, UINT nID) { CWnd* pView = (CWnd*)pContext->m_pNewViewClass ->CreateObject(); if (pView == NULL) return NULL; if (!pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0,0,0,0), this, nID, pContext)) return NULL; // can't continue without a view return pView; }

112 CFrameWnd class(contd.)  그러면 CreateView() 는 어디서 호출되나 ? int CFrameWnd::OnCreate(LPCREATESTRUCT lpcs) { return OnCreateHelper(lpcs, pContext); } int CFrameWnd::OnCreateHelper(LPCREATESTRUCT lpcs, CCreateContext* pContext) { if (CWnd::OnCreate(lpcs) == -1) return -1; // create special children first OnCreateClient(lpcs, pContext); }

113 CFrameWnd class(contd.) BOOL CFrameWnd::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext) { if (pContext != NULL && pContext->m_pNewViewClass != NULL) { CreateView(pContext, AFX_IDW_PANE_FIRST); }

114 CFrameWnd class(contd.)  CreateNewFrame() 이 호출되면  Windows 가 WM_CREATE message 를 보냄  OnCreate() 함수의 호출   OnCreateHelper() 의 호출   OnCreateClient() 의 호출   CreateView() 의 호출  결국 CreateNewFrame() 의 호출 결과임

115 CFrameWnd class(contd.)  CFrameWnd::InitialUpdateFrame()  Frame 의 모든 view 를 update 함 void CFrameWnd::InitialUpdateFrame(CDocument* pDoc, BOOL bMakeVisible) { CView* pView = NULL; if (bMakeVisible) { SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE); ActivateFrame(nCmdShow); if (pView != NULL) pView->OnActivateView(TRUE, pView, pView); } // update frame counts and frame title (may already have been visible) if (pDoc != NULL) pDoc->UpdateFrameCounts(); OnUpdateFrameTitle(TRUE); }

116 CDocument Class  CDocument  Declaration(AFXWIN.H) class CDocument : public CCmdTarget { public: const CString& GetTitle() const; virtual void SetTitle(LPCTSTR lpszTitle); const CString& GetPathName() const; virtual void SetPathName(LPCTSTR lpszPathName, BOOL bAddToMRU = TRUE); virtual BOOL IsModified(); virtual void SetModifiedFlag(BOOL bModified = TRUE); virtual POSITION GetFirstViewPosition() const; virtual CView* GetNextView(POSITION& rPosition) const; void UpdateAllViews(CView* pSender, LPARAM lHint = 0L, CObject* pHint = NULL); virtual void DeleteContents(); // delete doc items etc

117 CDocument Class (cont’d) // File helpers virtual BOOL OnNewDocument(); virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); virtual CFile* GetFile(LPCTSTR lpszFileName, UINT nOpenFlags, … ); virtual void ReleaseFile(CFile* pFile, BOOL bAbort); protected: CString m_strTitle; CString m_strPathName; CDocTemplate* m_pDocTemplate; CPtrList m_viewList; // list of views BOOL m_bModified; // changed since last saved virtual BOOL DoSave(LPCTSTR lpszPathName, BOOL bReplace = TRUE); virtual BOOL DoFileSave(); virtual void UpdateFrameCounts(); void DisconnectViews(); void SendInitialUpdate(); friend class CDocTemplate; };

118  Implementation(DOCCORE.CPP)  Key aspects  Creating documents  Saving documents  Communicating with views CDocument Class (cont’d)

119  Creating Documents  Empty document 일 경우 OnNewDocument() 함수 호출 OnNewDocument() 함수 호출  DeleteContents() 호출  Modified flag 를 FALSE 로 함  m_strPathName 이 NULL 인지 확인  File 로 부터 create 하는 경우 OnOpenDocument() 함수 호출 OnOpenDocument() 함수 호출  GetFile() 함수를 이용하여 file open  DeleteContents() 함수 호출  Modified flag 를 TRUE 로 함  CArchive class 를 이용하여 serialization  Modified flag 를 FALSE 로 함 CDocument Class (cont’d)

120 BOOL CDocument::OnNewDocument() { if (IsModified()) TRACE0("Warning: OnNewDocument replaces an unsaved document.\n"); DeleteContents(); m_strPathName.Empty(); // no path name yet SetModifiedFlag(FALSE); // make clean return TRUE; }

121 CDocument Class (cont’d) BOOL CDocument::OnOpenDocument(LPCTSTR lpszPathName) { CFileException fe; CFile* pFile = GetFile(lpszPathName, CFile::modeRead|CFile::shareDenyWrite, &fe); DeleteContents(); SetModifiedFlag(); // dirty during de-serialize CArchive loadArchive(pFile, CArchive::load | CArchive::bNoFlushOnDelete); loadArchive.m_pDocument = this; loadArchive.m_bForceFlat = FALSE; CWaitCursor wait; if (pFile->GetLength() != 0) Serialize(loadArchive); // load me loadArchive.Close(); ReleaseFile(pFile, FALSE); SetModifiedFlag(FALSE); // start off with unmodified return TRUE; }

122 CDocument Class (cont’d)  Saving Documents  OnSaveDocument() GetFile() 함수를 이용하여 file open GetFile() 함수를 이용하여 file open CArchive class 를 이용하여 serialization CArchive class 를 이용하여 serialization Modified flag 를 FALSE 로 함 Modified flag 를 FALSE 로 함

123 CDocument Class (cont’d) BOOL CDocument::OnSaveDocument(LPCTSTR lpszPathName) { CFileException fe; CFile* pFile = NULL; pFile = GetFile(lpszPathName, CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive, &fe); CArchive saveArchive(pFile, CArchive::store | CArchive::bNoFlushOnDelete); saveArchive.m_pDocument = this; saveArchive.m_bForceFlat = FALSE; CWaitCursor wait; Serialize(saveArchive); // save me saveArchive.Close(); ReleaseFile(pFile, FALSE); SetModifiedFlag(FALSE); // back to unmodified return TRUE; // success }

124  View 와의 통신  m_viewList 에 view 의 list 를 저장  통신이 필요한 경우 Destroy 시 Destroy 시  DisconnectViews() 함수를 호출하여 각 viwe 의 m_pDocument 가 NULL 이 되게 함 Frame 에 접근하고자 할 때 Frame 에 접근하고자 할 때  Cview::GetParentFrame() 함수 이용 View 들에게 document 의 변경을 알리고자 할 때 View 들에게 document 의 변경을 알리고자 할 때  UpdateAllViews() 함수 호출 CDocument Class (cont’d)

125 void CDocument::UpdateAllViews(CView* pSender, LPARAM lHint, CObject* pHint) // walk through all views { ASSERT(pSender == NULL || !m_viewList.IsEmpty()); // must have views if sent by one of them POSITION pos = GetFirstViewPosition(); while (pos != NULL) { CView* pView = GetNextView(pos); ASSERT_VALID(pView); if (pView != pSender) pView->OnUpdate(pSender, lHint, pHint); }

126 CView Class  CView  Declaration(AFXWIN.H)  Implementation(VIEWCORE.CPP) void CView::OnPaint() { // standard paint routine CPaintDC dc(this); OnPrepareDC(&dc); OnDraw(&dc); }

127 Document/View Internals CWinApp::OnFileOpen() CWinApp::OnFileNew() CDocManager::OnFileOpen() CDocManager::OnFileNew() CDocTemplate::OpenDocumentFile() CDocTemplate::CreateNewDocument() CDocTemplate::CreateNewFrame() WM_CREATE

128 Document/View…(contd.) CFrameWnd::OnCreate() CFrameWnd::OnCreateHelper() CFrameWnd::OnCreateClient() CFrameWnd::CreateView() CMyDocument::OnOpenDocument() CMyDocument::OnNewDocument()


Download ppt "Chap. 6 Dialog and Control Classes. Contents  CDialog class  Common Dialogs  Property Sheets  Control classes."

Similar presentations


Ads by Google