티스토리 뷰
대화상자 템플릿
대화상자 자체와 포함된 컨트롤에 대한 모든 정보를 가지고 있는 이진 데이터로서 리소스 형태로 실행 파일에 포함된다.
위 화면과 같은 데회상자 편집기의 리소스 편집기 내용은 아래와 같다.
1
2
3
4
5
6
|
IDD_MFCAPPLICATION5_FORM DIALOGEX 0, 0, 320, 200
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
FONT 9, "MS Shell Dlg", 0, 0, 0x1
BEGIN
LISTBOX IDC_LIST1,7,7,66,84,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
END
|
cs |
이와 같이 텍스트 형태로 기술한 *.RC 파일을 리소스 스크립터(Resource Script)라고 부르며, 리소스 컴파일러에 의해 이진 형태인 *.RES로 변환되고 링크 과정에서 실행파일에 포함된다.
프로그램 실행 중 대화상자를 생성하는 API 함수를 호출하면 OS는 실행 파일에 포함된 대화상자 템플릿을 토대로 대화상자를 생성하게 된다.
탭 순서는 BEBIN~END 사이에 있는 컨트롤 배치 순서가된다.
1. 모드형 대화상자 (Modal Dialog)
사용자가 대화상자를 통해 입력을 하거나 취소를 함으로써 대화를 마쳐야만 다음으로 진행할 수 있다.
<대화상자 만들기>
- 대화상자 리소스 작성
- CDialog 또는 CDialog의 파생 클래스 객체를 만든다. 이때 대화상자 리소스 ID를 생성자 인자로 넘긴다.
- CDialog::DoMoal() 호출
1
2
3
4
5
6
7
8
9
10
|
void CMFCApplication5View::OnLButtonDblClk(UINT nFlags, CPoint point)
{
CDialog dlg(IDD_DIALOG1);
if (dlg.DoModal() == IDOK)
MessageBox(L"OK버튼을 눌렀습니다.");
else
MessageBox(L"Cancel 버튼을 눌렀습니다.");
CFormView::OnMButtonDblClk(nFlags, point);
}
|
cs |
virtual BOOL CDialog::OnInitDialog() 호출 시점
CDialog::DoModal() 호출로 대화상자가 생성되면 WM_CREATE 메시지가 발생하고 OS는 이 메시지를 받아 대화상자 템플릿에 선언된 컨트롤을 모두 생성한 후 대화상자가 화면에 보이기 직전에 WM_INITDIALOG 메시지를 발생시키며 이때 OnInitDialog() 가 호출된다. (OnInitDialog()는 WM_INITDIALOG 메시지 핸들러)
이 함수는 메시지 핸들러지만 가상함수로 정의되어 있어 메시지맵을 사용하지 않아도 자동으로 호출된다.
용도 : 컨트롤 초기화, 키보드 포커스를 변경
virtual void CDialog::OnOK() 호출 시점
사용자가 OK버튼(IDOK)으루 누르면 호출된다. 이 버튼의 클릭 메시지 핸들러는 OnOK()로 이 역시 가상함수로 메시지 맵을 사용하지 않아도 자동 호출된다.
용도 : 컨트롤의 값을 읽거나 값의 타당성 검사 후 대화상자를 닫는다.
virtual void CDialog::OnCeancel() 호출 시점
사용자가 취소버튼(IDCANCEL)이나 윈도우 종료 버튼 또는 ESC키를 누르면 호출된다.
이 함수가 Cancel 버튼의 메시지 핸들러고 가상함수 이기에 메시지맵을 사용하지 않아도 자동 호출된다.
용도 : 대화상자를 닫는다.
1
2
3
4
5
6
7
8
9
10
|
void CDialog::OnOK()
{
...
EndDialog(IDOK);
}
void CDialog::OnCancel()
{
EndDialog(CANCEL);
}
|
cs |
위 코드와 같이 대화상자는 EndDialog()에 의해 종료시키고, EndDialog() 인수가 CDialog::DoModal() 의 리턴값이 된다.
CDialog::DoModal() 호출하면 WM_CREATE, WM_INITDIALOG 메시지가 순서대로 발생한다.
추가>>>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
CExamMFCApp theApp;
BOOL CExamMFCApp::InitInstance()
{
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
AfxEnableControlContainer();
CExamMFCDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: 여기에 [확인]을 클릭하여 대화 상자가 없어질 때 처리할
// 코드를 배치합니다.
}
else if (nResponse == IDCANCEL)
{
// TODO: 여기에 [취소]를 클릭하여 대화 상자가 없어질 때 처리할
// 코드를 배치합니다.
}
// 대화 상자가 닫혔으므로 응용 프로그램의 메시지 펌프를 시작하지 않고 응용 프로그램을 끝낼 수 있도록 FALSE를
// 반환합니다.
return FALSE;
}
|
cs |
일반적인 MFC 어플리케이션과 대화상자 프로젝트 가장 큰 차이 :
MFC어풀리케이션이 기본적으로 재정의한 InitInstance 함수에 있다. 이 함수가호출되기 이전의 구조는 MFC 프레임워크가 철하기 떄문에 모든 프로젝트에서 동일하지만 InitInstance 는 윈도우를 생성하는 을 하기 떄문에 대화상자 프로그램은 약간 다른 구조를 가진다.
대화상자 역시 InitInstance 함수의 역황은 초기화(5~7행)와 윈도우 생성(8~20행)에 있다. 대화상자 프로그램에서 윈도우를 생성하는 것은 일반 어플리케이션과 다르다.
MFC어플리케이션은 대화상자를 생성하기 위해서 CDialog클래스로 부터 상속받는 클래스를 하나 정의해야 한다. 이 클래스르르 이용해 InitInstance 함수에서 객체로 선언한다 CDialog 클래스는 윈도우 클래스의 하위 클래스이므로 멤버로 가지는 윈도우 핸들을 생성하기 위애 Create 함수를 호출해야 하지만 대화샂아 클래스의 경우 윈도우 생성과 더불어 메시지 루프를 내부적으로 구현하고 있는 DoModal 함수를 호출하여 윈도우를 생성한다.
대화상자의 경우 Cretae함수를 호출하지않고 DoModal 함수를 호출하는 것은 대화상자의 특성 때문이다. 대화샂아는 일반적으로 사용자와 대화를 목적으로 생성한다. 이런 대화상자는 사용자가 명확하게 의사 표현(확인 또는 취소)을 하기 전에는 다른 처리를 하면 안된다. 그래서 대화상자는 윈도우로서 생성된 다음에 사용자가 의사 표현하기 전까지 개디하며 이를 위해 다른 윈도우들과 달리 메시지 루프를 독립적으로 가지게 된다. 이 함수가 바로 DoMoal 함수이다. 즉, DoModal 함수는 내부적으로 Create함수를호출하여 윈도우를 생성하고 메시지 루프를 돌며 사용자의 의사 표현을 대기하는 함수라고 생각하면 된다. 대화상자 어플리케이션은 DoModal 함수에서 리턴하게 되면 InitInstance 함수로 돌아오게 되는데 개화상자 후에 추가적인 작업이 필요하면 여기서 기술할 수 있다.
대화상자 어플리케이션은 InitInstance 함수를 리턴하여 MFC 프리임워크로 돌아가야 한다. 여기서 특이한 것은 InitInstance 함수의 반환 값이 MFC 프레임워크의 InitInstance 함수는 TRUE 반환하지만 대화상자 InitInstance 함수의 반환 값은 FALSE 이다. MFC 프레임워크 Instance 함수가 FALSE 를 반환하면 더 이상 프레임워크를 실행하지 않고 단순히 어플리키에션 종료한다. MFC 프레임워크는 대화상자 어플리케이션에 대해서는 대화상자가 독립적인 메시지 루프를 가지고 있기 때문에 이것이 끝나면 또 다시 메시지 루프를 처리하거나 할 필요가 없다고 생각하고 종료하는 것만 구현하고 있다. 이것을 실행하기 위한 부분이 InitInstance 함수의 반환 값인 FALSE 이다.