Visual C++ 1

Download Report

Transcript Visual C++ 1

Visual C++
1
0. C++ Review
2
Virtual Function

동적 바인딩(dynamic binding)
•
•
•
DrawObj
프로그램의 수행 중에 실제 수행할 함수를 결정
Virtual function table(hidden pointer)
vs. 정적 바인딩(static binding)
int a
virtual Draw()
DrawObj* p_obj;
p_obj = new Point;
p_obj->Draw();
p_obj = new Line;
p_obj->Draw();
Point
Line
int x, y
Point start, end
virtual Draw()
virtual Draw()
virtual Calc()
p_obj = new PolyLine;
p_obj->Draw();
PolyLine
Point[5] pt
virtual Draw()
3
Virtual Function - 메모리 구조
p_obj = new PolyLine;
p_obj = new DrawObj;
p_obj->Draw();
p_obj->Draw();
50
100
350
430
180
550
430
250
DrawObj::Draw
Point[0] pt
350
Line::Draw
Point[1] pt
430
vtbl 50
vtbl 180
int a
int a
int x
int y
p_obj = new Line;
Point start
p_obj->Draw();
250
virtual
function
table
Point end
vtbl 100
int a
int x
int y
Point start
Point end
pointer
of
virtual
function
table
Point[2] pt
Line::Calc
Point[3] pt
Point[4] pt
550
PolyLine::Draw
Code 영역
4
Why MFC?
 이해가 쉬움
•
연관된 함수와 데이타를 “클
래스”를 이용하여 그룹화하
였음
 코드의 재사용성 향상
 소프트웨어 개발의 용이성
•
•
•
애플리케이션 프레임워크
(application framework) 제
공
멤버 함수 나열
코드 삽입의 용이성
응용프로그램
MFC
SDK API
운영체제
5
1. Hello, MFC
6
Introducing MFC
 MFC Design Philosophy
•
•
MFC should provide an object-oriented interface to the Windows
operating system that supports reusability, self-containment, and
other tenets of OOP.
It should do so without imposing undue overhead on the system
or unnecessarily adding to an application's memory
requirements.
 Document/View Architecture
 MFC Class Hierarchy
•
•
•
Serialization support
Run-time class information support
Diagnostic and debugging support
 AFX Functions
7
Commonly Used AFX Functions
 AfxAbort Unconditionally terminates an application; usually
called when an unrecoverable error occurs
 AfxBeginThread Creates a new thread and begins executing it
 AfxEndThread Terminates the thread that is currently
executing
 AfxMessageBox Displays a Windows message box
 AfxGetApp Returns a pointer to the application object
 AfxGetAppName Returns the name of the application
 AfxGetMainWnd Returns a pointer to the application's main
window
 AfxGetInstanceHandle Returns a handle identifying the
current application instance
 AfxRegisterWndClass Registers a custom WNDCLASS for an
MFC application
8
AFX Classes




어플리케이션 프로그램을 구성하는 오브젝트 단위로 분할
분리된 오브젝트는 철저하게 역할을 분담
프레임 윈도우와 뷰를 분리
도큐먼트와 뷰를 분리
CFram eWnd
CView
윈도우의 프레임( 틀) 을 관리 데이터를 보여주는 윈도우
CDocum ent
데이터를 저장, 처리
( 눈에는 안보임)
CWinApp
위의 세 오브젝트를 묶어주고, 프로그램을 구동 시킴 ( 눈에는 안보임)
9
AFX 클래스의 상속 관계
거의 모든 MFC 클래스의 기반 클래스
CObject
커맨드 메세지를 받는 기능
CCmdTarget
CWinApp
CDocument
CWnd
CFrameWnd
CView
프로그램을 구동시키는 기능
데이터를 저장하고 처리하는 기능
윈도우에 관련된 기능 ( 눈에 보이는 오브젝트)
거의 모든 MFC 클래스의 기반 클래스
CObject
CWnd
CFrameWnd
CView
CDialog
모든 윈도우 관련 클래스의 기반 클래스
프레임 윈도우 관련 클래스의 기반 클래스
뷰 관련 클래스의 기반 클래스
다이얼로그 박스 관련 클래스의 기반 클래스
프로그램 윈도우 프레임( 외곽) 을 관리하는 기능
CSplitterWnd
분할 윈도우 클래스
데이터를 보여주는 윈도우 관리하는 기능
CControlBar
컨트롤 바 관련 클래스의 기반 클래스
CPropertySheet
프로퍼티시트 클래스
CPropertyPage
프로퍼티페이지 클래스
COlePropertyPage
OLE 프로퍼티페이지 클래스
각종 컨트롤 클래스들
10
나머지 클래스들






그래픽 관련 클래스
자료 구조 클래스
파일 및 데이터베이스 관련 클래스
인터넷 관련 클래스
OLE 관련 클래스
에러 처리 및 디버깅을 위한 클래스
11
Hello, MFC
 The Hello window program
12
Hello.h
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance ();
};
class CMainWindow : public CFrameWnd
{
public:
CMainWindow ();
protected:
afx_msg void OnPaint ();
DECLARE_MESSAGE_MAP ()
};
13
Hello.cpp
#include <afxwin.h>
#include "Hello.h"
CMyApp myApp;
// CMyApp member functions
BOOL CMyApp::InitInstance ()
{
m_pMainWnd = new CMainWindow;
m_pMainWnd->ShowWindow (m_nCmdShow);
m_pMainWnd->UpdateWindow ();
return TRUE;
}
BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
ON_WM_PAINT ()
END_MESSAGE_MAP ()
CMainWindow::CMainWindow ()
{
Create (NULL, _T ("The Hello Application"));
}
void CMainWindow::OnPaint ()
{
CPaintDC dc (this);
CRect rect;
GetClientRect (&rect);
dc.DrawText (_T ("Hello, MFC"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
14
프로그램의 뼈대 만들기
 AppWiard가 해 주는 일
•
•
MFC의 AFX 클래스에서 상속을 받아 그림 1과 같이 네 개의 클래
스를 생성
상속 받은 클래스에는 MFC의 막강한 기능들이 상속
MFC 기반 클래스
파생 클래스
CObject
CCmdTarget
CWinApp
CMyApp
CDocument
CMyDoc
CWnd
CFrameWnd
CMainFrame
CView
CMyView
15
CWinApp 클래스
 CWinApp 클래스의 역할
•
•
•
•
•
프로그램의 시작과 종료를 담당
프로그램이 시작될 때, 메인 프레임 윈도우를 생성
무한루프를 돌면서 메시지를 뿌려줌
WM_QUIT 메시지를 만나면 무한루프를 빠져 나옴
프로그램을 전체를 대표하는 기능들을 수행
 CMyApp 클래스의 인스턴스가 유일하게 전역변수로 선언
16
CWinApp 클래스
 인스턴스가 생성되면서 다음 그림 멤버 함수를 차례로 호출
•
•
•
•
•
•
AfxGetApp – 프로그램 객체 포인터 반환
AfxWinInit – hInstance, nCmdShow 등을 멤버변수에 복사
InitApplication, InitInstance – 프로그램 초기화
Run – 메시지 루프
ExitInstance – WinMain으로 돌아감
AfxWinTerm – 프로그램 종료
CWinApp
CWinApp
프로그램 시작
Run( )
CMyApp
프로그램 시작
InitInstance( )
무한 루프
상
속
InitInstance( )
무한 루프
InitInstance( )
Run( )
ExitInstance( )
ExitInstance( )
프로그램 종료
프로그램 종료
ExitInstance( )
17
CWinApp 클래스
 “stdafx.h”는 “Standard Application Frameworks”의 약자
 AFX 클래스인 도큐먼트 클래스, 프레임 윈도우 클래스, 뷰 클래
스를 엮어서 등록하는 루틴
class CMyApp : public CWinApp
{
// ……
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMyApp)
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
//}}AFX_VIRTUAL
// ……
};
18
CWinApp 클래스
 도큐먼트 클래스, 프레임 윈도우 클래스, 뷰 클래스로 각각
CMyDoc, CMainFrame, CMyView 클래스를 사용할 것임을 명
시
 위 정보를 CSingleDocTemplate 클래스에 설정한 후 CWinApp
클래스의 멤버 함수인 AddDocTemplate 함수를 호출하여
CWinApp 클래스와 연결
CMyApp theApp;
BOOL CMyApp::InitInstance()
{
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CMyView));
AddDocTemplate(pDocTemplate);
return TRUE;
}
19
CWnd 클래스
메시지 핸들러 함수
•윈도우의
크기, 위치, 모양, 상태 등을 제어하기 위한 기능을 제공
•메시지 핸들러-윈도우에서 발생하는 메시지를 처리
윈도우 메시지
메시지 핸들러 함수
WM_CREATE
OnCreate
WM_ACTIVATE
OnActivate
WM_PAINT
OnPaint
WM_MOUSEMOVE
OnMouseMove
WM_DESTROY
OnDestroy
WM_LBUTTONDOWN
OnLButtonDown
WM_LBUTTONUP
OnLButtonUp
WM_LBUTTONDBLCLK
OnLButtonDblClk
WM_KEYDOWN
OnKeyDown
WM_KEYUP
OnKeyUp
WM_SIZE
OnSize
WM_MOVE
OnMove
WM_TIMER
OnTimer
WM_COMMAND
다른 방식으로 처리됨
20
메시지 핸들러 호출의 원리
 이벤트가 발생 윈도우 운영체제가 감지 프로그램의 메시지
큐에 적재  메시지 핸들로 호출
윈도우 운영체제
메시지
메시지 큐
WM_MOUSEMOVE
WM_PAINT
WM_ACTIVATE
WM_CREATE
차례로 꺼내서 처리함
CWinApp::Run( )
{
while(msg != WM_QUIT) {
switch (msg) {
case WM_CREATE:
OnCreate( ); break;
case WM_ACTIVATE:
OnActivate( ); break;
case WM_PAINT:
OnPaint( ); break;
.....
}
}
21
윈도우 메시지에 대응
CWnd
WM_CREATE
OnCreate
CWnd
CMyWnd
OnCreate
OnCreate
WM_CREATE
WM_ACTIVATE
WM_ACTIVATE
OnActivate
WM_KEYDOWN
OnActivate
WM_KEYDOWN
OnKeyDown
OnKeyDown
OnKeyDown
int CMyWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
CWnd::OnCreate(lpCreateStruct);
// 여기에 수행 하고자 하는 기능을 넣으면 됩니다.
}
22
메시지 맵
 가상 함수
•
•
•
바인딩 될 함수로 점프할 번지를 저장하기 위해 4바이트 짜리 포인
터가 필요
CWnd 클래스의 메시지 핸들러 함수가 약 200개  이를 모두 가상
함수로 선언하면 약 800바이트의 메모리가 더 필요
프레임 윈도우,뷰 윈도우, 툴바, 상태바, 다이얼로그 박스, 각종 컨
트롤 등 수십 개의 윈도우가 생성
 메시지 맵
•
파생 클래스의 메시지 핸들러 함수를 여기에 등록하면 기반 클래스
의 함수를 무시하고, 파생 클래스의 함수를 호출하는 매크로
CFrameWnd에서 상속 받은
CMainFrame 클래스의 메시지 맵 임을 나타냄
메시지 맵의 시작을 나타냄
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_MOUSEMOVE()
ON_WM_CREATE()
ClassWizard가 파싱하는 부분.
이 부분은 ClassWizard에 의해
자동으로 관리됨
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
메시지 맵의 끝을 나타냄
OnMouseMove 함수 오버라이딩
OnCreate 함수 오버라이딩
23
CFrameWnd 클래스
 일반적인 윈도우로서의 역할
•
프레임 윈도우도 일종의 윈도우
 프레임 윈도우로서의 고유한 역할
•
•
•
•
윈도우의 크기, 위치, 상태 등의 조절에 관한 일과 같은 윈도우로서
의 역할
툴바와 상태바를 다는 것은 CFrameWnd 클래스에서 상속을 받은
파생 클래스에서 추가
OnCreate 함수를 오버라이딩 하고, 그 함수 안에다가 툴바와 상태
바를 생성시켜 메다는 기능을 추가
오버라이딩 된 OnCreate 함수에서 기반 클래스의 OnCreate 함수
를 반드시 호출
int CMyWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
CWnd::OnCreate(lpCreateStruct);
// 여기에 수행 하고자 하는 기능을 넣으면 됩니다.
}
24
CFrameWnd 클래스
 afx_msg : virtual 대신 오버라이딩 된 함수임을 나타내기 위해
사용
class CMainFrame : public CFrameWnd
{
// ……
// Generated message map functions
protected:
//{{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
25
AFX 전체구조
CFrameWnd
protected/private 멤버
멤버 함수
멤버 변수
CWinApp
CDocument
CView
CMyApp 클래스의 인스턴스 ( 전역 변수)
26
CView 클래스
 일반적인 윈도우로서의 역할
•
CView 클래스는 프레임 윈도우의 클라이언트 영역 전체를 덮고 있
는 윈도우인 뷰라는 오브젝트를 클래스로 구현한 것
 뷰 윈도우로서의 고유한 역할
•
프로그램에서 다루는 데이터를 보여줌
class CMyView : public CView
{
public:
CMyDoc* GetDocument( );
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMyView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
//}}AFX_VIRTUAL
};
27
CView 클래스
 GetDocument()
•
도큐먼트 오브젝트의 포인터를 얻는 함수
 OnDraw()
•
각각 도큐먼트에서 데이터를 가져와 그리는 기능을 수행하는 함수
 OnXXXPrinting()
•
프린터 출력에 관한 함수
28
CDocument 클래스
 CDocument 클래스의 역할
•
•
•
•
•
파일로부터 데이터를 읽어오는 기능 (“파일” 메뉴의 “열기” 기능)
파일에 데이터를 저장하는 기능 (“파일” 메뉴의 “저장” 기능)
새로운 데이터를 만드는 기능 (“파일” 메뉴의 “새 파일” 기능)
작업 중인 데이터를 닫는 기능 (“파일” 메뉴의 “닫기” 기능)
데이터가 변경된 사실을 뷰 오브젝트에 알리는 기능
// MyDoc.h
class CMyDoc : public CDocument
{
protected: // create from serialization only
CMyDoc();
// Overrides
public:
virtual BOOL OnNewDocument();
// Implementation
public:
virtual ~CMyDoc();
};
29
Framework 클래스간 상호참조
CFrameWnd
GetActiveView
GetActiveDocument
GetParentFrame
AfxGetApp
AfxGetMainWnd
CDocument
CView
GetDocument
GetFirstViewPosition
GetNextView
30
Framework 클래스간 상호참조
 전역함수
•
CWinApp* AfxGetApp( )
CWinApp 파생 클래스의 인스턴스 포인터를 반환
 프로그램 상의 어디에서든 참조 가능

•
CWnd* AfxGetMainWnd( )
메인 프레임 클래스의 인스턴스 포인터를 반환
 프로그램 상의 어디에서든 참조 가능

 프레임 윈도우 클래스에서 도큐먼트/뷰 참조
•
virtual CDocument* GetActiveDocument( )

•
프레임 윈도우 클래스에서 도큐먼트 클래스를 참조
CView* GetActiveView( ) const

현재 프레임 윈도우와 연결된 뷰 클래스의 인스턴스 포인터를 반환
31
Framework 클래스간 상호참조
 프레임 윈도우 클래스에서 도큐먼트/뷰 참조
•
virtual CDocument* GetActiveDocument( )

•
현재 프레임 윈도우와 연결된 도큐먼트 클래스의 인스턴스 포인터를
반환
CView* GetActiveView( ) const

함수는 현재 프레임 윈도우와 연결된 뷰 클래스의 인스턴스 포인터를
반환
 뷰 클래스에서 프레임 윈도우/도큐먼트 참조
•
CFrameWnd* GetParentFrame( ) const

•
뷰 클래스에서 그 뷰를 둘러싸고 있는 프레임 윈도우를 참조
CDocument* GetDocument( ) const

뷰 클래스에서 그 뷰와 연결된 도큐먼트 클래스를 참조
32
Framework 클래스간 상호참조
 도큐먼트 클래스에서 뷰 참조
•
CDocument::GetFirstViewPosition, GetNextView
하나의 도큐먼트에 여러 개의 뷰가 결합
 도큐먼트에는 이와 연결된 뷰가 연결 리스트 구조로 관리

POSITION pos = GetFirstViewPosition();
while (pos != NULL)
{
CView* pView = GetNextView(pos);
pView->UpdateWindow();
}
 도큐먼트 클래스에서 프레임 윈도우 참조
•
•
SDI : AfxGetMainWnd 함수를 호출
MDI : 뷰를 거쳐서 참조
33
메시지를 이용한 통신
 CWnd::SendMessage
•
메시지가 메시지 큐를 거치지 않음
 CWnd::PostMessage
•
메시지를 메시지 큐에 넣어줌
 CWinApp 클래스나 CDocument 파생 클래스에서는
XxxxMessage 함수 호출 불가능
 AfxGetMainWnd( )->XxxxMessage( …, …, …)
34
실습
 “Hello MFC” 프로그램 작성
•
•




Project->Win32 Application
Project menu->settings(alt+F7)->general->Use MFC in a Shared
DLL
Menu 달기
System 메뉴없애기
Minimize,Maximize 버튼 없애기
초기 윈도우 크기, 위치 바꾸기
35
2. Menu
36
Menu 편집
 메뉴 항목을 선택하고, ID와 Caption을 편집
선택된 메뉴 항목
선택된 메뉴 항목의 ID
메뉴에 실제 출력될 문자열
37
Loading and Displaying a Menu
 메뉴를 읽어들여 윈도우에 붙인다.
 CFrameWnd::Create 함수에 메뉴의 ID를 전달
Create (NULL, _T ("My Application"), WS_OVERLAPPEDWINDOW,
rectDefault, NULL, MAKEINTRESOURCE (IDR_MAINFRAME));
 CFrameWnd::LoadFrame 함수 호출
LoadFrame (IDR_MAINFRAME, WS_OVERLAPPEDWINDOW,
NULL, NULL);
 CMenu 객체 생성후 LoadMenu 호출
CMenu menu;
menu.LoadMenu (IDR_MAINFRAME);
SetMenu (&menu); menu.Detach ();
38
Menu 바꾸기
Create (NULL, _T ("My Application"));
m_menuLong.LoadMenu (IDR_LONGMENU);
m_menuShort.LoadMenu (IDR_SHORTMENU);
SetMenu (m_bShortMenu ? &m_menuShort : &m_menuLong);
m_bShortMenu = TRUE;
SetMenu (&m_menuShort);
DrawMenuBar ();
m_bShortMenu = FALSE;
SetMenu (&m_menuLong);
DrawMenuBar ();
 CWnd::DrawMenuBar()
•
윈도우가 생성된 이후에 메뉴를 다시 그려줌
39
Responding to Menu Commands
 WM_COMMAND Message
•
wParam에 항목 ID 저장
 SDK에서는 switch-case 사용
 MFC에서는 ON_COMMAND 매크로 사용하여 메시지 맵 엔트
리 작성
ON_COMMAND (ID_FILE_NEW, OnFileNew)
ON_COMMAND (ID_FILE_OPEN, OnFileOpen)
ON_COMMAND (ID_FILE_SAVE, OnFileSave)
ON_COMMAND (ID_FILE_SAVE_AS, OnFileSaveAs)
ON_COMMAND (ID_FILE_EXIT, OnFileExit)
void CMainWindow::OnFileExit ()
{
PostMessage (WM_CLOSE, 0, 0);
}
40
Command Message
 프로그램 실행 중에 메뉴가 선택되면, WM_COMMAND 라는
윈도우 메시지가 발생
 어떤 메뉴가 눌렸는지를 구별하기 위해 메뉴의 ID가 추가적인
정보로 전달
 만일 OnCommand라는 메시지 핸들러에서 처리를 하면 할 일이
너무 많아짐
41
Command Message 전달 경로
 일반적인 윈도우 메시지를 처리하는 기능은  CWnd 클래스
 CWnd 상위에 있는 클래스는 윈도우 메시지를 받는 기능이 없
슴
 사용자가 메뉴 항목을 선택하여 프로그램에 명령을 내리면
WM_COMMAND 메시지가 모든 AFX 클래스에 전달
거의 모든 MFC 클래스의 기반 클래스
CObject
커맨드 메세지를 받는 기능
CCmdTarget
CWinApp
CDocument
CWnd
CFrameWnd
CView
프로그램을 구동시키는 기능
데이터를 저장하고 처리하는 기능
윈도우에 관련된 기능 ( 눈에 보이는 오브젝트)
프로그램 윈도우 프레임( 외곽) 을 관리하는 기능
데이터를 보여주는 윈도우 관리하는 기능
42
Command Message 처리
 프로그램의 데이터를 처리하는 기능  CDocument 파생 클래
스
 데이터를 화면에 표시하는 방법  CView 파생 클래스
 프로그램의 시작과 종료에 관련된 커맨드 CWinApp 파생 클
래스
 프레임 윈도우의 제어에 관계된 커맨드를 처리  CFrameWnd
파생 클래스
WM_COMMAND 메시지 전달 순서
CView
파생 클래스
CDocument
파생 클래스
CFrameWnd
파생 클래스
CWinApp
파생 클래스
43
Command Ranges
// In CMainWindow's message map
ON_COMMAND (ID_COLOR_RED, OnColorRed)
ON_COMMAND (ID_COLOR_GREEN, OnColorGreen)
ON_COMMAND (ID_COLOR_BLUE, OnColorBlue)
void CMainWindow::OnColorRed ()
{
m_nCurrentColor = 0;
}
void CMainWindow::OnColorGreen ()
{
m_nCurrentColor = 1;
}
void CMainWindow::OnColorBlue ()
{
m_nCurrentColor = 2;
}
44
Command Ranges
// In CMainWindow's message map
ON_COMMAND (ID_COLOR_RED, OnColor)
ON_COMMAND (ID_COLOR_GREEN, OnColor)
ON_COMMAND (ID_COLOR_BLUE, OnColor)
void CMainWindow::OnColor ()
{
UINT nID = (UINT) LOWORD (GetCurrentMessage ()->wParam); //wParam 에 의존
m_nCurrentColor = nID;
}
// In CMainWindow's message map
ON_COMMAND_RANGE (ID_COLOR_RED, ID_COLOR_BLUE, OnColor)
void CMainWindow::OnColor (UINT nID)
{
m_nCurrentColor = nID;
}
45
3. Graphic Device Interface
46
GDI
 그래픽 디바이스 인터페이스 (GDI: Graphic Device Interface)
•
그래픽 기능과 관련해서 윈도우 운영체제가 어플리케이션 프로그
램에 제공하는 모든 기능
 디바이스 컨텍스트 (DC: Device Context)
•
그래픽에 필요한 모든 옵션을 한곳에 모아둔 구조체
 GDI 오브젝트 (GDI Object)
•
독립적으로 저장되는 각 범주의 그래픽 옵션
범주
선 그리기 옵션
GDI 오브젝트
기본값
펜 (Pen)
1 픽셀 굵기의 검은색 실선
브러시 ( Brush)
단일 흰색 브러시
글꼴 옵션
글꼴 (Font)
시스템 글꼴
비트맵 옵션
비트맵 (Bitmap)
없음
팔레트 옵션
팔레트 (Palette)
없음
영역 옵션
영역 (Region)
없음
영역의 내부를 채우
는 옵션
47
그래픽 관련 MFC 클래스
 CDC 클래스
•
•
GDI 오브젝트를 통해 그래픽에 관련된 옵션을 저장
모든 그래픽 함수들은 CDC 클래스의 멤버 함수
CDC *pDC = GetDC();
pDC->Rectangle(10, 10, 100, 100);
ReleaseDC(pDC);
•
하위 클래스
CClientDC
 CWindowDC
 CPaintDC
 CMetaFileDC

48
CClientDC
 CDC 클래스에서 상속
 생성자 함수에서 GetDC를 호출
 소멸자 함수에서 ReleaseDC를 호출
CClientDC dc(this);
dc.Rectangle(10, 10, 100, 100);
윈도우 2
윈도우 1
DC2
프린터의 DC
모뎀의 DC
DC1
화면의 DC
플로터의 DC
DC.Rectangle(10, 10, 100,100);
DC1.Rectangle(10, 10, 100, 100)
DC2.Rectangle(200, 200, 300, 300)
49
GDI 오브젝트 클래스
 그래픽 옵션을 바꿔 주려면 새로운 설정을 갖는 GDI 오브젝트
클래스를 생성한 후에 이것을 DC에 넣고, 이 DC를 이용하여 그
림을 그림
GDI 오브젝트
MFC 클래스
펜
CPen
브러시 ( 붓)
CBrush
글꼴
CFont
비트맵
CBitmap
팔레트
CPalette
영역
CRgn
50
펜과 브러시
 펜과 브러시를 이용한 그래픽
•
•
현재 DC에 설정되어 있는 펜을 이용하여 경계선을 그림
폐곡선일 경우 안쪽을 현재 DC에 설정되어 있는 브러시로 채움
함수
그리기 기능
MoveTo, LineTo
선
Rectangle, FillRect, FrameRect, Draw3dRect
사각형
Ellipse
타원
Pie
파이
Arc, ArcTo, AngleArc, Chord
호
Polygon
다각형
PolyDraw, PolyBezier, PolyBezierTo
베지어 곡선
FrameRgn
영역의 경계선
51
그래픽 옵션 바꾸기
 펜 생성 예제
CPen pen;
pen.CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
CClinetDC dc(this);
dc.SelectObject(&pen);
dc.Rectangle(10, 10, 100, 100);
어떤 문제가
존재?
PS_SOLID
PS_DASH
PS_DOT
반지름
반지름
PS_SOLID
PS_INSIDEFRAME
PS_DASHDOT
PS_DASHDOTDOT
PS_NULL
PS_INSIDEFRAME
52
그래픽 옵션 바꾸기
 새로운 펜으로 선택하고 되돌리지 않으면 함수가 종료되는 순간
에 DC에 저장되어 있던 펜 오브젝트는 파괴
 SelectObject 함수의 리턴값으로 넘어오는 GDI 오브젝트 저장
CPen pen;
pen.CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
CClinetDC dc(this);
CPen *pOldPen = (CPen *)dc.SelectObject(&pen);
dc.Rectangle(10, 10, 100, 100);
dc.SelectObject(pOldPen);
53
내장 (Stock) GDI 오브젝트
 자주 쓰이는 스타일의 GDI 오브젝트는 윈도우 운영체제가 내장
 GetStockObject 함수 사용
CClientDC dc;
dc.SelectObject( GetStockObject(WHITE_PEN) );
 내장 오브젝트는 항상 메모리에 상주
54
실습
 튀는 공 예제 프로그램
55
레스터 오퍼레이션
 새로 그릴 그림과 기존에 그려져 있는 그림을 합성
 int SetROP2( int nDrawMode )
•
R2_COPYPEN

•
새로이 그려지는 그림으로 화면에 덮어 그림
R2_XORPEN
배경을 깨뜨리지 않고, 배경 위에서 움직이는 그림을 그릴 때 사용
 똑같은 그림을 두 번 그려주면 원래 있던 바탕색이 복원

바탕색
출력되는 색
흰색
새로 그려진 색이 반전되어 출력됩니다.
검정색
새로 그려진 색이 그대로 출력됩니다.
임의의 색
새로 그려진 색과 바탕색이 XOR 연산되어 출력되는데,
이 값은 바탕색과 새로 그려진 색 양쪽과 모두 무관한
엉뚱한 색이 됩니다.
56
실습
 마우스를 드래그 해서 선을 그릴 수 있는 프로그램
57
4. Dialog Box and Controls
58
다이얼로그 박스
 프로그램 수행 도중 사용자의 입력이 필요할 때 다이얼로그 박
스 출력
 다이얼로그 박스는 사용자로부터 입력 받은 데이터를 메인 루틴
에 넘기고 소멸
 다이얼로그 템플릿
•
•
다이얼로그 박스가 생성될 때 사용될 다이얼로그 박스의 모양에 대
한 설계도
리소스 파일에 저장
59
다이얼로그 박스 속성 설정
 Caption: 항목에는 다이얼로그 박스의 타이틀
 Font : 다이얼로그에서 사용하는 글꼴 설정
 Styles : 다이얼로그 박스의 스타일 설정
60
다이얼로그 박스 클래스
 CWnd 클래스 상속
•
CWnd 클래스에 있는 윈도우를 제어 기능 함수와 윈도우 메시지
핸들러 함수를 모두 이용
CObject
CWnd
CDialog
 CDialog 클래스를 상속을 받아서 사용
•
cf) 컨트롤은 MFC 클래스를 그대로 사용
61
다이얼로그 박스 만들기 (1/2)
 CDialog 파생 클래스 만들기
class CNameDlg : public CDialog
{
//…
enum { IDD = IDD_DIALOG1 };
//…
};
62
다이얼로그 박스 만들기 (2/2)
 CDialog 파생 클래스의 인스턴스 만들어 사용하기
 사용자의 입력을 받는 일은 다이얼로그 박스에 일임
#include “NameDlg.h”
void CDlgTestView::OnDialog( )
{
CNameDlg dlg;
// CDialog 파생 클래스의 인스턴스를 생성
dlg.DoModal( );
// CDialog 클래스의 멤버 함수를 호출
// 다이얼로그 박스에서 입력 받은 값을 이용하는 루틴…
}
63
CDialog 클래스의 기능




다이얼로그 박스와 컨트롤의 생성
메시지 핸들러 함수
커맨드 메시지 핸들러 함수
다이얼로그 박스는 확인 (OK) 버튼과 취소 (Cancel) 버튼과 각각
의 메시지 핸들러를 가지고 있슴
#include “NameDlg.h”
void CDlgTestView::OnDialog( )
{
CNameDlg dlg;
if( dlg.DoModal( ) == IDOK)
{
// OK 버튼이 눌렸을 때만 실행되는 부분
// 다이얼로그 박스에서 입력 받은 값을 이용하는 루틴…
}
}
64
CDialog 파생 클래스에 추가해야 하는 기능
 사용자가 컨트롤에 입력한 내용을 관리
•
사용자의 입력 내용을 컨트롤로부터 획득
 컨트롤 자체를 하나의 윈도우로 보고 제어
•
•
Show/Hide
활성화/비활성화
65
Value형 멤버변수
 컨트롤에 입력된 값과 연결된 CDialog 파생 클래스의 멤버 변수
 MFC는 컨트롤과 변수를 연결하여 컨트롤에 입력된 값을 변수
에 저장
 변수에 설정된 값을 컨트롤에 입력하는 것을 자동으로 수행
CDialog ÆÄ»ý Ŭ·¡½º
다이얼로그 박스
Value Çü ¸â¹ö º¯¼ö
이름 : 홍길동
CString m_strName
나이 : 28
int m_nAge
OK
Cancel
66
컨트롤과 Value형 멤버 변수 연결
 다이얼로그 템플릿에서 Value형 멤버 변수와 연결시키려는 컨
트롤을 선택 [Ctrl]키를 누른 상태에서 마우스 버튼을 더블 클
릭
 변수형을 선택
67
컨트롤과 Value형 멤버 변수 연결
 코드의 변화
CNameDlg::CNameDlg(CWnd* pParent /*=NULL*/)
: CDialog(CNameDlg::IDD, pParent)
{
class CNameDlg : public CDialog
//{{AFX_DATA_INIT(CNameDlg)
{
m_strName = _T("");
//…
m_nAge = 0;
//{{AFX_DATA(CNameDlg)
//}}AFX_DATA_INIT
enum { IDD = IDD_DIALOG1 };
}
CString m_strName;
void CNameDlg::DoDataExchange(CDataExchange* pDX)
int
{
m_nAge;
//}}AFX_DATA
CDialog::DoDataExchange(pDX);
//…
//{{AFX_DATA_MAP(CNameDlg)
};
DDX_Text(pDX, IDC_EDIT1, m_strName);
DDX_Text(pDX, IDC_EDIT2, m_nAge);
//}}AFX_DATA_MAP
}
68
컨트롤과 Value형 멤버 변수 사이의 데이터 전송
 UpdateData 함수를 이용한 데이터 전송
다 이 얼 로 그 박스
컨트롤
UpdateData(FALSE)
이름 : 일지매
CString m_strName;
나이 : 20
OK
Value형 멤버 변수
int m_nAge;
Cancel
UpdateData(TRUE)
 CDialog 클래스에서 기본적으로 호출하고 있는 UpdateData 함
수
•
•
다이얼로그 박스 시작 시 UpdateData(FALSE) 호출
다이얼로그 박스 종료 시 UpdateData(TRUE) 호출

값이 확인 (OK) 버튼이 눌려지는 순간에 Value형 멤버 변수에 저장
69
입력된 값의 유효성 검사
 사용자 입력의 유효성 검사의 필요성
 유효성 검사의 자동화
void CNameDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CNameDlg)
DDX_Text(pDX, IDC_EDIT1, m_strName);
DDV_MaxChars(pDX, m_strName, 10);
DDX_Text(pDX, IDC_EDIT2, m_nAge);
DDV_MinMaxInt(pDX, m_nAge, 0, 100);
//}}AFX_DATA_MAP
}
70
받을 문자열의 최대 길이를 지정
71
유효한 입력의 범위 설정
 유효한 입력의 범위를 최대값(Maximum Value)과 최소값
(Minimum Value)으로 설정
72
UpdateData 함수의 동작 과정
 UpdateData 함수는 내부적으로 DoDataExchange 함수를 호출
void CNameDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CNameDlg)
DDX_Text(pDX, IDC_EDIT1, m_strName);
DDV_MaxChars(pDX, m_strName, 10);
DDX_Text(pDX, IDC_EDIT2, m_nAge);
DDV_MinMaxInt(pDX, m_nAge, 0, 100);
//}}AFX_DATA_MAP
}
73
UpdateData 함수의 동작 과정

UpdateData(TRUE)
1.
2.
3.

DoDataExchang 함수가 호출
DDV_로 시작되는 함수들이 호출
DDX_로 시작하는 함수들이 호출
UpdateData(FALSE)
1.
2.
DoDataExchang 함수가 호출
DDX_로 시작하는 함수들이 호출
74
컨트롤에 따른 Value형 멤버 변수
 편집 박스 컨트롤
CStiring,int,UINT,long,DWORD,float,double,BYTE,short,BOOL,C
OleDateTime,COleCurrency
 리스트 박스 컨트롤과 콤보 박스 컨트롤
•
CString
 체크 박스 컨트롤
•
BOOL
75
컨트롤에 따른 Value형 멤버 변수
 라디오 버튼 컨트롤
•
•
•
Group 속성을 가진 라디오 버튼 컨트롤에서부터 다음 Group 속성
을 가진 라디오 버튼 컨트롤까지가 하나의 범주
Group 속성을 가진 컨트롤이 대표로 Value형 멤버 변수와 연결
int
76
Control형 멤버 변수
 MFC에는 모든 컨트롤들이 클래스로 구성
 컨트롤을 Control형 멤버 변수와 연결하여 제어
 모든 컨트롤 클래스의 기반 클래스는 CWnd
77
CWnd 클래스
 Create
•
윈도우를 생성
 ShowWindow
•
SW_SHOW ,SW_HIDE
 EnableWindow
•
윈도우를 활성화 시키거나 비활성화 시킴
 SetWindowPos
•
윈도우의 크기와 위치를 변경
 SetWindowText
•
윈도우의 메인 텍스트를 변경
78
CEdit 클래스
 GetSel
•
선택된 부분의 문자열을 얻어옴
 SetSel
•
특정 부분을 선택 영역으로 설정
 ReplaceSel
•
선택된 부분의 텍스트를 지정한 텍스트로 치환
 GetLineCount
•
편집 박스의 텍스트의 줄 수 반환
 GetLine
•
지정된 라인의 텍스트를 얻어옴
79
CButton 클래스
 푸시 버튼, 체크 박스 버튼, 라디오 버튼
 GetCheck
•
버튼이 눌려진 상태를 얻어옴
 SetCheck
•
버튼의 눌려짐 상태를 설정
80
CScrollBar 클래스
 GetScrollRange
•
스크롤바 컨트롤의 증감범위 반환
 SetScrollRange
•
스크롤바 컨트롤의 증감범위 설정
 GetScrollPos
•
스크롤바 컨트롤에 현재 설정된 값 반환
 SetScrollPos
•
스크롤바 컨트롤에 값 설정
81
CListBox 클래스와 CComboBox 클래스
 GetCount
•
컨트롤에 들어있는 총 문자열의 수를 반환
 GetCurSel, SetCurSel
•
•
선택된 문자열의 인덱스 반환하거나 설정
인덱스는 0부터 시작
 AddString, InsertString
•
문자열을 추가
 DeleteString,ResetContent
•
문자열을 삭제
 Dir
82
컨트롤의 제어
 WM_INITDIALOG 메시지 (OnInitDialog 메시지 핸들러 함수)
•
컨트롤의 초기화 루틴은 여기 들어간다.
 통지 (NOTIFICATION) 메시지
•
통지 메시지는 컨트롤에 발생한 사건을 알려주기 위해 그 컨트롤을
품고 있는 부모 윈도우인 다이얼로그 박스로 메시지를 보냄
 통지 메시지의 전달
•
통지 메시지는 다이얼로그로 전달이 된다.
83
Notification Message
 Button
•
BN_CLICKED, BN_DBLCLK
 Edit Box
•
EN_CHANGE, EN_SETFOCUS, EN_KILLFOCUS
 List Box
•
LBN_DBLCLK, LBN_SELCHANGE, LBN_SETFOCUS,
LBN_KILLFOCUS
 Combo Box
•
CBN_DBLCLK, CBN_SELCHANGE, CBN_SETFOCUS,
CBN_KILLFOCUS, CBN_EDITCHAGE
84
모달리스 다이얼로그 박스
 모달 다이얼로그 박스
•
다이얼로그 박스가 출력되어 있는 동안에는 그 다이얼로그 박스가
프로그램의 모든 제어권을 독점
 모달리스 다이얼로그 박스
•
다이얼로그 박스가 프로그램의 제어권을 독점하지 않음
모달
모달리스
생성 방법
DoModal 함수
Create 함수
종료 방법
EndDialog 함수
DestroyWindow 함수
인스턴스 선언
지역 변수로 선언
동적으로 할당
85
생성 방법
 Modal Dialog
•
•
DoModal 함수로 생성
다이얼로그 박스가 종료되면 각각 IDOK 또는 IDCANCEL
 Modaless Dialog
•
•
Create 멤버 함수를 호출하여 생성
모달리스 다이얼로그 박스를 생성시킨 후 바로 리턴
86
종료 방법
 Modal Dialog
•
•
•
EndDialog 함수 호출
OnOK 멤버 함수에서는 EndDialog(IDOK)가 호출
OnCancel 멤버 함수에서는 EndDialog(IDCANCEL)가 호출
 Modaless Dialog
•
•
•
EndDialog 함수를 호출 금지
DestroyWindow 함수를 이용하여 종료
OnOK 함수나 OnCancel 함수를 오버라이딩시 CDialog 클래스의
OnOK 함수나 OnCancel 함수가 호출되지 않도록 주의
87
인스턴스 생성
#include “ModalDlg.h”
void CMainFrame::OnModal()
class CModalessDlg; // CModalessDlg 클 래 스 를
사용할 것임을 선언
class CMainFrame : public CFrameWnd
{
{
//…
CModalDlg dlg;
CModalessDlg *m_pDlg;
dlg.DoModal();
//…
}
}
#include “ModalessDlg.h”
void CMainFrame::OnModaless()
{
m_pDlg = new CModalessDlg;
m_pDlg->Create(this);
}
88
class CModalessDlg : public CDialog
{
BOOL Create(CWnd* pParentWnd);
}
BOOL CModalessDlg::Create(CWnd* pParentWnd)
{
return CDialog::Create(IDD, pParentWnd);
}
void CModalessDlg::OnClose()
{
DestroyWindow();
}
void CModalessDlg::PostNcDestroy()
{
((CMainFrame *)AfxGetMainWnd())->m_pDlg = NULL;
delete this;
}
89
class CMainFrame : public CFrameWnd
{
CModalessDlg *m_pDlg;
};
void CMainFrame::OnModaless()
{
if(m_pDlg != NULL) {
// 다이얼로그 박스가 이미 출력되어 있는 경우
m_pDlg->SetFocus();
}
else{
// 다이얼로그 박스가 출력되어 있지 않은 경우
m_pDlg = new CModalessDlg;
m_pDlg->Create(this);
m_pDlg->ShowWindow(SW_SHOW);
}
}
90
다이얼로그 박스 기반 어플리케이션
91
다이얼로그 박스 기반 어플리케이션
 CWinApp 파생 클래스와 CDialog 파생 클래스 만으로 구성
BOOL CDlgAppApp::InitInstance()
{
//…
CDlgAppDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
//…
return FALSE;
}
92
5. 사용자 인터페이스
93
메인 프레임 윈도우에 메뉴 표시
BOOL CCmdUIApp::InitInstance( )
{
//…
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CCmdUIDoc),
RUNTIME_CLASS(CCmdUIView),
RUNTIME_CLASS(CMainFrame));
AddDocTemplate(pDocTemplate);
//…
}
94
다이얼로그 박스에 메뉴 표시
95
컨텍스트 메뉴
void CContextMenuView::OnContextMenu(CWnd* pWnd, CPoint point)
{
CMenu muTemp, *pContextMenu;
muTemp.LoadMenu(IDR_MAINFRAME);
pContextMenu = muTemp.GetSubMenu(0);
pContextMenu->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, AfxGetMainWnd());
}
BOOL TrackPopupMenu(UINT nFlags, int x,int y ,CWnd* pWnd ,LPCRECT
lpRect = NULL);




nFlag - TPM_CENTERALIGN,TPM_LEFTALIGN,TPM_RIGHTALIGN ,
TPM_LEFTBUTTON , TPM_RIGHTBUTTON
x , y – 컨텍스트 메뉴가 표시될 좌표
pWnd – 메뉴를 소유할 윈도우
lpRect – 클릭하면 컨텍스트 메뉴를 사라지게 할 영역
96
단축키 정의
 Resource  Accelerator
97
단축키가 정의된 커맨드의 메뉴 캡션
 “새 파일 (&N)\tCtrl+N”
 , “\t” 뒤에 씌여진 문자열은 메뉴의 우측에 정렬
 &N 은 사용자가 alt키를 사용하여 메뉴접근시의 단축키
98
사용자 인터페이스 갱신 핸들러
 ON_UPDATE_COMMAND_UI는 사용자 인터페이스의 갱신
에 관련된 작업을 수행하기 위한 매크로
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_UPDATE_COMMAND_UI (ID_RED, OnUpdateColor)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CMainFrame::OnUpdateColor(CCmdUI* pCmdUI)
{
}
99
ON_UPDATE_COMMAND_UI_RANGE 매크로
 ID_RED부터 ID_YELLOW까지 커맨드 ID를 갖는 사용자 인터
페이스의 갱신에 대한 모든 제어는 OnUpdateColor 함수에서
일괄 처리
 ON_UPDATE_COMMAND_UI_RANGE는 ClassWizard에서
지원하지 않음
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
//}}AFX_MSG_MAP단축키 정의
ON_UPDATE_COMMAND_UI_RANGE(ID_RED, ID_YELLOW,
OnUpdateColor)
END_MESSAGE_MAP()
void CMainFrame::OnUpdateColor(CCmdUI* pCmdUI)
{
}
100
CCmdUI 클래스
 CCmdUI 클래스는 사용자 인터페이스 갱신과 관련된 기능을 담
당하는 클래스
 m_nID : command ID
멤버 함수
Enable
기능
BOOL 형 인자를 받아, 사용자 인터페이스를 활성화
또는 비활성화 시킵니다.
SetText
사용자 인터페이스의 텍스트를 변경시켜 줍니다.
SetCheck
int 형 인자를 받아, 체크 표시를 하거나 체크 표시를
없앱니다.
SetRadio
SetCheck 함수와 비슷한 기능을 하나, 체크 표시를 점
으로 찍어 줍니다.
101
CCmdUI::Enable 함수
 메뉴를 활성화/비활성화 시킴
BEGIN_MESSAGE_MAP(CCmdUIView, CView)
…
ON_UPDATE_COMMAND_UI(ID_BEGIN, OnUpdateBegin)
ON_UPDATE_COMMAND_UI(ID_END, OnUpdateEnd)
END_MESSAGE_MAP()
void CCmdUIView::OnUpdateBegin(CCmdUI *pCmdUI)
{
pCmdUI->Enable(!m_bStart);
}
void CCmdUIView::OnUpdateEnd(CCmdUI *pCmdUI)
{
pCmdUI->Enable(m_bStart);
}
102
CCmdUI::SetText 함수
 메뉴의 캡션 바꾸기
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_COMMAND(IDM_BEGINEND, OnBeginend)
ON_UPDATE_COMMAND_UI(IDM_BEGINEND,
OnUpdateBeginend)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CMainFrame::OnUpdateBeginend(CCmdUI* pCmdUI)
{
if(m_bStart) pCmdUI->SetText("작업 중단(&E)");
else pCmdUI->SetText("작업 시작(&S)");
}
103
CCmdUI::SetCheck 함수
void CMainFrame::OnColorRed()
{
m_nColorCheck = LOWORD(GetCurrentMessage()->wParam);
}
void CMainFrame::OnColorBlue()
{
m_nColorCheck = LOWORD(GetCurrentMessage()->wParam);
}
void CMainFrame::OnUpdateColorRed(CCmdUI* pCmdUI)
{
if (pCmdUI->m_nID == m_nColorCheck)
pCmdUI->SetCheck(TRUE);
else
pCmdUI->SetCheck(FALSE);
}
void CMainFrame::OnUpdateColorBlue(CCmdUI* pCmdUI)
{
if (pCmdUI->m_nID == m_nColorCheck)
pCmdUI->SetCheck(TRUE);
else
pCmdUI->SetCheck(FALSE);
}
104
CCmdUI::SetCheck 함수
 메뉴에 체크표시
class CMainFrame : public CFrameWnd
{
//…
UINT m_nColorCheck;
//…
}
CMainFrame::CMainFrame()
{
m_nColorCheck = IDM_REDCHECK;
}
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_COMMAND_RANGE(IDM_REDCHECK, IDM_BLUECHECK, OnColorCheck)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CMainFrame::OnColorCheck(UINT nID)
{
m_nColorCheck = nID;
}
105
CCmdUI::SetCheck 함수
 일괄 처리
 ON_UPDATE_COMMAND_UI_RANGE 매크로를 이용
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_COMMAND_RANGE(IDM_REDCHECK,
ON_UPDATE_COMMAND_UI_RANGE(IDM_REDCHECK,IDM_BLUE
CHECK, OnUpdateColorCheck)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CMainFrame::OnUpdateColorCheck(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_nColorCheck == pCmdUI->m_nID);
}
106
CCmdUI::SetRadio 함수
 SetCheck 와 동일
void CMainFrame::OnUpdateColorRadio(CCmdUI* pCmdUI)
{
pCmdUI->SetRadio(m_nColorRadio == pCmdUI->m_nID);
}
107
툴바 생성
 CToolBar 클래스 인스턴스 생성
 Create, LoadToolBar 함수 호출
class CMainFrame : public CFrameWnd
{
//…
CToolBar m_wndToolBar;
//…
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
m_wndToolBar.Create(this);
m_wndToolBar.LoadToolBar(IDR_MAINFRAME);
return 0;
}
108
툴바 스타일 변경
 툴바가 생성된 후 SetBarStyle() 멤버 함수를 호출
 m_wndToolBar.GetBarStyle( )로 현재 설정되어 있는 스타일에
추가 가능
m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
•
•
•
•
•
CBRS_FLOAT_MULTI – 여러개의 툴바를 도킹
CBRS_SIZE_DYNAMIC – 사이즈 변환가능
CBRS_TOOLTIPS – 툴팁 도움말 표시
CBRS_FLYBY – 상태바에 도움말 표시
CBRS_GRIPPER – Gripper 추가
109
플로팅 툴바 만들기
 프레임 윈도우에서 분리될 수 있는 툴바
 툴바와 프레임 윈도우 양쪽에서 모두 EnableDocking 함수를 호
출
 EnableDocking 함수로 도킹 스타일을 설정
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
//…
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
return 0;
}
 도킹 스타일
•
CBRS_ALIGN_TOP, CBRS_ALIGN_BOTTOM, CBRS_ALIGN_LEFT ,
CBRS_ALIGN_RIGHT , CBRS_ALIGN_ANY
110
텍스트가 표시된 툴바 만들기
 SetButtonText
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
m_wndToolBar.SetButtonText(0, "새파일");
m_wndToolBar.SetSizes(CSize(48, 32), CSize(16, 15));
return 0;
}
 CreateEx 함수로 툴바를 생성시키면서 스타일을 설정
m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE |
CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY |
CBRS_SIZE_DYNAMIC)
111
다이얼로그 바
 버튼 외의 다른 컨트롤들을 많이 사용해야 한다면 툴바보다 다
이얼로그 바를 사용
 컴포넌트 갤러리를 이용하여 다이얼로그 바 만들기
•
Project – Add to project – Components and controls
112
상태바
 클래스 인스턴스 생성
class CMainFrame : public CFrameWnd
{
//…
CStatusBar m_wndStatusBar;
//…
}
 Create로 생성후 SetIndicators 함수로 상태바를 팬으로 분할
프레임 윈도우
ID_INDICA TOR_SCRL
ID_INDICA TOR_CAPS
CAP
NUM
SCRL
ID_INDICA TOR_NUM
ID_SEPARA TOR
113
상태바
static UINT indicators[] ={ID_SEPARATOR,
// status line indicator
ID_INDICATOR_CAPS, ID_INDICATOR_NUM, ID_INDICATOR_SCRL,};
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1;
// fail to create
}
m_wndStatusBar.SetPaneInfo(1, ID_SEPARATOR, SBPS_NOBORDERS, 200);
return 0;
}
114
상태바 제어하기
 팬 추가
•
indicators 배열에 ID_SEPARATOR를 하나 더 추가
 팬 정보 변경
m_wndStatusBar.SetPaneInfo(1, ID_SEPARATOR,SBPS_NORMAL, 200);
•
•
•
Index- 몇 번째 팬에 대한 정보를 설정할 것인지를 결정
nID - 팬에 어떤 정보를 표시할 지를 결정
nStyle - 팬의 스타일을 결정

•
SBPS_NOBORDERS,SBPS_POPOUT,SBPS_DISABLED,SBPS_STRETCH,SBPS_
NORMAL
cxWidth - 팬의 너비를 설정
 상태바에 문자열 표시
•
BOOL SetPaneText( int nIndex, LPCTSTR lpszNewText, BOOL bUpdate = TRUE );
115
실습
 상태바에 현재 마우스의 위치 표시
116
메시지 박스
int AfxMessageBox( LPCTSTR lpszText, UINT nType = MB_OK,
UINT nIDHelp = 0 );
 메시지 박스 스타일
•
MB_ABORTRETRYIGNORE
,
MB_OK,MB_OKCANCEL,MB_RETRYCANCEL,MB_YESNO,MB_
YESNOCANCEL
 출력될 버튼 스타일
메시지 박스 스타일
출력되는 아이콘
MB_ICONEXCLAMATION
MB_ICONINFORMATION
MB_ICONQUESTION
MB_ICONSTOP
117
메시지 박스
 디폴트 버튼 설정
•
MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON3
 모달리티 설정
•
•
MB_APPLMODAL
MB_SYSTEMMODAL
 리턴값
•
•
•
•
•
•
•
IDABORT
IDCANCEL
IDIGNORE
IDNO
IDOK
IDRETRY
IDYES
118
마우스커서
 WM_SETCURSOR 메시지
•
마우스 커서가 윈도우 사이를 넘나들 때마다 발생
 커서 로드
•
•
•

HCURSOR CWinApp::LoadStandardCursor( LPCTSTR lpszCursorName );
HCURSOR CWinApp::LoadCursor( LPCTSTR lpszResourceName ) const;
HCURSOR CWinApp::LoadCursor( UINT nIDResource ) const;
커서 설정
•
SetCursor 함수를 호출
BOOL CCursorView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
HCURSOR hCursor;
hCursor = AfxGetApp()->LoadStandardCursor(IDC_CROSS);
SetCursor(hCursor);
return TRUE;
}
주의!) 기반클래스의 SetCursor 함수 호출 금지!
119
마우스커서
 표준 커서 사용예
BOOL CCursorView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
HCURSOR hCursor;
hCursor = AfxGetApp()->LoadStandardCursor(IDC_CROSS);
SetCursor(hCursor);
return TRUE;
}
 모래시계 커서
void Function( )
{
BeginWaitCursor( );
// 여기에 시간이 걸리는 작업을 넣습니다.
EndWaitCursor( );
}
120
6. Control
121
기본 트롤들
Control Type
Buttons
List boxes
Edit controls
Combo boxes
Scroll bars
Static controls
WNDCLASS
"BUTTON“
"LISTBOX"
"EDIT"
"COMBOBOX"
“SCROLLBAR“
"STATIC"
MFC Class
CButton
CListBox
CEdit
CComboBox
CScrollBar
CStatic
122
Button
 버튼의 생성
CButton m_wndPushButton;
m_wndPushButton.Create (_T ("Start"), WS_CHILD ¦ WS_VISIBLE
¦ BS_PUSHBUTTON, rect, this, IDC_BUTTON);
123
Button Style
 BS_PUSHBUTTON - Creates a standard push button control
 BS_DEFPUSHBUTTON - Creates a default push button; used in
dialog boxes to identify the push button that's clicked if Enter is
pressed
 BS_CHECKBOX - Creates a check box control
 BS_AUTOCHECKBOX - Creates a check box control that checks and
unchecks itself when clicked
 BS_3STATE - Creates a three-state check box control
 BS_AUTO3STATE - Creates a three-state check box control that
cycles through three states—checked, unchecked, and
indeterminate—when clicked
 BS_RADIOBUTTON - Creates a radio button control
 BS_AUTORADIOBUTTON - Creates a radio button control that,
when clicked, checks itself and unchecks other radio buttons in the
group
 BS_GROUPBOX - Creates a group box control
124
Push Button
 BS_PUSHBUTTON 으로 설정
 버튼 클릭시 WM_COMMAND 메시지 생성해서 부모윈도우에
게 보냄
 Notificatin 으로 BN_CLICKED 가 보내짐
 BN_CLICKED 처리 메시지맵
ON_BN_CLICKED (IDC_BUTTON, OnButtonClicked)
void CMainWindow::OnButtonClicked ()
{
MessageBox (_T ("I've been clicked!"));
}
125
Check Box
 BS_CHECKBOX, BS_AUTOCHECKBOX, BS_3STATE,
BS_AUTO3STATE 중 한가지 스타일로 생성
m_wndCheckBox.SetCheck (BST_CHECKED); // Check
m_wndCheckBox.SetCheck (BST_UNCHECKED); // Uncheck
//---------------------------------------------------------------------------------void CMainWindow::OnCheckBoxClicked ()
{
m_wndCheckBox.SetCheck (m_wndCheckBox.GetCheck () ==
BST_CHECKED ? BST_UNCHECKED : BST_CHECKED);
}
//---------------------------------------------------------------------------------m_wndCheckBox.SetCheck (BST_INDETERMINATE);
126
Radio Buttons
 BS_RADIOBUTTON 이나 BS_AUTORADIOBUTTON 스타일
로 생성
 BS_AUTORADIOBUTTON 은 자동으로 체크
 BS_RADIOBUTTON 은 체크 상태를 수동으로 설정
(BN_CLICKED에서 처리)
 SetCheck() , GetCheck() 사용
 기본상태는 체크되지 않음
void CMainWindow::OnRadioButton1Clicked ()
{ //1번 버튼을 눌렀을때 나머지 버튼을 Unchecked 상태로 만듦
m_wndRadioButton1.SetCheck (BST_CHECKED);
m_wndRadioButton2.SetCheck (BST_UNCHECKED);
m_wndRadioButton3.SetCheck (BST_UNCHECKED);
m_wndRadioButton4.SetCheck (BST_UNCHECKED);
}
127
Radio button 그룹화
1. 버튼을 순서대로 하나씩 생성
2. 첫번째 버튼에 WS_GROUP 속성 추가
3. 다음번 WS_GROUP을 가진 컨트롤 이전까지의 컨트롤들이 하
나의 그룹
m_wndRadioButton1.Create (_T ("COM1"), WS_CHILD ¦ WS_VISIBLE ¦
WS_GROUP ¦ BS_AUTORADIOBUTTON, rect1, this, IDC_COM1);
m_wndRadioButton2.Create (_T ("COM2"), WS_CHILD ¦ WS_VISIBLE ¦
BS_AUTORADIOBUTTON, rect2, this, IDC_COM2);
m_wndRadioButton1.SetCheck (BST_CHECKED);
m_wndCheckBox.Create (_T ("Save settings on exit"),
WS_CHILD ¦ WS_VISIBLE ¦ WS_GROUP ¦ BS_AUTOCHECKBOX,
rectCheckBox, this, IDC_SAVESETTINGS);
128
Group Box
 BS_GROUPBOX로 생성
 부모에게 어떤 메시지도 보내지 않음
 단지 시각적 효과만 제공
129
CListBox
 리스트박스 생성
m_wndListBox.Create (WS_CHILD ¦ WS_VISIBLE ¦
LBS_STANDARD, rect, this, IDC_LISTBOX);
 LBS_STANDARD : WS_BORDER | WS_VSCROLL |
LBS_NOTIFY | LBS_SORT
 목록 추가
m_wndListBox.AddString (string);
m_wndListBox.InsertString (3, string);
 목록 개수 반환
CListBox::GetCount
 목록 삭제
CListBox::DeleteString
130
CListBox
 항목 선택
// In CMainWindow's message map
ON_LBN_DBLCLK (IDC_LISTBOX, OnItemDoubleClicked)
void CMainWindow::OnItemDoubleClicked ()
{
CString string;
int nIndex = m_wndListBox.GetCurSel ();
m_wndListBox.GetText (nIndex, string);
MessageBox (string);
}
 다중 항목 선택
•
GetCaretIndex
131
CStatic
 Static 컨트롤 생성
m_wndStatic.Create (_T ("Name"), WS_CHILD ¦ WS_VISIBLE ¦
SS_LEFT, rect, this, IDC_STATIC);
 SS_LEFT : rect 영역안에서 왼쪽 정렬
 기본적으로 사각형 왼쪽 위로 정렬  가운데 정렬은
SS_CENTERIMAGE
 Bitmap 출력
m_ctrlStatic.Create (_T (""), WS_CHILD | WS_VISIBLE | SS_BITMAP | SS_SUNKEN, rect ,
this, IDC_STATIC1);
HINSTANCE hInstance = AfxGetInstanceHandle();
HBITMAP hBitmap = LoadBitmap(hInstance ,MAKEINTRESOURCE(IDB_BITMAP1));
m_ctrlStatic.SetBitmap(hBitmap);
132
CEdit
 텍스트 편집에 사용
 복사, 잘라내기, 붙여넣기 기능 지원
 Edit 컨트롤 생성
m_wndEdit.Create (WS_CHILD ¦ WS_VISIBLE ¦ WS_BORDER ¦
ES_AUTOHSCROLL, rect, this, IDC_EDIT);
 WS_BORDER : 컨트롤 주위에 경계선 추가
 ES_AUTOHSCROLL : 수평방향으로 자동 이동
 Multiline Edit 컨트롤 생성
m_wndEdit.Create (WS_CHILD ¦ WS_VISIBLE ¦ WS_BORDER ¦
WS_HSCROLL ¦ WS_VSCROLL ¦ ES_MULTILINE, rect, this,
IDC_EDIT);
133
7. MDI
(Multiple Document Interface)
134
분할윈도우
 동적 분할 윈도우(Dynamic Split Window)
•
•
프로그램이 실행 중에 윈도우를 분할 가능
같은 데이터를 같은 방식으로 보여주되, 스크롤바를 이용하여 서로
다른 부분을 디스플레이
 정적 분할 윈도우(Static Split Window)
•
•
윈도우가 분할된 상태로 프로그램이 시작되고, 프로그램 실행 중에
분할된 윈도우 병합불가능
이용하면 같은 데이터라도 완전히 방식으로 표현가능
135
동적 분할 윈도우 구현
 Step 1: CSplitterWnd 클래스의 인스턴스 선언
•
CSplitterWnd m_wndSplitter;
 Step 2: OnCreateClient 함수 재정의
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs,
CCreateContext* pContext)
{
if (!m_wndSplitter.Create(this, 2, 2, CSize(10, 10), pContext))
{
TRACE0("분할 윈도우 생성에 실패 하였습니다.\n");
return FALSE; // failed to create
}
return TRUE;
}
 Step 3: 모든 View 를 갱신
•
View 클래스에서 UpdateAllViews(NULL); 호출
136
SDI vs. MDI
137
SDI vs. MDI
 CMDIFrameWnd와 CMDIChildWnd 클래스는 CFrameWnd
클래스에서 상속  프레임윈도우의 기능 가짐
 CMDIFrameWnd 클래스에는 CMDIChildWnd 클래스를 관리
 CMDIChildWnd 클래스에는 CMDIFrameWnd의 안쪽에 들어
가서 클래스의 관리를 받음
CWnd
CFrameWnd
CMDIFrameWnd
CMDIChildWnd
138
SDI 를 MDI 로 변환
1. 자식 프레임 윈도우 추가
• CMDIChildWnd에서 상속 받은 CChildFrame 클래스를 추가
2. 메인 프레임 윈도우의 기반 클래스 변경
3. 도큐먼트, 프레임 윈도우, 뷰 등록
1. CSingleDocTemplate->CMultiDocTemplate 으로 변경
2. RUNTIME_CLASS(CMainFrame)->
RUNTIME_CLASS(CChildFrame)으로 변경
4. AddDocTemplate 함수다음에 메인 프레임 생성
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
m_pMainWnd = pMainFrame;
5. 메인 프레임 윈도우의 생성자 함수를 public으로 변경
139
MDI 를 SDI 로 변환
1.
2.
3.
4.
5.
자식 프레임 윈도우 삭제
메인 프레임 윈도우의 기반 클래스 변경
도큐먼트, 프레임 윈도우, 뷰 등록
메인 프레임 생성
메인 프레임 윈도우에 동적 생성기능 추가
•
MainFrame에 있는 DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC
을 DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE로 변환
140
모든 뷰의 화면 갱신
void CMyClass::OnUpdateAllViews( )
{
CWinApp *pApp = AfxGetApp( );
POSITION posTemplate = pApp-> GetFirstDocTemplatePosition();
while(posTemplate)
{
CDocTemplate *pTemplate = pApp->GetNextDocTemplate(posTemplate);
POSITION posDoc = pTemplate->GetFirstDocPosition( )
while(posDoc)
{
CDocument *pDoc = pTemplate->GetNextDoc(posDoc);
POSITION posView = pDoc->GetFirstViewPosition( );
while(posView)
{
CView *pView = pDoc->GetNextView(posView);
pView->Invalidate( );
}
}
}
}
141
파일 메뉴 처리
ID_FILE_NEW
ID_FILE_OPEN
ID_FILE_SAVE
ID_FILE_SAVE_AS
142
파일 메뉴 처리
ID_FILE_NEW
ID_FILE_OPEN
ID_FILE_SAVE
ID_FILE_SAVE_AS
CWinApp 클래스
CDocument 클래스
OnFileNew( )
커맨드 핸들러 함수
새로운 도큐먼트 생성
새로운 인스턴스 생성됨
CDocument의 멤버 함수
OnNewDocument( ) 호출
OnNewDocument( ) 호출됨
OnFileOpen( )
커맨드 핸들러 함수
파일명을 입력 받음
OnOpenDocument( ) 함수의
인자로 넘겨 받음
새로운 도큐먼트 생성
새로운 인스턴스 생성됨
CDocument의 멤버 함수
OnOpenDocument( ) 호출
OnOpenDocument( ) 호출됨
Serialize( ) 함수 호출
OnFileSave( )
커맨드 핸들러 함수
처음 저장하는 경우:
파일명을 입력 받음
OnSaveDocument( ) 함수의
인자로 넘겨 받음
CDocument의 멤버 함수
OnSaveDocument( ) 호출
OnSaveDocument( ) 호출됨
Serialize( ) 함수 호출
OnFileSaveAs( )
커맨드 핸들러 함수
OnFileSave( )
함수와 같은 동작
143
Serialize
void CMyDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// 저장하기
ar << n;
}
else
{
// 읽어오기
ar >> n;
}
}
144
다중 도큐먼트 타입 MDI
145
Document Template
BOOL CDrawApp::InitInstance()
{
// …
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(
IDR_DRAWTYPE,
RUNTIME_CLASS(CDrawDoc),
RUNTIME_CLASS(CChildFrame),
RUNTIME_CLASS(CDrawView));
AddDocTemplate(pDocTemplate);
pDocTemplate = new CMultiDocTemplate(
IDR_TEXTTYPE,
RUNTIME_CLASS(CTextDoc),
RUNTIME_CLASS(CTextFrame),
RUNTIME_CLASS(CTextView));
AddDocTemplate(pDocTemplate);
// …
}
146
Document Template
 도큐먼트와 연결된 문자열의 항목에 따른 의미
항목
1
IDR_DrawTYPE 의 예
설정되어 있지 않음
용도
단일 도큐먼트 프로그램의 타이틀 바에 표시하는
문자열
2
Text
새로 생성된 도큐먼트의 디폴트 파일명
3
Text
새로 생성될 도큐먼트의 종류를 물어보는 대화상자
에 출력될 문자열
4
Text Files (*.txt)
열기 대화상자의 [파일 형식] Combo Box 컨트롤에
추가될 필터 이름
5
. Text
확장자
6
Text.Document
레지스트리에 저장되는 도큐먼트 유형 ID
7
Text Document
레지스트리에 저장되는 도큐먼트 유형 이름
147
도큐먼트 인스턴스 관리
CWinApp
CMultiDocTemplate
CDocument
CView
CView
CMultiDocTemplate
CDocument
CView
CDocument
CView
CDocument
CView
CView
148
OnFileNew
void CDrawApp::OnFileNew()
{
POSITION pos = GetFirstDocTemplatePosition( );
CDocTemplate *pTemplate;
for(int i=0 ; i<N ; i++)
pTemplate = GetNextDocTemplate(pos);
pTemplate->OpenDocumentFile(NULL);
}
149
OnFileOpen
150
OnFileOpen
void CDrawApp::OnFileOpen()
{
char szFilter[] = "Draw파일(*.drw), Text파일(*.txt) | *.drw;*.txt
|모든파일(*.*)|*.*||";
CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, szFilter);
if(dlg.DoModal( ) == IDOK)
OpenDocumentFile(dlg.GetPathName());
}
if(dlg.DoModal( ) == IDOK)
for(POSITION pos = dlg.GetStartPosition( ); pos != NULL ; )
OpenDocumentFile(dlg.GetNextPathName(pos));
151
Additional Function of CDocument
 OnCloseDocument : Called to close the document.
 OnNewDocument : Called to create a new document.
 OnOpenDocument : Called to open an existing document.
 OnSaveDocument : Called to save the document to disk.
152
Additional Function of CDocument
 IsModified: Indicates whether the document has been
modified since it was last saved.
 SetModifiedFlag: Sets a flag indicating that you have modified
the document since it was last saved.
 SetPathName: Sets the path of the data file used by the
document.
 SetTitle: Sets the document's title.
153
Additional Function of CView
 OnActivateView: Called when a view is activated.
 OnActivateFrame: Called when the frame window containing
the view is activated or deactivated.
 OnDraw: Called to render an image of the document for
screen display, printing, or print preview. Implementation
required.
 OnBeginPrinting, OnEndPrinting, OnEndPrintPreview,
OnPreparePrinting, OnPrint
154
CDocument & CView Interaction
 GetFirstViewPosition, GetNextView
POSITION pos = GetFirstViewPosition();
while (pos != NULL)
{
CView* pView = GetNextView(pos);
pView->Invalidate();
}
 GetDocument
155
CDocument & CView Interaction
Document
void UpdateAllViews( CView* pSender, LPARAM lHint = 0L,
CObject* pHint = NULL );
View 1
virtual void OnUpdate( CView* pSender, LPARAM lHint,
CObject* pHint );
View 2
virtual void OnUpdate( CView* pSender, LPARAM lHint,
CObject* pHint );
156
드래그 앤 드롭에 의한 파일 열기
BOOL CDrawApp::InitInstance()
{
//…
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
m_pMainWnd = pMainFrame;
// Enable drag/drop open
m_pMainWnd->DragAcceptFiles();
//…
}
157
8. Serialization
158
데이터 저장 및 읽어오기
 CObject 클래스에는 데이터를 저장하고 읽어오는 Serialize 함수
가 존재
 CObject 를 상속받은 클래스는 Serialize 함수를 이용하여 멤버
변수의 값을 읽고 저장가능
 Serialize 함수를 오버로딩하여 사용
159
Serialize 함수의 호출
 CDocument 파생 클래스는 CObject 클래스의 Serialize 함수를
오버라이딩하고 있슴
 CDocument 파생 클래스에서 Serialize 함수를 오버라이딩 하면
멤버 변수를 디스크에 저장하거나 읽어올 수 있슴
160
어플리케이션 프레임 워크의 파일 메뉴 처리 기능
 ID_FILE_NEW, ID_FILE_OPEN, ID_FILE_SAVE,
ID_FILE_SAVE_AS 는 자동으로 처리
 CWinApp에서 전처리를 하고 CDocument 클래스로 넘긴다.
ID_FILE_NEW
ID_FILE_OPEN
ID_FILE_SAVE
ID_FILE_SAVE_AS
161
파일 메뉴 처리
ID_FILE_NEW
ID_FILE_OPEN
ID_FILE_SAVE
ID_FILE_SAVE_AS
CWinApp 클래스
CDocument 클래스
OnFileNew( )
커맨드 핸들러 함수
새로운 도큐먼트 생성
새로운 인스턴스 생성됨
CDocument의 멤버 함수
OnNewDocument( ) 호출
OnNewDocument( ) 호출됨
OnFileOpen( )
커맨드 핸들러 함수
파일명을 입력 받음
OnOpenDocument( ) 함수의
인자로 넘겨 받음
새로운 도큐먼트 생성
새로운 인스턴스 생성됨
CDocument의 멤버 함수
OnOpenDocument( ) 호출
OnOpenDocument( ) 호출됨
Serialize( ) 함수 호출
OnFileSave( )
커맨드 핸들러 함수
처음 저장하는 경우:
파일명을 입력 받음
OnSaveDocument( ) 함수의
인자로 넘겨 받음
CDocument의 멤버 함수
OnSaveDocument( ) 호출
OnSaveDocument( ) 호출됨
Serialize( ) 함수 호출
OnFileSaveAs( )
커맨드 핸들러 함수
OnFileSave( )
함수와 같은 동작
162
Serialize
 CDocument 파생 클래스에는 Serialize 함수가 미리 오
버라이딩 된다.
void CDrawCrossDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
ar << n1 << n2;
}
else
{
// TODO: add loading code here
ar >> n1 >> n2;
}
}
163
CArchive 클래스
 CDocument 클래스와 CFile 클래스를 연결해 주기 위한 클래스
• CFile 는 파일을 관리하는 클래스
 OnOpenDocument 함수와 OnSaveDocument 함수가
CArchive 오브젝트와 CFile 오브젝트를 연결
 IsStoring() : 읽기상태 또는 저장상태를 판별
CDocument
Serialize
CArchive
CMemFile
CFile
메모리
디스크
CSocketFile
네트워크
164
데이터 저장 및 읽어오기
방법


CDocument 클래스의 OnOpenDocument 함수와
OnSaveDocument 함수를 오버라이딩하여 각각 데이터를 읽
어오는 루틴과 저장하는 루틴을 삽입
CDocument 클래스의 Serialize 함수를 오버라이딩 해서 데이
터를 읽어오는 루틴과 저장하는 루틴을 함께 구현
165
OnOpenDocument 와 OnSaveDocument 를 사용
BOOL CDrawCrossDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
// TODO: Add your specialized creation code here
return TRUE;
}
BOOL CDrawCrossDoc::OnSaveDocument(LPCTSTR lpszPathName)
{
// TODO: Add your specialized code here and/or call the base class
return CDocument::OnSaveDocument(lpszPathName);
}
166
Serialize 함수를 사용
void CDrawCrossDoc::Serialize(CArchive& ar)
{
int i;
if (ar.IsStoring())
{
ar << m_nCount;
for(i = 0 ; i <= m_nCount ; i++) {
ar << m_ptData[i];
}
}
else
{
ar >> m_nCount;
for(i = 0 ; i <= m_nCount ; i++) {
ar >> m_ptData[i];
}
}
}
167
9. Collection Class
168
CObList Construction and Tail Access
class CAge : public CObject
{
int m_years;
public:
CAge( int age=0 ) { m_years = age; }
};

CObList::CObList( int nBlockSize = 10 );
•

nBlockSize - The memory-allocation granularity for extending the list.
POSITION AddTail( CObject* newElement );
•
Adds a new element or list of elements to the tail of this list. The list can be empty
before the operation.
CObList list;
list.AddTail( new CAge( 21 ) );
list.AddTail( new CAge( 40 ) ); // List now contains (21, 40).
169
CObList Iteration
 POSITION CObList::GetHeadPosition()
•
Gets the position of the head element of this list.
 CObject* CObList::GetNext( POSITION& rPosition )
•
Gets the list element identified by rPosition, then sets rPosition to
the POSITION value of the next entry in the list.
 CObject* GetAt( POSITION position ) const
•
GetAt retrieves the CObject pointer associated with a given
position
for( pos = list.GetHeadPosition(); pos != NULL; )
{
list.GetNext( pos );
}
170
CObList Removal
 void CObList::RemoveAll()
•
Removes all the elements from this list and frees the associated
CObList memory. It is your responsibility to delete the objects
themselves.
CObList list;
CAge* pa1;
CAge* pa2;
ASSERT( list.IsEmpty()); // Yes it is.
list.AddHead( pa1 = new CAge( 21 ) );
list.AddHead( pa2 = new CAge( 40 ) ); // List now contains (40, 21).
ASSERT( !list.IsEmpty()); // No it isn't.
list.RemoveAll(); // CAge's aren't destroyed.
ASSERT( list.IsEmpty()); // Yes it is.
delete pa1; // Now delete the CAge objects.
delete pa2;
171
10. 고급그래픽
172
비트맵 그래픽
 비트맵 그래픽 vs 벡터 그래픽
 비트맵
•
작은 점들의 2차원 배열을 이용하여 영상정보를 표현
 벡터 그래픽
•
선, 면, 호, 원, 곡선, 다각형 등 그래픽스의 구성요소가 되는 객체의
조합으로 영상정보를 표현
픽셀
선
0
30
50
30
50
80
50
80
80
사각형
키 포인트
원
80
100 120
100 120 140
100 120 140 180
100 120 140 180 200
100 120 140 180 200 220
120 140 180 200 220 240
173
Bitmap GDI Object
 비트맵 GDI 오브젝트
•
•
윈도우에서는 비트맵을 하나의 GDI 오브젝트로 채택
CBitmap 클래스 cf) CPen , CBrush
 그래픽 함수들은 GDI 오브젝트를 참조하여 그래픽 작업 수행
 비트맵 GDI 오브젝트를 참조하는 그래픽 함수
•
•
•
BitBlt
 Bit Block Transfer의 약자
 임의의 DC에서 다른 DC로 비트맵 블록을 전송
StretchBlt
 임의이 DC에서 다른 DC로 비트맵 블록을 전송하되, 확대 또는
축소를 해서 전송
cf) 다른 그래픽함수와 달리 DC가 2개가 필요
174
비트맵을 출력시키는 전체 과정
윈도우
MemDC
WinDC
(xSrc, ySrc)
(x, y)
nWidth
BitBlt
nHeight
SelectObject
CBitmap
LoadBitmap
Res ource
175
화면 DC와 메모리 DC 만들기
 비트맵이 출력될 화면 윈도우의 DC
•

CClientDC WinDC(this);
메모리에 만들어진 DC
•
CDC MemDC;
 메모리 상에 존재하는 MemDC로부터 화면 윈도우로부터 얻어
진 WinDC로 비트맵 블록을 전송
176
화면 DC와 호환성을 갖는 메모리 DC 만들기
 비트맵 블록 전송을 위하여는 DC 간에 호환성을 가져야 한다.
 MemDC.CreateCompatibleDC(&WinDC);
•
MemDC와 WinDC는 호환성을 갖게 되어 서로 비트맵 블록 전송
이 가능
177
비트맵 읽어오기
 비트맵 데이터를 읽어오고, 관리하는 기능은 CBitmap 클래스가
수행
 리소스에 저장되어 있는 비트맵 데이터 로드
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP1);
 비트맵을 DC에 선택
•
CBitmap *pOldBitmap = (CBitmap )MemDC.SelectObject(&bitmap);
178
비트맵 블록 전송
 BOOL CDC::BitBlt(int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int
xSrc, int ySrc, DWORD dwRop )
인자
의미
x
화면에 출력할 x 좌표
y
화면에 출력할 y 좌표
nWidth
화면에 출력할 그림의 폭
nHeight
화면에 출력할 그림의 높이
pSrcDC
비트맵 블록을 전송할 소스 DC 의 포인터
xSrc
소스 비트맵에서 전송을 시작할 x 좌표
ySrc
소스 비트맵에서 전송을 시작할 y 좌표
dwRop
래스터 오퍼레이션 코드
Ex) WinDC.BitBlt(100, 200, 20, 30, &MemDC, 30, 40, SRCCOPY);
179
Bitmap 출력
void CMyWnd::DrawBitmap( )
{
CClientDC WinDC(this);
// 윈도우 DC를 얻음
CDC MemDC;
// 메모리 DC를 만듦
// MemDC를 WinDC와 호환성 있게 만들어 줌
MemDC.CreateCompatibleDC(&WinDC);
// 리소스에서 비트맵을 읽어옴
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP1);
// 비트맵을 DC에 선택
CBitmap *pOldBitmap = (CBitmap *)MemDC.SelectObject(&bitmap);
// 비트맵 블록을 전송
WinDC.BitBlt(100, 200, 20, 30, &MemDC, 30, 40, SRCCOPY);
// DC 복원
MemDC. SelectObject(pOldBitmap);
}
180
비트맵의 확대/축소
void CBMPView::OnDraw(CDC* pDC)
{
// 호환성 있는 메모리 DC를 생성
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
// 리소스에서 비트맵을 읽어 들여 DC에 선택
CBitmap bitmap;
bitmap. LoadBitmap(IDB_MAN);
CBitmap *pOldBitmap = (CBitmap *)MemDC.SelectObject(&bitmap);
// 비트맵 블록 전송
pDC->BitBlt(50, 50, 32, 32, &MemDC, 0, 0, SRCCOPY);
// 상하좌우로 뒤집어 출력
pDC->StretchBlt(100, 50, 32, 32, &MemDC, 32, 32, -32, -32, SRCCOPY);
// 2배 확대하여 출력
pDC->StretchBlt(150, 50, 64, 64, &MemDC, 0, 0, 32, 32, SRCCOPY);
// DC 복원
MemDC.SelectObject(pOldBitmap);
}
181
배경과 합성
마스크이미지와
배경이미지를
AND 연산
비트맵과
OR 연산
182
배경과 합성
static int nAnimate;
CClientDC dc(this);
CDC MemDC; // 호환성 있는 메모리 DC를 생성
MemDC.CreateCompatibleDC(&dc);
CBitmap bmpMask, bmpMan, bmpBack; // 리소스에서 비트맵 읽기
bmpMask.LoadBitmap(IDB_MASK);
bmpMan.LoadBitmap(IDB_MAN);
bmpBack.LoadBitmap(IDB_BACK);
CBitmap *pOldBitmap = (CBitmap *)MemDC.SelectObject(&bmpBack); // 배경 다시 그리기
dc.BitBlt(50, 50, 32, 32, &MemDC, 50, 50, SRCCOPY);
MemDC.SelectObject(&bmpMask); // 마스크 그리기
dc.BitBlt(50, 50, 32, 32, &MemDC, 32*nAnimate, 0, SRCAND);
MemDC.SelectObject(&bmpMan); // 아이콘 그림 그리기
dc.BitBlt(50, 50, 32, 32, &MemDC, 32*nAnimate, 0, SRCPAINT);
if(++nAnimate > 3) nAnimate = 0; // 애니메이션 카운터를 증가시킴
MemDC.SelectObject(pOldBitmap);
183
메모리 비트맵
 화면에는 보이지 않고, 메모리 상에만 존재 하는 비트맵
 고속 그래픽 출력을 위한 버퍼 로 사용 (더블버퍼링)
•
여러 출력 함수를 호출하면 그려지는 과정이 드러나면서 화면이 깜
박거려 보임
 비트맵을 블록 단위로 전송하는 것은 아주 고속으로 수행
184
메모리 비트맵에 도형 그려 출력
// 화면 DC와 호환성 있는 메모리 DC를 만듦
CDC BufferDC;
BufferDC.CreateCompatibleDC(pDC);
// 화면 DC와 호환성 있는 메모리 비트맵을 만듦
CBitmap bmpBuffer;
bmpBuffer.CreateCompatibleBitmap(pDC, 200, 200);
// 메모리 DC에 메모리 비트맵을 선택
CBitmap *pOldBitmap = (CBitmap *)BufferDC.SelectObject(&bmpBuffer);
// 메모리 DC에 그림을 그림
BufferDC.Rectangle(0, 0, 200, 200);
BufferDC.Rectangle(10, 10, 100, 100);
BufferDC.Ellipse(70, 70, 180, 180);
// 메모리 비트맵에 그려진 내용을 화면으로 전송
pDC->BitBlt(0, 0, 200, 200, &BufferDC, 0, 0, SRCCOPY);
// DC 복원
BufferDC.SelectObject(pOldBitmap);
185
11. 고급 컨트롤 제어
186
컨트롤 서브클래싱
 어떤 윈도우에 보내지는 메시지를 그 윈도우가 받기 전에 다른
윈도우에서 가로채어 처리하는 프로그래밍 테크닉
 서브클래싱에 의한 기능 수정
 컨트롤의 기능 중 수정하고자 하는 기능이 있으면 서브클래싱을
이용
 컨트롤의 서브클래싱
•
•
•
다이얼로그 템플릿을 이용하여 생성되는 원래 컨트롤 클래스를 그
대로 두고, 그 컨트롤로 가는 메시지를 가로채어 컨트롤의 동작을
변경
BOOL SubclassDlgItem(UINT nID, CWnd *pWnd)
 nID : 서브클래싱하고자 하는 컨트롤의 다이얼로그 템플릿에서
의 ID
 pWnd : 컨트롤의 부모 윈도우의 포인터
실제 프로그래밍을 할 때는 SubclassDlgItem 함수를 직접 호출해
주지 않아도 됨
187
컨트롤 서브클래싱
 구현할 기능
숫자 이외의 다른
문자를 입력하면
경고음이 출력
188
컨트롤 서브클래싱
 새로운 기능을 구현할 CEdit 파생 클래스
189
컨트롤 서브클래싱
 WM_CHAR 메시지를 처리
 백 스페이스 키나 숫자키가 눌리면 원래의 동작을 그대로 수행
 다른 키가 눌렸을 때는 경고음을 출력
void CNumEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if((nChar>='0' && nChar<='9') || (nChar==VK_BACK))
CEdit::OnChar(nChar, nRepCnt, nFlags);
else
MessageBeep(MB_ICONASTERISK);
}
190
Control 형 멤버 변수 연결
 다이얼로그 박스에 올라가 있는 편집 상자 컨트롤의 메시지를
가로채서 동작하도록 서브클래싱
191
컨트롤과 서브클래싱 클래스를 연결
#include "NumEdit.h"
#include "CharEdit.h"
void CEditDlg::DoDataExchange(CDataExchange* pDX)
class CEditDlg : public CDialog
{
{
CDialog::DoDataExchange(pDX);
//…
//{{AFX_DATA_MAP(CSubclassDlg)
//{{AFX_DATA(CSubclassDlg)
DDX_Control(pDX, IDC_EDIT1, m_ctrlNumEdit);
enum { IDD = IDD_SUBCLASSING };
DDX_Control(pDX, IDC_EDIT2, m_ctrlCharEdit);
CNumEdit
m_ctrlNumEdit;
//}}AFX_DATA_MAP
CCharEdit
m_ctrlCharEdit;
}
//}}AFX_DATA
//…
}
192
프로퍼티시트
 프로퍼티 시트(Property Sheet)
•
여러 개의 탭으로 이루어진 페이지들을 함께 가지고 있는 일종의
다이얼로그 박스
Property Sheet
Property Page
확인
Page 2
취소
Page 3
적용
193
프로퍼티 시트와 프로퍼티 페이지 클래스
 CProprtyPage 클래스가 CDialog 클래스에서 상속
 CPropertySheet 클래스는 CDialog에서 상속을 받지 않음
CWnd
CPropertySheet
CDialog
CPropertyPage
194
프로퍼티 페이지 만들기
 다이얼로그 템플릿 디자인
195
프로퍼티 페이지 만들기
 프로퍼티 페이지 클래스 만들기
196
프로퍼티 시트 만들기
 프로퍼티 시트 클래스 만들기
197
프로퍼티 시트에 프로퍼티 페이지 등록
 프로퍼티 시트에 프로퍼티 페이지를 등록하려면 프로퍼티 시트
클래스에 프로퍼티 페이지의 인스턴스가 있어야 함
#include "page1.h"
#include "page2.h"
#include "page3.h"
class CSheetDlg : public CPropertySheet
{
//…
CPage1 m_page1;
CPage2 m_page2;
CPage3 m_page3;
//…
}
198
프로퍼티 시트에 프로퍼티 페이지 등록
 CPropertySheet 파생 클래스의 생성자 함수에서
CPropertySheet 클래스의 멤버 함수 AddPage를 호출
CSheetDlg::CSheetDlg(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
{
AddPage(&m_page1);
AddPage(&m_page2);
AddPage(&m_page3);
}
CSheetDlg::CSheetDlg(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
AddPage(&m_page1);
AddPage(&m_page2);
AddPage(&m_page3);
}
199
프로퍼티 시트를 다이얼로그 박스처럼 출력하기
 DoModal 함수를 호출하면 프로퍼티 시트가 다이얼로그 박스처
럼 화면에 출력
#include “SheetDlg.h”
void CPropertyView::OnPropertysheet()
{
CSheetDlg dlg(IDS_SHEET);
dlg.DoModal();
}
 프로퍼티 시트의 타이틀 바에 출력될 문자열
200
위저드 형식 다이얼로그 박스 만들기
 위저드 형식으로 옵션 변경
void CPropertyView::OnWizard()
{
CSheetDlg dlg(IDS_SHEET);
dlg.SetWizardMode( );
if(dlg.DoModal() == ID_WIZFINISH)
{
AfxMessageBox(dlg.UserInput());
}
}
201
Button 설정
 각각의 CPropertyPage 파생 클래스에 대해 ClassWizard를 이
용하여 OnSetActive 함수를 오버라이딩
BOOL CPage1::OnSetActive()
{
((CPropertySheet *)GetParent())-> SetWizardButtons(PSWIZB_NEXT);
return CPropertyPage::OnSetActive();
}
BOOL CPage2::OnSetActive()
{
((CPropertySheet *)GetParent())-> SetWizardButtons(PSWIZB_BACK|PSWIZB_NEXT);
return CPropertyPage::OnSetActive();
}
BOOL CPage3::OnSetActive()
{
((CPropertySheet *)GetParent())->SetWizardButtons(PSWIZB_BACK|PSWIZB_FINISH);
return CPropertyPage::OnSetActive();
}
202
12. 고급 사용자 인터페이스
203
메뉴
 메인 메뉴얻기
•
CMenu* CWnd::GetMenu( ) const;
 팝업 메뉴 (서브 메뉴) 얻기
•
CMenu* CMenu::GetSubMenu( int nPos ) const;
 사용법
CMenu*pMainMenu = GetMenu( );
CMenu *pPopupMenu = pMainMenu->GetSubMenu(2);
204
메뉴 제어
 메뉴 항목 추가
•
AppendMenu(MF_STRING, ID_FILE_NEW, “새 파일(&N)”);
 Separator 추가
•
AppendMenu(MF_SEPARATOR)
 팝업 메뉴 추가
CMenu menuPopup;
menuPopup.CreateMenu();
menuPopup.AppendMenu((MF_STRING, ID_FILE_NEW, “새 파일(&N)”);
menuPopup.AppendMenu(MF_SEPARATOR)
menuPopup.AppendMenu((MF_STRING, ID_FILE_OPEN, “열기(&O)”);
CMenu*pMainMenu = GetMenu( );
CMenu *pPopupMenu = pMainMenu->GetSubMenu(2);
pPopupMenu->AppendMenu(MF_POPUP, (UINT)menuPopup, “팝업(&P)”);
menuPopup.Detach( );
205
메뉴 항목 변경
 커맨트 ID를 이용한 메뉴 항목 변경
ModifyMenu(IDM_EXPAND, MF_STRING | MF_BYCOMMAND,
IDM_SHRINK, “축소(&S)”);
•

메뉴 항목의 위치를 이용한 메뉴 항목 변경
•
ModifyMenu(5, MF_STRING | MF_BYPOSITION, IDM_SHRINK,
“축소(&S)”);
 메뉴 항목 삭제
•
•
pPopupMenu->DeleteMenu(2, MF_BYPOSITION);
pPopupMenu->DeleteMenu(ID_FILE_NEW, MF_BYCOMMAND);
206
다이나믹 메뉴
 메뉴 확장 명령 처리
void CMainFrame::OnExpand()
{
CMenu *pMenu = GetMenu()->GetSubMenu(1);
pMenu->ModifyMenu(IDM_EXPAND,
MF_STRING|MF_BYCOMMAND, IDM_SHRINK, "메뉴 축소(&S)");
pMenu->AppendMenu(MF_SEPARATOR);
pMenu->AppendMenu(MF_STRING, ID_FILE_NEW, "새 파일(&N)");
pMenu->AppendMenu(MF_STRING, ID_FILE_OPEN, "열기(&O)...");
pMenu->AppendMenu(MF_STRING, ID_FILE_SAVE, "저장(&S)");
}
207
다이나믹 메뉴
 메뉴 축소
•
resource symbol 에서 IDM_SHRINK 추가
void CMainFrame::OnShrink()
{
CMenu *pMenu = GetMenu()->GetSubMenu(1);
Menu->ModifyMenu(IDM_SHRINK,
MF_STRING|MF_BYCOMMAND, IDM_EXPAND, "메뉴 확장(&E)");
pMenu->DeleteMenu(1, MF_BYPOSITION);
pMenu->DeleteMenu(ID_FILE_NEW, MF_BYCOMMAND);
pMenu->DeleteMenu(ID_FILE_OPEN, MF_BYCOMMAND);
pMenu->DeleteMenu(ID_FILE_SAVE, MF_BYCOMMAND);
}
208
시스템 메뉴
 시스템 메뉴가 선택되면 WM_SYSCOMMAND 메시지가 발생
 OnSysCommand 메시지 핸들러 함수
•
afx_msg void OnSysCommand( UINT nID, LPARAM lParam );

nID : SC_CLOSE, SC_HSCROLL, SC_MAXIMIZE, SC_MINIMIZE,
SC_MOVE, SC_NEXTWINDOW, SC_PREVWINDOW, SC_RESTORE,
SC_SCREENSAVE, SC_SIZE, SC_TASKLIST, SC_VSCROLL
void CChildFrame::OnSysCommand(UINT nID, LPARAM lParam)
{
if( nID != SC_CLOSE)
CMDIChildWnd::OnSysCommand(nID, lParam);
}
209
시스템 메뉴 편집
BOOL CSysMenuDlg::OnInitDialog()
{
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
}
210
영역 선택을 위한 트래커
 CRectTracker 클래스의 인스턴스 생성
 선택 영역 초기화 및 스타일 설정
class CTrackerDoc : public CDocument
{
CRectTracker m_tracker;
};
CTrackerDoc::CTrackerDoc()
{
m_tracker.m_rect.left = 100;
m_tracker.m_rect.top = 100;
m_tracker.m_rect.right = 200;
m_tracker.m_rect.bottom = 200;
m_tracker.m_nStyle = CRectTracker::hatchedBorder|CRectTracker::resizeOutside;
}
void CTrackerView::OnDraw(CDC* pDC){
pDoc->m_tracker.Draw(pDC); //트래커 표시
}
211
트래커 동작
 HitTest(CPoint point)
•
•
•
트래커의 외부가 클릭되면 –1리턴
트래커의 8개의 핸들 중 하나가 클릭되면 0부터 7까지의 값 리턴
트래커의 내부가 클릭되면 8 리턴
void CTrackerView::OnLButtonDown(UINT nFlags, CPoint point)
{
CTrackerDoc* pDoc = GetDocument();
if (pDoc->m_tracker.HitTest(point) < 0)
// 마우스를 드래그 하여 새로운 영역을 선택
pDoc->m_tracker.TrackRubberBand(this, point);
else // 이미 선택되어 있는 영역을 변형
pDoc->m_tracker.Track(this, point);
Invalidate();
CView::OnLButtonDown(nFlags, point);
}
212
13. 파일 입출력
213
CFile 클래스 – 파일 열기
파일 열고 닫기
CFile file;
file.Open(_T(“File.txt”), CFile::modeReadWrite);
// … 파일에 데이터를 읽거나 쓰는 작업을 수행
file.Close( );
파일 접근 모드
접근 모드
설명
CFile::modeRead
파일을 읽기만 할 수 있습니다 .
CFile::modeWrite
파일에 쓰기만 할 수 있습니다 .
CFile::modeReadWrite
읽고 쓰기를 모두 할 수 있습니다 .
CFile::modeCreate
파일을 새로이 생성합니다 .
CFile::modeNoTruncate
기존에 있는 파일에 데이터를 기존의 파일을 덮어쓰지 않고 ,
맨 뒤에 추가해 줍니다 .
214
CFile 클래스
 파일 공유 모드
공유 모드
설명
CFile::shareDenyNone
공유하도록 파일을 엽니다 .
CFile::shareDenyRead
다른 프로그램의 읽기 접근을 거부합니다 .
CFile::shareDenyWrite
다른 프로그램의 쓰기 접근을 거부합니다 .
CFile::shareExclusive
다른 프로그램의 읽기, 쓰기를 모두 거부합니다 . (기본값 )
file.Open(_T(“File.txt”), CFile::modeCreate | CFile::modeWrite |
CFile::modeNoTruncate);
215
CFile 클래스 – 데이터 입출력
 파일에 데이터 쓰기
int buffer[1000];
CFile file;
file.Open(_(“File.dat”, CFile::modeCreate | CFile::modeWrite);
file.Write(buffer, 1000 * sizeof(int));
file.Close( );
 파일에서 데이터 읽기
CFile file;
file.Open(_T(“File.dat”), CFile::modeRead);
int nLength = file.GetLength( );
int *buffer = new BYTE [nLength];
file.Read(buffer, nLength);
file.Close( );
216
CFile 클래스 - 에러 처리
 에러의 가능성
•
•
•
지정한 파일이 디스크에 존재하지 않음
다른 프로그램에서 파일을 사용
디스크가 모두 차서 쓸 공간 부족
void main()
{
TRY{
int buffer[1000];
CFile file;
file.Open(_T("File.dat"), CFile::modeCreate | CFile::modeWrite);
file.Write(buffer, 1000 * sizeof(int));
file.Close( );
}
CATCH(CFileException, e){
e->ReportError( );
}
END_CATCH
}
217
CFile 클래스
 기타 파일 처리 함수
멤버 함수
설명
GetFilePath
파일의 전체 경로명을 반환합니다 .
GetFileName
파일 이름을 반환합니다 .
GetFileTitle
확장자를 제외한 파일 이름을 반환합니다 .
GetStatus
파일이 생성된 시간, 최종 변경된 시간, 크기 , 속성 등 파일의 상태를
얻습니다 .
SetStatus
파일의 상태를 지정합니다 .
Remove
파일을 지웁니다 .
Rename
파일의 이름을 바꿉니다 .
218
CArchive 클래스
 CDocument 클래스와 CFile 클래스를 연결해 주기 위한 클래스
CDocument
Serialize
CArchive
CMemFile
CFile
메모리
디스크
CSocketFile
네트워크
219
CArchive 클래스와 CFile 클래스 연결
 쓰기모드 생성
CFile file;
file.Open(_T("File.dat"), CFile::modeCreate |
CFile::modeWrite);
CArchive ar(&file, CArchive::store);
ar << data;
 읽기 모드 생성
CFile file;
file.Open(_T("File.dat"), CFile::modeRead);
CArchive ar(&file, CArchive::load);
ar >> data;
220
CArchive 클래스를 이용하여 읽고 쓰기
 데이터 입출력
double pi = 3.141592653;
ar.Write(&pi, sizeof(double));
ar.Read(&pi, sizeof(double));
 입출력 연산자 오버로딩
double pi = 3.141592653;
ar << pi;
ar >> pi;
 텍스트 입출력
double pi = 3.141592653;
CString str;
str.Format(“%f\n”, pi);
ar.WriteString(str);
ar.ReadString(str);
221
CFileDialog 클래스
 CFileDialog 클래스의 인스턴스를 선언하고, DoModal 함수를
호출
char szFilter[] = "Image (*.BMP, *.GIF, *.JPG)|*.BMP;*.GIF;*.JPG |All Files(*.*)|*.*||";
CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY, szFilter);
if(IDOK == dlg.DoModal())
{
CString strPathName = dlg.GetPathName();
}
222
CFileDialog 클래스

CFileDialog(BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL,
LPCTSTR lpszFileName = NULL, DWORD dwFlags =
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR l
pszFilter = NULL, CWnd *pParentWnd = NULL)
•
•
•
•
•
•
bOpenFileDialog – TRUE는 대화상자 타이틀 바에 “열기”라고 출
력되고, FALSE는 “다른 이름으로 저장” 출력
lpszDefExt - 기본 확장자
lpszFileName – 대화상자의 “파일 이름” 에디터 컨트롤에 출력될
파일명을 지정
dwFlags – 속성 설정
lpszFilter - 출력될 파일들을 확장자로 필터링
pParentWnd - 대화상자의 부모 윈도우를 지정
223
CFileDialog 클래스 속성
 파일 대화상자에 지정할 수 있는 속성 플래그
플래그
의미
OFN_EXPLORER
윈도우 탐색기 스타일로 출력합니다 .
OFN_ARROWMULTISELECT
파일을 한번에 여러 개 선택할 수 있습니다 .
OFN_CREATEPROMPT
존재하지 않는 파일명을 입력했을 경우 새로 생성하
겠냐는 메시지 박스를 출력합니다 .
OFN_FILEMUSTEXIST
존재하지 않는 파일명을 입력할 수 없도록 합니다 .
OFN_HIDEREADONLY
읽기 전용 파일은 출력하지 않습니다 .
OFN_LONGNAMES
긴 파일 이름 포맷을 지원하도록 합니다 .
OFN_OVERWRITEPROMPT
존재하는 파일명을 입력했을 경우 덮어쓰겠냐는 메
시지 박스를 출력합니다 .
OFN_PATHMUSTEXIST
이미 존재하는 디렉터리명만을 입력할 수 있습니다 .
224
CFileDialog 클래스의 멤버 함수
 다음 멤버 함수들을 호출하여 사용자의 입력 결과를 참조
함수
반환값
CString GetPathName
선택된 파일의 절대 경로
CString GetFileName
선택된 파일의 파일명과 확장자
CString GetFileExt
선택된 파일의 확장자
CString GetFIleTitle
선택된 파일의 파일명
BOOL GetReadOnlyPref
읽기 전용 여부
POSITION GetStartPosition
다중 선택의 경우
CString GetNextPathName
225
Serialize
 CFileDialog  CFile  CArchive 클래스로 이어지는 Serialize
 파일 직접 제어
void CMyDoc::OnFileExport( )
{
char szFilter[] = "Text File(*.txt)|*.txt|All Files(*.*)|*.*||";
CFileDialog dlg(FALSE, NULL, NULL, OFN_HIDEREADONLY, szFilter);
if(IDOK == dlg.DoModal())
{
CFile file;
file.Open( dlg.GetPathName(), CFile::modeCreate | CFile::modeWrite);
CArchive ar(&file, CArchive::store);
ar << data1;
ar << data2;
}
}
226
Serialize 가능한 클래스 만들기
1.
2.
3.
4.
5.
CObject 클래스로부터 직접 또는 간접적으로 상속을 받습니다.
생성자 함수를 만들어 줍니다.
헤더 파일에 DECLARE_SERIAL 매크로를 적어 줍니다.
소스 파일에 IMPLEMENT_SERIAL 매크로를 적어 줍니다.
Serialize 함수를 재정의 해서 데이터를 저장하는 루틴을 넣어줍
니다.
227
데이터 형식
 <<나 >> 연산자로 CArchive에 저장하고 읽어올 수 있는 데이터
형
저장하고 읽어올 수 있는 데이터 형식
기본 데이터
BYTE, WORD, LONG, DWORD, float, double, int, UINT, short, char
MFC 클래스
CSize, CPoint, CRect, CString, CTime, CTimeSpan, COleVarient,
COleCurrency, COleDataeTime, COleDateTimeSpan
228
Serialize
 Point.h
class CPoint3D : public CObject
{
public:
DECLARE_SERIAL(CPoint3D)
int m_x, m_y, m_z;
CPoint3D();
CPoint3D(int x, int y, int z);
void Serialize(CArchive& ar);
};
229
Cont’d
 Point.cpp
#include "Point3D.h"
IMPLEMENT_SERIAL(CPoint3D, CObject, 1 VERSIONABLE_SCHEMA)
CPoint3D::CPoint3D( )
{
m_x = m_y = m_z = 0;
}
CPoint3D::CPoint3D(int x, int y, int z)
{
m_x = x; m_y = y; m_z = z;
}
void CPoint3D::Serialize(CArchive& ar)
{
CObject::Serialize(ar);
if(ar.IsStoring())
ar << m_x << m_y << m_z;
else
ar >> m_x >> m_y >> m_z;
}
230
Cont’d
 main.cpp
void main()
{
// 쓰기
TRY
{
CPoint3D point(10, 20, 30);
CFile file;
file.Open(_T("File.dat"), File::modeCreate | CFile::modeWrite);
CArchive ar(&file, CArchive::store);
ar << &point;
}
CATCH(CFileException, e)
{
e->ReportError();
}
END_CATCH
231
Cont’d
// 읽기
TRY
{
CPoint3D point;
CFile file;
file.Open(_T("File.dat"), File::modeRead);
CArchive ar(&file, CArchive::load);
ar >> &point;
TRACE("(%d, %d, %d)\n", point.m_x, point.m_y, point.m_z);
}
CATCH(CFileException, e)
{
e->ReportError();
}
END_CATCH
}
232
버전관리

IMPLEMENT_SERIAL 매크로에서 버전을 숫자로 지정하고
VERSIONALBLE_SCHEMA 속성 지정
•
IMPLEMENT_SERIAL (CLine, CObject, 2 ¦ VERSIONABLE_SCHEMA)
 CArchive::GetObjectSchema ()
저장된 버전을 리턴
 주의 : CLine 클래스의 Serialize 함수를 명시적으로 호출하지 말고 >>,
<< 연산자를 사용하여야 함
•
CLine* pLine = new CLine (CPoint (0, 0), CPoint (100, 50));
ar << pLine;
CLine line (CPoint (0, 0), CPoint (100, 50));
ar << line; //ERROR!
233
버전에 따른 로딩방법
void CLine::Serialize (CArchive& ar)
{
CObject::Serialize (ar);
if (ar.IsStoring ())
ar << m_ptFrom << m_ptTo << m_clrLine;
else {
UINT nSchema = ar.GetObjectSchema ();
switch (nSchema) {
case 1: // Version 1 CLine
case 2: // Version 2 CLine
default: // Unknown version
AfxThrowArchiveException (CArchiveException::badSchema);
break;
}
}
}
234
14. MFC Internals
235
RTTI (Run-Time Type Information)
 런타임시에 객체의 클래스 이름 얻기
class CObject
{
public:
virtual char* GetClassName() const { return NULL;}
};
class CMyClass : public CObject
{
public:
static char s_lpszClassName[];
virtual char* GetClassName() const { return s_lpszClassName;}
};
char CMyClass::s_lpszClassName[] = "CMyClass";
236
MFC CRuntimeClass 구조체
 MFC 에서는 CRuntimeClass 구조체가 앞 장에서의 static 멤버
s_lpszClassName을 대신한다.
struct CRuntimeClass
{
char m_lpszClassName[21];
int m_nObjectSize;
CObject* (*pfnCreateObject)();
CObject* CreateObject();
};
 DECLARE_DYNAMIC/IMPLEMENT_DYMANIC 매크로를
삽입하면 CRuntimeClass 구조체가 static 형의
class<class_name>라는 이름을 가진 멤버변수 추가
•
ex) CMyClass  static CRuntimeClass classCMyClass;
237
Run-time 시에 이름얻기
 RUNTIME_CLASS 매크로
•
클래스의 static 객체인 CRuntimeClass 에 대한 포인터는
RUNTIME_CLASS 매크로로 얻어온다
#define RUNTIME_CLASS(class_name) (&class_name::class##class_name)
//사용예
ASSERT(RUNTIME_CLASS(CMyClass)->m_lpszClassName == "CMyClass";
 GetRuntimeClass 함수는 클래스의 static 형인 CRuntimeClass
클래스 객체에 대한 포인터를 리턴
virtual CRuntimeClass* GetRuntimeClass() const { return &classCMyClass; }
 객체로부터 클래스 이름의 문자열을 얻으려면 가상함수인
virtual CObject::GetRuntimeClass()를 호출
ASSERT(pMyObject->GetRuntimeClass()->m_lpszClassName == "CMyClass");
238
동적생성
 CreateObject 함수로 객체를 동적으로 생성
static CObject* CMyClass::CreateObject() {
return new CMyClass; }
CObject* CRuntimeClass::CreateObject() { return (*pfnCreateObject)(); }
 간접적으로 객체 생성하기
CRuntimeClass* pRTC = RUNTIME_CLASS(CMyObject);
CMyClass* pMyObject = (CMyClass*)pRTC->CreateObjet();
 DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE 를 사
용하면 동적 생성기능을 추가
239
CObject Features




Run-time class information
Dynamic creation
Serialization
Run-time object diagnostics
240
Run-time Class Information
 CObject를 상속받고 DECLARE_DYNAMIC 매크로와
IMPLEMENT_DYNAMIC 매크로를 사용하면 run-time 시에 클
래스의 정보를 얻을 수 있다.
// MyClass.h
class CMyClass : public Object
{
DECLARE_DYNAMIC(CMyClass);
public:
CMyClass();
};
//MyClass.cpp
IMPLEMENT_DYNAMIC(CMyClass,CObject)
DemoRTCI()
{
CObject* pObject = new CMyClass;
if (pObject->IsKindOf(RUNTIME_CLASS(CMyClass))){
CMyClass* pMyObject = (MyClass*) pObject;
}
}
241
Dynamic Creation
 DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE 매크
로를 사용하면 RTCI 기능과 함께 동적생성기능도 추가
CRuntimeClass* pRuntimeClass = RUNTIME_CLASS(CMyClass);
CObject* pObject = pRuntimeClass->CreateObject();
ASSERT(pObject->IsKindOf(RUNTIME_CLASS(CMyClass));
 Document/View 에서의 동적생성기능
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CLineDrawDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CLineDrawView));
AddDocTemplate(pDocTemplate);
242
Inside Document/View Architecture
 CWindApp 클래스 내의 CDocManager 클래스가
CDocTemplate 을 관리
•
CDocManager* m_pDocManager;
void CWinApp::AddDocTemplate(CDocTemplate* pTemplate)
{
if (m_pDocManager == NULL)
m_pDocManager = new CDocManager;
m_pDocManager->AddDoTemplate(pTemplate);
}
 CWinApp의 도큐먼트 템플릿 관리 함수들은 CDocManager 의
함수들을 연결
•
AddDocTemplate(), GetFirstDocTemplatePosition(),
GetNextDocTemplate(), OnFileNew(), OnFileOpen(),
OpenDocumentFile(), SaveAllModified() ...
243
Function Call Flow Chart
CWinApp::OnFileOpen()
CWinApp::OnFileNew()
CDocManager::OnFileOpen()
CDocManager::OnFileNew()
CDocTemplate::OpenDocumentFile()
CDocTemplate::CreateNewDocument()
CDocTemplate::CreateNewFrame()
WM_CREATE
CFrameWnd::OnCreateClient()
CFrameWnd::CreateView()
CMyDocument::OnOpenDocument()
WM_INITIALUPDATE
메시지 발생
244