Overview MFC 프로그램구조 HCI Programming 2 (321190) 2008년가을학기 9/30/2008 박경신 MFC 개요 MFC 발전과정과주요특징이해 MFC 구조 MFC 구성요소, 클래스계층도, 주요클래스 MFC 최상위클래스인 CObject 가제공하는서비스이해 MFC 가제공하는전역함수사용법 MFC 응용프로그램구조 MFC Application Framework Class AppWizard 를이용한 MFC 프로그래밍 AppWizard 에의해생성된객체 AppWizard 가자동으로생성하는코드의구조이해 2 MFC 발전과정 MFC 발전과정 MFC - 윈도우프로그램작성에유용한클래스의집합체 연도 개발도구 MFC 버전 주요특징 1992 MS C 7.0 1.0 16비트윈도우 API를클래스화 OLE 1.0 지원 1993 비주얼 C++ 1.0 2.0 도큐먼트 / 뷰구조도입으로 MFC의기본골격완성 DDX/DDV, 사용자인터페이스관련클래스추가 정적 / 동적 MFC 라이브러리지원 1993 비주얼 C++ 1.5 2.5x OLE 2.01 지원 ODBC 클래스추가 1994 비주얼 C++ 2.x 3.x 32비트윈도우 API로전환 멀티스레드지원 윈속 (Winsock), MAPI 지원 3 연도 개발도구 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 서버클래스추가 2005 비주얼 C++ 2005 8.0 MFC Windows Forms 지원 4
MFC 주요특징 생산성향상 윈도우응용프로그램을작성하는데드는수고를크게덜어줌 라이브러리재사용 비주얼 C++ 에서제공하는 AppWizard, ClassWizard 같은자동화된코드생성도구를사용하여코딩시간을단축 운영체제의확장된기술과연관된편리한클래스제공 - 인쇄기능, OLE, ActiveX, 등 사용자인터페이스지원 - 메뉴, 툴바, 상태바등 네트워크, 데이터베이스관련기술지원 안정성 강한타입체크, 예외처리, 동적메모리할당과해지 MFC 주요특징 코드크기최소화 MFC 가제공하는코드는 DLL 형태로사용할수있으므로실행파일의크기가증가하는것을막을수있음 API 함수사용 API 함수를직접호출가능 예, ::ReleaseCapture();. C++ 언어를이용하여기존의 C 언어에비해 API 를좀더편하게사용가능 - 오버로딩 (overloading) 과디폴트인자 (default argument) 등을이용하여간편화 SDK 프로그래밍에대한기반지식을재활용 5 6 MFC 구성요소 MFC 클래스계층도 구성요소 MFC 클래스 CObject 파생클래스 : 188 개 나머지 : 40 개 ( MFC 6.0 기준 ) 매크로와전역변수및전역함수 7 8 MFC VS2005 http://msdn2.microsoft.com/en-us/library/ws8s10w4(vs.80).aspx
MFC 주요클래스 CObject 기반클래스 대부분 MFC 클래스가 CObject 클래스로부터상속됨 실행시간클래스정보추출, 동적객체생성, 직렬화, 객체상태검사, 집합클래스간호환성등을지원 Application Framework Class (AFX) 응용프로그램의기본구조를위한클래스 CWinApp 응용프로그램을표현하는클래스 인스턴스를초기화하고, 메시지루프를설정 CFrameWnd 윈도우의프레임을관리 윈도우이동, 크기조절등 CView 윈도우의클라이언트영역을관리하는클래스 데이터를보여주는기능 CDocument 다루는데이터구조, 파일을관리 9 MFC 주요클래스 Window 구성요소관련클래스 윈도우, 다이얼로그박스, 콘트롤등제공 CWnd, CDialog, CEdit, CListBox, 그리기와페인팅관련클래스 디바이스컨텍스트와 GDI 객체등을제공 CDC, CPaintDC, CGdiObject, CBitmap, CBrush, CFont, CPalette, CPen, CRgn.. 자료형, 자료구조클래스 CPoint, CRect, CSize, CString, CTime, CArray, CList, CMap, 파일및데이터베이스관련클래스 CFile, CDatabase, CRecordset, CRecordView, 네트워크 ( 인터넷 ) 관련클래스 CHttpServer, CSocket, CInternetConnection, CHttpConnection 10 MFC 주요클래스 OLE 관련클래스 Object Linking and Embedding 예외처리및디버깅관련클래스 CObject::Dump, CException, CMemoryState CObject 클래스 CObject 서비스 -<afx.h> 서비스이름 실행시간클래스정보 기능 프로그램실행중객체정보 ( 클래스타입, 크기등 ) 를알아낸다. 동적객체생성객체를동적으로생성한다. 직렬화객체를저장하거나읽어들인다. 타당성점검객체상태를점검한다. 집합클래스와의호환성 서로다른클래스객체를집합클래스에저장할수있도록한다. 11 12
실행시간클래스정보 실행시간클래스정보 (RTCI, Run-Time Class Information) 기능추가를위한매크로포함 실행시간클래스정보 실행시간클래스정보사용예 // MyClass.h class CMyClass : public CObject DECLARE_DYNAMIC(CMyClass) ; // MyClass.cpp #include "MyClass.h" IMPLEMENT_DYNAMIC(CMyClass, CObject) 13 BOOL IsMyClass(CObject *pobj) // pobj 가가리키는객체가 CMyClass 타입인지확인한다. if(pobj->iskindof(runtime_class(cmyclass)) else 14 동적객체생성 동적객체생성 동적객체생성 (Dynamic Object Creation) 기능추가를위한매크로포함 // MyClass.h class CMyClass : public CObject DECLARE_DYNCREATE(CMyClass) public: CMyClass(); ; 동적객체생성사용예 // 객체를동적으로생성한다. CRuntimeClass* pruntimeclass = RUNTIME_CLASS(CMyClass); CObject* pobject = pruntimeclass->createobject(); // 객체를성공적으로생성했는지여부를확인한다. ASSERT(pObject->IsKindOf(RUNTIME_CLASS(CMyClass))); // MyClass.cpp #include "MyClass.h" IMPLEMENT_DYNCREATE(CMyClass, CObject) 15 16
직렬화 직렬화 (Serialization) 기능추가를위한매크로포함 직렬화 CObject 의직렬화가상함수재정의 // MyClass.h class CMyClass : public CObject DECLARE_SERIAL(CMyClass) public: CMyClass(); virtual void Serialize (CArchive& ar); ; // 가상함수를재정의 // MyClass.cpp #include "MyClass.h" IMPLEMENT_SERIAL(CMyClass, CObject, 1) void CMyClass::Serialize (CArchive& ar) // CObject 가제공하는가상함수인 Serialize() 함수를재정의한다. 17 18 3 단계매크로기능정리 타당성점검 단계매크로이름사용목적사용위치 1 2 3 DECLARE_DYNAMIC IMPLEMENT_DYNAMIC DECLARE_DYNCREATE IMPLEMENT_DYNCREATE DECLARE_SERIAL IMPLEMENT_SERIAL 실행시간클래스정보 실행시간클래스정보 실행시간클래스정보, 동적객체생성 실행시간클래스정보, 동적객체생성 실행시간클래스정보, 동적객체생성, 직렬화 실행시간클래스정보, 동적객체생성, 직렬화 클래스선언부 (*.H) 클래스정의부 (*.CPP) 클래스선언부 (*.H) 클래스정의부 (*.CPP) 클래스선언부 (*.H) 클래스정의부 (*.CPP) 19 객체의내부상태를확인하기위한 AssertValid() 함수재정의 // MyClass.h class CMyClass : public CObject // 멤버변수 int m_start; int m_end; public: virtual void AssertValid( ) const; ; 20
타당성점검 타당성점검기능추가 집합클래스와의호환성 CObject 포인터를저장할수있는집합클래스 // MyClass.cpp #include "MyClass.h" virtual void CMyClass::AssertValid( ) const CObject::AssertValid(); ASSERT(m_start > 0); // m_start 값이 0보다큰값인지를검증 ASSERT(m_end < 100); 종류 클래스이름 배열 CObArray, CArray( 템플릿클래스 ) 리스트 CObList, CList( 템플릿클래스 ) 맵 CMapWordToOb, CMapStringToOb, CMap( 템플릿클래스 ) 21 22 MFC 전역함수 함수이름 기능 AfxMessageBox() 메시지상자를표시한다. AfxGetApp() 응용프로그램객체의주소를리턴한다. AfxMessageBox() 사용예 void CMainFrame::OnLButtonDown(UINT nflags, CPoint point) AfxMessageBox(" 마우스를클릭했습니다."); AfxGetMainWnd() 메인윈도우객체의주소를리턴한다. AfxGetAppName() 응용프로그램의이름을리턴한다. AfxGetInstanceHandle() 인스턴스핸들을리턴한다. AfxBeginThread() 스레드를시작한다. AfxEndThread() 스레드를종료한다. 23 24
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()); 25 26 MFC 응용프로그램구조 Application Framework Class (AFX) CWndApp 클래스 CWnd 클래스 (CFrameWnd, CView) CDocument 클래스 AppWizard 를이용한 MFC 프로그래밍 AppWizard 에의해생성된객체 Message Handler MFC 응용프로그램구조 일반적인 MFC 프로그램구성요소 27 28
MFC 응용프로그램의구조 (AFX) CFrameWnd CView CDocument Application Framework 프레임윈도우와뷰를분리한이유 프레임에부여된역할 ( 창의크기조절, 확대, 축소등 ) 을기본적으로제공 뷰에서는실제보여주어야할데이터만을적절하게처리하여제공 도큐먼트와뷰를분리한이유 데이터저장및처리 (CDocument) 와이를보여주는 (CView) 을분리하여클래스의역할을분리하여클래스를단순화 하나의데이터 (Document) 로여러개의뷰 (View) 형태를제공 윈도우의프레임 ( 틀 ) 을관리데이터를보여주는윈도우데이터를저장, 처리 CWinApp : 응용프로그램관리, 프로그램구동 29 30 SDI (Single Document Interface) AFX Class 계층구조 CObject CCmdTarget MFC 클래스의기반클래스 메시지맵구조지원,WM_COMMAND 메시지처리 CWinApp CDocument 프로그램구동 데이터구조, 파일관리 Template CWnd 화면에보여지는윈도우관리기능 CFrameWnd CView 프로그램윈도우프레임 ( 외곽 ) 을관리 ( 타이틀바, 메뉴, 상태바, 툴바등을관리 ) 데이터를보여주는윈도우관리하는기능 31 32
CWinApp 클래스 CWinApp Class 역할 프로그램전체를대표하는기능 프로그램의시작과종료를담당 프로그램이시작될때, 메인프레임윈도우를생성시킴 메시지루프 응용프로그램실행단계 theapp 라는 CWinApp 의인스턴스가전역변수로선언됨으로써실행됨 WinMain 에서 CWinApp 의함수를순서대로호출하면서실행 CWinApp 멤버함수재정의 새로운 MFC 응용프로그램을생성하면, CWinApp 를상속받는클래스가생성되며, 필요시관련함수재정의 CWinApp 프로그램시작 InitInstance() Run() CWinApp 프로그램시작 InitInstance() Run() 상속 CMyApp 초기화 / 종료화과정을프로그램할필요가있을경우 InitInstance() ExitInstance() ExitInstance() ExitInstance() 33 프로그램종료 프로그램종료 34 CWnd 클래스 프레임창, 대화상자, 자식창, 컨트롤및도구모음과같은컨트롤막대등의모든창에대한 Base class 멤버함수 윈도우관리에필요한 Windows API 를캡슐화 윈도우의크기, 위치, 모양, 상태등을제어하기위한함수 윈도우에서발생하는메시지를처리하기위한함수 ( 메시지핸들러 ) 하위클래스에서구체적으로이용 CFrameWnd 윈도우의스타일관리 ( 크기, 위치,..) 메뉴, 툴바, 상태바, 뷰생성및관리 CView 프로그램에서다루는데이터를화면에출력 클라이언트영역에서발생되는마우스, 키보드메시지처리를위한메시지핸들러오버라이딩 CWnd & HWND CWnd 개체는 C++ 윈도우 ( 창 ) 개체이면서 Windows 윈도우 ( 창 ) 를나타냄 CWnd 생성자 : C++ 윈도우개체를할당하고초기화 Create 멤버함수 : Windows 윈도우생성 HWND는 Windows 윈도우의핸들 HWND 인수를사용하는대부분의 Windows 윈도우관리 API는 CWnd의멤버함수로캡슐화 35 36
CWnd 하위클래스 CDocument 클래스 CWnd CFrameWnd CControlBar CPropertySheet CDialog CView Control class 프레임형태의윈도우컨트롤바프로퍼티시트대화상자 View 윈도우컨트롤 ( 버튼, 에디트, 리스트박스등 ) 프로그램에서사용되는데이터를저장하고, 읽고, 처리하기위한모든기능을수행 파일로부터데이터를읽어오는기능 ( 파일 메뉴의 열기 기능 ) 파일로부터데이터를저장하는기능 ( 파일 메뉴의 저장 기능 ) 새로운파일생성기능 ( 파일 메뉴의 새로만들기 기능 ) 작업중인파일닫기기능 ( 파일 메뉴의 닫기 기능 ) 변경된데이터를뷰객체에알려주는기능등 37 38 AppWizard 를이용한 MFC 응용프로그램생성 AppWizard 시작 - 프로젝트종류선택 AppWizard 를이용한 MFC 응용프로그램생성 AppWizard 39 40
AppWizard 를이용한 MFC 응용프로그램생성 AppWizard SDI, Use MFC in a Shared DLL, 한국어선택 AppWizard 를이용한 MFC 응용프로그램생성 AppWizard 데이터베이스 41 42 AppWizard 를이용한 MFC 응용프로그램생성 AppWizard 사용자인터페이스 AppWizard 를이용한 MFC 응용프로그램생성 AppWizard ActiveX 를선택해제 43 44
AppWizard 를이용한 MFC 응용프로그램생성 AppWizard Generated Classes AppWizard 를이용한 MFC 응용프로그램생성 코드추가 45 46 주요클래스 응용프로그램클래스 // Simple.h class CSimpleApp : public CWinApp public: CSimpleApp(); virtual BOOL InitInstance(); afx_msg void OnAppAbout(); DECLARE_MESSAGE_MAP() ; 47 48
응용프로그램클래스 응용프로그램클래스 // Simple.cpp BEGIN_MESSAGE_MAP(CSimpleApp, CWinApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) END_MESSAGE_MAP() CSimpleApp::CSimpleApp() CSimpleApp theapp; 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(); 49 return TRUE; 50 응용프로그램클래스 프레임윈도우클래스 // 대화상자 (CAboutDlg) 관련클래스선언및정의부분 - 생략 // void CSimpleApp::OnAppAbout() CAboutDlg aboutdlg; aboutdlg.domodal(); 51 // MainFrm.h class CMainFrame : public CFrameWnd public: CMainFrame(); protected: DECLARE_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() ; 52
프레임윈도우클래스 프레임윈도우클래스 // MainFrm.cpp IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd) BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_CREATE() ON_WM_SETFOCUS() END_MESSAGE_MAP() CMainFrame::CMainFrame() CMainFrame::~CMainFrame() 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 -1;.. return 0; 53 54 프레임윈도우클래스 프레임윈도우클래스 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(); // 뷰창으로포커스를이동 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); 55 56
뷰클래스 뷰클래스 // 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() ; // ChildView.cpp CChildView::CChildView() CChildView::~CChildView() BEGIN_MESSAGE_MAP(CChildView,CWnd ) ON_WM_PAINT() END_MESSAGE_MAP() 57 58 뷰클래스 뷰클래스 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); void CChildView::OnPaint() CPaintDC dc(this); dc.textout(100, 100, CString(" 안녕하세요.")); return TRUE; 59 60
요약 MFC 응용프로그램실행단계 클래스종류 응용프로그램클래스 (CSimpleApp) Simple.cpp, Simple.h 프레임윈도우클래스 (CMainFrame) MainFrm.cpp, MainFrm.h 뷰클래스 (CChildView) ChildView.cpp, ChildView.h 베이스클래스이름 CWinApp CFrameWnd CWnd 핵심함수 - 주역할 InitInstance() - 프레임윈도우생성 Run() - 메시지루프제공 OnCreate() - 뷰생성 OnPaint() - 화면출력 OnPaint() 에서 OnDraw() 호출구조 어플리케이션시작 CMyApp::InitInstance() CWinApp::Run() 프로그램이시작되면윈도우 OS 는프레임워크내부에있는 WinMain( ) 함수를호출. CWinApp 로부터파생된클래스의어플리케이션전역객체 (theapp) 를찾음. WinMain() 함수가어플리케이션전역객체 (theapp) 를찾은후호출되는가상함수로반드시재정의하여사용. 메인프레임윈도우를구성하고출력하는데필요한함수호출 CWinApp 의 Run( ) 에서메시지를해당윈도우로전달하는메시지루프를수행. 이함수는 InitInstance( ) 호출후에호출됨 61 62 CMyView::OnPaint WM_PAINT 메시지를처리하는메시지핸들러. 어플리케이션종료 사용자가시스템메뉴의 [ 닫기 ] 를선택하면 CMyFrame 객체가소멸되고 Run() 의메시지루프를빠져나와 WinMain() 를끝내고 CMyApp 객체 (theapp) 가소멸 63