1.28k likes | 1.52k Views
Chap. 6. Dialog and Control Classes. Contents. CDialog class Common Dialogs Property Sheets Control classes. CDialog Class. Dialog 의 종류 Modal dialog Close 될 때 까지 다른 부분을 사용할 수 없음 DoModal() 함수를 이용 예 : common dialog box Modeless dialog Close 되기 전에 다른 부분을 사용할 수 있음 Create() 함수를 이용
E N D
Chap. 6 Dialog and Control Classes
Contents • CDialog class • Common Dialogs • Property Sheets • Control classes
CDialog Class • Dialog의 종류 • Modal dialog • Close될 때 까지 다른 부분을 사용할 수 없음 • DoModal()함수를 이용 • 예 : common dialog box • Modeless dialog • Close되기 전에 다른 부분을 사용할 수 있음 • Create()함수를 이용 • DestroyWindow()함수를 이용하여 명시적으로 종료함 • 예 : find and replace dialog box
CDialog Class (cont’d) • History • MFC 1.0 • Modal dialog : CModalDialog • Modeless dialog : CDialog • Current version • Modal dialog : CDialog • Modeless dialog : Cdialog • AFXWIN.H // all CModalDialog functionality is now in CDialog #define CModalDialog CDialog
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;
Win32 APIs • Dialog생성을 위한 Win32 APIs • CreateDialog() • Modeless dialog생성, template resource이용 • CreateDialogIndirect() • Modeless dialog생성, template pointer이용 • DialogBox() • Modal dialog생성, template resource이용 • DialogBoxIndirect() • Modal dialog생성, template pointer이용
Win32 APIs (cont’d) • CDialog Class • 오직 CreateDialogIndirect() API을 이용 • Modality를 내부적으로 구현 • AFXWIN.H • DLGCORE.CPP, AFXWIN2.INL
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();
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();
CDialog (cont’d) 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) • 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) • 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) • virtual OnCmdMsg() • Command message처리작업 • virtual CheckAutoCenter() • Auto-center옵션이 체크되었는지 확인 • virtual SetOccDialogInfo() • M_pOccDialogInfo변수에 데이터를 setting • virtual PreInitDialog() • WM_INITDIALOG message이전에 불리워지는 함수 • PreModal() • DoModal()함수 실행을 위한 준비작업 • PostModal() • DoModal()함수가 끝난후의 뒤처리
Modal Dialog Creation • 일반적으로 두가지의 과정을 거침 • CDialog construction • DoModal()함수의 호출 • CDialog construction • DLGCORE.CPP에 있음 • 두가지 버전이 있으며 CDialog class의 필요한 변수에 값을 입력하는 역할을 함
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; }
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;
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); }
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(); }
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; }
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)); } }
Modal Dialog Creation (cont’d) • 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) • Dialog를 생성하고 보여줌 • CWnd::CreateDlgIndirect()함수 호출 • 내부적으로 Win32API인 CreateDialogIndirect()를 호출 • CWnd::RunModalLoop()함수 호출 • Dialog가 끝날때 까지 일을 수행 • 사용자가 ok나 cancel버튼을 누르면 CWnd::EndModalLoop()함수가 호출됨 • Dialog를 화면에서 보이지 않게 함 • Dialog가 종료하면 EnableWindow(TRUE)를 호출 • Parent window를 enable시킴 • 마지막 단계 • DestroyWindow()함수 호출 • PostModal()함수 호출
Modeless Dialog Creation • Modeless dialog creation • 두가지 과정을 거침 • New operator를 사용하여 변수 생성 • CDialog::Create()함수 호출
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; }
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); }
Modeless Dialog Creation (cont’d) • CDialog::Create()(DLGCORE.CPP) • Template name과 help ID를 내부 변수에 저장 • Dialog resource를 찾고 load함 • CDialog::CreateIndirect()함수 호출 • 내부적으로 Win32 API인 CreateDialogIndirect()함수 호출 • 사용자가 ok나 cancel버튼을 누르면 EndDialog()가 호출되어 dialog가 사라짐
Dialog Terminator void CDialog::EndDialog(int nResult) { ASSERT(::IsWindow(m_hWnd)); if (m_nFlags & (WF_MODALLOOP|WF_CONTINUEMODAL)) EndModalLoop(nResult); ::EndDialog(m_hWnd, nResult); }
CDialog Control Initialization • Dialog에 있는 control의 초기화 작업 • Resource에 의한 초기화 • Combo box를 예로 살펴봄 • Data는 “one”, “two”, “three”라 가정 • 다음과 같은 코드가 생성되지 않는다. m_pCombo->AddString(“one”); m_pCombo->AddString(“two”); m_pCombo->AddString(“three”);
CDialog Control Initialization (cont’d) • 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) • Resource file 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
CDialog Control Initialization (cont’d) • CWnd::ExecuteDlgInit()(WINCORE.CPP) • 두가지 버전이 존재 • Argument로 dialog template name • Argument로 dialog data에 대한 pointer • 일단 첫번째 버전의 함수가 dialog template name을 가지고 resource 파일에서 control의 data를 load함 • 이 후 pointer를 얻어서 두번째 버전의 함수를 호출 • why CWnd class member function?
CDialog Control Initialization (cont’d) • 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; }
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); }
DDX/DDV (cont’d) • Question • CDataExchange class의 역할 • Control들과 멤버 변수들간의 정보 교환은 언제, 어디에서, 어떻게 이루어지는가 • DDX/DDV 함수는 무슨 일들을 하는가
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 };
DDX/DDV (cont’d) • 멤버 변수 • m_bSaveAndValidate • TRUE data가 control에서 변수로 감 • FALSE data가 변수에서 control로 감 • Validation은 TRUE일때만 일어남 • m_pDlgWnd • Dialog에 대한 CWnd pointer • m_hWndLastControl • Previous control에 대한 handle을 저장 • m_bEditLastControl • Previous control이 수정되었는지를 저장
DDX/DDV (cont’d) • 멤버 함수 • Constructor • PrepareCtrl() • Non-edit control을 위한 준비 • PrepareEditCtrl() • Edit control을 위한 준비 • Fail() • Validation이 실패하면 호출됨 • Focus를 previous control로 보내고 CUserException예외를 발생시킴 • PrepareOleCtrl() • OLE control을 위한 준비
DDX/DDV (cont’d) • 특징 • DDX/DDV는 Serialize과정과 유사 • CDataExchange 는 CArchive 와 비슷 • DoDataExchange()는 Serialize() 와 비슷 • Save/load tag를 가짐
DDX/DDV (cont’d) • 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) 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); } }
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); } }
DDX/DDV (cont’d) • 언제 DoDataExchange()가 호출되는가? • 필요할 때 마다 UpdateData()함수 호출 • 위 함수 내부에서 DoDataExchange()를 호출함 • UpdateData()(WINCORE.CPP)
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 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); } }
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 }
Common Dialogs • Common Dialogs • 표준 interface제공을 위하여 • 종류 • CColorDialog • CFileDialog • CFindReplaceDialog • CFontDialog • CPrintDialog • CPageSetupDialog ( MFC 4.0 )
Common Dialogs (cont’d) • Steps • 생성자 호출 • DoModal() 호출 • IDOK가 리턴될 때 적절한 처리 CFileDialog myDialog(TRUE, NULL, NULL, OFN_FILEMUSTEXIST); if ( myDialog.DoModal() == IDOK ) { Cstring strPath = myDialog.GetPathName(); CString strFile = myDialog.GetFileName(); } else // User selected Cancel …
Common Dialogs (cont’d) • 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) • 예제 dialog • CFileDialog(AFXDLGS.H) 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;
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); };
Common Dialogs (cont’d) • 예제 dialog • CFileDialog(AFXDLGS.H) • OPENFILENAME structure • 여러 개의 virtual protected 함수 • 기타 여러 정보 저장을 위한 변수 • CFileDialog의 생성(DLGFILE.CPP) • 생성자의 argument들을 OPENFILENAME structure의 멤버에 setting함(m_ofn) • Window95이상일 경우에는 OFN_EXPLORER와 OFN_ENABLEHOOK flag를 set함 • OFN_ENABLEHOOK Hook routine을 제공(_AfxCommDlgProc()를 m_ofn의 hook field에 set)