03: MFC 프로그램구조 학습목표 MFC 발전과정과주요특징을개괄적으로이해한다. MFC 최상위클래스인 CObject 가제공하는서비스를이해한다. MFC 가제공하는전역함수사용법을익힌다. AppWizard 가자동으로생성하는코드의구조를이해한다.
MFC 발전과정 (1/2) 연도 개발도구 MFC 버전 주요특징 1992 MS C 7.0 1.0 16 비트윈도우 API 를클래스화 OLE 1.0 지원 1993 비주얼 C++ 1.0 20 2.0 도큐먼트 / 뷰구조도입으로 MFC 의기본골격완성 1993 비주얼 C++ 1.5 2.5x OLE 2.01 지원 ODBC 클래스추가 DDX/DDV, 사용자인터페이스관련클래스추가정적 / 동적 MFC 라이브러리지원 1994 비주얼 C++ 2.x 3.x 32비트윈도우 API로전환 멀티스레드지원 윈속 (Winsock), MAPI 지원 1
MFC 발전과정 (2/2) 연도 개발도구 MFC 버전 주요특징 1995 비주얼 C++ 4.x 4x 4.x 공통컨트롤클래스추가 DAO와 32비트 ODBC 지원인터넷관련클래스추가 1997 비주얼 C++ 5.0 4.21 ATL 추가 1998 비주얼 C++ 6.0 6.0 ATL 업그레이드여러개의새로운클래스추가 (CHtlmView,...) OLE DB, ADO 지원강화 2002 비주얼 C++.NET 7.0 새로운 MFC DLL 사용 (MFC70.DLL) MFC와 ATL의통합강화사용자인터페이스클래스추가유틸리티클래스추가 ATL 서버클래스추가 2
MFC 주요특징 (1/3) 윈도우응용프로그램을작성하는데드는수고를크게덜어준다. 라이브러리재사용 AppWizard, ClassWizard,... API를기반으로한 SDK 프로그램과대등한속도를가진다. 인라인함수 코드크기증가를최소화한다. MFC DLL 3
MFC 주요특징 (2/3) API 함수를직접호출할수있다. ( 예 ) ::ReleaseCapture(); C 언어로작성된윈도우응용프로그램을쉽게 C++ 언어로바꿀수있다. SDK 프로그래밍에대한기반지식을재활용할수있다. C++ 언어를이용하여기존의 C 언어에비해 API 를좀더편하게사용할수있다. ( 예 ) 디폴트인자 4
MFC 주요특징 (3/3) API 를직접사용해서구현할경우복잡도가높은부분을 MFC 를이용하면쉽게구현할수있다. 인쇄기능지원, 툴바와상태바처리, 데이터베이스지원, OLE 와액티브 X,... 5
MFC 구성요소 (1/2) 구성요소 CObject 파생클래스 : 188 개 MFC 클래스 나머지 : 40 개 ( MFC 6.0 기준 ) 매크로와전역변수및전역함수 6
MFC 구성요소 (2/2) 클래스계층도 7
CObject 클래스 CObject 서비스 서비스이름 기능 실행시간클래스정보프로그램실행중객체정보를알아낸다. 동적객체생성객체를동적으로생성한다. 직렬화객체를저장하거나읽어들인다. 타당성점검객체상태를점검한다. 집합클래스와의호환성 서로다른클래스객체를집합클래스에저장할수있도록한다. 8
실행시간클래스정보 (1/2) 실행시간클래스정보기능추가 // MyClass.h class CMyClass : public CObject DECLARE_DYNAMIC(CMyClass)... }; // MyClass.cpp #include "MyClass.h" IMPLEMENT_DYNAMIC(CMyClass, CObject)... 9
실행시간클래스정보 (2/2) 실행시간클래스정보사용예 BOOL IsMyClass(CObject *pobj) // pobj 가가리키는객체가 CMyClass 타입인지확인한다. if(pobj->iskindof(runtime_class(cmyclass))... } else... } } 10
동적객체생성 (1/2) 동적객체생성기능추가 // MyClass.h class CMyClass : public CObject DECLARE_DYNCREATE(CMyClass) DYNCREATE(CMyClass) public: }; CMyClass();... // MyClass.cpp #include "MyClass.h" IMPLEMENT_DYNCREATE(CMyClass, CObject)... 11
동적객체생성 (2/2) 동적객체생성사용예 // 객체를동적으로생성한다. CRuntimeClass* pruntimeclass = RUNTIME_CLASS(CMyClass); CObject* pobject = pruntimeclass->createobject(); // 객체를성공적으로생성했는지여부를확인한다. ASSERT(pObject->IsKindOf(RUNTIME >IsKindOf(RUNTIME_CLASS(CMyClass))); 12
직렬화 (1/2) 직렬화기능추가 // MyClass.h class CMyClass : public CObject DECLARE_SERIAL(CMyClass) public: }; CMyClass(); virtual void Serialize (CArchive& ar);... 13
직렬화 (2/2) 직렬화기능추가 (cont d) // MyClass.cpp #include "MyClass.h" IMPLEMENT_SERIAL(CMyClass, CObject, 1) void CMyClass::Serialize (CArchive& ar) // CObject가제공하는가상함수인 Serialize() 함수를재정의한다. }... 14
3 단계매크로 단계매크로이름사용목적사용위치 1 DECLARE_DYNAMIC IMPLEMENT_DYNAMIC 실행시간클래스정보실행시간클래스정보 클래스선언부 (*.H) 클래스정의부 (*.CPP) 2 DECLARE_DYNCREATE IMPLEMENT_DYNCREATE 실행시간클래스정보, 동적객체생성실행시간클래스정보, 동적객체생성 클래스선언부 (*.H) 클래스정의부 (*.CPP) 3 DECLARE_SERIAL IMPLEMENT_SERIAL 실행시간클래스정보, 동적객체생성, 직렬화실행시간클래스정보, 동적객체생성, 직렬화 클래스선언부 (*.H) 클래스정의부 (*.CPP) 15
타당성점검 (1/2) 타당성점검기능추가 // MyClass.h class CMyClass : public CObject // 멤버변수 int m_start; int m_end; public: virtual void AssertValid( ) const;... }; 16
타당성점검 (2/2) 타당성점검기능추가 (cont d) // MyClass.cpp #include "MyClass.h" virtual void CMyClass::AssertValid( ) const CObject::AssertValid(); ASSERT(m_start > 0); ASSERT(m_end < 100); }... 17
집합클래스와의호환성 CObject 포인터를저장할수있는집합클래스 종류 클래스이름 배열 CObArray, CArray( 템플릿클래스 ) 리스트 CObList, CList( 템플릿클래스 ) 맵 CMapWordToOb, CMapStringToOb, CMap( 템플릿클래스 ) 18
MFC 전역함수 함수이름 기능 AfxMessageBox() 메시지상자를표시한다. AfxGetApp() 응용프로그램객체의주소를리턴한다. AfxGetMainWnd() 메인윈도우객체의주소를리턴한다. AfxGetAppName() 응용프로그램의이름을리턴한다. AfxGetInstanceHandle() 인스턴스핸들을리턴한다. AfxBeginThread() 스레드를시작한다. AfxEndThread() 스레드를종료한다. 19
AfxMessageBox() 사용예 void CMainFrame::OnLButtonDown(UINT nflags, CPoint point) AfxMessageBox(" 마우스를클릭했습니다."); } 20
사용예 AfxGetApp(), AfxGetMainWnd(), AfxGetAppName() void CMainFrame::OnLButtonDown(UINT nflags, CPoint point) TRACE(" 응용프로그램객체의주소 : %p = %p\n", AfxGetApp(), &theapp); TRACE(" 프레임윈도우객체의주소 : %p = %p\n", AfxGetMainWnd(), theapp.m_pmainwnd); TRACE(" 응용프로그램이름 :%s\n", AfxGetAppName()); } 21
AfxGetInstanceHandle() 사용예 void CMainFrame::OnLButtonDown(UINT nflags, CPoint point) // 인스턴스핸들값은실행파일이로드된가상메모리의 // 주소를나타낸다. TRACE(" 실행파일이로드된가상메모리의주소 : %p\n", AfxGetInstanceHandle()); } 22
MFC 응용프로그램구조 (1/2) 프레임윈도우 (= 메인윈도우 ) + 뷰 23
MFC 응용프로그램구조 (2/2) 일반적인 MFC 프로그램구성요소 24
AppWizard 를이용한 MFC 응용프로그램생성 (1/7) 프로젝트종류선택 25
AppWizard 를이용한 MFC 응용프로그램생성 (2/7) AppWizard 1 단계 26
AppWizard 를이용한 MFC 응용프로그램생성 (3/7) AppWizard 2 단계 27
AppWizard 를이용한 MFC 응용프로그램생성 (4/7) AppWizard 3 단계 28
AppWizard 를이용한 MFC 응용프로그램생성 (5/7) AppWizard 4 단계 29
AppWizard 를이용한 MFC 응용프로그램생성 (6/7) AppWizard 5 단계 30
코드추가 AppWizard 를이용한 MFC 응용프로그램생성 (7/7) 31
주요클래스 32
응용프로그램클래스 (1/4) // Simple.h class CSimpleApp : public CWinApp public: CSimpleApp(); virtual BOOL InitInstance(); afx_msg void OnAppAbout(); DECLARE_MESSAGE_MAP() }; 33
응용프로그램클래스 (2/4) // Simple.cpp BEGIN_MESSAGE_MAP(CSimpleApp, CWinApp) ON_COMMAND(ID_APP_ABOUT, APP ABOUT OnAppAbout) Ab END_MESSAGE_MAP() CSimpleApp::CSimpleApp() } CSimpleApp theapp; 34
응용프로그램클래스 (3/4) BOOL CSimpleApp::InitInstance() SetRegistryKey(_T( T("Local AppWizard-Generated Applications")); CMainFrame* pframe = new CMainFrame; m_pmainwnd = pframe; pframe->loadframe(idr_mainframe, WS_OVERLAPPEDWINDOW FWS_ADDTOTITLE, NULL, NULL); pframe->showwindow(sw >ShowWindow(SW_SHOW); SHOW); pframe->updatewindow(); } return TRUE; 35
응용프로그램클래스 (4/4) // 대화상자관련클래스선언및정의부분 - 생략 //... void CSimpleApp::OnAppAbout() CAboutDlg aboutdlg; aboutdlg.domodal(); } 36
프레임윈도우클래스 (1/5) // MainFrm.h class CMainFrame : public CFrameWnd public: CMainFrame(); protected: DECLARE_DYNAMIC(CMainFrame) DYNAMIC(CMainFrame) public: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); virtual BOOL OnCmdMsg(UINT nid, int ncode, void* pextra, AFX_CMDHANDLERINFO* phandlerinfo); virtual ~CMainFrame(); CChildView m_wndview; protected: afx_msg int OnCreate(LPCREATESTRUCT lpcreatestruct); afx_msg void OnSetFocus(CWnd *poldwnd); DECLARE_MESSAGE_MAP() MAP() }; 37
프레임윈도우클래스 (2/5) // MainFrm.cpp IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd) BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_CREATE() ON_WM_SETFOCUS() END_MESSAGE_MAP() CMainFrame::CMainFrame() } CMainFrame::~CMainFrame() } 38
프레임윈도우클래스 (3/5) int CMainFrame::OnCreate(LPCREATESTRUCT lpcreatestruct) if (CFrameWnd::OnCreate(lpCreateStruct) C (l C t t) == -1) return -1; if (!m_wndview.create(null, NULL, AFX_WS_DEFAULT_VIEW, CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL)) TRACE0("Failed to create view window\n"); return -1; } } return 0; 39
프레임윈도우클래스 (4/5) BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) if(!cframewnd::precreatewindow(cs) C Wi d ) return FALSE; cs.dwexstyle &= ~WS_EX_CLIENTEDGE; cs.lpszclass = AfxRegisterWndClass(0); return TRUE; } void CMainFrame::OnSetFocus(CWnd* poldwnd) m_wndview.setfocus(); } 40
프레임윈도우클래스 (5/5) BOOL CMainFrame::OnCmdMsg(UINT nid, int ncode, void* pextra, AFX_CMDHANDLERINFO* phandlerinfo) if (m_wndview.oncmdmsg(nid, ncode, pextra, phandlerinfo)) return TRUE; } return CFrameWnd::OnCmdMsg(nID, ncode, pextra, phandlerinfo); 41
뷰클래스 (1/4) // ChildView.h class CChildView : public CWnd public: CChildView(); protected: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); public: virtual ~CChildView(); protected: afx_msg void OnPaint(); DECLARE_MESSAGE_MAP() }; 42
뷰클래스 (2/4) // ChildView.cpp CChildView::CChildView() } CChildView::~CChildView() } BEGIN_MESSAGE_MAP(CChildView,CWnd ) ON_WM_PAINT() END_MESSAGE_MAP() 43
뷰클래스 (3/4) BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) if (!CWnd::PreCreateWindow(cs)) C Wi d ( return FALSE; cs.dwexstyle = WS_EX_CLIENTEDGE; cs.style &= ~WS_BORDER; cs.lpszclass = AfxRegisterWndClass ( CS_HREDRAW CS_VREDRAW CS_DBLCLKS, ::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL); } return TRUE; 44
뷰클래스 (4/4) void CChildView::OnPaint() CPaintDC dc(this); dc.textout(100, 100, CString(" 안녕하세요.")); } 45
요약 클래스종류 베이스클래스이름 핵심함수 - 주역할 응용프로그램 InitInstance() - 프레임윈도우를생성한다. CWinApp 클래스 Run() - 메시지루프를제공한다. 프레임윈도우 CFrameWnd OnCreate() - 뷰를생성한다. 클래스 뷰클래스 CWnd OnPaint() - 화면에출력한다. 46