@ 윈도우 응용 프로그램의 특징
1. GUI
2. 메시지 구동 방식
- 프로그램 제어를 OS와 분담하여 처리
- OS : 이벤트 감지후 해당 프로그램에 message 전달
- Event-Driven 방식 ( event : 사용자의 물리적 조작에 의해 발생)
이벤트 발생 -> 운영체제 감지 -> 메시지 전달
* 이벤트가 발생하면 운영체제가 이를 감지해 시스템 메시지 대기열에 들어간뒤
해당하는 응용 프로그램 메시지 대기열로 dispatch되서 처리된다.
* 메시지 전달
- 부가정보 포함 : 이벤트가 일어난 프로그램등
- 구조체로 정의됨
* 프로그래머는 초기화와 이벤트 핸들링만 해주면 된다. (나머지는 자동으로 됨)
|
< Message Driven Architecture (메시지 구동구조) >
- SDI (single document interface) (ex) 메모장, 익스플로어
- MDI (multiple document interface) (ex) 엑셀, 비쥬얼
- Dialog Based (ex) 계산기, 지뢰찾기 형태
헝거리언 표기법
대, 소문자를 혼용하여 변수의 의미와 데이터 타입을 알 수 있도록 표기.
접두어(Prefix) |
데이터 타입 |
접두어(Prefix) |
데이터 타입 |
a u clr |
배열(Array) unsigned int COLORREF |
i
str |
인덱스(Index) CString형 변수 |
메시지나 스타일 등을 나타내는 매크로 상수들은 접두어를 이용하여 의미전달을 한다.
[메시지(Message)]
접두어(Prefix) |
의미 |
BM_ CB_ DM_ EM_ LB_ WM_ |
버튼 메시지 |
[스타일(Style)]
접두어(Prefix) |
의미 |
BS_ |
버튼 스타일 |
데이터 타입을 요약하면 다음과 같습니다.
데이터 타입 |
의미 |
데이터 타입 |
의미 |
BOOL LONGLONG ULONGLONG TCHAR WORD
CPoint
CSize
|
논리형(TRUE, FALSE) 64비트 부호 있는 정수 64비트 부호 없는 정수 유니코드 또는 윈도우 문자 16비트
2차원 좌표 계의 점 멤버변수(x,y) 가로와 세로 길이 멤버변수(cx, cy) |
HFONT LPCSTR LPTSTR LPCTSTR UINT
CRect
CString POSITION |
폰트에 대한 핸들 유니코드 또는 윈도우 문자열의 포인터 유니코드 또는 윈도우 문자열 상수의 포인터 메시지 처리에 대한 결과를 나타내
사각형의 좌측 상단과 우측 하단의 좌표 멤버(left, top, right, bottom) 문자열 저장 기능 리스트에 저장된 항목을 가리키는 포인터 |
2. MFC의 구성요소
1. CObject 클래스로부터 상속 받은 클래스
대다수의 클래스들은 CObject 클래스로부터 상속을 받습니다.
따라서 이러한 클래스들은 CObject *로 전부 주소를 대입할 수 있습니다.
2. CObject 클래스로부터 상속 받지 않은 클래스
이러한 클래스들은 특별한 기능을 하는 클래스인 경우가 많습니다.
3. 전역함수(Afx로 시작)와 매크로(함수의 옵션)
Ex) int AfxMessageBox(LPCTSTR lpszText, UINT nType = MB_OK, UINT nIDHelp = 0)
모든 클래스들에서 이용해야 하는 함수인 경우가 많으므로 중요합니다.
4. API 함수
MFC는 API 함수들을 비슷한 기능을 하는 함수들끼리 그룹별로 묶어서 클래스를 구현한 경우가 많으므로 이들 사이의 관계를 알아두고 활용할 수 있어야 합니다.
3. MFC의 클래스 계층도
4. MFC 프로젝트
MFC AppWizard를 이용한 프로젝트 생성 절차
[파일] – [새로 만들기] – [프로젝트] – Visual C++의 MFC 탭에서 [MFC 응용 프로그램]을 선택
프로젝트 명(TestMFC)
응용 프로그램 종류
Single Document(단일 문서): 프레임 윈도우가 하나 인 경우(SDI)
Multiple document(다중 문서): 프레임 윈도우가 여러 개 인 경우(MDI)
Dialog based(대화 상자 기반): 대화상자 프로그램
프로젝트스타일: 윈도우의 모양을 결정
탐색기 또는 표준 스타일
MFC 사용 – Dll을 포함해서 프로젝트를 생성할 것인지 여부
공유 DLL에서 MFC사용 – MFC로 시작하는 DLL파일이 설치되어 있어야 함
정적 라이브러리에서 MFC 사용 – DLL 파일이 없어도 실행되지만 프로그램의 부피가 커짐
Document/View architecture support(문서/뷰 아키텍쳐 지원)?
데이터부분과 뷰 부분을 분리하는 기능을 지원할 것인지를 설정
언어 선택과 유니코드 사용여부 선택
2단계: 복합 문서지원
없음 |
OLE를 지원하지 않는 어플리케이션을 생성 |
컨테이너 |
OLE를 컨테이너 어플리케이션을 생성 |
미니 서버 |
OLE복합문서를 생성하고 관리하는 OLE서버 어플리케이션을 생성. 단, 독립적으로 실행이 되지 않음 (컨테이너 프로그램 내에서만 수행) |
풀 서버 |
OLE복합문서를 생성하고 관리하는 OLE서버 어플리케이션을 생성. Mini-server와 달리 독립적으로 실행 |
컨테이너/풀 서버 |
OLE 컨테이너와 서버역할을 동시에 하는 어플리케이션을 생성. **ActiveX document server** |
Visual C++ MFC - chapter 1.MFC 시작
3단계
파일의 확장자를 설정할 수 있고 제목표시줄에 보이는 텍스트 설정
4단계
데이터베이스 설정 기능
5단계: 윈도우 프레임의 모양
6단계: 고급 기능 설정
7단계: 기본적인 클래스의 이름을 정의하고 View 클래스의 부모 클래스를 선택
TestMFC 프로젝트 작성 시 생성되는 파일
TestMFC.sln TestMFC.vcproj TestMFC.dsw TestMFC.dsp |
솔루션 파일 프로젝트파일 워크 스페이스파일(6.0) 프로젝트파일(6.0) |
TestMFC.h, TestMFC.cpp |
응용 프로그램 클래스가 정의되어 있습니다. |
MainFrm.h, MainFrm.cpp |
메인 프레임 클래스가 정의 되어 있습니다. |
TestMFCDoc.h, TestMFCDoc.cpp |
도큐먼트 클래스가 정의 되어 있습니다. |
TestMFCView.h, TestMFCView.cpp |
뷰 클래스가 정의 되어 있습니다. |
TestMFC.rc |
리소스 정의 파일 |
TestMFC.ncb |
클래스 위저드가 사용하는 정보파일 |
Readme.txt |
간단한 설명이 들어있습니다. |
StdAfx.h, StdAfx.cpp |
PCH 파일을 만드는데 사용됩니다. |
Visual C++ 은 컴파일 속도의 증가를 위해 미리 컴파일 된 헤더(PCH: PreCompiled Header) 라는 기법을 사용합니다.
C컴파일러는 컴파일 시간의 대부분을 헤더파일을 컴파일 하기 위해 소모하게 되는데 헤더파일은 내용을 직접 변경시키지 않는 경우가 많기 때문에 다시 컴파일을 하지 않아도 될 경우가 많습니다.
Visual C++ 은 헤더파일을 한 번만 컴파일 한 후 컴파일 결과를 PCH 파일에 저장해 두고 다음부터 컴파일 할 때는 헤더파일을 직접 컴파일 하지 않고 미리 컴파일 해 놓은 결과인 pch 파일만을 가지고 실행합니다.
PCH기법을 사용하기 위해 만들어진 파일이 StdAfx.h와 StdAfx.cpp 파일입니다.
5. MFC의 4대 클래스
1. CTestMFCApp: CWinApp로부터 상속됩니다.
- 3개 클래스(CMainFrame, CTestDoc, CTestView) 통합 관리하고 프로그램 전체를 대표하는 기능을 수행
- 프로그램의 시작과 끝을 담당.
- 프로그램이 시작할 때 메인 프레임을 만들어 줍니다.
- 사용자에 의한 이벤트에 따라 메시지를 발생시키고 메시지 정보를 처리함수(핸들러)로 보냅니다.
WM_QUIT 메시지가 올 때까지 계속 반복합니다.
응용 프로그램 클래스(Application Program Class)란 윈도우즈 프로그램 그 자체를 나타냅니다.
프로젝트의 메인 클래스입니다.
응용 프로그램 클래스는 보통 프로젝트 이름과 같은 이름의 파일에 저장되며 클래스 이름 뒤에는 App가 추가됩니다.
즉 TestMFC.vcproj 프로젝트에서 응용 프로그램 클래스는 TestMFC.h 파일에 선언되고 구현파일은 TestMFC.cpp가 되며, 응용 프로그램 클래스는 CTestMFCApp가 됩니다.
앞에 붙인 C는 클래스라는 뜻입니다.
소스에 포함된 주석 문은 프로그래머가 소스를 쉽게 파악할 수 있도록 하기 위해 AppWizard가 붙인 것입니다.
생성자 함수가 있을 것입니다.
InitInstance()는 프로그램을 초기화하는 루틴을 넣습니다.
이 함수의 시작 부분에
AfxMessageBox(TEXT("Hello MFC"));
이 코드를 지정하면 윈도우를 생성하기 전에 메시지 박스를 화면에 출력할 것입니다.
OnAppAbout 함수는 도움말 항목을 눌렀을 때 발생하는 메시지에 대한 처리 부분입니다.
MFC에서는 특정 메시지에 대한 처리를 함수를 생성해서 구현합니다.
일반적으로 함수 명은 메시지 이름 앞에 On을 붙여서 정의합니다.
CWinApp클래스의 주요 멤버
m_hInstance: 현재 응용 프로그램의 인스턴스 핸들
m_lpCmdLine: 프로그램을 실행하였을 때 명령 줄 정보
m_nCmdShow: 프로그램이 보여지는 모양
m_pActiveWnd: 최상위 프레임 윈도우에 대한 포인터로 일반적으로 CMainFrame에 대한 포인터 입니다.
m_pszAppName: 프로그램의 제목
m_pszExeName: 확장자를 제외한 실행 파일명
InitInstance(): 응용 프로그램이 초기화되는 시점에서 호출되는 함수
대부분 재 정의 되어있으며 직접 코드 수정 가능
Run(): 메시지 루프를 처리해주는 함수로 재정의 되어있지 않으며 수정할 수 없음
ExitInstance(): 응용 프로그램이 종료하는 시점에 호출
재정의 되어 있지 않으므로 직접 재정의 해서 사용해야 함
CMainFrame: MainFrm.h/ MainFrm.cpp
CFrameWnd 클래스로부터 상속됩니다.
메인 프레임 클래스는 MainFrm.h 파일에 정의되어 있으며 구현파일은 MainFrm.cpp입니다.
이 클래스는 프로젝트의 종류에 상관없이 거의 고정된 역할을 하므로 프로젝트 이름과 상관없이 이름이 고정되어 있습니다.
프로그램의 외형을 만드는 역할을 담당합니다.
OnCreate()함수가 이 부분을 담당합니다.
이 함수는 WM_CREATE 메시지에 의해 호출됩니다.
현재는 이 함수에 툴바와 상태 표시줄을 생성하는 코드가 작성되어 있습니다.
PreCreateWindow(CREATESTRUCT& cs)
이 함수는 윈도우를 생성하기 전에 수행되는 함수입니다.
이 함수의 매개 변수인 cs의 값을 변경하게 되면 처음 생성되는 윈도우의 위치나 크기 등을 변경할 수 있습니다.
실행 중 윈도우의 모양을 변경하고자 한다면 SetWindowPos 함수를 이용해야 합니다.
CTestMFCDoc: CDocument로부터 상속됨
- 프로그램의 데이터를 파일에 저장하고 읽기 위한 클래스
저장, 열기를 담당합니다.
이 클래스의 멤버함수인 onNewDocument()는 응용 프로그램이 실행되면 반드시 한번은 수행을 하게 됩니다
CTestMFCView: CView로부터 상속됨
- 사용자로부터의 입력을 처리하거나 작업의 결과를 화면에 출력하는 클래스
- 보여지는 부분을 담당.
CTestMFCView 클래스는 CView 클래스로부터 상속을 받습니다.
화면출력을 담당하는 클래스입니다.
또한 뷰 클래스는 프로그램 실행 중에 키보드나 마우스로부터의 입력을 처리하는 역할을 하고 있습니다.
화면의 중앙에 HelloWorld를 출력하는 프로그램 작성
HelloView.cpp
void CHelloView::OnDraw(CDC* pDC)
{
CHelloDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
RECT ClientRect;
GetClientRect(&ClientRect);
pDC->DrawText(TEXT("Hello MFC!"),-1, &ClientRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
6.0에서는 위의 소스만을 복사하면 되지만 2008에서는 매개변수인 pDC가 주석 처리 되어 있으므로 해제하고 사용해야 합니다.
MFC가 제공하는 Template에 소스 추가하는 방법
1. 이미 존재하는 기능의 수정 및 보강
이미 존재하는 기능을 수정하거나 보강한다는 것은 기본적으로 파생클래스에서 기반클래스의 멤버 함수를 재정하는 것을 의미합니다.
MFC에서 상속을 받아 파생 클래스를 만듦으로써 프로그램의 틀을 구현하고 기반 클래스에서 상속 받은 기능 중에 수정해야 할 부분이 있다면 재정의를 통해 그 부분만 원하는 대로 고치거나 기능을 추가할 수 있는 것입니다.
클래스 뷰에서 클래스를 선택하면 아래쪽 창에 이미 작성된 함수 명이 보일 것입니다.
함수를 더블 클릭하면 그 함수의 내용이 작성된 곳으로 이동하므로 소스를 작성하면 됩니다.
이 때 함수를 선택하면 Description 에 함수에 대한 간단한 설명이 나오게 됩니다.
보이지 않는 메시지나 함수는 클래스 뷰에서 클래스를 선택하고 마우스 오른쪽을 눌러서 속성 창을 보이게 한 후 메시지를 작성하면 됩니다.
2. 존재하지 않는 기능의 추가
존재하지 않는 새로운 기능을 추가한다는 것은 MFC에서 상속 받아 만들어진 클래스에 새로운 멤버 함수나 멤버 변수를 추가하는 것을 의미합니다.
Class View에서 클래스를 선택하고 오른쪽 마우스 버튼을 누르고 [추가]에서 변수 또는 함수를 선택해서 변수의 경우는 접근
배열이나 포인터 변수를 생성하고자 한다면 클래스의 선언 부에 가서 직접 선언하고 생성자 함수에서 직접 초기화하면 됩니다.
함수를 추가하는 경우에도 이처럼 수행하면 됩니다.
프로그램 작성 시 알아두면 좋은 것
1. 멤버 함수나 멤버 변수 삭제
멤버 변수나 함수를 삭제 할 때는 클래스 뷰에서 멤버 변수를 더블 클릭해서 멤버 변수가 선언된 곳으로 이동해서 삭제 하고 초기화가 자동으로 되어 있다면 생성자 함수에 가서 직접 삭제해야 합니다.
2. 전역 변수나 함수 선언
클래스의 멤버 함수들이 정의 된 중간에 변수나 함수를 만들면 전역으로 선언되며 클래스뷰에는 Global에 보이게 됩니다.
3. 새로운 클래스 만들기
[프로젝트] – [클래스 추가]를 눌러서 Class Type을 결정합니다.
이 때 MFC가 가지고 있는 클래스인지 일반 클래스인지 결정합니다.
그리고 일반 클래스라면 클래스이름을 입력하고 구현하면 됩니다.
MFC 클래스라면 기반 클래스가 어떤 것인지 선택하고 이름을 입력하고 만들면 .cpp 파일과 .h 파일을 생성해 줍니다.
4. 클래스 삭제
MFC에서는 모든 클래스가 헤더파일과 구현파일을 생성해 내므로 클래스를 삭제하고자 할 때는 프로젝트가 생성된 폴더에 가서 실제로 파일을 삭제하고 와야 합니다.
5. 작업도중 워크스페이스에 클래스가 보이지 않을 때 처리 방법
프로젝트를 닫고 프로젝트가 저장된 폴더로 이동해서 .ncb 파일을 삭제하고 프로젝트를 다시 열면 됩니다.
ncb 파일은 전체적인 소스를 관리하는 파일 이기 때문입니다.
6. 작업 도중 에러를 수정하다가 수 많은 클래스 이름이나 구조체의 이름이 워크스페이스에 보일 때
대부분은 MFC가 미리 정의해 둔 구조체나 클래스를 변경한 경우이므로 이를 원래대로 해주면 됩니다.
사용자가 마우스로 클릭한 위치에 사각형을 그려주는 프로젝트 작성
1. SDI옵션으로 MFC프로젝트 작성
2. View클래스에 m_Rect라는 멤버 함수 작성
void m_Rect(CPoint point)
3. 멤버 함수 정의
CClientDC dc(this);
dc.Rectangle(point.x, point.y, point.x+20, point.y+20);
4. LButtonDown 함수 정의
클래스 위저드를 이용해서 호출한 후 작성
m_Rect(point);
클래스간 상호 참조
CWinAppe에 대한 접근: AfxGetApp()로 어디에서나 접근 가능
CMainFrame에 대한 접근: AfxGetMainWnd()로 어디에서나 접근 가능
CDocument에 대한 접근: MainFrame에서는 GetActiveDocument()로 접근
View에서는 GetDocument()로 접근
CView에 대한 접근: MainFrame에서는 GetActiveView()로 접근
6. MFC에서 알아두면 편리한 클래스
1) 클래스 들 간의 상속 관계
CObject 클래스에서 CCmdTarget 클래스 파생
CCmdTarget은 사용자가 정의한 메시지(메뉴, 단축키 등)을 처리할 수 있는 클래스입니다.
CCmdTarget으로부터 CWinApp, CDocument, CWnd 파생
이 세 개의 클래스들은 따라서 사용자가 정의한 메시지(메뉴, 단축키 등)을 처리할 수 있습니다.
이 중에서 CWnd만이 화면에 보여집니다.
CWnd 클래스로부터는 CFrameWnd, CView, 컨트롤 클래스들이 상속을 받습니다.
이러한 클래스들은 모든 메시지를 전부 처리할 수 있습니다.
2) CString 클래스
const char*나 LPCTSTR 대신 CString 객체를 직접 사용할 수 있습니다.
각종 연산자와 멤버 함수가 정의 되어 있어 문자열 사용하는데 편리합니다.
CString 클래스의 객체에 다른 데이터 타입을 이용하고자 하면 Format 함수를 이용하면 됩니다.
C언어의 printf 형태로 이용하면 됩니다.
예) CString 객체 str에 정수 100, 200을 할당하는 방법
str.Format("x=%d, y=%d", 100, 200);
CString 형 객체의 내용을 char * 타입으로 변환하고자 한다면
(LPSTR)(LPCTSTR)CString객체)로 변환하면 됩니다
3)CPoint
점의 좌표를 저장하는 클래스
API의 POINTS 구조체와 유사
4)CRect
2개의 점의 좌표를 저장하는 클래스
5)CSize
가로와 세로 길이를 저장하는 클래스
Visual C++ MFC - chapter 1.MFC 시작
'C & C++ > C & C++' 카테고리의 다른 글
[MFC] 주요 클래스 (0) | 2011.04.25 |
---|---|
[MFC] 기본 구조 (0) | 2011.04.25 |
[Tip] Enter Key 클릭시 종료 방지 [PreTranslateMessage 사용] (0) | 2011.04.25 |
[TIP] MFC, STL 간단 사용팁 (0) | 2011.04.23 |
UNICODE 에 대하여 (0) | 2011.04.23 |
댓글