학습목표    1

학습주제    1

예습내용    1

실습방법    1

        1

중요함수    1

모들리스대화상자와 윈도우메시지 만들기

학습목표

모데리스대화상자 기반 에플리케이션과 윈도우메세지를 만드는 방법을 공부한다.

학습주제

메뉴에서 모들리스를 선택하면 모델리스 대화 상자가 나타나며 이는 이름을 선택할 경우 바로 메인 프로그램등을 구동할 있습니다. 우리가 아래한글 등에서 찾기를 실행하면 이러한 응용 프로그램을 있습니다.

단원의 내용은 “Visusal C++.NET 실전 프로그래밍”,이재원저, 가메출판사  p428~p442 참조 했습니다.

예습내용

싱글다큐먼트

실습방법

   

 

프로그램은 앞에서의 Modal 프로그램을 그대로 사용 합니다.

 

1. 다이어로그 리소스 추가

“Resource View”에서 다이어로그 리소스를 추가한 후에 아래 포를 참조하여 다이어로그를 구성한다. 다이어로그박스의 ID 생성되는 기본 값을 그대로 사용한다.

 

컨트롤

ID

Caption

컨트롤 변수

텍스트

기본값

이름

 

에디트

IDC_NAME

 

 

텍스트

기본값

이름변경

 

라디오버튼

IDC_PARK

박태준

Category : Value

Variable type : int

Variable name : m_Name

라디오버튼

IDC_HUH

허만권

 

라디오버튼

IDC_LEE

이상용

 

 

 

2. 다이어로그 클래스 추가

위에서 다이어로그를 관리하기 위해 클래스를 만든다. 마우스로 다이어로그 박스를 더블크릭 하거나 마우스 오른쪽키를 눌러서 클래스 추가 선택한다. 클래스 이름은 “CNameDlg” 입력한다.

 

             

 

3. 모들리스 대화 상자의 생성

View 클래스에 모들리스 대화상자를 관리하기 위한 CNameActDlg 객체포인터 m_pDlg 변수추가 이용하여 추가한다.

 

아래와 같이 CNameActDlg* m_pDlg;” 자동 선언된 것을 볼수 있으며 DialogTestView.cpp” 생성자 CDialogTestView()”에는 “m_pDlg(NULL)” 같이 NULL 초기화 되어 있는 것을 있다.

DialogTestView.h  NameActDlg.h include 한다.

 

 

// DialogTestView.h : CDialogTestView 클래스의인터페이스

//

 

#pragma once

#include "NameActDlg.h"

 

 

class CDialogTestView : public CView

{

protected: // serialization에서만만들어집니다.

              CDialogTestView();

              DECLARE_DYNCREATE(CDialogTestView)

 

// 특성입니다.

public:

              CDialogTestDoc* GetDocument() const;

 

// 작업입니다.

public:

 

// 재정의입니다.

public:

              virtual void OnDraw(CDC* pDC);  // 이뷰를그리기위해재정의되었습니다.

              virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

protected:

              virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);

              virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);

              virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

 

// 구현입니다.

public:

              virtual ~CDialogTestView();

#ifdef _DEBUG

              virtual void AssertValid() const;

              virtual void Dump(CDumpContext& dc) const;

#endif

 

protected:

 

// 생성된메시지맵함수

protected:

              DECLARE_MESSAGE_MAP()

public:

              afx_msg void OnNameModal();

              afx_msg void OnNameModeless();

              CNameActDlg* m_pDlg;

};

 

#ifndef _DEBUG  // DialogTestView.cpp의디버그버전

inline CDialogTestDoc* CDialogTestView::GetDocument() const

   { return reinterpret_cast<CDialogTestDoc*>(m_pDocument); }

#endif

 

m_pDlg 초기화

 

CDialogTestView::CDialogTestView()

: m_pDlg(NULL)

{

              // TODO: 여기에생성코드를추가합니다.

 

}

 

 

리소스뷰 메뉴” IDR_MAINFRAME 열고 아래와 같이 메뉴항목을 추가한다.

 

 

 

메뉴항목

ID

비고

 

 

이름

 

메뉴바

 

 

이름선택(Modeless)

ID_NAME_MODELESS

 

 

 

클래스뷰에서 “CDialogTestView”클래스를 선택하고 오른쪽 그림과 같이 “OnNameModeless” 명령 핸들러를 추가 한다.

 

아래와 같이 같이 프로그램 한다.

 

If 중에서 else 처리를 보면 m_pDlg 객체에 포인터 메모리를 할당하고 Create() 함수에 다이어로그 리소스  “IDD_DIALOG2” 인자로 지정하여 실행함으로 대화상자를 생성한 후에 ShowWindow() 멤버 함수를 이용해 화면에 나타나게 한다.

 

 

void CDialogTestView::OnNameModeless()

{

              // TODO: 여기에명령처리기코드를추가합니다.

              if(m_pDlg != NULL)

                             m_pDlg->ShowWindow(SW_SHOW);

              else

              {

                             m_pDlg = new CNameActDlg;

                             m_pDlg->Create(IDD_DIALOG2);

                             m_pDlg->ShowWindow(SW_SHOW);

              }

}

4. 모들리스 대화상자의 종료

모달 대화상자는 new 이용한 메모리 할당을 하지 않아 [확인]  [취소] 버튼을 누르면 자동으로 종료 되었다. 그러나 모들리스 대화 상자는 new, 이용해 메모리를 할당 하였으므로 다음 가지로 처리한다.

    메모리를 남겨두어 보이지 않게 처리하였다. 다시 나타낸다.

    메모리를 삭제하고 나오며, 다시 모달리스 대화상자를 때는 new 이용해 새로운 메모리와 대화상자를 만든다. (윈동우 메시지를 이용하여 처리)

다음은 1 방법으로 프로그램 것이다. 프로그램은 이상 없이 동작한다.

 

윈도우메시지 만들기

 

이번에는 대화상자를 닫을 해당 클래스를 모두 delete 하여 메모리에서 삭제하고 다시 대화상자를 때는 메모리를 만들기로 한다. 여기서 중요한 점은 NameActDlg 클래스에서 메모리를 delete 한다. 그러면 View 클래스에서 다시 m_pDlg NULL로 선언해야 한다. 그러나 delete 작업은 NameActDlg 클래스에서 하고 m_pDlg View 클래스에 존재하기에 이를 실행하기 위해서는 delete 시에 WM_DESTROY_DLG”  메시지를 View 클래스로 보내고 메시지 핸들러 함수에서 m_pDlg 객체 포인터를 초기화 하도록 한다.

 

다이어로그 박스에서 [확인] 취소 버튼을 더블 클릭하여 아래와 같은 두개의 핸들러 함수를 만들고 아래와 프로그램한다.

 

 

void CNameActDlg::OnBnClickedOk()

{

              // TODO: 여기에컨트롤알림처리기코드를추가합니다.

              DestroyWindow();

              return;

 

              OnOK();

}

 

void CNameActDlg::OnBnClickedCancel()

{

              // TODO: 여기에컨트롤알림처리기코드를추가합니다.

              DestroyWindow();

              return;

 

              OnCancel();

}

 

 

CNameActDlg 클래스를 선택한 후에 속성”->”재정의에서 아래 그림과 같이 PostNcDestroy() 함수를 추가한다. 그리고 View 클래스로 WM_DESTROY_DLG” 메시지를 전송한 후에 delete 연산자를 사용하여 대화상자에 할당된 메모리를 반환한다.

프로그램에 DialogTestDoc DialogTestView 클래스를 include 한다.

 

// NameActDlg.cpp : 구현파일입니다.

//

 

#include "stdafx.h"

#include "DialogTest.h"

#include "NameActDlg.h"

 

#include "DialogTestDoc.h"

#include "DialogTestView.h"

 

// =============== 중간 생략 =========================

 

void CNameActDlg::PostNcDestroy()

{

              // TODO: 여기에특수화된코드를추가및/또는기본클래스를호출합니다.

              CFrameWnd* pWnd = (CFrameWnd*)AfxGetMainWnd();

              CView* pView = pWnd->GetActiveView();

              pView->SendMessage(WM_DESTROY_DLG);

              delete this;

              CDialog::PostNcDestroy();

}

 

WM_DESTROY_DLG” 메시지는 표준 윈도우 메시지가 아니라 사용자 정의 메시지 이므로 “WM_USER” 메시지를 통해 정의 된다. 그러므로 이를 “stdafx.h” 헤더 파일에 정의를 해줘야 한다.

 

 

// stdafx.h : 자주사용하지만자주변경되지는않는

// 표준시스템포함파일및프로젝트관련포함파일이

// 들어있는포함파일입니다.

 

#pragma once

 

#ifndef _SECURE_ATL

#define _SECURE_ATL 1

#endif

 

//================== 중간생략 ===========================

 

#include <afxwin.h>         // MFC 핵심및표준구성요소입니다.

#include <afxext.h>         // MFC 확장입니다.

 

#include <afxdisp.h>        // MFC 자동화클래스입니다.

 

#ifndef _AFX_NO_OLE_SUPPORT

#include <afxdtctl.h>                          // Internet Explorer 4 공용컨트롤에대한MFC 지원입니다.

#endif

#ifndef _AFX_NO_AFXCMN_SUPPORT

#include <afxcmn.h>                                        // Windows 공용컨트롤에대한MFC 지원입니다.

#endif // _AFX_NO_AFXCMN_SUPPORT

 

#define WM_DESTROY_DLG             WM_USER+5

 

 

 

View 클래스에서 그림과 같이 함수 추가를 선택한 후에  윈도우 메시지맵에 직접 코딩한다.

매개변수 목록은 매개변수 형식 매개변수 이름 입력하고 추가버튼을 누르면 메개변수 목록 표시 된다.

 

 

//=================  중간 생략 =====================================

// CDialogTestView

 

IMPLEMENT_DYNCREATE(CDialogTestView, CView)

 

BEGIN_MESSAGE_MAP(CDialogTestView, CView)

              // 표준인쇄명령입니다.

              ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)

              ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)

              ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)

              ON_COMMAND(ID_NAME_MODAL, &CDialogTestView::OnNameModal)

              ON_COMMAND(ID_NAME_MODELESS, &CDialogTestView::OnNameModeless)

              ON_MESSAGE(WM_DESTROY_DLG, OnDestroyDlg)  // WM_DESTROY_DLG 메시지핸들러

END_MESSAGE_MAP()

 

//=================  중간 생략 =====================================

 

LRESULT CDialogTestView::OnDestroyDlg(WPARAM wParam, LPARAM lParam)

{

              m_pDlg = NULL;

              return LRESULT();

}

 

 

대화상자 기능 구현

세사람을 선택하는 라디오버튼을 누르면 SetName(int nButton) 함수를 실행하여 EditBox 이름을 표시하고 Doc 클래스의 m_Name 값을 저장 하도록 하겠습니다.

 

NameActDlg 클래스에 아래와 같이 함수를 추가한다.

 

 

void CNameActDlg::SetName(int nButton)

{

              CString str;

              switch(nButton) {

                             case 0:

                                           str.Format("박태준값=%d",nButton);

                                           break;

                             case 1:

                                           str.Format("허만권값=%d",nButton);

                                           break;

                             case 2:

                                           str.Format("이상용값=%d",nButton);

                                           break;

              }

              SetDlgItemText(IDC_NAME, str);

              UpdateData(FALSE);

 

              //Doc 클래스로값을저장

              CFrameWnd* pWnd = (CFrameWnd*)AfxGetMainWnd();

              ((CDialogTestDoc*)pWnd->GetActiveDocument())->m_Name = nButton;

}

 

void CNameActDlg::OnBnClickedPark()

{

              // TODO: 여기에컨트롤알림처리기코드를추가합니다.

              SetName(0);

}

 

void CNameActDlg::OnBnClickedHuh()

{

              // TODO: 여기에컨트롤알림처리기코드를추가합니다.

              SetName(1);

}

 

void CNameActDlg::OnBnClickedLee()

{

              // TODO: 여기에컨트롤알림처리기코드를추가합니다.

              SetName(2);

}

 

 

다이어로그 박스가를 시작할 Doc 클래스에 저장되어 있는 초기치를 표시하는 프로그램을 하겠습니다. [NameActDlg 클래스->속성->재정의]에서 “OnInitDialog” 함수를 선택 합니다.

라디오 버튼은 Modal 에서와 동일하게 지정 합니다.

 

void CNameActDlg::SetName(int nButton)

{

              CString str;

              switch(nButton) {

                             case 0:

                                           str.Format("박태준값=%d",nButton);

                                           break;

                             case 1:

                                           str.Format("허만권값=%d",nButton);

                                           break;

                             case 2:

                                           str.Format("이상용값=%d",nButton);

                                           break;

              }

              SetDlgItemText(IDC_NAME, str);

              m_Name = nButton;

              UpdateData(FALSE);

 

              //Doc 클래스로값을저장

              CFrameWnd* pWnd = (CFrameWnd*)AfxGetMainWnd();

              ((CDialogTestDoc*)pWnd->GetActiveDocument())->m_Name = nButton;

}

 

void CNameActDlg::OnBnClickedPark()

{

              // TODO: 여기에컨트롤알림처리기코드를추가합니다.

              SetName(0);

}

 

void CNameActDlg::OnBnClickedHuh()

{

              // TODO: 여기에컨트롤알림처리기코드를추가합니다.

              SetName(1);

}

 

void CNameActDlg::OnBnClickedLee()

{

              // TODO: 여기에컨트롤알림처리기코드를추가합니다.

              SetName(2);

}

 

BOOL CNameActDlg::OnInitDialog()

{

              CDialog::OnInitDialog();

 

              // TODO:  여기에추가초기화작업을추가합니다.

              CFrameWnd* pWnd = (CFrameWnd*)AfxGetMainWnd();

              SetName(((CDialogTestDoc*)pWnd->GetActiveDocument())->m_Name);

 

              return TRUE;  // return TRUE unless you set the focus to a control

              // 예외: OCX 속성페이지는FALSE를반환해야합니다.

}

 

 

 

처음

   

 

중요함수