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 2.0 도큐먼트/뷰 구조 도입으로 MFC의 기본 골격 완성 DDX/DDV, 사용자 인터페이스 관련 클래스 추가 정적/동적 MFC 라이브러리 지원 비주얼 C++ 1.5 2.5x OLE 2.01 지원 ODBC 클래스 추가 1994 비주얼 C++ 2.x 3.x 32비트 윈도우 API로 전환 멀티스레드 지원 윈속(Winsock), MAPI 지원
MFC 발전 과정 (2/2) 연도 개발 도구 MFC 버전 주요 특징 1995 비주얼 C++ 4.x 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 서버 클래스 추가
MFC 주요 특징 (1/3) 윈도우 응용 프로그램을 작성하는데 드는 수고를 크게 덜어준다. 라이브러리 재사용 AppWizard, ClassWizard, ... API를 기반으로 한 SDK 프로그램과 대등한 속도를 가진다. 인라인 함수 코드 크기 증가를 최소화한다. MFC DLL
MFC 주요 특징 (2/3) API 함수를 직접 호출할 수 있다. (예) ::ReleaseCapture(); C 언어로 작성된 윈도우 응용 프로그램을 쉽게 C++ 언어로 바꿀 수 있다. SDK 프로그래밍에 대한 기반 지식을 재활용할 수 있다. C++ 언어를 이용하여 기존의 C 언어에 비해 API를 좀더 편하게 사용할 수 있다. (예) 디폴트 인자
MFC 주요 특징 (3/3) API를 직접 사용해서 구현할 경우 복잡도가 높은 부분을 MFC를 이용하면 쉽게 구현할 수 있다. 인쇄 기능 지원, 툴바와 상태바 처리, 데이터베이스 지원, OLE와 액티브X, ...
MFC 구성 요소 (1/2) 구성 요소 CObject 파생 클래스: 188개 MFC 클래스 나머지: 40개 매크로와 전역 변수 및 전역 함수
MFC 구성 요소 (2/2) 클래스 계층도
CObject 클래스 CObject 서비스 서비스 이름 기능 실행 시간 클래스 정보 프로그램 실행 중 객체 정보를 알아낸다. 동적 객체 생성 객체를 동적으로 생성한다. 직렬화 객체를 저장하거나 읽어 들인다. 타당성 점검 객체 상태를 점검한다. 집합 클래스와의 호환성 서로 다른 클래스 객체를 집합 클래스에 저장할 수 있도록 한다.
실행 시간 클래스 정보 (1/2) 실행 시간 클래스 정보 기능 추가 // MyClass.h class CMyClass : public CObject { DECLARE_DYNAMIC(CMyClass) ... }; // MyClass.cpp #include "MyClass.h" IMPLEMENT_DYNAMIC(CMyClass, CObject)
실행 시간 클래스 정보 (2/2) 실행 시간 클래스 정보 사용 예 BOOL IsMyClass(CObject *pObj) { // pObj가 가리키는 객체가 CMyClass 타입인지 확인한다. if(pObj->IsKindOf(RUNTIME_CLASS(CMyClass)){ ... } else{
동적 객체 생성 (1/2) 동적 객체 생성 기능 추가 // MyClass.h class CMyClass : public CObject { DECLARE_DYNCREATE(CMyClass) public: CMyClass(); ... }; // MyClass.cpp #include "MyClass.h" IMPLEMENT_DYNCREATE(CMyClass, CObject)
동적 객체 생성 (2/2) 동적 객체 생성 사용 예 // 객체를 동적으로 생성한다. CRuntimeClass* pRuntimeClass = RUNTIME_CLASS(CMyClass); CObject* pObject = pRuntimeClass->CreateObject(); // 객체를 성공적으로 생성했는지 여부를 확인한다. ASSERT(pObject->IsKindOf(RUNTIME_CLASS(CMyClass)));
직렬화 (1/2) 직렬화 기능 추가 // MyClass.h class CMyClass : public CObject { DECLARE_SERIAL(CMyClass) public: CMyClass(); virtual void Serialize (CArchive& ar); ... };
직렬화 (2/2) 직렬화 기능 추가 (cont’d) // MyClass.cpp #include "MyClass.h" IMPLEMENT_SERIAL(CMyClass, CObject, 1) void CMyClass::Serialize (CArchive& ar) { // CObject가 제공하는 가상 함수인 Serialize() 함수를 재정의한다. } ...
3단계 매크로 단계 매크로 이름 사용 목적 사용 위치 1 DECLARE_DYNAMIC 실행 시간 클래스 정보 클래스 선언부 (*.H) IMPLEMENT_DYNAMIC 클래스 정의부 (*.CPP) 2 DECLARE_DYNCREATE 실행 시간 클래스 정보, 동적 객체 생성 IMPLEMENT_DYNCREATE 3 DECLARE_SERIAL 동적 객체 생성, 직렬화 IMPLEMENT_SERIAL
타당성 점검 (1/2) 타당성 점검 기능 추가 // MyClass.h class CMyClass : public CObject { // 멤버 변수 int m_start; int m_end; public: virtual void AssertValid( ) const; ... };
타당성 점검 (2/2) 타당성 점검 기능 추가 (cont’d) // MyClass.cpp #include "MyClass.h" virtual void CMyClass::AssertValid( ) const { CObject::AssertValid(); ASSERT(m_start > 0); ASSERT(m_end < 100); } ...
집합 클래스와의 호환성 CObject 포인터를 저장할 수 있는 집합 클래스 종류 클래스 이름 배열 CObArray, CArray(템플릿 클래스) 리스트 CObList, CList(템플릿 클래스) 맵 CMapWordToOb, CMapStringToOb, CMap(템플릿 클래스)
MFC 전역 함수 함수 이름 기능 AfxMessageBox() 메시지 상자를 표시한다. AfxGetApp() 응용 프로그램 객체의 주소를 리턴한다. AfxGetMainWnd() 메인 윈도우 객체의 주소를 리턴한다. AfxGetAppName() 응용 프로그램의 이름을 리턴한다. AfxGetInstanceHandle() 인스턴스 핸들을 리턴한다. AfxBeginThread() 스레드를 시작한다. AfxEndThread() 스레드를 종료한다.
AfxMessageBox() 사용 예 void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point) { AfxMessageBox("마우스를 클릭했습니다."); }
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()); }
AfxGetInstanceHandle() 사용 예 void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point) { // 인스턴스 핸들값은 실행 파일이 로드된 가상 메모리의 // 주소를 나타낸다. TRACE("실행 파일이 로드된 가상 메모리의 주소: %p\n", AfxGetInstanceHandle()); }
MFC 응용 프로그램 구조 (1/2) 프레임 윈도우(=메인 윈도우) + 뷰
MFC 응용 프로그램 구조 (2/2) 일반적인 MFC 프로그램 구성 요소
AppWizard를 이용한 MFC 응용 프로그램 생성 (1/8) 프로젝트 종류 선택
AppWizard를 이용한 MFC 응용 프로그램 생성 (2/8)
AppWizard를 이용한 MFC 응용 프로그램 생성 (3/8)
AppWizard를 이용한 MFC 응용 프로그램 생성 (4/8)
AppWizard를 이용한 MFC 응용 프로그램 생성 (5/8)
AppWizard를 이용한 MFC 응용 프로그램 생성 (6/8)
AppWizard를 이용한 MFC 응용 프로그램 생성 (7/8)
AppWizard를 이용한 MFC 응용 프로그램 생성 (8/8) 코드 추가
주요 클래스
응용 프로그램 클래스 (1/4) // Simple.h class CSimpleApp : public CWinApp { virtual BOOL InitInstance(); afx_msg void OnAppAbout(); DECLARE_MESSAGE_MAP() };
응용 프로그램 클래스 (2/4) // Simple.cpp BEGIN_MESSAGE_MAP(CSimpleApp, CWinApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) END_MESSAGE_MAP() CSimpleApp::CSimpleApp() { } CSimpleApp theApp;
응용 프로그램 클래스 (3/4) BOOL CSimpleApp::InitInstance() { SetRegistryKey(_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_SHOW); pFrame->UpdateWindow(); return TRUE; }
응용 프로그램 클래스 (4/4) // 대화상자 관련 클래스 선언 및 정의 부분 - 생략 // ... void CSimpleApp::OnAppAbout() { CAboutDlg aboutDlg; aboutDlg.DoModal(); }
프레임 윈도우 클래스 (1/5) // MainFrm.h class CMainFrame : public CFrameWnd { protected: DECLARE_DYNAMIC(CMainFrame) virtual BOOL PreCreateWindow(CREATESTRUCT& cs); virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); virtual ~CMainFrame(); CChildView m_wndView; afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnSetFocus(CWnd *pOldWnd); DECLARE_MESSAGE_MAP() };
프레임 윈도우 클래스 (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()
프레임 윈도우 클래스 (3/5) int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -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 0;
프레임 윈도우 클래스 (4/5) BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; cs.dwExStyle &= ~WS_EX_CLIENTEDGE; cs.lpszClass = AfxRegisterWndClass(0); return TRUE; } void CMainFrame::OnSetFocus(CWnd* pOldWnd) m_wndView.SetFocus();
프레임 윈도우 클래스 (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); }
뷰 클래스 (1/4) // ChildView.h class CChildView : public CWnd { public: protected: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); virtual ~CChildView(); afx_msg void OnPaint(); DECLARE_MESSAGE_MAP() };
뷰 클래스 (2/4) // ChildView.cpp CChildView::CChildView() { } BEGIN_MESSAGE_MAP(CChildView,CWnd ) ON_WM_PAINT() END_MESSAGE_MAP()
뷰 클래스 (3/4) BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) { if (!CWnd::PreCreateWindow(cs)) 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; }
뷰 클래스 (4/4) void CChildView::OnPaint() { CPaintDC dc(this); dc.TextOut(100, 100, CString("안녕하세요.")); }
요약 클래스 종류 베이스 클래스 이름 핵심 함수 - 주 역할 응용 프로그램 CWinApp InitInstance() - 프레임 윈도우를 생성한다. Run() - 메시지 루프를 제공한다. 프레임 윈도우 CFrameWnd OnCreate() - 뷰를 생성한다. 뷰 CWnd OnPaint() - 화면에 출력한다.