Upload
adie
View
244
Download
3
Embed Size (px)
DESCRIPTION
Chapter 06 MFC Dialog 와 Control Class. Contents. CDialog class Common Dialogs Property Sheets Control classes. CDialog Class. Dialog 의 종류 Modal dialog Close 될 때 까지 다른 부분을 사용할 수 없음 DoModal() 함수를 이용 예 : common dialog box Modeless dialog Close 되기 전에 다른 부분을 사용할 수 있음 Create() 함수를 이용 - PowerPoint PPT Presentation
Citation preview
비트교육센터[3]
비트교육센터
CDialog ClassDialog 의 종류
– Modal dialogClose 될 때 까지 다른 부분을 사용할 수 없음DoModal() 함수를 이용예 : common dialog box
– Modeless dialogClose 되기 전에 다른 부분을 사용할 수 있음Create() 함수를 이용DestroyWindow() 함수를 이용하여 명시적으로 종료함예 : find and replace dialog box
비트교육센터[4]
비트교육센터
CDialog Class (cont’d)History
– MFC 1.0 Modal dialog : CModalDialogModeless dialog : CDialog
– Current version Modal dialog : CDialogModeless 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 somethingm_pDlgMyDlgPtr->DestroyWindow();m_pDlgMyDlgPtr = NULL;
비트교육센터[6]
비트교육센터
Win32 APIsDialog 생성을 위한 Win32 APIs
– CreateDialog()Modeless dialog 생성 , template resource 이용
– CreateDialogIndirect()Modeless dialog 생성 , template pointer 이용
Modal()/Modaless 를 만들때 모두 사용되는 함수
– DialogBox()Modal dialog 생성 , template resource 이용
– DialogBoxIndirect()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 constructpublic: 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);
// Operationspublic: // 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();// Implementationpublic: 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– Button 을 위한 help ID
m_lpszTemplateName– Resource template 의 이름
m_hDialogTemplate– 일단 load 된 후의 resource template 의 handle
m_lpDialogInit– 초기화에 관련된 data 에 대한 pointer
CDialog (cont’d)
비트교육센터[12]
비트교육센터
m_pParentWnd– Parent window 에 대한 pointer
m_hWndTop– Top-level parent window
m_pOccDialogInfo– OLE controls 을 위한 stored information
– 멤버 함수virtual PreTranslateMessage()
– 특별한 message(tool tips, context-sensitive help) 에 대한 filtering
CDialog (cont’d)
비트교육센터[13]
비트교육센터
virtual OnCmdMsg()– Command message 처리작업
virtual CheckAutoCenter()– Auto-center 옵션이 체크되었는지 확인
virtual SetOccDialogInfo()– M_pOccDialogInfo 변수에 데이터를 setting
virtual PreInitDialog()– WM_INITDIALOG message 이전에 불리워지는 함수
PreModal()– DoModal() 함수 실행을 위한 준비작업
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 loopDWORD dwFlags = MLF_SHOWONIDLE;if (GetStyle() & DS_NOIDLEMSG) dwFlags |= MLF_NOIDLEMSG;VERIFY(RunModalLoop(dwFlags) == m_nModalResult);
} CWnd Run 함수를 대치한다 .
비트교육센터[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 modelessASSERT(m_hWnd == NULL);
// allow OLE servers to disable themselvesCWinApp* pApp = AfxGetApp();if (pApp != NULL) pApp->EnableModeless(FALSE);
// find parent HWNDHWND hWnd = CWnd::GetSafeOwner_
(m_pParentWnd->GetSafeHwnd(), &m_hWndTop);
// hook for creation of dialogAfxHookWindowCreate(this);
// return window to use as parent for dialogreturn hWnd; 부모 핸들
}
비트교육센터[20]
비트교육센터
Modal Dialog Creation (cont’d)
int CWnd::RunModalLoop(DWORD dwFlags) CWnd Run 함수를 대치한다 .{ CWnd 에 존재한다 .( 다이얼로그 이외의 다른 클레스에서도 사용된다는 의미 ) 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 를 생성하기 위한 준비
PreModal() 함수를 호출함– Safety checks
Parent window handle 을 찾음– m_hWndTop 에 저장
EnableWindow(FALSE) 를 호출– Parent window 를 disable 시킴
Modal Dialog Creation (cont’d)
비트교육센터[22]
비트교육센터
– Dialog 를 생성하고 보여줌CWnd::CreateDlgIndirect() 함수 호출내부적으로 Win32API 인 CreateDialogIndirect() 를 호출CWnd::RunModalLoop() 함수 호출Dialog 가 끝날때 까지 일을 수행사용자가 ok 나 cancel 버튼을 누르면 CWnd::EndModalLoop()
함수가 호출됨Dialog 를 화면에서 보이지 않게 함Dialog 가 종료하면 EnableWindow(TRUE) 를 호출Parent window 를 enable 시킴
– 마지막 단계DestroyWindow() 함수 호출PostModal() 함수 호출
Modal Dialog Creation (cont’d)
비트교육센터[23]
비트교육센터
Modeless dialog creation– 두가지 과정을 거침
New operator 를 사용하여 변수 생성 힙메모리에 변수 생성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 soonreturn 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() 함수 호출– 사용자가 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 InitializationDialog 에 있는 control 의 초기화 작업
– Resource 에 의한 초기화– Combo box 를 예로 살펴봄
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 DLGINITBEGIN IDC_COMBO1, 0x403, 4, 00x6e6f, 0x0065, IDC_COMBO1, 0x403, 4, 00x7774, 0x006f, IDC_COMBO1, 0x403, 6, 00x6874, 0x6572, 0x0065, 0END
예제를 쎃넣을 경우 다음과 같은 내용이 첨부된다 .
비트교육센터[31]
비트교육센터
CWnd::ExecuteDlgInit()(WINCORE.CPP)– 두가지 버전이 존재
Argument 로 dialog template nameArgument 로 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)– 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)++;
AddString 등의 동일한 작업을 할수 있게 if 문 작성됨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/DDVDDX/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{// Attributespublic: 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_bSaveAndValidateTRUE data 가 control 에서 변수로 감FALSE data 가 변수에서 control 로 감Validation 은 TRUE 일때만 일어남
– m_pDlgWndDialog 에 대한 CWnd pointer
– m_hWndLastControlPrevious control 에 대한 handle 을 저장
– m_bEditLastControlPrevious control 이 수정되었는지를 저장
비트교육센터[37]
비트교육센터
멤버 함수– Constructor– PrepareCtrl()
Non-edit control 을 위한 준비– PrepareEditCtrl()
Edit control 을 위한 준비– Fail()
Validation 이 실패하면 호출됨Focus 를 previous control 로 보내고 CUserException 예외를
발생시킴– PrepareOleCtrl()
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 이동– DDV_MaxChars()(DLGDATA.CPP)
m_bSaveAndValidate 값이 TRUE 인경우 validation 코드 수행– DDX_TextWithFormat()(DLGDATA.CPP)
String 과 int 사이의 conversion
DDX/DDV (cont’d)
비트교육센터[40]
비트교육센터
DDX/DDV (cont’d)
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); 맴버변수에서 컨트롤로 (FALSE) }}
비트교육센터[41]
비트교육센터
DDX/DDV (cont’d)
void AFXAPI DDV_MaxChars(CDataExchange* pDX, CString const& value, int nChars) 예 ) 범위에 맞는지 틀린지 check{ 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 preppDX->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]
비트교육센터
DDX/DDV (cont’d)
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 recursepThreadState->m_hLockoutNotifyWindow = m_hWnd;BOOL bOK = FALSE; // assume failureTRY {
DoDataExchange(&dx);bOK = TRUE; // it worked
}CATCH(CUserException, e) {
// validation failed - user already alerted, fall throughASSERT(!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 itemreturn;
}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 DialogsCommon Dialogs
– 표준 interface 제공을 위하여– 종류
CColorDialogCFileDialogCFindReplaceDialogCFontDialogCPrintDialogCPageSetupDialog ( 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 를 가지고 있다 .
대응되는 API 를 가지고 있다 .
예 ) 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 blockvirtual int DoModal();CString GetPathName() const; // return full path and filenameCString GetFileName() const; // return only filenameCString GetFileExt() const; // return only extCString GetFileTitle() const; // return file titleBOOL GetReadOnlyPref() const; // return TRUE if readonly checked// Enumerating multiple file selectionsPOSITION 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여러 개의 virtual protected 함수기타 여러 정보 저장을 위한 변수
– CFileDialog 의 생성 (DLGFILE.CPP)생성자의 argument 들을 OPENFILENAME structure 의 멤버에 settin
g 함 (m_ofn)Window95 이상일 경우에는 OFN_EXPLORER 와 OFN_ENABLEHOOK f
lag 를 set 함– OFN_ENABLEHOOK Hook routine 을 제공 (_AfxCommDlgProc() 를 m_of
n 의 hook field 에 set)
Common Dialogs (cont’d)
비트교육센터[51]
비트교육센터
– CFileDialog::DoModal()(DLGFILE.CPP)M_bOpenFileDialog 변수의 값을 보고 Win32 API 인 GetOpenFileNa
me() 을 호출할건지 GetSaveFileName() 을 호출할건지를 결정
Common Dialogs (cont’d)
비트교육센터[52]
비트교육센터
Common Dialogs (cont’d)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 SheetsTabbed dialogsMFC 3.0 때부터 제공하나의 dialog 에서 사용자로부터 많은 입력을 받을 수 있는 인터페이스
비트교육센터[54]
비트교육센터
Property Sheets (cont’d)두개의 class
– CPropertySheet 버튼역할Tabbed dialog 를 위한 class
– CPropertyPage 리소스와 관련Tabbed dialog 의 각각의 tab(page) 을 위한 class
일반 dialog 와의 차이점– Apply 버튼 제공
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() 호출
OK/Apply/Cancel 버튼이 자동적으로 추가– 3-2. (modeless property sheet)
CPropertySheet 의 파생클래스 생성한 뒤 인스턴스를 생성하고 Create() 함수 호출
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 ClassDeclaration of CPropertySheet
– AFXDLGS.H (CWnd 의 파생클래스임… ) 다이얼로그의 특성을 가져오기가 어렵다는 뜻임 .
class CPropertySheet : public CWnd{// Attributespublic: 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)// Operationspublic: 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);// Implementationpublic: 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()– 수많은 constructor 들이 호출하는 공통 함수
m_pages– CPtrArray 형의 pointer 로 CPropertyPage class 의 pointer 의 배열
CPropertySheet Class (cont’d)
비트교육센터[61]
비트교육센터
m_strCaption– Property sheet 의 caption
m_pParentWnd– Parent window 에 대한 pointer
m_bStacked– Tab 을 stacked mode 로 할건지 scrolled mode 로 할 건지를 결정
m_bModeless– Property sheet 를 modal 로 할건지 modeless 로 할건지
CPropertySheet Class (cont’d)
비트교육센터[62]
비트교육센터
CPropertySheet::DoModal()– DLGPROP.CPP– 내부 수행
AfxDeferRegisterClass() 호출– 내부적으로 InitCommonControls() 함수 호출 (Windows common controls
DLL 을 초기화 )BuildPropPageArray() 호출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]
비트교육센터
CPropertySheet Class (cont’d)
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 ClassesControl class 의 세가지 group
– Old fashioned (6)Button, combo box, edit, list box, scroll bar, static
– New fangledWindow common controls
– OLE controls
비트교육센터[68]
비트교육센터
Old-Fashioned 특징
– 모두 CWnd 에서 상속받음– Cbitmap, CBitmapButton, CComboBox, CEdit, CListBox, CDragListBox, CCheckList
Box, CScrollBar, CStatic– Declaration 은 AFXWIN.H– Implementation
AFXWIN2.INLWINCTRL1.CPPWINCTRL2.CPPWINCTRL3.CPPWINBTN.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, CRichEditCtr
l, CSliderCtrl, CSpinButtonCtrl, …– Declaration 은 AFXCMN.H– Implementation
AFXCMN.INLWINCTRL2.CPPWINCTRL4.CPP
비트교육센터[72]
비트교육센터
ContentsIntroductionArchitectureInside document/view architectureDocument/view internals
비트교육센터[73]
비트교육센터
IntroductionApplication 의 data 관리
– Data 를 분리하여 관리하자 .– 중요한 이슈
누가 data 를 관리할 것인가누가 data 를 update 할 것인가data 의 rendering 어떻게 다르게 할 것인가…
– Print 와 print preview 의 지원– 두 부분
Data management(Document)User-interface management(Frame/View)
비트교육센터[74]
비트교육센터
Introduction (cont’d)기존의 방법
– 분리하지 않고 하나의 클래스에서 처리– 대단히 복잡
중요성– Multiple ways to represent your data
Rendering & Updating– Multiple types of data
User interface
비트교육센터[75]
비트교육센터
ArchitectureDocument 와 view
– DocumentApplication 의 data 를 의미
– ViewApplication 의 data 의 표현을 의미
비트교육센터[76]
비트교육센터
Document/View ComponentsMFC document/view architecture 를 위한 4 개의 components
– Documents– Views– Document/view frames– Document templates
비트교육센터[77]
비트교육센터
Documents– CDocument class
Managing file I/OUpdating renderings of the dataCCmdTarget(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) 로 부터 상속 받음– CCmdTarget Command message (WM_COMMAND) 를 받을 수 있음– CWnd Window message(WM_PAINT) 를 받을 수 있음
View 는 border 가 없는 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 classSingle Document Interface워드패드
– MDI CMDIChildWnd classMultiple Document IntefaceMS Word
Document/View Components(cont’d)
비트교육센터[81]
비트교육센터
Document templates– CDocTemplate class– Document, view, frame 을 묶어서 하나의 unit 으로 관리– 각각의 서로 다른 document type 에 대하여 하나씩의 template 을 가질 수 있다 . – 실제 사용시
한 type 의 document CSingleDocTemplate class여러 type 의 document CMultiDocTemplate class
Document/View Components(cont’d)
비트교육센터[82]
비트교육센터
CSingleDocTemplate– 생성자의 인자
Resource IDDocumet/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 을 생성함생성이 끝나면 CWinApp::AddDocTemplate() 호출
– CWinApp 의 document template list 에 추가함
CWinApp에서 각각의 DoucmentTemplate를 관리한다 .
버전이 올라가면서 이탬플릿을 관리하는 것을 만들었는데CDocMenager이다 .
비트교육센터[85]
비트교육센터
CWinApp 의 역할 (cont’d)
BOOL CTestApp::InitInstance(){
…CMultiDocTemplate* pDocTemplate;pDocTemplate = new CMultiDocTemplate(
IDR_TESTTYPE,RUNTIME_CLASS(CTestDoc),RUNTIME_CLASS(CChildFrame), // custom MDI child frameRUNTIME_CLASS(CTestView));
AddDocTemplate(pDocTemplate); 리스트로 넣어주는부분…
}
비트교육센터[86]
비트교육센터
Document/View Arch. InternalsDocument/View arch. 의 기본
– CWinAppDocument template 의 관리
– Document templateFrames/Views/Documents 의 관리
비트교육센터[87]
비트교육센터
CDocManager ClassCDocManager
– CWinApp 와 CDocTemplate 사이의 interface 역할– CWinApp 가 필요한 document template 의 list 를 관리하는 역할– CWinApp 의 declaration(AFXWIN.H)
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 exitvirtual void CloseAllDocuments(BOOL bEndSession); virtual int GetOpenDocumentCount();CPtrList m_templateList;int GetDocumentCount();
};
비트교육센터[89]
비트교육센터
CDocManager Class(contd.)Declaration(AFXWIN.H)
– 멤버 변수m_templateList
– CPtrList type– 실제 document template 의 list
– 멤버 함수대부분의 함수가 m_templateList 에 대한 조작과 CWinApp 와의 inte
rface 를 위해서 존재
비트교육센터[90]
비트교육센터
CDocManager Class(contd.)대부분의 CWinApp 의 document template 관련 함수는 CDocManag
er 의 함수를 그대로 호출함– 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 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 templatespublic:
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
비트교육센터[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 classCDocTemplate
– Document/View/Frame 을 관리– Base class– 실제 사용시에는 둘중하나의 파생클래스를 사용
CSingleDocTemplate– DOCSINGL.CPP
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);// Attributespublic: 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
– Document template 에 대한 resource IDm_pDocClass
– CDocument 에 대한 CRuntimeClass structure 의 pointerm_pFrameClass
– CFrameWnd 에 대한 CRuntimeClass structure 의 pointer
비트교육센터[101]
비트교육센터
CDocTemplate class(contd.)m_pViewClass
– CView 에 대한 CRuntimeClass structure 의 pointerm_strDocStrings
– Document template 의 string resourceImplementation(DOCTEMPL.CPP)
– Document/View/Frame 을 생성하는 함수CDocTemplate::CreateNewDocument()CDocTemplate::CreateNewFrame()
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;
View 의 생성에 필요한 정보들을 저장한다 .(4 가지… )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 생성생성된 document 를 open 된 document list 에 추가
– CDocTemplate::CreateNewFrame()CCreateContext 에 필요한 정보를 채움m_pFrameClass->CreateObject() 를 이용해 frame 생성Frame 에 필요한 resource 를 load
비트교육센터[105]
비트교육센터
CDocTemplate class(contd.)– CCreateContext structure
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/frameCView* m_pLastView;CFrameWnd* m_pCurrentFrame;
// ImplementationCCreateContext();
};
비트교육센터[106]
비트교육센터
CDocTemplate class(contd.)– CCreateContext structure
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( 여러개저장필요 LinkedList 사용 )– CPtrList m_docList;– int m_nUntitledCount; Untitled document 의 수를 저장함 (Untitled[X])
비트교육센터[108]
비트교육센터
CDocTemplate class(contd.)– CMultiDocTemplate::OpenDocumentFile()
DOCMULTI.CPPDocument 와 frame 의 생성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 nameSetDefaultTitle(pDocument);pDocument->OnNewDocument();
} else {// open an existing document( 기존의 파일을 오픈하는 경우 )
CWaitCursor wait;pDocument->OnOpenDocument(lpszPathName);pDocument->SetPathName(lpszPathName);
}return pDocument;
}
비트교육센터[110]
비트교육센터
CFrameWnd classCFrameWnd
– CView 의 생성 !– m_pViewActive
현재 atcive 한 view 에 대한 pointerCFrameWnd::GetActiveView()CFrameWnd::SetActiveView()
– InitialUpdateFrame() 함수모든 view 의 OnInitialUpdate() 함수를 호출함
비트교육센터[111]
비트교육센터
CFrameWnd class(contd.)
Implementation(WINFRM.CPP)– CFrameWnd::CreateView()
진정한 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;}Frame 윈도우가 부모윈도우 , View 윈도우가 자식윈도우가 될것이라는 것을 암시
비트교육센터[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 firstOnCreateClient(lpcs, pContext);
}
비트교육센터[113]
비트교육센터
CFrameWnd class(contd.)
여기서 CreateView 가 호출된다 .
BOOL CFrameWnd::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext){
if (pContext != NULL && pContext->m_pNewViewClass != NULL)
{CreateView(pContext, AFX_IDW_PANE_FIRST);
}}
여기부분을 수정하게 되면 다중의 View 도 구현이 된다 .
비트교육센터[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 ClassCDocument
– 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() 함수 호출– DeleteContents() 호출– Modified flag 를 FALSE 로 함– m_strPathName 이 NULL 인지 확인
– File 로 부터 create 하는 경우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 yetSetModifiedFlag(FALSE); // make clean
return TRUE;}
CDocument Class (cont’d)
비트교육센터[121]
비트교육센터
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;}
CDocument Class (cont’d)
비트교육센터[122]
비트교육센터
CDocument Class (cont’d)Saving Documents
– OnSaveDocument()GetFile() 함수를 이용하여 file openCArchive class 를 이용하여 serializationModified 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 시– DisconnectViews() 함수를 호출하여 각 viwe 의 m_pDocument 가 NULL
이 되게 함 자신을 관리하는 Docment(m_ViewList) 를 가리키는 포인터
Frame 에 접근하고자 할 때– Cview::GetParentFrame() 함수 이용
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(); //view 의 포지션을 가져오고while (pos != NULL){
CView* pView = GetNextView(pos); // 각각의 View 포인터ASSERT_VALID(pView);if (pView != pSender)
pView->OnUpdate(pSender, lHint, pHint);}
}
CDocument Class (cont’d)
비트교육센터[126]
비트교육센터
CView ClassCView
– Declaration(AFXWIN.H)– Implementation(VIEWCORE.CPP)
void CView::OnPaint(){
// standard paint routineCPaintDC dc(this);OnPrepareDC(&dc);OnDraw(&dc);
}
비트교육센터[127]
비트교육센터
Document/View Internals
CWinApp::OnFileOpen()CWinApp::OnFileOpen() CWinApp::OnFileNew()CWinApp::OnFileNew()
CDocManager::OnFileOpen()CDocManager::OnFileOpen() CDocManager::OnFileNew()CDocManager::OnFileNew()
CDocTemplate::OpenDocumentFile()CDocTemplate::OpenDocumentFile()
CDocTemplate::CreateNewDocument()CDocTemplate::CreateNewDocument()
CDocTemplate::CreateNewFrame()CDocTemplate::CreateNewFrame()
WM_CREATEWM_CREATE
비트교육센터[128]
비트교육센터
Document/View…(contd.)
WM_CREATEWM_CREATE
CFrameWnd::OnCreate()CFrameWnd::OnCreate()
CFrameWnd::OnCreateHelper()CFrameWnd::OnCreateHelper()
CFrameWnd::OnCreateClient()CFrameWnd::OnCreateClient()
CFrameWnd::CreateView()CFrameWnd::CreateView()
CMyDocument::OnOpenDocument()CMyDocument::OnOpenDocument()
CMyDocument::OnNewDocument()CMyDocument::OnNewDocument()