Transcript Part 1

ISLab ICE HUFS
Windows Programming
박상원
[email protected]
한국외국어대학교 정보통신공학과
ISLab ICE HUFS
서론
목차
• 객체지향이란?
• MFC의 역사
• MFC를 위한 C++의 기초
ISLab ICE HUFS
MFC Tutorial
3
객체지향 개념의 등장 배경
• 프로그래밍 언어의 발전
– 기계어 -> 어셈블리어 -> 고급언어
• 함수 기반 프로그래밍
– 1970년대 - 1980년대
• 소프트웨어의 위기
– 생산성 향상의 한계
• 객체지향 개념의 등장
– 1980년대
ISLab ICE HUFS
MFC Tutorial
4
객체지향이란?
메시지
객체
메쏘드 호출
이벤트
ISLab ICE HUFS
MFC Tutorial
5
객체지향의 핵심 내용(1)
• 객체란
– 데이타(자료구조; 상태변수)와 오퍼레이터(함수)가 하나로 묶여있는 형태
• 추상 데이타 타입(ADT;abstract data type)
– 클래스를 이용하여 표현
• 계승(inheritance)
– 동적 바인딩(dynamic binding)
– cf) Static binding
• 다형성(polymorphism)
– Overloading : 동일한 함수의 이름 사용 가능
– Overriding : 상위 클래스에서 정의된 함수를 하위 클래스에서 재 정의
– Template : 타입을 인자로 하여 새로운 타입을 생성
ISLab ICE HUFS
MFC Tutorial
6
MFC를 위한 C++의 기초
•
•
•
•
클래스
계승
생성자 및 소멸자
Virtual Function을 이용한 동적 바인딩
ISLab ICE HUFS
MFC Tutorial
7
클래스란?
• 객체를 기술할 수 있는 수단을 제공
– 자료 구조 (member data)
– 오퍼레이션 (member function)
모델링
실세계
컴퓨터세계
ISLab ICE HUFS
MFC Tutorial
8
클래스의 계승(1)
• 계승을 통한 코드의 재 사용 가능
– 생산성 향상
• 이름 충돌(name conflict) 발생
• 다중 계승의 문제점
– virtual base class로 계승
ISLab ICE HUFS
MFC Tutorial
9
클래스의 계승(2)
class B : virtual public A
{
...
};
A
int x;
class C : virtual public A
{
...
};
B
int y;
C
int z;
D
int z;
ISLab ICE HUFS
MFC Tutorial
10
생성자(1)
• 생성자(constructor) 호출
– 메모리 할당과 생성자는 별개
– 메모리 할당
• new : 힙(heap)에 객체 생성
• 지역변수 : 스택(stack)에 객체 생성
• 전역변수 : 프로그램 코드 영역에 객체 생성
– 생성자는 메모리 할당이 끝난 객체의 각 데이타 부분을 초기화하
는 역할
ISLab ICE HUFS
MFC Tutorial
11
생성자(2)
A::A(int n) : m_nNo(n)
{
}
A
int m_nNo
B::B(int i) : A( i )
{
ptr = new char[ i ];
}
B
char* ptr
A* pA = new B(3);
3
500
500
힙/스택/코드 영역
힙 (heap) 영역
ISLab ICE HUFS
MFC Tutorial
12
소멸자(1)
• 소멸자(destructor)의 virtual 함수화
– 소멸자는 객체 자체의 메모리 영역을 없애는 것이 아님
– 그 객체가 new 등을 이용하여 실행중에 만든 객체를 메모리에서
없애는 역할을 한다.
ISLab ICE HUFS
MFC Tutorial
13
소멸자(2)
A* ptr = new A;
delete ptr;
ptr = new B(3);
delete ptr; <- 문제 발생. A의 소멸자만 불린다.
3
500
500
접근못하는 메모리
(garbage)
힙/스택/코드 영역
힙 (heap) 영역
ISLab ICE HUFS
MFC Tutorial
14
Virtual Function(1)
• 동적 바인딩(dynamic binding)
– 프로그램의 수행 중에 실제 수행할 함수를 결정
– vitual function table(hidden pointer)
• 정적 바인딩(static binding)
ISLab ICE HUFS
MFC Tutorial
15
Virtual Function(2)
DrawObj
int a
DrawObj* p_obj;
virtual Draw()
p_obj = new Point;
p_obj->Draw();
Point
p_obj = new Line;
p_obj->Draw();
p_obj = new PolyLine;
p_obj->Draw();
Line
int x, y
Point start, end
virtual Draw()
virtual Draw()
virtual Calc()
PolyLine
Point[5] pt
virtual Draw()
ISLab ICE HUFS
MFC Tutorial
16
Virtual Function - 메모리 구조
p_obj = new DrawObj;
p_obj->Draw();
p_obj = new PolyLine;
p_obj->Draw();
vtbl 50
vtbl 180
int a
int a
Point start
50
100
350
430
180
550
430
250
DrawObj::Draw
350
Line::Draw
Point end
p_obj = new Line;
p_obj->Draw();
Point[0] pt
Point[1] pt
vtbl 100
int a
Point start
Point end
pointer
of
virtual
function
table
Point[2] pt
Point[3] pt
250
virtual
function
table
430
Point[4] pt
Line::Calc
550
PolyLine::Draw
MFC Tutorial
Code 영역
ISLab ICE HUFS
17
Virtual Function 사용 예
CObList list;
DrawObj* p_obj;
p_obj = new Line;
list.AddTail(p_obj);
p_obj = new Point;
list.AddTail(p_obj);
. . . .
POSITION pos = list.GetHeadPosition();
while(pos != NULL)
{
p_obj = (DrawObj*)list.GetNext(pos);
p_obj->Draw();
}
List
Line
Point
Line
PolyLine
Point
ISLab ICE HUFS
MFC Tutorial
18
ISLab ICE HUFS
MFC 기초
목차
•
•
•
•
•
SDK와 MFC의 비교
MFC 클래스 종류
AppWizard를 이용한 프로젝트 생성
Develop Studio 사용법
Hungarian 표기법
ISLab ICE HUFS
MFC Tutorial
20
Windows API
• Applicatoin Programming Interface
• Windows System Calls
• Windows 3.1
– Win16 API
• Windows 95/NT
– Win32 API
• C 라이브러리
ISLab ICE HUFS
MFC Tutorial
21
SDK 프로그래밍
• SDK(Software Development Kit)
– 윈도우 프로그래밍을 위한 여러 가지 툴과 라이브러리로 구성되
어 있는 마이크로소프트에 의해 발표된 소프트웨어 패키지
– 윈도우 프로그래밍시 호출하여 사용할 수 있는 함수들이 포함
(윈도우 API)
– C 라이브러리
ISLab ICE HUFS
MFC Tutorial
22
메시지와 메시지 큐
• 메시지(message)?
– 윈도우에서 발생하는 사건들의 표현
– 숫자 (winuser.h)
• 메시지 큐(queue)
– 하나의 프로그램에 하나씩 할당
윈도우에 사건이 발생하면
운영체제는 이를 메시지로
만들어
발생 순서대로 메시지 큐에
넣는다.
ISLab ICE HUFS
MFC Tutorial
23
메시지 루프, 윈도우 프로시저
• 메시지 루프
– 메시지 큐에서 메시지를 하나씩 꺼내어 거기에 맞게 처리
• 윈도우 프로시저
– 메시지의 실제 처리
운영체제
응용 프로그랭
메시지를 하나씩 읽어다가
이를 처리할 윈도우의 윈도우
프로시저를 호출한다.
ISLab ICE HUFS
MFC Tutorial
24
메시지에 의한 동작
• Message-driven operations
윈도우에 사건이 발생하면
운영체제는 이를 메시지로
만들어 발생 순서대로
메시지 큐에 넣는다.
msg
메시지 큐
int WinMain(HINSTANCE ......)
{
. . .
InitApplication(hInstance);
InitInstance(hInstance);
. . .
. . .
while(GetMessage(....))
{
. . .
DispatchMessage(. . .);
}
. . .
}
함수
ISLab ICE HUFS
MFC Tutorial
25
SDK 프로그램의 예
#include “windows.h”
#include “generic.h”
// SDK의 API와 각종 상수, 구조체가 정의된 헤더 화일
// 이 프로그램 내에서 사용할 상수가 정의되고 함수가
// 선언된 헤더 화일
HINSTANCE hInst;
HWND hMainWnd;
// 인스턴스 핸들을 기억해둔다.
// 메인 윈도우 핸들을 기억해 둔다.
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
if (!hPrevInstance)
if (!InitApplication(hInstance))
return FALSE;
// 윈도우 클래스를 등록한다.
hInst = hInstance;
// 인스턴스 핸들을 전역 변수에 기억해둔다.
if (!InitInstance(hInstance, nCmdShow)) // 메인 윈도우를 생성한다.
return FALSE;
ISLab ICE HUFS
MFC Tutorial
26
// 메시지 루프에 진입한다.
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
ISLab ICE HUFS
MFC Tutorial
27
InitApplication
BOOL InitApplication(HINSTANCE hInstance)
{
WNDCLASS wc; // WNDCLASS는 윈도우 클래스의 등록에 필요한 구조체이다.
wc.style = NULL;
wc.lpfnWndProc=MainWndProc; // 윈도우의 윈도우 프로시저 이름을 지정한다
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
// 윈도우가 속한 인스턴스의 핸들을 지정한다.
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);// 이 윈도우의 아이콘 지정
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // 이 윈도우의 커서 지정
wc.hbrBackground = GetStockObject(WHITE_BRUSH); // 배경색 지정
wc.lpszMenuName = “EX_Menu”;
// 이 윈도우의 메뉴를 지정한다
wc.lpszClassName = “EX_WClass”; // 이 윈도우의 클래스 이름을 지정한다.
return RegisterClass(&wc);
// 이 윈도우 클래스를 등록한다.
}
ISLab ICE HUFS
MFC Tutorial
28
InitInstance
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hMainWnd = hWnd = CreateWindow(
“EX_WClass”,
// 생성하려는 윈도우의 윈도우 클래스 이름
“EX Program”,
// 윈도우의 타이틀을 지정한다.
WS_OVERLAPPEDWINDOW, // 윈도우의 스타일을 지정한다.
CW_USEDEFAULT,
// 윈도우의 시작 X 좌표
CW_USEDEFAULT,
// 윈도우의 시작 Y 좌표
CW_USEDEFAULT,
// 윈도우의 폭
CW_USEDEFAULT,
// 윈도우의 높이
NULL,
// 부모 윈도우의 핸들
NULL,
hInstance,
// 이 윈도우가 속한 인스턴스의 핸들
NULL
);
if (!hWnd) return FALSE; // 윈도우가 실패했으면
ShowWindow(hWnd, nCmdShow); // 메인 윈도우의 형태를 결정하고 WM_PAINT 발생
UpdateWindow(hWnd);
// WM_PAINT 메시지를 바로 처리해버린다.
return TRUE;
}
ISLab ICE HUFS
MFC Tutorial
29
윈도우 스타일(1)
WS_OVERLAPPED
WS_SYSMENU
WS_CAPTION
WS_THICKFRAME
WS_MINIMIZEBOX
WS_MAXIMIZEBOX
WS_CHILD
WS_VISIBLE
WS_BORDER
WS_MAXIMIZE
WS_MINIMIZE
WS_HSCROLL
WS_VSCROLL
겹쳐질 수 있는 윈도우를 생성한다.
윈도우에 시스템 메뉴를 붙인다.
윈도우에 타이틀바를 사용한다.
윈도우의 테두리선을 굵은선으로 한다.
축소 버튼을 윈도우 타이틀바 오른쪽에 붙인다.
확대 버튼을 윈도우 타이틀바 오른쪽에 붙인다.
다른 윈도우의 자식 윈도우로 생성한다.
윈도우의 생성과 동시에 윈도우를 보이게 한다.
윈도우에 테두리를 긋는다.
윈도우를 전체 화면 크기로 생성한다.
윈도우를 아이콘 모양으로 생성한다.
윈도우에 수평 스크롤바를 붙여 생성한다.
윈도우에 수직 스크롤바를 붙여 생성한다.
ISLab ICE HUFS
MFC Tutorial
30
윈도우 스타일(2)
WS_POPUP
WS_CLIPSIBLINGS
WS_CLIPCHILDREN
팝업 윈도우를 생성한다. 이것은 WS_CHILD와
함께 사용될 수 없다.
같은 레벨의 자식 윈도우간에 겹치는 영역이 있을
때 각각의 자식 윈도우가 다른 겹치는 자식 윈도우
의 영역으로 넘어가지 못하도록 한다. 이 스타일을
주지 않았을 경우 자식 윈도우끼리 겹칠 때 이상하
게 그려지는 상황이 발생할 수 있다.
자식 윈도우가 차지하는 영역은 부모 윈도우의 영
역에서 제외된다. 부모 윈도우를 생성할 경우 주어
야 한다.
#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION \
| WS_SYSMENU | WS_THICKFRAME \
| WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
ISLab ICE HUFS
MFC Tutorial
31
윈도우 프로시저 MainWndProc
long APIENTRY MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND: // 사용자가 메뉴 항목을 선택하면 발생하는 메시지
{
case ID_FILE_EXIT:
SendMessage(hWnd, WM_CLOSE, 0, 0);
break;
}
case WM_PAINT: // 윈도우의 사용자 영역이 복구되어야 할 때 발생하는 메시지
{
HDC hDC;
PAINTSTRUCT ps;
hDC = BeginPaint(hWnd, &ps);
TextOut(hDC, 10, 10, “Hello, everybody”, 16);
EndPaint(hWnd, &ps);
break;
}
ISLab ICE HUFS
MFC Tutorial
32
case WM_DESTROY: // 윈도우가 없어지기 직전에 발생하는 메시지
{
PostQuitMessage(0);
break;
}
default:
// 처리하지 못한 메시지를 넘긴다.
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
ISLab ICE HUFS
MFC Tutorial
33
generic.h & resource.h
• generic.h
#include “resource.h”
int PASCAL WinMain(HANDLE, HANDLE, LPSTR, int);
BOOL InitApplication(HANDLE);
BOOL InitInstance(HANDLE, int);
long APIENTRY MainWndProc(HWND, UINT, WPARAM, LPARAM);
• resource.h
#define ID_FILE_EXIT 100
ISLab ICE HUFS
MFC Tutorial
34
generic.rc
#include "resource.h"
// Menu
#define APSTUDIO_READONLY_SYMBOLS
#include "afxres.h"
EX_Menu MENU DISCARDABLE
BEGIN
POPUP "File"
BEGIN
MENUITEM "Exit",
ID_FILE_EXIT
END
END
#undef APSTUDIO_READONLY_SYMBOLS
// Korean resources
#if !defined(AFX_RESOURCE_DLL) ||
defined(AFX_TARG_KOR)
#ifdef _WIN32
#ifdef APSTUDIO_INVOKED
LANGUAGE LANG_KOREAN,
SUBLANG_DEFAULT
#pragma code_page(949)
#endif //_WIN32
#endif
// Korean resources
#ifndef APSTUDIO_INVOKED
// Generated from the TEXTINCLUDE 3
resource.
#endif
// not APSTUDIO_INVOKED
ISLab ICE HUFS
MFC Tutorial
35
핸들(Handle)
• 무엇인가를 구별하기 위해 붙인 번호
– 예) 윈도우 핸들 (HWND)
• 윈도우가 여러 개 존재할 경우 이를 구별하기 위해 윈도우마다 번호를 하나
씩 부여
• 핸들 타입 앞에는 H가 붙는다.
• UINT로부터 재정의
– #define UINT
HANDLE
– #define HANDLE HWND
ISLab ICE HUFS
MFC Tutorial
36
타입
BOOL
참, 거짓을 나타내는 타입으로 int로부터 재정의 되었으며
TRUE, FALSE 값을 갖는다.
LPSTR
char 타입에 대한 포인터, 즉 char * 와 같다.
Long Pointer to STRing을 나타낸다.
LPCTSTR는 const char * 와 같다.
HWND
윈도우들을 구별하기 위해 윈도우에 붙여지는 핸들 타입
HINSTANCE
인스턴스의 구별을 위해 인스턴스마다 부여되는 핸들 타입
UINT
unsigned int에 해당. Win32에서는 4 바이트
HANDLE
모든 핸들 타입의 원조에 해당하는 타입. UINT로 부터
typedef 문을 이용해 재정의. H로 시작되는 모든 핸들
타입은 모두 이것으로부터 typedef 문으로 재정의 됨.
WPARAM
UINT로부터 재정의. 메시지에 수반되는 부가 정보를 나타냄.
LPARAM
LONG으로부터 재정의. 메시지에 수반되는 부가 정보 표시
ISLab ICE HUFS
MFC Tutorial
37
주요 메시지(1)
WM_CREATE
윈도우가 생성될 때 발생한다. 정확히 말하면 CreateWindow API가
호출되었을 때 발생한다. 이 메시지 처리부에서 초기화 작업을
수행하는 것이 일반적이다. 아직 윈도우가 보이지 않는다.
WM_SIZE
윈도우의 크기가 변화하면 발생. 이 메시지가 발생하면 그 뒤에
WM_PAINT가 따라서 발생한다.
WM_PAINT
윈도우의 사용자 영역이 가려졌다가 앞으로 나온다든가 해서 다시
그려질 일이 생기면 발생하는 메시지이다. InvalidateRect와 같은
API로 발생시키는 것도 가능하다.
WM_COMMAND
사용자가 메뉴에서 명령을 선택하면 발생
WM_CLOSE
사용자가 윈도우의 시스템 메뉴에서 닫기(Close)를 택하면 발생.
DefWindowProc 함수는 WM_CLOSE 메시지를 받으면
WM_DESTROY 메시지를 발생
ISLab ICE HUFS
MFC Tutorial
38
주요 메시지(2)
WM_DESTROY
윈도우가 없어지기 직전에 발생한다. 여기서는 앞
서 윈도우 프로시저의 실행중에 할당한 자원들이
있다면 이를 운영체제에 반환하는 역할을 수행함.
메인 윈도우의 WM_DESTROY 메시지 처리부에서
는 끝부분에서 PostQuitMessage 함수를 호출하는
것이 일반적이다.
WM_QUIT
PostQuitMessage 함수를 호출하면 이 메시지가 만
들어져 메시지 큐에 들어가게 된다. 메시지 루프에
서 이 메시지를 읽어가면 GetMessage 함수의 리턴
값이 FALSE가 되기 때문에 메시지 루프가 끝나게
되고 프로그램이 종료된다.
ISLab ICE HUFS
MFC Tutorial
39
MFC란
• 클래스 라이브러리
– 클래스의 집합 (함수의 집합이 아님)
• 애플리케이션 프레임워크(application framework)
– AppWizard
– ClassWizard
– Project Workspace
ISLab ICE HUFS
MFC Tutorial
40
MFC 구조
• MFC는 SDK API의 기능을 구분
하여 클래스 계층구조를 입힌
것
• 응용 프로그램은 SDK API를 직
접 부를 수 있음
• “Handle”은 분류의 기준이 됨
응용프로그램
MFC
SDK API
운영체제
ISLab ICE HUFS
MFC Tutorial
41
왜 MFC 인가?
• 이해가 쉬움
– 연관된 함수와 데이타를 “클래스”를 이용하여 그룹화하였음
• 코드의 재사용성 향상
• 소프트웨어 개발의 용이성
– 애플리케이션 프레임워크(application framework) 제공
– 멤버 함수 나열
– 코드 삽입의 용이성
ISLab ICE HUFS
MFC Tutorial
42
Handle을 이용한 분류 - SDK(1)
RECT rc;
GetClientRect(hWnd, &rc);
MoveWinodw(hWnd, x, y, x2, y2, TRUE);
ISLab ICE HUFS
MFC Tutorial
43
Handle을 이용한 분류 - MFC(1)
class CWnd : public CCmdTarget
{
HWND m_hWnd;
...
BOOL GetClientRect(LPRECT lpRect);
BOOL MoveWindow(int x,int y,int width,int height,BOOL bDraw=TRUE);
...
}
BOOL CWnd::GetClientRect(LPRECT lpRect) --> inline 함수를 이용하여 성능 저하를 막는다
{
::GetClientRect(m_hWnd, lpRect);
}
BOOL CWnd::MoveWindow(int x, int y, int width, int height, BOOL bDraw)
{
::MoveWindow(m_hWnd, x, y, width, height);
}
ISLab ICE HUFS
MFC Tutorial
44
Handle을 이용한 분류 - SDK(2)
HDC hDC = GetDC(hWnd);
Rectangle(hDC, 10, 10, 100, 100);
TextOut(hDC, 10, 10, “Sample”, 6);
ReleaseDC(hWnd, hDC);
ISLab ICE HUFS
MFC Tutorial
45
Handle을 이용한 분류 - MFC(2)
class CDC : public CObject
{
HDC m_hDC;
. . . .
BOOL Rectangle(int x1, int y1, int x2, int y2);
BOOL TextOut(int x, int y, LPSTR lpStr, int size);
}
BOOL CDC::Rectangle(int x1, int y1, int x2, int y2)
{
::Rectangle(m_hDC, x1, y1, x2, y2);
}
BOOL CDC:: TextOut(int x, int y, LPSTR lpStr, int size)
{
::TextOut(m_hDC, x, y, lpStr, size);
}
ISLab ICE HUFS
MFC Tutorial
46
SDK - 자원 획득 및 반환
• SDK
{
HDC hDC;
hDC = GetDC(hWnd);
// 자원 획득
Rectangle(hDC,10,10,100,100);
TextOut(hDC,10,10,“Sample”,6);
ReleaseDC(hWnd, hDC);
// 반드시 자원을 반환해야 한다.
}
ISLab ICE HUFS
MFC Tutorial
47
C++의 장점(생성자/소멸자) - MFC
{
CClientDC dc(this);
dc.Rectangle(10, 10, 100, 100);
dc.TextOut(10,10,“Sample”,6);
} // 소멸자 불림
CClientDC::CClientDC(CWnd* pWnd)
{
m_hWnd = pWnd->GetSafeHwnd();
m_hDC = ::GetDC(m_hWnd);
}
// 윈도우 핸들을 얻는다.
// 윈도우의 Device Context를 얻음
CClientDC::~CClientDC()
{
::ReleaseDC(m_hWnd, m_hDC); // Device Context를 해제한다.
}
ISLab ICE HUFS
MFC Tutorial
48
C++의 장점 - 부재인자
• SDK
int MessageBox(HWND hWnd, LPCSTR lpszText, LPCSTR lpszTitle, UNIT flag);
InvalidateRect(HWND hWnd, LPCRECT lpRect, BOOL bErase);
• MFC
int AfxMessageBox(LPCSTR lpszText, UINT nType = MB_OK, UINT nIDHelp = 0);
void InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE);
ISLab ICE HUFS
MFC Tutorial
49
C++의 장점 - 중복 정의
• 함수 중복 정의(function overloading)
BOOL Rectangle(int x1, int y1, int x2, int y2);
BOOL Rectangle(LPCRECT lpRect);
• 연산자 중복 정의(operator overloading)
CRect a, b, c;
c.left = a.left + b.left;
c.right = a.right + b.right;
c.top = a.top + b.top;
c.bottom = a.bottom + b.bottom;
c = a + b;
ISLab ICE HUFS
MFC Tutorial
50
MFC 클래스 종류
•
•
•
•
•
일반 목적의 클래스
윈도우 API 클래스
애플리케이션 프레임워크 클래스
고 수준 추상화 클래스
운영체제 확장 클래스
ISLab ICE HUFS
MFC Tutorial
51
일반 목적의 클래스
•
•
CObject : 모든 클래스의 상위 클래스
예외 처리 클래스
–
•
콜렉션(collection) 클래스
–
–
–
•
CFile, CStdioFile, CMemFile
시간 및 시간 간격(time span) 클래스
–
•
Cstring
파일 클래스
–
•
CByteArray, CWordArray, CDWordArray, CPtrArray, CObArray, CStringArray, CUintArray
CObList, CPtrList, CStringList
CMapPtrToWord, CMapPtrToPtr, CMapStringToOb, CMapStringToPtr, CMapStringToString,
CMapWordToOb, CMapWordToPtr
동적 문자열 클래스
–
•
CException, CArchiveException, CFileException, CMemoryException, CNotSupportedException,
COleException, CDBException, CResourceException, CUserException
CTime, CTimeSpan
그외
–
CPoint, CSize, CRect등
ISLab ICE HUFS
MFC Tutorial
52
윈도우 API 클래스 (1)
•
응용 프로그램에서 사용하는 클래스
– CCmdTarget, CCmdUI, CWinThread, CWinApp
•
객체 동기화 관련 클래스
– CSyncObject, CCriticalSection, CSemaphore, CMutex, CEvent, CSingleLock,
CMultiLock
•
응용 프로그램 관련 클래스
– CCommandLineInfo, CWaitCursor
•
메뉴 : Cmenu
•
CWnd : 모든 윈도우 클래스의 상위 클래스
– 프레임 윈도우(frame window)
• CFrameWindow, CMDIFrameWindow, CMDIChildWnd
– CWnd 계승 클래스
• CDialog, 콘트롤 클래스(CButton, CListBox, CEdit 등)
ISLab ICE HUFS
MFC Tutorial
53
윈도우 API 클래스 (2)
•
다이얼로그
–
•
다이얼로그 DDX/DDV
–
•
CDataExchange
콘트롤 클래스
–
–
•
CFileDialog, CColorDialog, CFontDialog, CPrintDialog, CFindReplaceDialog
CButton, CBitmapButton, CComboBox, CEdit, CStatic, CScrollBar, CListBox, CCheckListBox,
CVBControl
CAnimateCtrl, CDragListBox, CHeaderCtrl, CHotKeyCtrl, CImageList, CListCtrl, CProgressCtrl,
CRichEditCtrl, CSliderCtrl, CSpinButtonCtrl, CStatusBarCtrl, CTabCtrl, CToolBarCtrl,
CToolTipCtrl, CTreeCtrl
GDI 및 그림 관련 클래스
–
–
CPaintDC, CWindowDC, CClientDC, CMetaFileDC
CGdiObject, CFont, CPen, CBrush, CBitmap, CPalette, CRgn
ISLab ICE HUFS
MFC Tutorial
54
애플리케이션 프레임워크 클래스
•
문서/뷰 관련 클래스
– CDocTemplate, CSingleDocTemplate, CMultiDocTemplate
– CDocument, Cview
•
문맥 지원 도움말(context-sensitive help)
ISLab ICE HUFS
MFC Tutorial
55
고 수준 추상화 클래스
• 확장된 뷰(enhanced view)
– CScrollView, CFormView
– 콘트롤 뷰 : CEditView, CListView, CRichEditView, CTreeView
• 분리 윈도우
– CSplitterWnd
• 콘트롤 바
– CControlBar
– CToolBar, CStatusBar, CDialogBar
ISLab ICE HUFS
MFC Tutorial
56
운영체제 확장 클래스 (1)
•
OLE 지원
– OLE Document
• CDocItem, COleServerItem, COleClientItem, COleDocument, COleLinkingDoc,
COleServerDoc, COleIPFrameWnd
– 클래스 팩토리(class factories)
• COleObjectFactory, COleTemplateServer
– 오토메이션(automation)
– 통일된 데이타 전송
• COleDataSource, COleDataObject, COleDropSource, COleDropTarget
– OLE 콘트롤
• COleControl, COlePropertyPage, COleControlModule, COleObjectFactoryEx,
COleConnectionPoint, CPropExchange, CFontHolder, CPictureHolder
ISLab ICE HUFS
MFC Tutorial
57
운영체제 지원 클래스(2)
•
ODBC 지원
– CDatabase, CRecordset, CFiledExchange, CLongBinary, CRecordView
•
DAO 지원
– CDaoWorkspace, CDaoDatabase, CDaoRecordset, CDaoRecordView,
CDaoQueryDef, CDaoTableDef, CDaoException, CDaoFiledExchange
•
MAPI 지원
•
Winsock 지원
– CAsyncSocket, Csocket
•
펜 윈도우 지원
– CHEdit, CBEdit
– 제한 : 16 비트 환경
ISLab ICE HUFS
MFC Tutorial
58
코드 재 사용 방법
Component Gallery
AppWizard
Custom
AppWizard
MFC 확장
응용
프로그램
MFC
ISLab ICE HUFS
MFC Tutorial
59
AppWizard를 통한 Project 생성(1)
• Project 생성 (project 이름: Obedit)
– New 메뉴 (MFC AppWizard (.exe)
• Database, OLE 메뉴
– None
• Multiple document 선택
ISLab ICE HUFS
MFC Tutorial
60
AppWizard를 통한 Project 생성(2)
• Advanced Options
– File extension : obe
– Main frame caption: Obedit
– Doc type name: Obedit
File type ID: Obedit.Document
– File new name: Obedit
File type name: Obedit Document
Filter name: Obedit Files(*.obe)
• MFC library 사용 방법
– As a shared DLL (MFC42.DLL 필요)
• Base class 선택
– CObeditView 클래스의 상위 클래스로 CScrollView 선택
ISLab ICE HUFS
MFC Tutorial
61
Developer Studio
• Project Workspace
–
–
–
–
클래스 뷰(class view)
리소스 뷰(resource view, AppStudio 대신)
파일 뷰(file view)
인포 뷰(info view)
• 작업 영역
– source code browser / wizard bar / resource editor
– online help
ISLab ICE HUFS
MFC Tutorial
62
클래스 뷰/파일 뷰/리소스 뷰
ISLab ICE HUFS
MFC Tutorial
63
클래스 뷰(class view)
•
클래스에 함수 및 멤버 추가
– 클래스 이름에 마우스 커서를 위치
시킨 후 오른쪽 버튼을 클릭
– 멤버 함수 추가
– 멤버 변수 추가
•
특정 위치로 커서 이동
•
계승 관계 표시
ISLab ICE HUFS
MFC Tutorial
64
파일 뷰(file view)
• 프로젝트에 있는 화일들을 열거
• 프로젝트에서 화일 삭제
• (.net) 솔루션 탐색기
ISLab ICE HUFS
MFC Tutorial
65
Hungarian 표기법
Type
char
BOOL
int
UINT
WORD
LONG
DWORD
* (pointer)
FAR *
LPSTR
handle
callback
Prefix
c
b
n
n
w
l
dw
p
lp
lpsz
h
lpfn
예
cDirSeperator
bIsSending
nVariableCount
nMyUnsignedInt
wListID
lAxisRatio
dwPackedmessage
pWnd
lpWnd
lpszFileName
hWnd
lpfnHookProc
비고
z는 NULL로 끝남을
의미
함수 포인터
ISLab ICE HUFS
MFC Tutorial
66
Hungarian 표기법 - MFC 확장
Type
CRect
CPoint
CSize
CString
CWnd
CWnd *
Prefix
rect
pt
sz
str
Wnd
pWnd
예
rectScroll
ptMouseClick
szRectangle
strFind
WndControl
pWndDialog
ISLab ICE HUFS
MFC Tutorial
67
Hungarian 표기법 - Symbol
Type
여러 리소스에서 공유
Dialog 리소스
Dialog 리소스 Help context ID
(for context-sensitive help)
비트맵 리소스
커서 리소스
아이콘 리소스
menu, toolbar command
Command help context
Message box prompt
Message box help context
String 리소스
다이얼로그 템플릿의 control
Prefix
IDR_
IDD_
HIDD_
예
IDR_MAINFRAME
IDD_ABOUT
HIDD_HELP_ABOUT
범위
1-0x6FFF
1-0x6FFF
0x2001- 0x26FF
IDB_
IDC_
IDB_SMILEY
IDC_HAND
1-0x6FFF
1-0x6FFF
ID_
HID_
IDP_
HIDP_
IDS_
IDC_
ID_CIRCLE_TOOL
0x8000-0xDFFF
HID_CIRCLE_TOOL
0x1800-0x1DFF
IDP_FATALERROR8-0xDFFF
HIDP_FATALERROR
0x3008-0x3DFF
IDS_ERROR12
1-0x7FFF
IDC_COMBO1
8-0xDFFF
ISLab ICE HUFS
MFC Tutorial
68
ISLab ICE HUFS
MFC의 기본 구조 이해
MFC의 철학(1)
• 예제 프로그램 컴파일 후 수행
– Open 메뉴 선택
• 화일 선택시 일반적인 절차에 대한 코딩
1 화일 오픈 다이얼로그 박스를 띄운다.
2 사용자의 입력을 받아 해당 화일을 연다. 만일 MDI 프로그램이면 자식
윈도우를 하나 연다. SDI 프로그램이라면 전에 갖고 있던 자료 구조를
해제한다.
3 화일을 프로그램의 정의에 맞게 해석하여 읽어들인다. 즉 화일의 내용을
메모리 상의 자료구조로 변환한다.
4 읽어들인 내용을 윈도에 그린다. 이 부분의 구현은 대개 윈도를 무효화
(invalidate)하여 이루어진다.
ISLab ICE HUFS
MFC Tutorial
70
MFC의 철학(2)
• 실제 사용자가 해야 할 일 (3번)
– 장점
• 에러의 가능성 감소
• 프로그래밍 시간 및 노력 감소
ISLab ICE HUFS
MFC Tutorial
71
CDocument
class CDocument : public CCmdTarget
{
...
void OnFileOpen(); // 파일오픈 명령을 실행하면 불려진다.
BOOL GetOpenFileName(LPCTSTR); // 다이얼로그를 띄워 파일이름을 입력
// 화일 입출력을 담당하는 함수 (pure virtual function)
virtual void Serialize(CFile cfile) = 0;
CWnd* GetWindow(); // 현재 문서의 내용을 보여주는 윈도우 포인터를 리턴
...
}
ISLab ICE HUFS
MFC Tutorial
72
CDocument::OnFileOpen
void CDocument::OnFileOpen()
{
CString szFileName; // CString은 문자배열에 해당하는 클래스
if (!GetOpenFileName(szFileName))
return;
CFile cfile(szFileName); //
cfile.Open();
//
Serialize(cfile);
// 화일의
cfile.Close();
// 화일을
CWnd* pWnd = GetWindow();
pWnd->Invalidate(NULL);
// 다이얼로그 박스를 띄워 파일이름을
// 입력받는다.
CFile은 MFC에서 화일 I/O를 담당
화일을 오픈한다.
내용을 읽어들인다(user가 작성)
닫는다.
// 이 문서의 내용을 보여주는 윈도의 핸들을
// 얻어 그 내용을 그리도록 WN_PAINT 메시지
// 발생
}
ISLab ICE HUFS
MFC Tutorial
73
CMyDocument 클래스
// CDocument는 실제 바로 사용하지 못함(MFC class)
// 계승하여 사용하여야
class CMyDocument : public CDocument
{
// My data structure
int m_nNumOfObjects;
Objects obj[100];
public:
void Serialize(CFile cfile); // virtual function
};
ISLab ICE HUFS
MFC Tutorial
74
WinMain
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
if (!hPrevInstance)
// 처음으로 실행되는 경우에는
InitApplication(hInstance); // 윈도우 클래스를 등록한다.
InitInstance(hInstance);
// 메인 윈도우를 생성한다.
while(GetMessage(....))
// 메시지 루프
{
....
DispatchMessage(...);
// 메시지를 윈도우 프로시저로 나눔
}
// 프로그램이 종료되기 전에 청소 작업을 행한다.
....
return msg.wParam;
}
ISLab ICE HUFS
MFC Tutorial
75
MFC의 WinMain
•
MFC\SRC\winmain.cpp
•
CWinApp 클래스에 존재
CWinApp::InitApplication
CWinApp::InitInstance
CWinApp::Run
CWinApp::ExitInstance
•
•
InitInstance, ExitInstance 만
override 하여 사용 가능
가상 함수의 중요성
ISLab ICE HUFS
MFC Tutorial
76
SDI
•
•
•
•
CObeditApp -> CWinApp
CMainFrame -> CMDIFrameWnd
CObeditDoc -> CDocument
CObeditView -> CView
ISLab ICE HUFS
MFC Tutorial
77
MDI
CObeditApp -> CWinApp
CMainFrame -> CMDIFrameWnd
CChildFrame -> CMDIChildWnd
CObeditDoc -> CDocument
CObeditView -> CView
ISLab ICE HUFS
MFC Tutorial
78
Document/View 구조
문서클래스
2. 그 내용을 반영한다.
뷰클래스
1. 사용자의 입력을
받는다
3. 윈도우로
출력한다.
ISLab ICE HUFS
MFC Tutorial
79
전체 구조
• CWinApp
– 하나의 응용 프로그램을 가리키는 클래스
• CDocument
– 응용 프로그램의 자료구조를 저장하는 클래스
• CView
– 응용 프로그램의 모습을 화면에 출력하는 클래스
• 하나의 document에는 여러 개의 view가 연관될 수 있음
– 예) 탐색기, Visual C++ 에디터 창
ISLab ICE HUFS
MFC Tutorial
80
CObeditApp 클래스
class CObeditApp : public CWinApp
{
public:
CObeditApp();
//{{AFX_VIRTUAL(CObeditApp)
public:
virtual BOOL InitInstance();
//}}AFX_VIRTUAL
// 프로그램의 초기화
//{{AFX_MSG(CObeditApp)
afx_msg void OnAppAbout();
...
//}}AFX_MSG
ISLab ICE HUFS
MFC Tutorial
81
InitInstance 함수
BOOL CObeditApp:InitInstance()
{
....
LoadStdProfileSettings(); // 표준 INI 화일 option을 읽어들임
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(
IDR_OBEDITTYPE,
RUNTIME_CLASS(CObeditDoc),
RUNTIME_CLASS(CChildFrame),
RUNTIME_CLASS(CObeditView));
AddDocTemplate(pDocTemplate); // View-Doc 등록
CMainFrame* pMainFrame = new CMainFrame; // main window 생성
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
m_pMainWnd = pMainFrame;
ISLab ICE HUFS
MFC Tutorial
82
...
RegisterShellFileTypes(TRUE);
// 화일의 icon, 확장자 등록
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (!ProcessShellCommand(cmdInfo))
return FALSE;
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
return TRUE;
}
ISLab ICE HUFS
MFC Tutorial
83
Obedit.ini 화일
[Recent File List]
File1=D:\obedit\step8\new.OBE
File2=D:\obedit\step7\test4.OBE
ISLab ICE HUFS
MFC Tutorial
84
레지스트리 작업
•
•
INI 파일 기록 및 읽기
–
UINT GetProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault);
–
CString GetProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszDefault = NULL);
–
BOOL WriteProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue);
–
BOOL WriteProfileString( LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue );
레지스트리에 읽기 및 쓰기
–
void SetRegistryKey( LPCTSTR lpszRegistryKey );
–
void SetRegistryKey( UINT nIDRegistryKey );
ISLab ICE HUFS
MFC Tutorial
85
레지스트리
void CObeditApp::LoadStdProfileSettings()
{
// 나름대로 초기화 값을 읽어다 저장한다.
// GetProfileInt...
//
CWinApp::LoadStdProfileSettings(); // 선조 함수 호출
}
ISLab ICE HUFS
MFC Tutorial
86
윈도우 생성
• WM_CREATE
– OnCreate 함수 호출
ISLab ICE HUFS
MFC Tutorial
87
CMainFrame 클래스
class CMainFrame : public CMDIFrameWnd
{
DECLARE_DYNAMIC(CMainFrame)
....
protected:
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;
protected:
//{{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT
lpCreateStruct);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
// 메시지 맵
};
ISLab ICE HUFS
MFC Tutorial
88
OnCreate 함수
ISLab ICE HUFS
MFC Tutorial
89
MFC MDI 프로그램의 윈도우 구조
MDI 메인 윈도우
타이틀
파일
편집
타이틀
MDI 클라이언트
윈도우
MDI 자식 윈도우
뷰 윈도우
ISLab ICE HUFS
MFC Tutorial
90
CObeditView 클래스
class CObeditView : public CView
{
....
public:
CObeditDoc* GetDocument(); // 뷰에 연결된 문서객
체의 포인터 반환
....
//{{AFX_VIRTUAL(CObeditView)
public:
virtual void OnDraw(CDC* pDC); // WM_PAINT가 왔
을 때 실행
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo*
pInfo);
virtual void OnBeginPrinting(CDC* pDC,
CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC,
CPrintInfo* pInfo);
//}}AFX_VIRTUAL
....
ISLab ICE HUFS
MFC Tutorial
91
주요 CView 멤버함수
GetDocument
뷰와 연계된 문서 오브젝트에 대한 포인터를 돌려준다.
AddDocTemplate 함수를 통해 m_pDocument 멤버는
MFC가 뷰를 생성할 때 알아서 초기화
OnInitialUpdate
뷰가 처음 만들어질 때 호출된다.
OnDraw
뷰와 연계된 문서오브젝트의 내용을 윈도우 위에 그려준다.
OnPrint
뷰와 연계된 문서오브젝트의 내용을 프린터로 출력
OnUpdate
문서오브젝트의 내용이 변경되었을 때 문서오브젝트
쪽에 불러준다.
ISLab ICE HUFS
MFC Tutorial
92
CObeditDoc 클래스
class CObeditDoc : public CDocument
{
....
//{{AFX_VIRTAUL(CObeditDoc)
public:
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
// file I/O
//}}AFX_VIRTUAL
....
};
ISLab ICE HUFS
MFC Tutorial
93
주요 CDocument 멤버 함수
IsModified
문서오브젝트의 내용이 마지막으로 저장된 후에 변경된
적이 있는지 알려준다.
SetModifiedFlag
문서오브젝트의 내용이 변경되었음을 표시했다.
UpdateAllViews
문서오브젝트의 내용이 바뀌었을 때 이 내용을 연계된
뷰에게 알려준다. 이 안에서는 뷰클래스의 OnUpdate
함수를 부른다.
DeleteContent
문서오브텍트가 닫힐 때 불려진다. 이 때 문서오브젝트
의 청소 작업을 해야 한다.
OnNewDocument
사용자가 File 메뉴의 New 명령을 수행하면 불린다.
OnOpenDocument
사용자가 File 메뉴의 Open 명령을 수행하면 불린다.
OnSaveDocument
사용자가 File 메뉴의 Save 명령을 수행하면 불린다.
OnCloseDocument
사용자가 File 메뉴의 Close 명령을 수행하면 불린다.
ISLab ICE HUFS
MFC Tutorial
94
모든 뷰 수정
• Document class는 자신과 연관이 있는 view object를 리스트의 형태
로 관리
–
CPtrList m_viewList
• View에서 수정
• Document 수정
• UpdateAllViews 호출
ISLab ICE HUFS
MFC Tutorial
95
UpdateAllViews
View
Document
자료구조에 변화가 생긴다.
GetDocument 함수로 관련 이 변화를 관련된 모든 뷰에
문서 오브젝트를 알아낸다.
반영하기위해 UpdateAllViews
그 다음 데이터를 갱신한다.
함수를 호출한다.
각 뷰별로 화면을 다시 그린 UpdateAllViews
함수에서는
다.
OnUpdate 함수를 호출한다.
ISLab ICE HUFS
MFC Tutorial
96
ISLab ICE HUFS
UI 붙이기
메뉴 작성
File
Object
View
New
Line
Toolbar
Open
Ellipse
Status Bar
Close
Rectangle
Color Bar
Save
-----------------Save As…
Pen Attribute Zoom
---------Print
Print Preview
Print Setup…
---------Send
Summary Info
---------Recent File
---------Exit
Window
Help
New Window
About
Cascade
Time
Title
Arrange Icons
ISLab ICE HUFS
MFC Tutorial
98
메뉴 리소스 작성
• 리소스 뷰에서
– IDR_MAINFRAME(child window가 없을 때)
– IDR_OBEDITTYPE
ISLab ICE HUFS
MFC Tutorial
99
메뉴 작성
&Line
&Ellipse
&Rectangle
ID_OBJECT_LINE
ID_OBJECT_ELLIPSE
ID_OBJECT_RECTANGLE
&Pen Attribute ID_OBJECT_PENATTR
&Color Bar
&Zoom\tCtrl+Z
풍선 도움말
Draw a line\nLine
Draw a ellipse\nEllipse
Draw a rectangle\nRectangle
Change the attribute of a
pen\nPen
ID_VIEW_COLORBAR
Show or hide color palette
ID_VIEW_ZOOM
Set zoom ratio
ID_SEPARATOR(분리자 메뉴)
MEMU ID
단축키
ISLab ICE HUFS
MFC Tutorial
100
단축키 작성
• 리소스 뷰의 Accelerator 이용
ISLab ICE HUFS
MFC Tutorial
101
아이콘 변경
ISLab ICE HUFS
MFC Tutorial
102
툴바의 수정
• 리소스 뷰에서
– IDR_MAINFRAME
ISLab ICE HUFS
MFC Tutorial
103
배율 설정
• 새로운 ToolBar 생성
ISLab ICE HUFS
MFC Tutorial
104
MyToolBar.h 수정
Class CMyToolBar : public CToolBarCtrl -> CToolBar로 수정
(.net에서는 바로 선택)
{
// Construction
public:
CMyToolBar();
// Attributes
. . . .
ISLab ICE HUFS
MFC Tutorial
105
MyToolBar.cpp 수정
BEGIN_MESSAGE_MAP(CMyToolBar, CToolBarCtrl) -> CToolBar로 수정
//{{AFX_MSG_MAP(CMyToolBar)
// NOTE - the ClassWizard will add and remove mapping ..
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
ISLab ICE HUFS
MFC Tutorial
106
MainFrm.h 수정
#include “MyToolBar.h”
// 추가
class CMainFrame : public CMDIFrameWnd
{
DECLARE_DYNAMIC(CMainFrame)
public:
CMainFrame();
. . . .
protected:
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar; -> CMyToolBar m_wndToolBar로 수정
ISLab ICE HUFS
MFC Tutorial
107
리소스 파일
• obedit.rc
• 텍스트를 리소스 뷰에서 그래픽으로 나타냄
– 리소스 편집의 편리
ISLab ICE HUFS
MFC Tutorial
108
Obedit.rc 수정
IDR_MAINFRAME TOOLBAR DISCARDABLE 16,15
BEGIN
BUTTON
ID_FILE_NEW
BUTTON
ID_FILE_OPEN
BUTTON
ID_FILE_SAVE
SEPARATOR
BUTTON
ID_OBJECT_LINE
BUTTON
ID_OBJECT_ELLIPSE
BUTTON
ID_OBJECT_RECTANGLE
SEPARATOR
BUTTON
ID_OBJECT_PENATTR
BUTTON
ID_FILE_PRINT
BUTTON
ID_APP_ABOUT
SEPARATOR
SEPARATOR
// 12번째 스태택바 붙일 위치 (0부터 세어서)
SEPARATOR
SEPARATOR
// 14번째 스태틱컨트롤을 붙일 위치
END
ISLab ICE HUFS
MFC Tutorial
109
MainFrame에 변수 추가
• CMainFrame에 멤버 추가
– CScrollBar
– CStatic
m_zoomScroll;
m_zoomStatic
ISLab ICE HUFS
MFC Tutorial
110
CMainFrame::OnCreate 수정
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
. . .
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
CRect rect;
80 픽셀
// Scroll Bar 생성
m_wndToolBar.SetButtonInfo(12, ID_ZOOMSCROLL, TBBS_SEPARATOR, 80);
m_wndToolBar.GetItemRect(12, &rect);
rect.top = 3;
if (!m_wndToolBar.m_zoomScroll.Create(WS_VISIBLE | SBS_HORZ |
WS_TABSTOP, rect, &m_wndToolBar, ID_ZOOMSCROLL))
return -1;
Resource Symbol로 등록
ISLab ICE HUFS
MFC Tutorial
111
// 스태택 컨트롤 추가
m_wndToolBar.SetButtonInfo(14, ID_ZOOMSTATIC, TBBS_SEPARATOR, 60);
m_wndToolBar.GetItemRect(14, &rect);
rect.top = 6;
if (!m_wndToolBar.m_zoomStatic.Create(“배율”, WS_VISIBLE | SS_LEFT |
WS_TABSTOP, rect, &m_wndToolBar, ID_ZOOMSTATIC))
return -1;
Resource Symbol로 등록
return 0;
}
ISLab ICE HUFS
MFC Tutorial
112
리소스 심볼 등록
#define ID_ZOOMSCROLL 101
// 리소스 심볼을 등록하는 것과 왼쪽과 같이
// 정의하는 것은 동일한 효과임
심볼 등록
ISLab ICE HUFS
MFC Tutorial
113
생성된 모습
ISLab ICE HUFS
MFC Tutorial
114
CToolBar 클래스의 주요 함수
CommandToIndex
버튼 ID를 주면 툴바의 좌측부터 세어 그에 해당하는 인덱스를 준다.
0부터 센다.
GetItemID
CommandToIndex와는 반대로 버튼의 인덱스로부터 버튼 ID를 얻어준다.
Create
툴바를 생성한다.
EnableDocking
도커블 툴바로 동작할 수 있도록 설정하며 프로임 윈도우의 어느 곳에
붙을 수 있는지도 명시한다.
GetBarStyle툴바의 스타일을 얻어온다.
SetBarStyle
툴바의 스타일을 설정한다.
GetButtonInfo
특정 버튼에 대한 정보를 얻어온다.
SetButtonInfo
특정 버튼의 정보를 변경한다.
GetCount
툴바 버튼의 총수를 얻어온다(SEPARATOR 포함).
GetItemRect
버튼 ID를 주면 그 버튼의 툴바에서의 위치를 돌려준다.
LoadBitmap
버튼 모양을 담고 있는 비트맵을 로드한다.
SetHeight
툴바의 버튼 높이를 변경한다.
SetSizes
툴바의 크기를 변경한다.
ISLab ICE HUFS
MFC Tutorial
115
상태바(Status Bar)
• 생성 순서
– CStatusBar 오브젝트를 만든다.
– CStatusBar 오브젝트의 Create 함수를 호출하여 상태바 윈도우를
생성
– SetIndicator 함수를 호출하여 각 텍스트 출력창과 스트링 ID를
연결시킨다.
static UINT indicators[ ] =
{
ID_SEPARATOR,
// status line indicator
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
ISLab ICE HUFS
MFC Tutorial
116
클래스 위저드
클래스 이름
메뉴
가상함수
메시지
이미 만든 함수들
ISLab ICE HUFS
MFC Tutorial
117
Pane 텍스트 수정
• SetWindowText 함수로 텍스트 갱신
• Command UI 핸들러의 SetText 함수 호출
void CMainFrame::OnUpdateIndicatorTime(CCmdUI* pCmdUI)
{
pCmdUI->SetText(“Pane에 출력”);
}
• SetPaneText 함수 이용
CStatusBar bar;
bar.SetPaneText(0, “Pane에 출력”);
ISLab ICE HUFS
MFC Tutorial
118
상태바의 수정(1)
• indicators 변수 수정(MainFrm.cpp)
static UINT indicators [] =
{
ID_SEPARATOR,
// status line indicator
ID_SEPARATOR,
// 추가
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
ISLab ICE HUFS
MFC Tutorial
119
상태바의 수정(2)
• CMainFrame 클래스의 OnCreate 함수 수정
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
...
DockControlBar(&m_wndToolBar);
m_wndStatusBar.SetPaneInfo(1,ID_INDICATOR_TIME,SBPS_NORMAL,60);
return 0;
}
– 1은 상태바의 두 번째 창을 가리킨다.
– 폭은 오른쪽부터 계산
– Resource Symbol을 이용하여 ID_INDICATOR_TIME 등록
ISLab ICE HUFS
MFC Tutorial
120
시간 출력
• 클래스 위저드를 이용하여 명령 UI 갱신핸들러 생성
– View 메뉴의 ClassWizard 선택
• Object IDs: ID_INDICATOR TIME
• Messages: UPDATE_COMMAND_UI
– 함수 생성 (OnUpdateIndicatorTime)
void CMainFrame::OnUpdateIndicatorTime(CCmdUI* pCmdUI)
{
char timebuf[12];
_strtime(timebuf);
pCmdUI->SetText(timebuf);
}
• 이벤트 발생시 마다 매번 함수 호출
ISLab ICE HUFS
MFC Tutorial
121
MFC의 주요 전역 함수
AfxGetApp
AfxGetAppName
AfxGetInstanceHandle
AfxGetMainWnd
GetCurrentMessage
AfxSocketInit
AfxBeginThread
AfxEndThread
AfxGetThread
프로그램을 대표하는 프로그램 오브젝트에 대한
포인터를 돌려준다.
프로그램의 이름을 돌려준다.
프로그램의 인스턴스 핸들을 돌려준다.
메인 프레임 윈도우 오브젝트에 대한 포인터를
돌려준다.
현재 처리 중인 메시지에 대한 메시지 스트럭처를
돌려준다. 메시지 핸들러 등에서 메시지 스트럭처
를 직접 접근하고 싶을 때 이용한다.
윈도우 소켓을 초기화하기 위해 부른다.
새로운 스레드를 시작한다.
현재의 스레드를 끝낸다.
현재 실행 중인 스레드에 대한 포인터
(CWinThread)를 돌려준다.
ISLab ICE HUFS
MFC Tutorial
122
컬러 바 클래스 생성
• 클래스 위저드에서 새로운 클래스 생성
– Add Class/New에서 CMyColorBar 클래스 생성
– 상위 클래스로 CToolBarCtrl을 선택
– MyColorBar.cpp, MyColorBar.h에서 CToolBarCtrl을 CToolBar로 수
정
– 정확한 색 선택: Image 메뉴의 Adjust Colors... 선택 후 숫자로 색
입력
ISLab ICE HUFS
MFC Tutorial
123
툴바 리소스 생성
• 리소스 뷰에서 새로운 Toolbar 생성
– 버튼의 자료구조 (MyColorBar.cpp에 정의)
COLORREF color[16] =
{
RGB( 0, 0, 0),
RGB(192,192,192),
RGB(255, 0, 0),
RGB( 0,255, 0),
RGB( 0, 0,255),
RGB(128, 0, 0),
RGB( 0,128, 0),
RGB( 0, 0,128),
};
RGB(255,255,255),
RGB(128,128,128),
RGB(255,255, 0),
RGB( 0,255,255),
RGB(255, 0,255),
RGB(128,128, 0),
RGB( 0,128,128),
RGB(128, 0,128)
ISLab ICE HUFS
MFC Tutorial
124
색깔 선택
• Image 메뉴
– Adjust Colors...
ISLab ICE HUFS
MFC Tutorial
125
ColorBar 생성
#include “MyColorBar.h”
class CMainFrame : public CMDIFrameWnd
{
DECLARE_DYNAMIC(CMainFrame)
...
protected:
CToolBar m_wndToolBar;
CMyColorBar m_wndColorBar;
...
};
ISLab ICE HUFS
MFC Tutorial
126
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
....
m_wndStatusBar.SetPaneInfo(1,ID_INDICATOR_TIME,SBPS_NORMAL,60);
if (!m_wndColorBar.Create(this,WS_CHILD | WS_VISIBLE |
CBRS_SIZE_FIXED | CBRS_LEFT | CBRS_FLYBY, ID_COLORBAR) ||
!m_wndColorBar.LoadToolBar(IDR_MYCOLORBAR))
{
return FALSE;
}
m_wndColorBar.SetColumns(2);
m_wndColorBar.EnableDocking(CBRS_ALIGN_LEFT | CBRS_ALIGN_RIGHT);
DockControlBar(&m_wndColorBar);
return 0;
}
ISLab ICE HUFS
MFC Tutorial
127
void CMyColorBar::SetColumns(UINT nColumn)
{
int nCount = GetToolBarCtrl().GetButtonCount();
for(int i = 0; i < nCount; i++)
{
UINT nStyle = GetButtonStyle(i);
BOOL bWrap = (((i+1) % nColumn) == 0);
if (bWrap)
nStyle |= TBBS_WRAPPED;
else
nStyle &= ~TBBS_WRAPPED;
SetButtonStyle(i, nStyle);
}
Invalidate();
GetParentFrmae()->RecalcLayout();
}
ISLab ICE HUFS
MFC Tutorial
128
ISLab ICE HUFS
도형 처리 추가
사용자 클래스 디자인
CDrawObject
CLine
CEllipse
CRectangle
ISLab ICE HUFS
MFC Tutorial
130
사용자 클래스
class CDrawObject : public CObject
{
protected:
CDrawObject(WORD objType, COLORREF crColor, int nPenStyle,
int nPenWidth);
public:
COLORREF m_crColor; // 이 도형의 색상
int m_nPenStyle;
// 도형 둘레를 긋는 선의 스타일. PS_SOLID,
// PS_DOT,PS_DASH,PS_DASHDOT,PS_DASHDOTDOT
// 등의 값이 가능하다.
int m_nPenWidth;
// 도형 둘레를 긋는 선의 폭
int m_rcRect;
// 도형의 위치를 나타낸다.
public:
WORD m_wObjType;
// 이 오브젝트의 타입을 가리킨다. 이 타입을 가리키는
// 값은 밑에 있는 enum ObjectType의 objectLine,
// objectRectangle, objectEllipse 중의 하나가
// 될 수 있다.
ISLab ICE HUFS
MFC Tutorial
131
enum ObjectType {
objectLine, objectEllipse, objectRectangle
};
virtual
virtual
virtual
virtual
virtual
virtual
virtual
virtual
~CDrawObject();
void DrawObject(CDC *pDC) = 0; // pure virtual function
void SetStartPoint(CPoint pt) {m_rcRdct.TopLeft() = pt;}
void SetEndPoint(CPoint pt) {m_rcRect.BottomRight()=pt;}
CPoint& GetStartPoint() { return m_rcRect.TopLeft(); }
CPoint& GetEndPoint() { return m_rcRect.BottomRight(); }
void GetBoundingRect(CRect *pRect);
void Serialize(CArchive& ar);
#ifdef _DEBUG
virtual void AssertValid() const; // 유효성 여부 검사
virtual void Dump(CDumpContext& dc) const; // 객체의 내용을 디버그
// 윈도우로
#endif
};
ISLab ICE HUFS
MFC Tutorial
132
class CLine : public CDrawObject
{
protected:
DECLARE_SERIAL(CLine)
public:
CLine();
CLine(COLORREF crColor, int nPenStyle, int nPenWidth);
virtual ~CLine();
virtual void DrawObject(CDC *pDC);
virtual void Serialize(CArchive& ar);
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
};
ISLab ICE HUFS
MFC Tutorial
133
class CEllipse : public CDrawObject
{
protected:
DECLARE_SERIAL(CEllipse)
public:
CEllipse();
CEllipse(COLORREF crColor, int nPenStyle, int nPenWidth);
virtual ~CEllipse();
virtual void DrawObject(CDC* pDC);
virtual void Serialize(CAarchive& ar);
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
};
ISLab ICE HUFS
MFC Tutorial
134
class CRectangle : public CDrawObject
{
protected:
DECLARE_SERIAL(CRectangle)
public:
CRectangle();
CRectangle(COLORREF crColor, int nPenStyle, int nPenWidth);
virtual ~CEllipse();
virtual void DrawObject(CDC* pDC);
virtual void Serialize(CAarchive& ar);
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
};
ISLab ICE HUFS
MFC Tutorial
135
#include “stdafx.h”
#include “DrawObj.h”
CDrawObject::CDrawObject(WORD objType, COLORREF crColor, int nPenStyle, int
nPenWidth)
: m_wObjType(objType), m_crColor(crColor), m_nPenStyle(nPenStyle),
m_nPenWidth(nPenWidth)
{
m_rcRect.SetRectEmpty();
}
CDrawObject::~CDrawObject()
{
}
void CDrawObject::GetBoundingRect(CRect* pRect)
{
pRect->left = min(m_rcRect.left, m_rcRect.right);
pRect->right = max(m_rcRect.left, m_rcRect.right);
pRect->top = min(m_rcRect.top, m_rcRect.bottom);
pRect->bottom = max(m_rcRect.top, m_rcRect.bottom);
pRect->InflateRect(m_nPenWidth, m_nPenWidth);
}
ISLab ICE HUFS
MFC Tutorial
136
void CDrawObject::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
}
else
{
}
}
#ifdef _DEBUG
void CDrawObject::AssertValid() const
{
CObject::AssertValid();
}
void CDrawObject::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
}
#endif
ISLab ICE HUFS
MFC Tutorial
137
IMPLEMENT_SERIAL(CLine, CObject, 1)
CLine::CLine()
: CDrawObject(objectLine, RGB(0,0,0), PS_SOLID, 1)
{ }
CLine::CLine(COLORREF crColor, int nPenStyle, int nPenWidth)
: CDrawObject(objectLine, crColor, nPenStyle, nPenWidth)
{ }
CLine::~CLine()
{ }
void CLine::DrawObject(CDC* pDC)
{
CPen pen, *ppenOld;
pen.CreatePen(m_nPenStyle, m_nPenWidth, m_crColor);
ppenOld = pDC->SelectObject(&pen);
pDC->MoveTo(m_rcRect.TopLeft());
pDC->LineTo(m_rcRect.BottomRight());
pDC->SelectObject(ppenOld);
}
ISLab ICE HUFS
MFC Tutorial
138
void CLine::Serialize(CArchive& ar)
{
CDrawObject::Serialize(ar);
if (ar.IsStoring())
{
}
else
{
}
}
#ifdef _DEBUG
void CLine::AssertValid() const
{
CDrawObject::AssertValid();
}
void CLine::Dump(CDumpContext& dc) const
{
CDrawObject::Dump(dc);
}
#endif
ISLab ICE HUFS
MFC Tutorial
139
IMPLEMENT_SERIAL(CEllipse, CObject, 1)
CEllipse::CEllipse()
: CDrawObject(objectEllipse,RGB(0,0,0),PS_SOLID,1)
{ }
CEllipse::CEllipse(COLORREF crColor, int nPenStyle, int nPenWidth)
: CDrawObject(objectEllipse, crColor, nPenStyle, nPenWidth)
{ }
void CEllipse::DrawObject(CDC* pDC)
{
CBrush br, *pbrOld;
CPen pen, *ppenOld;
br.CreateSolidBrush(m_crColor);
pen.CreatePen(m_nPenStyle, m_nPenWidth, m_crColor);
pbrOld = pDC->SelectObject(&br);
ppenOld = pDC->SelectObject(&pen);
pDC->Ellipse(&m_rcRect);
pDC->SelectObject(pbrOld);
pDC->SelectObject(ppenOld);
}
ISLab ICE HUFS
MFC Tutorial
140
CEllipse::~CEllipse()
{ }
void CEllipse::Serialize(CArchive& ar)
{
CDrawObject::Serialize(ar);
if (ar.IsStoring())
{
}
else
{
}
}
#ifdef _DEBUG
void CEllipse::AssertValid() const
{
CDrawObject::AssertValid();
}
void CEllipse::Dump(CDumpContext& dc) const
{
CDrawObject::Dump(dc);
}
#endif
ISLab ICE HUFS
MFC Tutorial
141
IMPLEMENT_SERIAL(CRectangle, CObject, 1)
CRectangle::CRectangle()
: CDrawObject(objectRectangle,RGB(0,0,0),PS_SOLD,1)
{ }
CRectangle::CRectangle(COLORREF crColor,int nPenStyle,int nPenWidth)
: CDrawObject(objectEllipse, crColor, nPenStyle, nPenWidth)
{ }
void CRectangle::DrawObject(CDC* pDC)
{
CBrush br, *pbrOld;
CPen pen, *ppenOld;
br.CreateSolidBrush(m_crColor);
pen.CreatePen(m_nPenStyle, m_nPenWidth, m_crColor);
pbrOld = pDC->SelectObject(&br);
ppenOld = pDC->SelectObject(&pen);
pDC->Rectangle(&m_rcRect);
pDC->SelectObject(pbrOld);
pDC->SelectObject(ppenOld);
}
ISLab ICE HUFS
MFC Tutorial
142
CRectangle::~CRectangle()
{ }
void CRectangle::Serialize(CArchive& ar)
{
CDrawObject::Serialize(ar);
if (ar.IsStoring())
{
}
else
{
}
}
#ifdef _DEBUG
void CRectangle::AssertValid() const
{
CDrawObject::AssertValid();
}
void CRectangle::Dump(CDumpContext& dc) const
{
CDrawObject::Dump(dc);
}
#endif
ISLab ICE HUFS
MFC Tutorial
143
윈도우 운영체제에서의 출력
응용 프로그램
WIN32 API
GDI (Graphic Device Interface)
디바이스 드라이버
실제 출력 장치
ISLab ICE HUFS
MFC Tutorial
144
DirectX
• 윈도우 3.1의 그래픽 출력 속도 저하 극복을 위해
– 게임 (WinG)
• DirectDraw
– DirectX의 그래픽 부분 라이브러리
• DirectPlay
– 네트워크 게임을 만드는데 사용할 수 있는 라이브러리
• DirectSound
– 사운드 기능을 제공해 주는 라이브러리
• DirectInput
– 조이스틱 등의 제어에 사용할 수 있는 라이브러리
ISLab ICE HUFS
MFC Tutorial
145
디바이스 컨텍스트
• Device Context
• 윈도우 운영체제에서 출력 대상을 지칭하는 것
• 논리적으로 볼 때 붓, 펜, 팔레트, 종이(비트맵), 폰트 등
의 그림을 그리기 위한 도구의 집합
• 장치와 문관하게 GDI 함수 호출 가능
• 붓과 펜은 DC 내에 하나씩 존재
• GetDC & ReleaseDC
ISLab ICE HUFS
MFC Tutorial
146
DC의 종류
• CClientDC
– 윈도우의 클라이언트 영역
• CWindowDC
– 윈도우 전체 디바이스 컨텍스트
– 윈도우의 경계선, 캡션 영역 등에도 그리기 가능
• CPaintDC
– WM_PAINT 발생시에 사용
ISLab ICE HUFS
MFC Tutorial
147
윈도우 운영체제에서의 출력 절차
출력할 장치의 디바이스 컨텍스트의 핸들을 얻는다.
GDI로 앞에서 얻은 핸들에 출력을 행한다.
디바이스 컨텍스트를 제거한다.
ISLab ICE HUFS
MFC Tutorial
148
SDK에서의 붓과 펜의 변경 절차
1. 펜이나 붓을 생성한다(CreatePen, CreateSolidBrush).
2. 디바이스 컨텍스트를 얻는다(GetDC나 BeginPaint).
3. 2에서 얻은 디바이스149 컨텍스트의 드로잉 툴을 1에서 만든 드로잉 툴로
바꾼다(SelectObject). 교체하면서 원래 들어있던 펜이나 붓을 기억해야.
4. GDI를 이용해 출력 작업을 수행한다.
5. 3에서 기억해 놓았던 원래의 붓이나 펜을 원상복구 시킨다(SelectObject).
6. 디바이스 컨텍스트를 윈도우 운영체제로 반환한다.
7. 1에서 만든 펜이나 붓을 삭제한다(DeleteObject).
ISLab ICE HUFS
MFC Tutorial
149
CDC 클래스의 주요 함수(1)
CreateCompatibleDC
GetSafeHdc
IsPrinting
SetROP2
SetBkColor
SetTextColor
MoveTo, LineTo
Arc, ArcTo
PolyDraw
PloyLine
Polygon
인자로 주어진 DC와 같은 속성을 갖는 DC를
메모리에 만든다.
현재 오브젝트가 둘러싸고 있는 디바이스 컨텍스트
핸들을 돌려준다.
프린트 DC인지 아닌지의 여부를 돌려준다.
그리기모드를 변경하는데 사용된다.
글자출력 시의 배경색을 지정한다.
글자출력 시의 글자색을 지정한다.
직선을 긋는데 사용한다.
원호를 그리는데 사용한다.
직선과 베지어 스프라인을 연속적으로 그림
직선을 연속적으로 그리는데 사용
직선을 연속적으로 그리는데 처은 점과 마지막
점을 잇는다
ISLab ICE HUFS
MFC Tutorial
150
CDC 클래스의 주요 함수(2)
PolyBezier
InvertRect
DrawIcon
Draw3dRect
Ellipse
Pie
Rectangle
RountRect
SetPixel
BitBlt
TextOut
DrawText
베이어 스프라인을 연속적으로 그리는데 사용
주어진 영역을 반전하는데 사용한다.
주어진 위치에 주어진 아이콘을 그려준다.
입체적인 사각형을 그리는데 사용한다.
타원(원 포함)을 그리는데 사용한다.
부채꼴을 그리는데 사용한다.
사각형을 그리는데 사용한다.
모서리가 둥근 사각형을 그리는데 사용한다.
점을 찍는데 사용한다.
한 디바이스 컨텍스트의 내용을 다른 디바이스 컨텍스트로
복사한다.
주어진 위치에 텍스트를 출력한다.
주어진 사각형 내에 텍스트를 출력한다.
ISLab ICE HUFS
MFC Tutorial
151
View 클래스 변경(1)
#include “DrawObj.h”
class CObeditView : public CScrollView
{
....
// Attributes
public:
CObeditDoc* GetDocument();
int m_nSelectedColorID; // 현재 컬러 팔레트에서 선택된 버튼의 인덱스
COLORREF m_crCurColor; // 컬러 팔레트에서 선택된 버튼에 해당하는 RGB 값
int m_nPenStyle;
// 현재 선택된 펜 스타일
int m_nPenWidth;
// 현재 선택된 펜의 굵기
CDrawObject* m_pCurDrawObject; // 현재 만들어지고 있는 도형
WORD m_wCurDrawObject; // 현재 선택된 도형이 무엇인지 나타낸다.
....
};
ISLab ICE HUFS
MFC Tutorial
152
View 클래스 변경(2)
extern COLORREF color[16];
CObeditView::CObeditView()
{
m_nSelectedColorID = 0; // 디폴트로 선택되는 컬러 팔레트의 버튼은 첫번째
m_crCurColor = color[m_nSelectedColorID]; // 첫번째 버튼에 해당하는 색
m_nPenStyle = PS_SOLID; // 펜의 초기 스타일
m_nPenWidth = 1;
m_pCurDrawObject = NULL;
m_wCurDrawObject = CDrawObject::objectLine;
}
ISLab ICE HUFS
MFC Tutorial
153
메뉴 선택 코드 추가
• 클래스 위저를 통한 메뉴 함수 구현
ISLab ICE HUFS
MFC Tutorial
154
메뉴 선택 함수
void CObeditView::OnObjectLine()
{
m_wCurDrawObject = CDrawObject::objectLine;
}
void CObeditView::OnObjectRectangle()
{
m_wCurDrawObject = CDrawObject::objectRectangle;
}
void CObeditView::OnObjectEllipse()
{
m_wCurDrawObject = CDrawObject::objectEllipse;
}
ISLab ICE HUFS
MFC Tutorial
155
메뉴의 UPDATE_COMMAND_UI
void CObeditView::OnUpdateObjectLine(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_wCurDrawObject == CDrawObject::objectLine);
}
void CObeditView::OnUpdateObjectRectangle(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_wCurDrawObject == rawObject::objectRectangle);
}
void CObeditView::OnUpdateObjectRectangle(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_wCurDrawObject == DrawObject::objectRectangle);
}
ISLab ICE HUFS
MFC Tutorial
156
칼라 메뉴
void CObeditView::OnPalettecolor1()
{
m_nSelectedColorID = 0;
m_crCurColor = color[0];
}
// 컬러 팔레트 메뉴 함수. 16번 반복
void CObeditView::OnUpdatecolor1(CCmdIO* pCmdUI)
{
pCmdUI->SetCheck(m_nSelectedColorID == 0);
}
ISLab ICE HUFS
MFC Tutorial
157
Message Map
• 기존 윈도우 프로시저를 대신
BEGIN_MESSAGE_MAP(CObeditView, CScrollView)
//{{AFX_MSG_MAP(CObeditView)
ON_COMMAND(ID_OBJECT_ELIIPSE, OnObjectEllipse)
ON_UPDATE_COMMAND_UI(ID_OBJECT_ELLIPSE, OnUpdateObjectEllise)
ON_COMMAND(ID_OBJECT_LINE, OnObjectLine)
ON_UPDATE_COMMAND_UI(ID_OBJECT_LINE, OnUpdateObjectLine)
ON_COMMAND(ID_OBJECT_RECTANGLE, OnObjectRectangle)
ON_UPDATE_COMMAND_UI(ID_OBJECT_RECTANGLE, OnUpdateObjectRectangle)
//}}AFX_MSG_MAP
//Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
END_MESSAGE_MAP()
ISLab ICE HUFS
MFC Tutorial
158
윈도우의 입력 메시지 종류
• 하드웨어적인 이유로 발생하는 메시지
– 키보드
– 마우스
– 타이머
• 키보드 메시지나 마우스 메시지를 해석하여 발생하는 메시지
– 캐릭터
– 스크롤 바
– 메뉴
ISLab ICE HUFS
MFC Tutorial
159
키보드 입력 메시지
• 종류
– WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP
• 가상 키 코드 (virtual keycode) - lParam
비트 0 - 15
비트 16 - 23
비트
비트
비트
비트
비트
비트
24
25 - 26
27 - 28
29
30
31
키의 반복 횟수
키의 스캔 코드
(키보드 제조업체에 따라 다를 수 있다)
확장 키 여부 (1 : 확장키, 0 : 아님)
쓰이지 않음
윈도우 운영체제가 내부적으로 사용
컨텍스트 코드 (1 : Alt 키가 눌림, 0 : 안 눌림)
키의 이전 상태 (1 : 키가 눌려져 있었음, 0 : 아님)
키의 현재 전환 상태
(1 : 키가 떼어지는 것, 0 : 눌려지는 것)
ISLab ICE HUFS
MFC Tutorial
160
문자 입력 메시지
• 종류
– WM_CHAR, WM_SYSCHAR
• 메시지 발생 순서
– 아스키 코드가 있을 때(SDK에서는 TranslateMessage 함수가 반
드시 불려야
WM_KEYDOWN
-->
WM_CHAR
-->
WM_KEYUP
– 아스키 코드가 없을 때(예 : ENTER)
WM_KEYDOWN
-->
WM_KEYUP
• 인자
– wParam : 아스키 코드
– lParam : WM_KEYDOWN, WM_KEYUP에서와 같음
ISLab ICE HUFS
MFC Tutorial
161
마우스 메시지의 처리
• 마우스 이벤트의 종류
–
–
–
–
–
–
–
WM_LBUTTONDBLCLK
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_MOUSEMOVE
WM_RBUTTONDBLCLK
WM_RBUTTONDOWN
WM_RBUTTONUP
• 넘어오는 좌표 : Pixel 단위
ISLab ICE HUFS
MFC Tutorial
162
마우스 메시지와 윈도우
t1에서 t2 사이에는 1번 윈도우로
마우스 메시지가 발생하고,
t2와 t3 사이에는 2번 윈도우로
메시지가 발생한다.
1
t1
t2
t3
2
마우스 커서의 이동 자취
ISLab ICE HUFS
MFC Tutorial
163
드래그시의 문제점
• SetCapture, ReleaseCapture
1. 드래그 시작
2. 윈도우 바깥으로 나가면
마우스 메시지가 이
윈도우에게로 발생하지
않는다.
ISLab ICE HUFS
MFC Tutorial
164
타이머 입력 메시지
• 종류
– WM_TIMER
• 주기적으로 하고 싶은 일이 있을 때 사용되는 메시지
– 예) 워드프로세서에서 주기 저장, 테트리스 게임에서 적당 시간
간격으로 블록을 떨어뜨릴 때
• SetTimer, KillTimer
ISLab ICE HUFS
MFC Tutorial
165
타이머 설정
• CMainFrame 클래스의 OnCreate 함수에서 설정
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
...
DockControlBar(&m_wndToolBar);
m_wndStatusBar.SetPaneInfo(1,ID_INDICATOR_TIME,SBPS_NORMAL,60);
SetTimer(1, 1000, NULL);
return 0;
}
ISLab ICE HUFS
MFC Tutorial
166
WM_TIMER 메시지 처리 함수
void CMainFrame::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
char timebuf[12];
_strtime(timebuf);
m_wndStatusBar.SetPaneText(1, timebuf, TRUE);
CMDIFrameWnd::OnTimer(nIDEvent);
}
• CMainFrame이 아닌 다른 클래스에서 불릴때
void f()
{
...
((CMainFrame*)AfxGetMainWnd())->UpdateTime(); // 다른 클래스에서
...
}
ISLab ICE HUFS
MFC Tutorial
167
타이머 해제
void CMainFrame::f()
{
...
SetTimer(1, 1000, NULL);
SetTimer(2, 10000, lpFuction);
...
}
void CMainFrame::g()
{
...
KillTimer(1);
KillTimer(2);
...
}
void lpFunction(HWND hWnd, UINT, UINT, DWORD)
{
...
}
ISLab ICE HUFS
MFC Tutorial
168
타이머 사용시 주의점
• PC 타이머 칩이 발생시키는 최소 시간 간격 : 55 밀리초
• 메시지 큐에서 약간의 지연 발생
• WM_TIMER 메시지 처리가 늦어지면 메시지가 쌓여 큐가
넘칠 수 있으므로 메시지 큐에서는 하나의 WM_TIMER
만 가능 (WM_PAINT도 마찬가지)
ISLab ICE HUFS
MFC Tutorial
169
스크롤 바 입력 메시지
• 종류
– WM_VSCROLL, WM_HSCROLL
SB_PAGEUP
SB_PAGEDOWN
SB_LINEUP
SB_LINEDOWN
ISLab ICE HUFS
MFC Tutorial
170
메뉴 입력 메시지
• 종류
– WM_COMMAND, WM_SYSCOMMAND
• 단축키 사용 가능
• ASCII vs. VIRTKEY
ISLab ICE HUFS
MFC Tutorial
171
LButtonDown
void CObeditView::OnLButtonDown(UINT nFlags, CPoint point)
{
switch(m_wCurDrawObject) // 객체 생성
{
case CDrawObject::objectLine :
m_pCurDrawObject = new CLine(m_crCurColor, m_nPenStyle, m_nPenWidth);
break;
case CDrawObject::objectRectangle :
m_pCurDrawObject = new CRectangle(m_crCurColor,m_nPenStyle,m_nPenWidth);
break;
case CDrawObject::objectEllipse :
m_pCurDrawObject = new CEllipse(m_crCurColor, m_nPenStyle, m_nPenWidth);
break;
}
m_pCurDrawObject->SetStartPoint(point); // 객체의 시작위치 저장
m_pCurDrawObject->SetEndPoint(point);
SetCapture();
}
// 모든 마우스 메시지가 CObeditView 객체로 온다.
// 마우스 메시지 독점. 마우스 드래그를 지원하기 위해
// ReleaseCapture 호출 때까지
ISLab ICE HUFS
MFC Tutorial
172
MouseMove
void CObeditView::OnMouseMove(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
// 드래그 중인지 판단
{
CClientDC dc(this);
dc.SetROP2(R2_NOTXORPEN); // XOR 모드로 그림을 그린다.
m_pCurDrawObject->DrawObject(&dc); // 이전에 그려졌던 도형을 지운다
m_pCurDrawObject->SetEndPoint(point); // 새로운 도형의 위치 저장
m_pCurDrawObject->DrawObject(&dc); // 새로운 위치에 도형을 그린다.
// virtual function
}
}
ISLab ICE HUFS
MFC Tutorial
173
LButtonUp
void CObeditView::OnLButtonUp(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{
CClientDC dc(this);
m_pCurDrawObject->SetEndPoint(point);
m_pCurDrawObject->DrawObject(&dc);
ReleaseCapture(); // 마우스 독점 해제
}
}
ISLab ICE HUFS
MFC Tutorial
174
윈도우에서의 화면 복구
1
1
1
2
1번 윈도우에 의해 가려
졌던 2번 윈도우가 클릭
된다.
2
가려졌던 영역이 일단
WM_ERASEBKGND
메시지에 의해 지워진다.
2
WM_PAINT 메시지에
의해 가려졌던 영역이
복구된다.
ISLab ICE HUFS
MFC Tutorial
175
WM_PAINT
• 화면을 복구하는데 사용
– 윈도우로 출력하는데 사용되는 메시지가 아니다.
• 윈도우가 처음 생성될 때도 한번 발생
• 새로 그려야 할 영역 고려
ISLab ICE HUFS
MFC Tutorial
176
WM_PAINT - SDK
• SDK에서
– 반드시 BeginPaint / EndPaint 함수를 이용하여야 한다.
– 그려야 할 영역을 PAINTSTRUCT 인자로 알 수 있기 때문
HDC hDC;
PAINTSTRUCT ps;
hDC = BeginPaint(hWnd, &ps);
// ps.rcPaint에 복구 영역의 좌표가 들어있다.
// 이 부분만 딱 그려줄 수 있다면 가장 이상적이다.
EndPaint(hWnd, &ps);
ISLab ICE HUFS
MFC Tutorial
177
WM_PAINT
• OnDraw 함수 호출
void CView::OnPaint()
{
CPaintDC dc(this);
OnPrepareDC(&dc);
OnDraw(&dc);
}
ISLab ICE HUFS
MFC Tutorial
178
자료 구조 유지
• 다시 그리기 위한 자료 구조 유지
class CObeditDoc : public CDocument
{
....
// Attributes
public:
CObList m_objectList;
....
}
ISLab ICE HUFS
MFC Tutorial
179
LButtonUp 수정
void CObeditView::OnLButtonUp(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{
CClientDC dc(this);
m_pCurDrawObject->SetEndPoint(point);
m_pCurDrawObject->DrawObject(&dc);
ReleaseCapture(); // 마우스 독점 해제
CObeditDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDoc->m_objectList.AddTail(m_pCurDrawObject);
}
}
ISLab ICE HUFS
MFC Tutorial
180
OnDraw
void CObeditView::OnDraw(CDC* pDC)
{
ObeditDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CRect rectClip, rectObject;
pDC->GetClipBox(&rectClip);
// 복구해야할 영역
POSITION pos = pDoc->m_objectList.GetHeadPosition();
while( pos != NULL )
{
CDrawObject* pObject = (CDrawObject*) pDoc->m_objectList.GetNext(pos);
pObject->GetBoundingRect(&rectObject);
// 복구해야할 영역과 겹치는 부분만 다시 그림
if (!rectObject.IntersectRect(&rectObject, &rectClip))
continue;
pObject->DrawObject(pDC);
}
}
ISLab ICE HUFS
MFC Tutorial
181
SDK/MFC에서의 메시지 처리
LONG __export FAR PASCAL
MainWndProc(HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE :
OnCreate();
break;
case WM_PAINT :
OnPaint();
break;
case WM_DESTROY :
OnDestroy();
break;
default :
DefWindowProc();
}
return OL;
}
BEGIN_MESSAGE_MAP(CMyWnd, CWnd)
ON_WM_CREATE()
ON_WM_PAINT()
ON_WM_DESTROY()
END_MESSAGE_MAP()
AFX_MSGMAP_ENTRY _messageEntries[]=
{
{ WM_CREATE, OnCreate },
{ WM_PAINT, OnPaint },
{ WM_DESTROY, OnDestroy }
};
ISLab ICE HUFS
MFC Tutorial
182
MFC에서의 메시지 처리(1)
• CMainFrame
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
ON_WM_CREATE()
END_MESSAGE_MAP()
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// 상위 클래스의 OnCreate 부터 부른 다음 작업 수행
if(CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.Create(this) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
....
ISLab ICE HUFS
MFC Tutorial
183
MFC에서의 메시지 처리(2)
• CWnd
_AFXWIN_INLINE afx_msg int CWnd::OnCreate(LPCREATESTRUCT)
{
return (int)Default();
// DefWindowProc()을 부름
}
– 대부분의 메시지는 거의 모두 Default()를 부름
ISLab ICE HUFS
MFC Tutorial
184
명령 경로 배정(command routing)
• WM_COMMAND, WM_UPDATE_COMMAND_UI
– CCmdTarget로부터 계승받은 클래스만 받을 수 있다.
• 메뉴 처리
– CWnd가 아닌 CDocument, CView에서 처리하는 것이 자연스러움
• 예) 화일 저장, 색 선택
ISLab ICE HUFS
MFC Tutorial
185
CCmdTarget 클래스
CObject
CCmdTarget
CWinApp
CDocTemplate
CMultiDocTemplate
CWnd
CSingleDocTemplate
CFrameWnd
CView
CDocument
CDialog
ISLab ICE HUFS
MFC Tutorial
186
Routing 순서
Comand를 받은 오브젝트
routing 순서
프레임 윈도우
1. 활성화된 자식윈도우 혹은 뷰
2. 자기 자신
3. CWinApp 오브젝트
뷰(View)
1. 자기 자신
2. 자신과 연관된 문서오브젝트
문서(Document)
1. 자기 자신
2. 이 문서가 속한 문서템플릿
다이얼로그
1. 자기 자신
2. 이 다이얼로그를 소유한 윈도우 오브젝트
3. CWinApp 오브젝트
ISLab ICE HUFS
MFC Tutorial
187
CCmdUI의 멤버 함수
멤버함수 이름
Enable
기능
메뉴 항목의 상태를 활성화시키거나 그레이 상태로
만든다.
SetCheck
메뉴 항목의 옆에 체크 표시를 만든다. 툴바 버튼의
경우에는 눌려진 상태로 표시한다.
SetRadio
기능 자체는 SetCheck와 같은데 체크 표시 대신에
 표시를 사용한다.
SetText
메뉴 항목의 텍스트를 변경한다. 툴바 버튼에
대해서는 별 의미가 없다.
ISLab ICE HUFS
MFC Tutorial
188
메시지 맵 매크로(1)
• 기존의 윈도우 메시지
– WM_XXXX, ON_WM_XXXX, OnXxxxx
• 예) WM_CHAR, ON_WM_CHAR, OnChar
– WM_COMMAND, WM_UPDATE_COMMAND_UI 메시지는 예외
• 함수의 이름을 사용자가 정할 수 있음, void 처리함수이름(void);
• 사용자 정의 메시지
– WM_USER에서 0x7FFF 사이의 값
– ON_MESSAGE
– LONG 처리함수 이름(DWORD, LONG);
ISLab ICE HUFS
MFC Tutorial
189
등록된 메시지(2)
• 등록된 메시지
– RegisterWindowMessage 함수를 이용해 메시지 값을 만든 경우
– ON_REGISTERED_MESSAGE, 함수의 인자는 사용 자 정의 메시지
와 동일
• 콘트롤로부터의 알림(notification) 메시지
– ON_CONTROL(알림코드, 컨트롤ID, 처리함수 이름)
– void 처리함수이름(void);
ISLab ICE HUFS
MFC Tutorial
190
사용자 정의 메시지
• 종류
– WM_USER(0x7fff) 부터
• 메시지 전달 방법
– SendMessage
• 메시지를 발생시켜 해당 윈도우에서 그 메시지의 처리가 끝난 다음
에야 리턴
– PostMessage
• 메시지를 해당 윈도우가 소속된 메시지 큐에 집어넣고 바로 리턴
– 메시지 부가 인자로 다량의 데이타를 보낼 때는 사용자 데이타
타입을WPARAM이나 LPARAM로 캐스팅해서 보낸다.
ISLab ICE HUFS
MFC Tutorial
191
사용자 정의 메시지 예
#define WM_MYMESSAGE (WM_USER + 1)
SendMessage(hTargetWnd, WM_MYMESSAGE, 0, (LPARAM)lpStr);
BEGIN_MESSAGE_MAP(...)
WM_MESSAGE(WM_MYMESSAGE, OnMyMessage)
END_MESSAGE()
void CMyWin::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
lpData = (LPSTR)lParam;
...
}
ISLab ICE HUFS
MFC Tutorial
192
메시지맵 매크로
• 종류
–
–
–
–
ON_COMMAND_RANGE
ON_COMMAND_EX
ON_UPDATE_COMMAND_UI_RANGE
ON_CONTROL_RANGE
ISLab ICE HUFS
MFC Tutorial
193
Message Map Macro의 예
• CObeditView.cpp
BEGIN_MESSAGE_MAP(CObeditView, CScrollView)
//{{AFX_MSG_MAP(CObeditView)
....
//}}AFX_MSG_MAP
// Standard printing commands
....
ON_COMMAND_RANGE(ID_PALETTECOLOR1, ID_PALETTECOLOR16,
OnColorPalette)
ON_UPDATE_COMMAND_UI_RANGE(ID_PALETTECOLOR1, ID_PALETTECOLOR16,
OnUpdateColorPalette)
END_MESSAGE_MAP()
ISLab ICE HUFS
MFC Tutorial
194
class CObeditView : public CScrollView
{
....
protected:
//{{AFX_MSG(CObeditView)
....
//}}AFX_MSG
afx_msg void OnColorPalette(UINT nID);
afx_msg void OnUpdateColorPalette(CCmdUI* pCmdUI);
DECLARE_MESSAGE_MAP()
};
void CObeditView::OnColorPalette(UINT nID)
{
m_nSelectedColorID = nID;
m_crCurColor = color[nID - (UINT)ID_PALETTECOLOR1];
}
void CObeditView::OnUpdateColorPalette(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(pCmdUI->m_nID == (UINT)m_nSelectedColorID);
}
ISLab ICE HUFS
MFC Tutorial
195
void CMainFrame::OnViewColorbar()
{
if (m_wndColorBar.GetStyle() & WS_VISIBLE)
m_wndColorBar.ShowWindow(SH_HIDE);
else
m_wndColorBar.ShowWindow(SH_SHOW);
RecalcLayout();
void CMainFrame::OnUpdateViewColorbar(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_wndColorBar.GetStyle() & WS_VISIBLE);
}
ISLab ICE HUFS
MFC Tutorial
196
GDI 객체
• GDI 객체 종류
– CBitmap, CBrush, CFont, CPalette, Cpen, CRgn
• GDI 존속기간
– GetSafeHdc 함수 이용
void A::f()
{
CFont* pOldFont = pDC->SelectObject(m_pPrintFont);
m_hOldFont = (HFONT) pOldFont->GetSafeHandle();
}
void A::g()
{
if (m_hOldFont)
pDC->SelectObject(CFont::FromHandle(m_hOldFont));
}
ISLab ICE HUFS
MFC Tutorial
197
폰트 설정
void CTestView::ShowFont(CDC* pDC, int& nPos, int nPoints)
{
TEXTMETRIC tm;
CFont
fontText;
CString strText;
CSize
sizeText;
fontText.CreateFont(-nPoint*20, 0, 0, 0, 400, FALSE, FALSE, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, “Arial”);
CFont* pOldFont = (CFont*)pDC->SelectObject(&fontText);
pDC->GetTextMetrics(&tm);
strText.Format(“This is %d-point Arial”, nPoints);
sizeText = pDC->GetTextExtent(strText);
pDC->TextOut(0, nPos, strText);
pDC->SelectObject(pOldFont);
nPos -= tm.tmHeight + tm.tmExternalLeading;
}
ISLab ICE HUFS
MFC Tutorial
198
ISLab ICE HUFS
스크롤 기능
목차
•
•
•
•
•
매핑 모드
좌표계
스크롤 기능
스크롤 바
논리 물리 좌표간 변환
ISLab ICE HUFS
MFC Tutorial
200
Mapping Mode
• 매핑 모드(mapping mode)
– 윈도우 출력함수(GDI)에서 출력좌표를 해석하는 방법
– 디바이스 컨텍스트(device context)마다 존재
– 디폴트 매핑 모드는 MM_TEXT
• MM_TEXT
– 출력 원점이 윈도우 클라이언트 영역의 좌측 상단
– 출력 원점에서 X 좌표는 오른쪽으로 증가, Y 좌표는 아래 방향으
로 증가
– 단위 : 픽셀(pixel)
– 단점 : 해상도에 따라 출력되는 내용의 크기가 달라진다.
• 예) 프린트
ISLab ICE HUFS
MFC Tutorial
201
Mapping Mode의 종류
매핑모드
MM_TEXT
MM_LOMETRIC
MM_HIMETRIC
MM_LOENGLISH
MM_HIENGLISH
MM_TWIPS
MM_ISOTROPIC
MM_ANISOTROPIC
단위
픽셀
0.1 mm
0.01 mm
0.1 in
0.01 in
1/1440 in
지정가능
지정가능
X 방향증가
오른쪽
오른쪽
오른쪽
오른쪽
오른쪽
오른쪽
지정가능
지정가능
Y방향증가
아래쪽
위쪽
위쪽
위쪽
위쪽
위쪽
지정가능
지정가능
– MM_ISOTROPIC, MM_ANISOTROPIC 을 이용하여 화면 확대/축소 가능
ISLab ICE HUFS
MFC Tutorial
202
MM_TWIPS
• 프린터에 가장 많이 사용
• 1 twip은 1/20 포인트에 해당 (1포인트는 1/72 인치에 해
당)
• 예 : 12포인트 문자
– 12 X 20 = 240 트윕
ISLab ICE HUFS
MFC Tutorial
203
매핑 모드의 변경
• CDC 클래스의 SetMapMode 함수 이용
CClientDC dc(this);
dc.SetMapMode(MM_LOMETRIC);
dc.TextOut(100, 500, “테스트중입니다.-1”);
dc.TextOut(100, -500, “테스트중입니다.-2”);
테스트중입니다.-1
500
윈도우 밖으로 출력되어 보이지 않는다.
500
100
테스트중입니다.-2
ISLab ICE HUFS
MFC Tutorial
204
좌표계
• 디바이스(device) 좌표
– 실제 출력 장치의 좌표
• 논리(logical) 좌표
– 출력함수에 사용하는 좌표
• 디바이스 좌표와 논리 좌표간의 변환이 필요
– DPtoLP
– LPtoDP
ISLab ICE HUFS
MFC Tutorial
205
좌표계의 원점 이동
• SetWindowOrg
– 논리 좌표의 원점 이동
• SetViewportOrg
– 디바이스 좌표의 원점 이동
ISLab ICE HUFS
MFC Tutorial
206
CClientDC dc(this);
dc.SetMapMode(MM_LOMETRIC);
dc.MoveTo(0,0);
dc.LineTo(100, -100);
(0,0)
1 cm
1 cm
ISLab ICE HUFS
MFC Tutorial
207
CClientDC dc(this);
dc.SetMapMode(MM_LOMETRIC);
dc.SetViewportOrg(100,100);
// 디바이스 좌표의 원점 이동
dc.MoveTo(0,0);
dc.LineTo(100,-100);
(0,0)
(100,100)
1 cm
1 cm
ISLab ICE HUFS
MFC Tutorial
208
CClientDC dc(this);
dc.SetMapMode(MM_LOMETRIC);
dc.SetWindowOrg(100,100); // 윈도우 좌표의 원점 이동
dc.MoveTo(0,0);
dc.LineTo(100,-100);
변경된 원점
1 cm
(0,0)
1 cm
1 cm
1 cm
ISLab ICE HUFS
MFC Tutorial
209
좌표계 사이의 좌표 변환
• DPtoLP
– 디바이스 좌표를 현재 사용중인 매핑모드에 맞춰 논리 좌표로 변
환
• LPtoDP
– 논리 좌표를 현재 사용중인 매핑모드에 맞춰 디바이스 좌표로 변
환
– 예) 마우스 커서의 위치를 논리 좌표로 변환하는 경우
• 마우스 좌표는 디바이스 좌표와 동일한 특성을 갖는다. 즉 윈도우 클
라이언트 영역의 좌측 상단을 기준으로 픽셀 단위의 좌표가 넘어온
다.
ISLab ICE HUFS
MFC Tutorial
210
단위 길이 계산
• SetWindowExt / GetWindowExt
• SetViewportExt / GetViewportExt
ISLab ICE HUFS
MFC Tutorial
211
CScrollView를 이용한 스크롤 기능
• 스크롤에 관계된 작업이 CScrollView에 이미 구현
• 편집 문서의 크기 결정
– 스크롤 영역 설정의 기능
void CObeditView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CSize sizeTotal;
// TODO: calculate the total size of this view
sizeTotal.cx = sizeTotal.cy = 100;
SetScrollSizes(MM_TEXT, sizeTotal);
}
ISLab ICE HUFS
MFC Tutorial
212
SetScrollSize
• OnInitialUpdate 함수
– 뷰 오브젝트가 생성된 뒤에 바로 호출되는 함수
• SetScrollSize
–
void CScrollView::SetScrollSize(int nMapMode, SIZE sizeTotal,
const SIZE& sizePage, const SIZE& sizeLine);
– 편집 문서의 크기, 매핑모드, 스크롤 작업의 크기를 알림
– 스크롤 작업의 크기
• 스크롤 바를 눌렀을 때 얼마나 스크롤할 것인지 그 양을 말함
• 실행 중에 매핑모드에 변경이 생기면 그때마다 SetScrollSize를 호출
하여 변경사항을 반드시 반영해야 함
– sizePage : PageDown을 눌렀을 때. 디폴트 값 = 문서 크기의
1/10
– sizeLine : 스크롤 라인. 디폴트 값 = 문서 크기의 1/100
ISLab ICE HUFS
MFC Tutorial
213
문서 크기의 지정
class CObeditDoc : public CDocument
{
....
public:
CObList m_objectList;
CSize m_sizeDoc;
// 문서의 크기
CSize GetDocumentSize() { return m_sizeDoc; };
....
}
CObeditDoc::CObeditDoc()
{
m_sizeDoc = CSize(500, 500);
}
void CObeditView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
SetScrollSizes(MM_TEXT, GetDocument()->GetDocumentsSize());
}
ISLab ICE HUFS
MFC Tutorial
214
스크롤 바
• 문서 영역
• 엄지(thumb)
– 현재 뷰가 보여주고 있는 부분이 편집문서에서 어디에 위치한 것
인가
– 현재 보이는 부분이 전체적으로 볼 때 어느 정도의 부분을 차지
하는지
• 비례 스크롤바(proportional scrollbar)
ISLab ICE HUFS
MFC Tutorial
215
출력 원점의 보정
• 스크롤이 일어나면 편집 문서와 출력함수의 원점이 달라
짐
– SetViewportOrg, SetWindowOrg을 이용하여 두 원점을 하나로 만
듬
– 즉 CDC 클래스의 출력함수에서 사용하는 출력원점을 편집 문서
의 원점으로 이동시킴
– 항상 편집 문서의 원점을 바탕으로 한 좌표를 사용하도록 하면
좌표의 변환없이 문서의 좌표를 그대로 출력에 이용할 수 있음
• 이와 같은 일을 CScrollView가 알아서 한다.
ISLab ICE HUFS
MFC Tutorial
216
편집문서
500
100
윈도우
500
100
300
300
ISLab ICE HUFS
MFC Tutorial
217
마우스 좌표와 논리 좌표의 충돌
마우스가 넘겨주는 좌표
편집문서의 좌표
뷰
전체문서
ISLab ICE HUFS
MFC Tutorial
218
LButtonDown
void CObeditView::OnLButtonDown(UINT nFlags, CPoint point)
{
CClientDC dc(NULL);
OnPrepareDC(&dc); // 오브젝트의 매핑 모드와 원점을 현재의 스크롤 상태에
// 맞게 변환
// 즉 1. 매핑 모드 변환
// 2. 스크롤 바의 엄지 값을 읽어 그만큼 출력 장치의
//
원점을 뒤로 이동
dc.DPtoLP(&point); // 좌표 단위의 변환 및 원점의 위치까지 고려하여 좌표
// 좌표 변환 수행
// 즉, 마우스 좌표를 편집 문서의 원점으로부터의
// 좌표로 변환
switch(m_wCurDrawObject)
{
case CDrawObject::objectLine :
..........
}
ISLab ICE HUFS
MFC Tutorial
219
MouseMove
void CObeditView::OnMouseMove(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DPtoLP(&point);
dc.SetROP2(R2_NOTXORPEN);
m_pCurDrawObject->DrawObject(&dc);
m_pCurDrawObject->SetEndPoint(point);
m_pCurDrawObject->DrawObject(&dc);
}
ISLab ICE HUFS
MFC Tutorial
220
LButtonUp
void CObeditView::OnLButtonUp(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DPtoLP(&point);
m_pCurDrawObject->SetEndPoint(point);
m_pCurDrawObject->DrawObject(&dc);
ReleaseCapture();
CObeditDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDoc->m_objectList.AddTail(m_pCurDrawObject);
}
ISLab ICE HUFS
MFC Tutorial
221
View의 화면 출력 과정
• OnDraw에서 OnPrepareDC를 불러야 하나?
• WM_PAINT 처리 시 OnPaint 호출
void CView::OnPaint()
{
CPaintDC dc(this);
OnPrepareDC(&dc);
OnDraw(&dc);
}
– 화면 출력 과정을 분리
– OnDraw는 순수 가상 함수(pure virtual function)이다. 그러므로
반드시 하위 클래스에서 작성해야 한다.
– OnPrepareDC는 가상 함수(virtual function)
–
virtual void OnPrepareDC(CDC* pDC, CPrintInfo* pInfo=NULL);
ISLab ICE HUFS
MFC Tutorial
222
ISLab ICE HUFS
화면 확대/축소 기능
목차
•
•
•
•
•
익스텐트(extent)란?
배율 설정
다이얼로그 만들기
DDX/DDV
SDK와의 비교
ISLab ICE HUFS
MFC Tutorial
224
익스텐트(extent)란
• 특정 매핑 모드에서의 단위 길이
– MM_ISOTROPIC
– MM_ANISOTROPIC
• 현재 논리 좌표와 디바이스 좌표의 단위 길이를 구하거나
새로 설정 가능
• 논리 좌표와 디바이스 좌표는 단위 길이가 다를 수 있다.
• 익스텐트(extent) 조절
GetWindowExt
GetViewportExt
SetWindowExt
SetViewportExt
논리 좌표의 단위 길이 구함
디바이스 좌표의 단위 길이 구함
논리 좌표의 단위 길이 설정
디바이스 좌표의 단위 길이 설정
ISLab ICE HUFS
MFC Tutorial
225
간단한 배율 설정 방법
• 배율 : N%
CClientDC dc(this);
dc.MoveTo(100, 100);
dc.LineTo(300, 400);
CClientDC dc(this);
dc.MoveTo((int)(float)100*N/100, (int)(float)100*N/100);
dc.LineTo((int)(float)300*N/100, (int)(float)400*N/100);
• 단점
– 실수 연산 시 발생할 수 있는 값의 오차 문제
– 코드의 복잡도 증가
ISLab ICE HUFS
MFC Tutorial
226
익스텐트 조절을 통한 배율
• 디바이스좌표 = 논리좌표 X ED / EL
– ED : 디바이스 좌표의 단위 길이
– EL : 논리 좌표의 단위 길이
CClientDC dc(this);
dc.SetViewportExt(N, N);
dc.SetWindowExt(100, 100); // 좌표 X N / 100
dc.MoveTo(100, 100);
dc.LineTo(300, 400);
ISLab ICE HUFS
MFC Tutorial
227
View 수정
• CObeditView 클래스에 멤버 변수로 배율 추가
class CObeditView : public CScrollView
{
....
UINT m_zoomRatio;
....
};
CObeditView::CObeditView()
{
m_nSelectedColorID = 0;
m_crCurColor = color[m_nSelectedColorID];
....
m_zoomRation = 100; // 초기값으로 100% 설정
}
ISLab ICE HUFS
MFC Tutorial
228
OnPrepareDC 함수 수정
• 클래스 바나 위저드를 이용하여 OnPrepareDC 함수 삽입
void CObeditView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
CScrollView::OnPrepareDC(pDC, pInfo);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetViewportExt(m_zoomRatio, m_zoomRatio);
pDC->SetWindowExt(100, 100);
}
• 익스텐트의 값을 음수로 주면 그림의 방향이 반대가 된다.
ISLab ICE HUFS
MFC Tutorial
229
다이얼로그 박스 만들기
• 리소스 뷰에서 새로운 다이얼로그 추가
IDD_ZOOMDLG
Spin Control의 Properties
IDC_EDITZOOM
IDC_SPINZOOM
ISLab ICE HUFS
MFC Tutorial
230
다이얼로그 클래스 생성
• 클래스 위저드 이용
ISLab ICE HUFS
MFC Tutorial
231
DDX/DDV
ISLab ICE HUFS
MFC Tutorial
232
데이타 맵
class CZoomDlg : public CDialog
{
......
// Dialog Data
//{{AFX_DATA(CZoomDlg)
enum { IDD = IDD_ZOOMDLG };
CSpinButtonCtrl m_spinZoom;
UINT m_editZoom;
//}}AFX_DATA
......
};
ISLab ICE HUFS
MFC Tutorial
233
DoDataExchange
void CZoomDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CZoomDlg)
DDX_Control(pDX, IDC_SPINZOOM, m_spinZoom);
DDX_Text(pDX, IDC_EDITZOOM, m_editZoom);
DDX_MinMaxUInt(pDX, m_editZoom, 10, 800);
//}}AFX_DATA_MAP
}
OnInitDialog에서 컨트
롤의 값을 설정한다.
다이얼로그박스호출
전에 값을 설정
CDialog 클래스의
데이타맵에 있는 변수
다이얼로그박스의
실행이 정상적으로
끝나면 값을
읽어온다.
OnOK에서 컨트롤
의 값을 읽어온다.
ISLab ICE HUFS
MFC Tutorial
234
UpdateData
• UpdateData 함수를 이용하여 DoDataExchange 함수 호
출
– 인자
• TRUE : 컨트롤의 값을 데이타맵의 변수로 읽어옴
• FALSE : 데이타맵의 변수 값을 컨트롤로 설정
ISLab ICE HUFS
MFC Tutorial
235
OnInitDialog
• WM_INITDIALOG
– 클래스 위저드에서 선택
BOOL CZoomDlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_spinZoom.SetBuddy(GetDlgItem(IDC_EDITZOOM);
m_spinZoom.SetRange(10, 500);
m_spinZoom.SetBase(10);
m_spinZoom.SetPos(m_editZoom);
return TRUE;
}
ISLab ICE HUFS
MFC Tutorial
236
CSpinButtonCtrl
SetBuddy
스핀 콘트롤이 증감시킨 값을 표시할 윈도우를 지정
이런 윈도우를 버디(buddy) 윈도우라고 함
GetDlgItem 함수를 이용하여 콘트롤 객체의 포인터를 구함
SetRange
스핀 콘트롤로 입력할 수 있는 최대값, 최소값을 지정
SetBase
스핀 콘트롤이 버디 윈도우에 값을 출력할 때 그 값의 형식
16이면 16진수, 10이면 십진수
SetPos
스핀 콘트롤에 표시할 값을 지정
ISLab ICE HUFS
MFC Tutorial
237
OnOK
• 클래스 위저드를 이용하여 함수 생성 가능
• UpdateData 호출을 해야 한다.
– 생성시 UpdateDate(TRUE)를 OK 버튼이 눌려지면 UpdateData(FALSE)를 호출하
여야 하나 이것은 모두 상위 클래스인 CDialog에 만들어져 있으므로 하위 클래스
에서 생성하지 않아도 된다.
ISLab ICE HUFS
MFC Tutorial
238
배율 메뉴 추가
• 메뉴 ID_VIEW_ZOOM를 처리하는 함수 추가
(CObeditView.cpp)
#include “stdafx.h”
#include “Obedit.h”
...
#include “ZoomDlg.h”
void CObeditView::OnViewZoom()
{
CZoomDlg zoomDlg(this);
zoomDlg.m_editZoom = m_zoomRatio;
if (zoomDlg.DoModal() != IDOK)
return;
m_zoomRatio = zoomDlg.m_editZoom;
SetZoomFactor(zoomDlg.m_editZoom);
Invalidate();
}
ISLab ICE HUFS
MFC Tutorial
239
SetZoomFactor
void CObeditView::SetZoomFactor(UINT zoomFactor)
{
m_zoomRatio = zoomFactor;
CClientDC dc(this);
OnPrepareDC(&dc);
CSize size = GetDocument()->GetDocumentSize();
dc.LPtoDP(&size);
SetScrollSize(MM_TEXT, size);
}
ISLab ICE HUFS
MFC Tutorial
240
Dialog 생성 방법
• 모든 다이얼로그는 CDialog로 부터 계승
• 생성 방법
– Resource view에서 dialog template 생성
– Class Wizard 호출
• Control로부터의 노티피케이션(notification) 메시지 처리
• 각각의 다이얼로그 박스 컨트롤에서 입력되는 값 저장 및 컨트롤에
서의 값을 읽어 오는 데이터 멤버도 만듦 (DDX)
• 데이타 값의 범위 지정 가능 (DDV)
ISLab ICE HUFS
MFC Tutorial
241
Modal/Modeless
• Modal
– DoModal 함수 호출
• Modeless
– Create 함수 호출
– Dialog box를 resource view에서 그릴 때 dialog box의 프로퍼티
로 VISIBLE을 반드시 주어야 한다.
ISLab ICE HUFS
MFC Tutorial
242
SDK에서의 다이얼로그 생성 방법
IDD_TESTDIALOG
IDOK
IDCANCEL
IDC_NUMBER
ISLab ICE HUFS
MFC Tutorial
243
class CTestDialog : public CDialog
{
// Construction
public:
CTestDialog(CWnd* pParent = NULL);
// Dialog Data
//{{AFX_DATA(CTestDialog)
enum { IDD = IDD_TESTDIALOG };
//}}AFX_DATA
WORD m_wInputVal;
// Overrides
//{{AFX_VIRTUAL(CTestDialog)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CTestDialog)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
ISLab ICE HUFS
MFC Tutorial
244
GetDlgItem - 값 설정
BOOL CTestDialog::OnInitDialog()
{
CDialog::OnInitDialog(); // UpdateDate(FALSE) 호출
CString szStr;
szStr.Format(“%d”, m_wInputVal);
((CEdit*)GetDlgItem(IDC_NUMBER))->SetWindowText(szStr);
((CEdit*)GetDlgItem(IDC_NUMBER))->SetFocus();
return FALSE;
}
• 반드시 cast 연산자 사용
• SetFocus : 윈도우에 입력 포커스 설정
ISLab ICE HUFS
MFC Tutorial
245
GetDlgItem - 값 읽기
void CTestDialog::OnOK()
{
CString szStr;
((CEdit*)GetDlgItem(IDC_NUMBER))->GetWindowText(szStr);
m_wInputVal = atoi(szStr);
CDialog::OnOK(); // UpdateData(TRUE) 호출
// EndDialog(IDOK) 호출
}
ISLab ICE HUFS
MFC Tutorial
246
SDK Dialog 사용시
{
. . .
CTestDialog testDlg(this);
testDlg.m_wInputVal = nVal;
if (testDlg.DoModal() == IDOK)
{
nVal = testDlg.m_wInputVal;
}
}
ISLab ICE HUFS
MFC Tutorial
247
Modeless Dialog
• 지역 변수로 생성하면 않된다.
CTestDialog::CTestDialog(CWnd* pParent)
: CDialog(CTestDialog::IDD, pParent)
{
Create(CTestDialog::IDD, pParent); // modeless dialog 생성
}
void CObeditView::f()
{
CTestDialog testDlg(this);
}
// 지역변수로 만들면 lifetime이 끝나면서
// 사라진다.
void CObeditView::g()
{
CTestDialog* pDlg = new CTestDialog(this);
}
ISLab ICE HUFS
MFC Tutorial
248
모드리스 다이얼로그 생성
Visible 세팅
ISLab ICE HUFS
MFC Tutorial
249
DDX/DDV 사용시
ISLab ICE HUFS
MFC Tutorial
250
DDX/DDV를 사용한 클래스 정의
class CTestDialog : public CDialog
{
public:
WORD m_nVal;
CTestDialog(CWnd* pParent = NULL);
//{{AFX_DATA(CTestDialog)
enum { IDD = IDD_TESTDIALOG };
UINT m_wNumber;
//}}AFX_DATA
//{{AFX_VIRTUAL(CTestDialog)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
....
}
ISLab ICE HUFS
MFC Tutorial
251
DoDataExchange
void CTestDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTestDialog)
DDX_TEXT(pDX, IDC_NUMBER, m_wNumber);
DDV_MinMaxUInt(pDX, m_wNumber, 50, 200);
//}}AFX_DATA_MAP
}
ISLab ICE HUFS
MFC Tutorial
252
DDX/DDV 매크로
DDX_CBIndex, DDX_CBString, DDX_CBStringExact
DDX_LBIndex, DDX_LBString, DDX_LBStringExact
DDX_Check
DDX_Radio
DDX_Scroll
DDX_Text
DDX_Control
콤보 박스 관련
리스트 박스 관련
체크 박스 관련
라디오 박스 관련
스크롤바 관련
에디트 콘트롤 관련
ISLab ICE HUFS
MFC Tutorial
253
다이얼로그 클래스
CDialog
CCommonDialog
CFileDialog
CFontDialog
CColorDialog
CFindReplaceDialog
CPrintDialog
CPageSetupDialog
ISLab ICE HUFS
MFC Tutorial
254
배율 설정 기능의 ToolBar로의 적용
• CMainFrame 클래스에 다음 함수 정의
void CMainFrame::SetZoomRange(int nMin, int nMax)
{
m_wndToolBar.m_zoomScroll.SetScrollRange(nMin, nMax);
}
void CMainFrame::SetZoomPos(int nPos)
{
m_wndToolBar.m_zoomScroll.SetScrollPos(nPos);
CString szTemp;
szTemp.Format(“%d %%”, nPos);
m_wndToolBar.m_zoomStatic.SetWindowText(szTemp);
}
ISLab ICE HUFS
MFC Tutorial
255
CObeditView::OnInitialUpdate
#include “MainFrm.h”
. . .
void CObeditView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();
pFrame->SetZoomRange(10, 800);
pFrame->SetZoomPos(m_zoomRatio);
SetScrollSize(MM_TEXT, GetDocument()->GetDocumentSize());
}
ISLab ICE HUFS
MFC Tutorial
256
CObeditView::SetZoomFactor
void CObeditView::SetZoomFactor(UINT zoomFactor)
{
m_zoomRatio = zoomRatio;
CClientDC dc(NULL);
OnPrepareDC(&dc);
CSize size = GetDocument()->GetDocumentSize();
dc.LPtoDP(&size);
SetScrollSize(MM_TEXT, size);
CMainFrame *pMain = (CMainFrame*)AfxGetMainWnd();
pMain->SetZoomPos(m_zoomRatio);
}
ISLab ICE HUFS
MFC Tutorial
257
WM_HSCROLL 처리
#include “ObeditDoc.h”
#include “ObeditView.h”
. . .
void CMyToolBar::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
int nMin, nMax;
m_zoomScroll.GetScrollRange(&nMin, &nMax);
int nOldPos, nCurPos = m_zoomScroll.GetScrollPos();
nOldPos = nCurPos;
switch(nSBCode)
{
case SB_LEFT :
nCurPos = nMin;
break;
ISLab ICE HUFS
MFC Tutorial
258
case SB_RIGHT :
nCurPos = nMax;
break;
case SB_LINELEFT :
nCurPos -= 10;
break;
case SB_LINERIGHT :
nCurPos += 10;
break;
case SB_PAGELEFT :
nCurPos -= 50;
break;
case SB_PAGERIGHT :
nCurPos += 50;
break;
case SB_THUMBTRACK :
case SB_THUMBPOSITION :
nCurPos = nPos;
break;
}
ISLab ICE HUFS
MFC Tutorial
259
if (nCurPos < nMin)
nCurPos = nMin;
else if (nCurPos > nMax)
nCurPos = nMax;
if (nOldPos == nCurPos)
return;
m_zoomScroll.SetScrollPos(nCurPos);
CString szTemp;
szTemp.Format(“%d %%”, nCurPos);
m_zoomStatic.SetWindowText(szTemp);
// set zoom ratio to view window
CMDIChildWnd* pChildFrame = (CMDIChildWnd *)
(((CMDIFrameWnd*)AfxGetMainWnd())->MDIGetActive());
CObeditView* pView = (CObeditView*)pChildFrame->GetActiveView();
pView->SetZoomFactor(nCurPos);
pView->Invalidate();
}
ISLab ICE HUFS
MFC Tutorial
260
마우스 커서의 변환
• SetCursor
void CObeditView::OnLButtonDown()
{
. . .
::SetCapture(AfxGetApp()->LoadCursor(IDC_MYCURSOR1);
}
// WM_SETCURSOR 메시지 처리
BOOL CObeditView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
::SetCursor(AfxGetApp()->LoadCursor(IDC_MYCURSOR2);
return TRUE;
}
ISLab ICE HUFS
MFC Tutorial
261
ISLab ICE HUFS
기타 Dialog Box 구현
목차
• Owner Draw List Box
• Property Sheet
ISLab ICE HUFS
MFC Tutorial
263
Owner-Draw List Box
•
•
•
•
•
펜 속성을 선택하는 dialog
각 펜의 모양을 그림으로 list box에 표현
List box의 각 항목을 직접 그려야 함
List box의 각 항목의 순서를 지정할 수 있어야 함
List box에 그릴 각 항목의 크기를 알 수 있어야 함
ISLab ICE HUFS
MFC Tutorial
264
펜 속성 지정 다이얼로그
Static. IDC_STATIC
Edit Box. IDC_EDITWIDTH
Spin. IDC_SPINWIDTH
List Box. IDC_LISTSTYLE
비트맵이
들어가기
때문
ISLab ICE HUFS
MFC Tutorial
265
CPenAttrDlg
• CPenAttrDlg 클래스 생성
• Member Variable - Class Wizard
– m_editWidth
– m_listStyle
– m_spinWidth
Value
Control
Control
UINT
CListBox
CSpinButtonCtrl
ISLab ICE HUFS
MFC Tutorial
266
CLineStyleListBox 클래스 생성
• CListBox로부터 계승
• Owner-Draw List Box를 위하여 다음 함수를 재정의
– CompareItem
• 정렬의 대상이 명확하지 않기 때문에 이를 비교하기 위한 함수
– DrawItem
• 리스트 박스의 항목을 그릴 때 각 항목마다 호출되는 함수
– MeasureItem
• 항목의 높이를 정하기 위해 각 항목마다 호출되는 함수
ISLab ICE HUFS
MFC Tutorial
267
MeasureItem
#define COLOR_ITEM_HEIGHT 20
void CLineStyleListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItem)
{
lpMeasureItem->itemHeight = COLOR_ITEM_HEIGHT;
}
ISLab ICE HUFS
MFC Tutorial
268
DrawItem(1)
void CLineStyleListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
int nStyle = (int)lpDrawItemStruct->itemData;
if (lpDrawItemStruct->itemAction & ODA_DRAWENTIRE)
{
CPen Pen(nStyle, 1, RGB(0,0,0)); // 검은 색 펜을 만든다
CPen* pOldPen = pDC->SelectObject(&Pen);
int y = lpDrawItemStruct->rcItem.top + (lpDrawItemStruct
->rcItem.bottom + lpDrawItemStruct->rcItem.top)/2);
pDC->MoveTo(0, y);
pDC->LineTo(lpDrawItemStruct->rcItem.right, y);
pDC->SelectObject(pOldPen);
}
ISLab ICE HUFS
MFC Tutorial
269
DrawItem(2)
if ((lpDrawItemStruct->itemState & ODS_SELECTED) &&
(lpDrawItemStruct->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)))
{
// item has been selected - hilite frame
pDC->InvertRect(&lpDrawItemStruct->rcItem);
}
if (!(lpDrawItemStruct->itemState & ODS_SELECTED) &&
(lpDrawItemStruct->itemAction & ODA_SELECT))
{
pDC->InvertRect(&lpDrawItemStruct->rcItem);
}
}
ISLab ICE HUFS
MFC Tutorial
270
CompareItem
int CLineStyleListBox::CompareItem(LPCOMPAREITEMSTRUCT
lpCompareItemStruct)
{
int nStyle1 = (int)lpCompareItemStruct->itemData1;
int nStyle2 = (int)lpCompareItemStruct->itemData2;
if (nStyle1 == nStyle2)
return 0;
else if (nStyle1 < nStyle2)
return -1;
else
return 1;
}
ISLab ICE HUFS
MFC Tutorial
271
DRAWITEMSTRUCT
typedef
UINT
UINT
UINT
UINT
struct tagDRAWITEMSTRUCT {
CtlType; // Owner-Draw 리스트 박스의 경우에는 ODT_LISTBOX가 들어옴
CtlID;
// Control ID가 들어온다.
itemID; // List box에서 몇 번째 항목인지를 나타내는 인덱스가 들어옴
itemAction; // 지금 list box에 취해진 작업의 종류를 나타낸다.
// ODA_DRAWENTIRE : list box 자체가 다시 그려져야 할 때
// ODA_FOCUS : list box에 포커스가 새로 왔거나 포커스를 잃을 때
// ODA_SELECT : list box의 선택 상태가 변경되었을 때
UINT itemState; // 지금 항목의 상태를 나타낸다. 상태에 따라 그려주는 것이
// 달라지기 때문에 중요하다. Ownerdraw list box의 경우에는
// ODS_DISABLED : 이 항목이 비활성화된 것으로 그려져야 하는 경우
// ODS_FOCUS : 이 항목에 입력 포커스가 있는 것으로 그려져야 할 때
// ODS_SELECTED : 이 항목이 선택된 것으로 그려져야 할 경우
HWND hWnditem; // ownerdraw list box의 window handle
HDC hDC;
// 이 항목이 그려질 영역에 대한 device context handle
// 핸들을 기반으로 존재하는 모든 클래스들은 핸들로부터 클래스
// 오브젝트를 만들어 주는 FromHandle이라는 멤버함수를 가지고 있다.
// DrawItem 함수에서는 이 핸들을 CDC 클래스로 변환하여 사용한다. RECT
rcItem;
// 이 항목의 위치를 나타낸다. 반드시 이 안에만 그려야 함
DWORD itemDate; // 이 항목에 들어간 값을 나타낸다. 보통의 list box라면
// 여기에 텍스트가 들어가게 된다.
ISLab ICE HUFS
} DRAWITEMSTRUCT;
MFC Tutorial
272
리스트 박스에 항목 추가
• InsertString
– 절렬 순서에 관계없이 항목을 지정한 곳에 넣는다.
• AddString
– 정렬한 다음에 리스트 박스에 추가
– CompareItem 함수를 호출하여 정렬하게 된다.
• 오너드로인 경우 그 항목을 그릴 때 사용할 수 있는 값을
줌
– 예제에서는 펜의 스타일을 인자로 사용
• 직접 데이타 맵을 수정해야
ISLab ICE HUFS
MFC Tutorial
273
Data Map 수정
// PenAttrDlg.h : header file
//
#include “LineStyleListBox.h”
class CPenAttrDlg : public CDialog
{
// Construction
public:
int m_lineStyle;
// 선의 스타일을 가리키는 변수
CPenAttrDlg(CWnd* pParent = NULL);
// Dialog Data
//{{AFX_DATA(CPenAttrDlg)
enum { IDD = IDD_PENATTRIBUTE; };
CSpinButtonCtrl m_spinWidth;
CLineStyleListBox m_listStyle;
UINT m_editWidth;
//}}AFX_DATA
ISLab ICE HUFS
MFC Tutorial
274
WM_INITDIALOG
BOOL CPenAttrDlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_spinWidth.SetBuddy(GetDlgItem(IDC_EDITWIDTH));
m_spinWidth.SetRange(1, 20);
m_spinWidth.SetBase(10);
m_spinWidth.SetPos(m_editWidth);
m_listStyle.AddString((LPCTSTR)(PS_SOLID));
m_listStyle.AddString((LPCTSTR)(PS_DASH));
m_listStyle.AddString((LPCTSTR)(PS_DOT));
m_listStyle.AddString((LPCTSTR)(PS_DASHDOT));
m_listStyle.AddString((LPCTSTR)(PS_DASHDOTDOT));
m_listStyle.AddString((LPCTSTR)(PS_NULL));
return TRUE;
}
ISLab ICE HUFS
MFC Tutorial
275
OnOK
void CPenAttrDlg::OnOK()
{
int index = m_listStyle.GetCurSel();
m_lineStyle = (UINT)m_listStyle.GetItemData(index);
CDialog::OnOK();
}
ISLab ICE HUFS
MFC Tutorial
276
메뉴 처리 함수 생성
• ID_OBJECT_PENATTR 명령의 COMMAND 메시지 핸들러
#include “PenAttrDlg.h”
. . .
void CObeditView::OnObjectPenattr()
{
CPenAttrDlg penAttrDlg(this);
penAttrDlg.m_editWidth = m_nPenWidth;
penAttrDlg.m_lineStyle = m_nPenStyle;
if (penAttrDlg.DoModal() != IDOK)
return;
m_nPenWidth = penAttrDlg.m_editWidth;
m_nPenStyle = penAttrDlg.m_lineStyle;
}
ISLab ICE HUFS
MFC Tutorial
277
Property Sheet
• 여러 개의 Property Page로 하나의 Property Sheet를 생성
ISLab ICE HUFS
MFC Tutorial
278
파일 정보 다이얼로그 생성
Static. IDC_APPNAME
Edit. IDC_AUTHOR
Edit. IDC_KEYWORDS
List Box.
IDC_COMMENTS
Edit. IDC_TITLE
Edit. IDC_SUBJECT
IDD_SUMM_PAGE
ISLab ICE HUFS
MFC Tutorial
279
Dialog Properties
ISLab ICE HUFS
MFC Tutorial
280
CSummaryPage 클래스 생성
• 상위 클래스로 CPropertyPage 선택
• Member Variables (Class Wizard)
–
–
–
–
–
–
IDC_APPNAME
IDC_AUTHOR
IDC_COMMENTS
IDC_KEYWORDS
IDC_SUBJECT
IDC_TITLE
m_AppName
m_Author
m_Comments
m_Keywords
m_Subject
m_Title
Value
Value
Value
Value
Value
Value
CString
CString
CString
CString
CString
CString
ISLab ICE HUFS
MFC Tutorial
281
파일 통계 다이얼로그
IDC_REVNUM
IDC_EDITTIME
IDC_CREATEDATE
IDC_LASTPRINT
IDC_LASTSAVE
ISLab ICE HUFS
MFC Tutorial
282
CFileStatPage 클래스 생성
• 상위 클래스로 CPropertyPage 선택
• Member Variables (Class Wizard)
–
–
–
–
–
IDC_CREATEDATE m_CreateDate
Value
IDC_EDITTIME
m_EditTime
IDC_LASTPRINT
m_LastPrint
IDC_LASTSAVE
m_LastSave
IDC_REVNUM
m_RevNum
CString
Value
Value
Value
Value
CString
CString
CString
CString
ISLab ICE HUFS
MFC Tutorial
283
Document 클래스에 멤버 추가
class CObeditDoc : public CDocument
{
. . .
public:
CString m_AppName;
CString m_Author;
CString m_Comments;
CString m_Keywords;
CString m_Subject;
CString m_Title;
CString
UINT
CString
CString
UINT
CTime
. . .
m_CreateDate;
m_EditTime;
m_LastPrint;
m_LastSave;
m_RevNum;
m_StartTime;
ISLab ICE HUFS
MFC Tutorial
284
생성자
CObeditDoc::CObeditDoc()
{
m_sizeDoc = CSize(500, 500);
m_AppName = _T(“도형편집기”); // 유니코드 혹은 ANSI 문자열
}
ISLab ICE HUFS
MFC Tutorial
285
OnNewDocument
BOOL CObeditDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
m_EditTime = 0;
m_RevNum = 0;
char szTemp[32];
_strdate(szTemp);
m_CreateDate = szTemp;
m_CreateDate += “ “;
_strtime(szTemp);
m_CreateDate += szTemp;
m_StartTime = CTime::GetCurrentTime();
return TRUE;
}
ISLab ICE HUFS
MFC Tutorial
286
Property Sheet 생성
• CPropertySheet
– 하나 이상의 Property Page로 구성
– 각 PropertyPage 객체를 AddPage 함수를 이용하여 등록
ISLab ICE HUFS
MFC Tutorial
287
ID_FILE_SUMMARY_INFO
#include “FileStatPage.h”
#include “SummaryPage.h”
. . .
void CObeditView::OnFileSummaryInfo()
{
CPropertySheet sheet(_T(“문서정보”));
CSummaryPage sum;
CFileStatPage state;
sheet.AddPage(&sum);
sheet.AddPage(&state);
sum.m_AppName = GetDocument()->m_AppName;
sum.m_Author = GetDocument()->m_Author;
sum.m_Comments = GetDocument()->m_Comments;
sum.m_Keywords = GetDocument()->m_Keywords;
sum.m_Subject = GetDocument()->m_Subject;
sum.m_Title = GetDocument()->m_Title;
ISLab ICE HUFS
MFC Tutorial
288
state.m_CreateDate = GetDocument()->m_CreateDate;
state.m_EditTime.Format(“%d”, GetDocument()->m_EditTime);
state.m_LastPrint = GetDocument()->m_LastPrint;
state.m_LastSave = GetDocument()->m_LastSave;
state.m_RevNum.Format(“%d”, GetDocument()->m_RevNum);
if (sheet.DoModal() != IDOK)
return;
GetDocument()->m_AppName = sum.m_AppName;
GetDocument()->m_Author = sum.m_Author;
GetDocument()->m_Comments = sum.m_Comments;
GetDocument()->m_Keywords = sum.m_Keywords;
GetDocument()->m_Subject = sum.m_Subject;
GetDocument()->m_Title = sum.m_Title;
}
ISLab ICE HUFS
MFC Tutorial
289
CProperySheet 클래스
• 보통의 윈도우임
• 일반적인 다이얼로그처럼 사용
– DoModal
– Create
• Style
CObject
– Child
– Thin
– More Styles - Disabled
CCmdTarget
CWnd
CPropertySheet
ISLab ICE HUFS
MFC Tutorial
290
CProperSheet 클래스 멤버 함수
•
•
•
•
AddPage
RemovePage
GetPageCount
SetActivePage
– 특정 페이지를 전면으로
– CPropertyPage* pPropPage = GetPage(0);
• OnCreate
– 프라퍼티시트에 다른 콘트롤을 달때
– MoveWindow : 프로퍼티시트의 크기 확대시
– GetWindowRect : 현재 윈도우의 크기와 위치를 알고자 할때
ISLab ICE HUFS
MFC Tutorial
291
적용 버튼 활성화
• CPropertyPage::SetModified(TRUE)
– 적용 버튼이 활성화된다.
• 적용 버튼에 대한 핸들러 작성
– 적용 버튼의 컨트롤 ID : ID_APPLY_NOW
– COMMAND 메시지 핸들러 작성
– 직접 메시지맵을 수정해야
BEGIN_MESSAGE_MAP(CMyPropertySheet, CPropertySheet)
//{{AFX_DATA(CMyPropertySheet)
ON_COMMAND(ID_APPLY_NOW, OnApplyNow)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
ISLab ICE HUFS
MFC Tutorial
292
적용 처리 함수
class CMyPropertySheet : public CPropertySheet
{
public:
DECLARE_DYNAMIC(CMyPropertySheet)
....
// Message Handlers
protected:
//{{AFX_MSG(CMyPropertySheet)
afx_msg void OnApplyNow();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
void CMyPropertySheet::OnApplyNow()
{
Default();
.... // 리턴하기 전에 프로퍼티시트를 구성하는 각 페이지마다
// SetModified(FALSE)를 호출해야
}
ISLab ICE HUFS
MFC Tutorial
293
Wizard 모드
• SetWizardMode
• SetWizardButton
• SetFinishText
– Finish 버튼에 나타나는 타이틀을 변경하고자 할 때
ISLab ICE HUFS
MFC Tutorial
294
SetWizardMode
void CObeditView::OnFileSummaryInfo()
{
CPropertySheet sheet(_T("문서정보"));
CSummaryPage sum;
CFileStatPage state;
sheet.AddPage(&sum);
sheet.AddPage(&state);
sheet.SetWizardMode();
sum.m_AppName = GetDocument()->m_AppName;
sum.m_Author
= GetDocument()->m_Author;
sum.m_Comments = GetDocument()->m_Comments;
ISLab ICE HUFS
MFC Tutorial
295
SetWizardButton
PSWIZB_BACK
PSWIZB_NEXT
PSWIZB_FINISH
PSWIZB_DISABLEDFINISH
뒤로
다음
종료
종료
버튼을
버튼을
버튼을
버튼을
활성화한다.
활성화한다.
활성화한다.
disable한다.
BOOL CMyPropertyPage::OnSetActive() // virtual function
{
CPropertySheet* pSheet = (CPropertySheet*)GetParent();
pSheet->SetWizardButton( PSWIZB_NEXT );
return CPropertySheet::OnSetActive();
}
ISLab ICE HUFS
MFC Tutorial
296
ISLab ICE HUFS
파일 I/O 기능의 추가
목차
•
•
•
•
MFC의 파일 I/O 구조
문서 변경 여부
CFile, CArchive
Serialize
ISLab ICE HUFS
MFC Tutorial
298
MFC의 파일 I/O 구조
• CWinApp, CDocument 클래스에서 미리 일반화시켜 놓았
다.
• 사용자는 필요한 부분의 가상 함수만 제공
New
Open
Close
Save
Save As
CWinApp::OnFileNew
CWinApp::OnFileOpen
CDocument::OnFileClose
CDocument::OnFileSave
CDocument::OnFileSaveAs
• New, Open도 실제로는 CDocument 클래스 내에 정의된
부분을 호출
ISLab ICE HUFS
MFC Tutorial
299
OnFileNew
• MDI 프로그램의 경우라면 -> MDI 자식윈도우 클래스와
뷰 클래스의 오브젝트를 만든다.
• SDI 프로그램의 경우라면 -> 이미 만들어져 있는 뷰를 그
대로 사용한다.
• 다음으로 문서클래스의 오브젝트를 생성한다.
• 그리고 나서 문서클래스(CDocument 클래스)의
OnNewDocument 멤버함수를 호출한다.
• 뷰클래스의 OnInitialUpdate 함수를 호출한다.
ISLab ICE HUFS
MFC Tutorial
300
OnFileOpen
• 읽어 들일 파일 이름을 입력받기 위한 파일 열기 다이얼
로그 박스를 띄운다.
• MDI 프로그램의 경우라면 -> MDI 자식윈도우 클래스의
오브젝트와 뷰클래스의 오브젝트를 만든다.
• SDI 프로그램의 경우라면 -> 이미 만들어져 있는 뷰를 그
대로 사용한다.
• 다음으로 문서클래스의 오브젝트를 생성한다.
• 파일의 내용을 읽어들이기 위해 문서클래스의
OnOpenDocument 멤버함수를 호출한다.
• 뷰클래스의 OnInitialUpdate 함수를 호출한다.
ISLab ICE HUFS
MFC Tutorial
301
파일 열기 다이얼로그 박스
ISLab ICE HUFS
MFC Tutorial
302
OnFileClose
• 현재 문서가 저장되지 않았으면(IsModified 함수 호출)
저장 여부를 묻는 메시지박스를 띄운다. 저장하겠다고 하
면 파일 이름이 있는 경우, 문서클래스의
OnSaveDocument 함수를 불러 저장
• 저장하겠다고 했지만 파일 이름이 없는 경우, 파일 이름
을 입력받기 위한 다이얼로그 박스를 띄워 이름을 입력받
아 저장한다(역시 OnSaveDocument 호출)
• 문서 클래스의 OnCloseDocument 함수를 불러 이 문서
와 관련된 청소 작업을 한다.
ISLab ICE HUFS
MFC Tutorial
303
OnCloseDocument
• 현재 편집중이던 문서와 관련된 자료 구조 등을 정리하는
작업과 윈도우 등을 닫는 작업을 수행한다.
• 자료 구조를 정리하기 위해 문서클래스의
DeleteContents 함수를 호출한다.
ISLab ICE HUFS
MFC Tutorial
304
문서 변경 여부
• SetModifiedFlag
– 문서가 변경되는 지점에서 SetModifiedFlag() 함수 호출
• IsModified
– 문서가 변경되었는지를 알아내는 함수. 이전에 SetModifiedFlag
함수를 불렀다면 TRUE가 아니면 FALSE가 반환된다.
– 파일을 저장하면 이 플래그는 다시 FALSE로 바뀐다.
ISLab ICE HUFS
MFC Tutorial
305
OnFileSave
• 편집중인 문서의 파일 이름이 있으면 문서클래스의
OnSaveDocument 함수를 불러 저장
• 편집중인 문서의 파일 이름이 없으면 파일 이름을 입력받
기 위한 다이얼로그 박스를 띄워 이름을 입력받아 저장
(역시 OnSaveDocument 호출)
ISLab ICE HUFS
MFC Tutorial
306
OnFileSaveAs
• 파일 이름을 입력받기 위한 다이얼로그 박스를 띄운다.
• 이름이 입력되면 OnSaveDocument 함수를 불러 문서
의 내용을 저장한다.
ISLab ICE HUFS
MFC Tutorial
307
CFile, CArchive
CFile file;
// CFile 클래스의 file 오브젝트를 정의한다.
file.Open( “sample”, CFile::modeRead );
// 파일을 오픈한다.
DeleteContents();
// 지금까지 편집중이던 이전 문서의 내용을 삭제
CArchive archive(&file, CArchive::loadArchive); // file 오브젝트를 대신
// 하는 CArchive 클래스의 archive 오브젝트를
// 생성한다.
Serialize(archive);
// 파일의 내용을 읽어들인다.
archive.Close();
// 파일 입출력을 대행하던 archive를 닫는다.
file.Close();
// 파일을 닫는다.
ISLab ICE HUFS
MFC Tutorial
308
CArchive
• 저장될 대상과 실제 저장 매체(storage medium) 사이의
매개체 역할을 수행
• 저장 매체의 특성에 관계없이 CArchive 클래스의 멤버 함
수만을 이용하여 입출력
– 파일, 소켓, OLE
파일
저장대상이 되는
자료구조나
전송대상이 되는
자료구조
CArchive
클래스
네트웍
ISLab ICE HUFS
MFC Tutorial
309
CArchive 클래스의 멤버 함수
>> operator
BYTE, WORD, LONG, DWORD, float, double과 같은
일반수형과 Cobject로부터 계승된 클래스의 읽기 담당
<< operator
BYTE, WORD, LONG, DWORD, float, double과 같은
일반수형과 Cobject로부터 계승된 클래스의 저장 담당
Read
이진 데이터를 읽어들인다.
Write
이진 데이터를 저장한다.
WriteString
한 줄의 문자열을 저장한다.
ReadString
한 줄의 문자열을 읽어들인다.
GetFile
CArchive 클래스의 오브젝트가 대신하고 있는 CFile
오브젝트의 포인터를 돌려준다
IsLoading
CArchive 클래스의 오브젝트를 읽기 작업을 위해 오픈한
경우에는 TRUE가 리턴
IsWritingCArchive 클래스의 오브젝트를 저장 작업을 위해 오픈한 경우에는
TRUE가 리턴
ISLab ICE HUFS
MFC Tutorial
310
Serialize
void CObeditDoc::Serialize(CArchive& ar)
{
if (ar.IsLoading())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
ISLab ICE HUFS
MFC Tutorial
311
직렬화(serialization)
• 디스크에 저장하거나 읽는 작업
• 디스크에 저장할 때는 순서대로 데이터를 저장해야 하므
로 직렬화라는 이름을 붙임
• Linked list의 멤버 함수에도 Serialize 함수가 있음.
– 이것은 각 노드에 있는 객체의 Serialize 함수를 불러준다.
ISLab ICE HUFS
MFC Tutorial
312
CObeditDoc::Serialize(1)
....
#include
#include
#include
#include
....
“stdafx.h”
“Obedit.h”
“ObeditDoc.h”
“DrawObj.h”
void CObeditDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
CTime curTime = CTime::GetCurrentTime();
m_LastSave = curTime.Format("%m/%d/%y %H:%M:%S");
CTimeSpan elapsedTime = curTime - m_StartTime;
m_EditTime += elapsedTime.GetTotalSeconds();
m_StartTime = curTime;
ISLab ICE HUFS
MFC Tutorial
313
CObeditDoc::Serialize(2)
m_RevNum++;
m_StartTime = CTime::GetCurrentTime();
ar
ar
ar
ar
ar
ar
<<
<<
<<
<<
<<
<<
m_AppName;
m_Author;
m_Comments;
m_Keywords;
m_Subject;
m_Title;
ar
ar
ar
ar
ar
<<
<<
<<
<<
<<
m_CreateDate;
m_EditTime;
m_LastPrint;
m_LastSave;
m_RevNum;
ar
ar
ar
ar
ar
ar
ar
ar
ar
ar
ar
ar << m_sizeDoc;
}
else
{
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
m_AppName;
m_Author;
m_Comments;
m_Keywords;
m_Subject;
m_Title;
m_CreateDate;
m_EditTime;
m_LastPrint;
m_LastSave;
m_RevNum;
ar >> m_sizeDoc;
}
m_objectList.Serialize(ar);
}
ISLab ICE HUFS
MFC Tutorial
314
CLine::Serialize
void CLine::Serialize(CArchive& ar)
{
CDrawObject::Serialize(ar);
if (ar.IsLoading())
{
}
else
{
}
}
ISLab ICE HUFS
MFC Tutorial
315
CDrawObject::Serialize
void CDrawObject::Serialize(CArchive& ar)
{
CObject::Serialize(ar);
if (ar.IsStoring())
{
ar << m_wObjType;
ar << m_crColor;
ar << m_nPenStyle;
ar << m_nPenWidth;
ar << m_rcRect;
}
else
{
ar >> m_wObjType;
ar >> m_crColor;
ar >> m_nPenStyle;
ar >> m_nPenWidth;
ar >> m_rcRect;
}
}
ISLab ICE HUFS
MFC Tutorial
316
CObject::Serialize
• 호출하지 않으면 파일 입출력이 제대로 동작 안함
• CObject 클래스에 관한 정보를 저장하고 읽어들이는 기
능
• 이 정보를 바탕으로 도형클래스를 따로 생성하지 않아도
자동으로 도형클래스를 생성하고 있다.
ISLab ICE HUFS
MFC Tutorial
317
Serialize 함수 호출 순서
CDocument의 Serialize 함수
도형리스트의 Serialize 함수호출
(m_objectList.Serialize)
일단 프로그램
전체에 걸친 정
보를 입출력 한
다
도형별로 Serialize 함수를 호출
ISLab ICE HUFS
MFC Tutorial
318
SetModifiedFlag
ISLab ICE HUFS
MFC Tutorial
319
SetModifiedFlag 추가
void CObeditView::OnLButtonUp(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DPtoLP(&point);
m_pCurDrawObject->SetEndPoint(point);
m_pCurDrawObject->DrawObject(&dc);
ReleaseCapture();
CObeditDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDoc->m_objectList.AddTail(m_pCurDrawObject);
pDoc->SetModifiedFlag(TRUE);
}
}
ISLab ICE HUFS
MFC Tutorial
320
DeleteContents
void CObeditDoc::DeleteContents()
{
while(!m_objectList.IsEmpty())
{
delete m_objectList.RemoveHead();
}
CDocument::DeleteContents();
}
ISLab ICE HUFS
MFC Tutorial
321
CArchive 클래스 연산자 <<, >>가 가능한
타입
•
•
•
•
•
•
CObject에 대한 포인터
CString
SIZE, CSize, POINT, CPoint, RECT, CRect
CTime, CTimeSpan
float, double
BYTE, WORD, DWORD, LONG
• CObject 포인터가 아닌 일반 객체는 Serialize 함수를 호
출하여 입출력해야 한다.
ISLab ICE HUFS
MFC Tutorial
322
ISLab ICE HUFS
프린터 관련 명령
목차
• MFC의 프린트 구조
• MFC에서의 미리보기 구조
ISLab ICE HUFS
MFC Tutorial
324
MFC에서의 프린터
• 관련 메뉴
– Print, Print Setup, Print Preview
• CPrintDialog
ISLab ICE HUFS
MFC Tutorial
325
프린트 관련 메뉴
메뉴
Print
Print Setup
Print Preview
기능
프린터로 인쇄
프린터의 환경 설정
프린터 출력을 화면
으로
처리함수 이름 및 정의 위치
OnFilePrint(CView)
OnFilePrintSetup(CWinApp)
OnFilePrintPreview(CView)
ISLab ICE HUFS
MFC Tutorial
326
화면과 프린터출력의 비교
• 거의 모든 함수가 표준화되어 있다.
– 화면 출력에도 사용하는 그래픽 디바이스에 관계없이 단일한 하
나의 함수 집합(GDI, Graphic Device Interface)을 이용할 수 있다.
- CDC 클래스
– 그외
• ODBC(Open Database Connectivity)
• MCI(Media Control Interface)
– 프린터 출력시에도 CDC 클래스를 이용하여 출력
• 차이점
– 여러 장의 종이에 출력
– 출력 상태 표시
ISLab ICE HUFS
MFC Tutorial
327
프린터 작업시 뷰클래스가 해야 하는 일
• 최대 몇페이지나 출력할 수 있는지, 어느 페이지서부터
어느 페이지까지 출력할 것인지를 결정 - 프린터 다이얼
로그 박스를 띄워 선택을 입력받는다.
• 특정 페이지를 출력하도록 요구받았을 때 그 부분을 그릴
수 있어야 한다. 필요하다면 머리말과 꼬리말을 출력할
수 있어야 한다.
• 출력에 필요한 폰트와 다른 GDI 자원들을 할당하고 제거
할 수 있어야 한다.
• 프린터 다이얼로그를 띄워 프린터 DC를 구함
• 일반적인 코딩은 가상함수로 제공
ISLab ICE HUFS
MFC Tutorial
328
CView::OnFilePrint
CView::OnPreparePrinting
CView::OnBeginPrinting
출력문서의 페이지 수를 결정해 준다.
다음으로 DoPreparePrinting 함수를 호출하여 프린트 다이
얼로그박스를 표시하고 DC를 생성한다.
프린트 작업동안 필요한 각종 리소스를 할당한다.
CDC::StartDoc
프린트 작업이 시작됨을 프린터에 알린다.
CView::OnPrepareDC
CDC::StartPage
CView::OnPrint
프린트와 관계된 여러가지 DC의 속성들을 바꾸어준다.
더 출력할 페이지가 있는지 검사한다.
프린트 디바이스 쪽에 새 페이지의 출력이 시작되었음을
알린다.
머릿말과 꼬릿말이 있으면 출력하고 지정된 페이지를
출력한다.
CDC::EndPage
페이지의 출력이 끝났음을 알린다.
CDC::EndDoc
문서 전체의 출력이 끝났음을 알린다.
CView::OnEndPrinting
OnBeginPrinting에서 할당했던 리소스들을 제거한다.
ISLab ICE HUFS
MFC Tutorial
329
MFC의 프린트 기능의 구현
• 뷰클래스의 다음 함수의 구현을 어떻게 만드느냐에 달림
–
–
–
–
–
OnPreparePrinting
OnBeginPrinting
OnEndPrinting
OnPrepareDC
OnPrint
• 프린트 다이얼로그를 띄우고 프린트 DC를 만들고 프린트
취소 다이얼로그를 띄우고 하는 일은 MFC가 알아서 수행
ISLab ICE HUFS
MFC Tutorial
330
프린트 제어를 위한 CDC 클래스의 함수
• Escape Sequence 함수
• StartDoc
– 새로운 문서의 출력이 나감을 알린다.
• StartPage
– 새로운 페이지의 출력이 나감을 알린다.
• EndPage
– 페이지의 출력이 끝났음을 알린다.
• EndDoc
– 문서의 출력이 종료되었음을 알린다.
ISLab ICE HUFS
MFC Tutorial
331
CPrintInfo(1)
• OnPreparePrinting 함수의 인자로 넘어옴
• 프린터와 관련한 사용자의 입력을 저장하거나 프린트, 미
리보기 관련 정보를 보관
• 예
– 프린트 할 페이지의 범위
– 현재 프린트하고 있는 페이지의 번호
– 출력용지의 크기 등
ISLab ICE HUFS
MFC Tutorial
332
CPrintInfo(2)
struct CPrintInfo // Printing information structure
{
CPrintInfo();
~CPrintInfo();
CPrintDialog* m_pDD;
// 여기에 프린트 공통 다이얼로그의 포인터를 보관
BOOL m_bPreview;
// 미리보기상태(TRUE)인지 프린트상태(FALSE)인지 표시
BOOL m_bContinuePrinting; // 프린트를 계속할 것인지의 여부를 표시
UINT m_nCurPage;
// 현재 인쇄중이거나 미리보기중인 페이지
UINT m_nNumPreviewPages; // 동시에 미리보기하려는 페이지 수
CString m_strPageDesc;
// 페이지번호를 표시하기위한 포맷 스트링
LPVOID m_lpUserData;
// pointer to user created struct
CRect m_rectDraw;
// 인쇄할 종이의 크기
void
void
UINT
UINT
UINT
UINT
SetMinPage(UINT nMinPage);
SetMaxPage(UINT nMaxPage);
GetMinPage() const;
GetMaxPage() const;
GetFromPage() const;
GetToPage() const;
// 출력가능한 페이지의 범위
// 사용자가 입력한 출력 페이지의
// 범위
};
ISLab ICE HUFS
MFC Tutorial
333
OnPrint의 디폴트 코딩
void CView::OnPrint(CDC* pDC, CPrintInfo*)
{
ASSERT_VALID(pDC);
// Override and set printing variables based on page number
OnDraw(pDC); // Call Draw
}
• 페이지의 개념이 없음
• OnDraw를 조금 수정하여 프린트에도 적용
• OnPrint호출 전에 OnPrepareDC를 먼저 호출한다.
– 윈도우 매핑모드 변경
– CScrollView의 경우 : 스크롤 상황에 맞추어 원점을 이동
ISLab ICE HUFS
MFC Tutorial
334
View 클래스 수정
• 출력이 나가는 종이의 높이 지정
class CObeditView : public CScrollView
{
...
int m_nPaperHeight;
...
};
ISLab ICE HUFS
MFC Tutorial
335
OnPreparePrinting
BOOL CObeditView::OnPreparePrinting(CPrintInfo* pInfo)
{
pInfo->m_nNumPreviewPages = 1;
// 미리보기 할 페이지 수를 1로 정함
return DoPreparePrinting(pInfo);
}
• 사용자가 출력 용지를 설정하기 전까지는 몇 페이지에 걸
쳐 출력이 일어날지 모름
• 워드 프로세서의 경우 미리 출력 용지를 결정하므로
pInfo->SetMaxPage 함수를 호출하여 출력할 페이지
를 결정할 수 있음
ISLab ICE HUFS
MFC Tutorial
336
OnBeginPrinting(1)
void CObeditView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
{
m_nPaperHeight = pDC->GetDeviceCaps(VERTRES);
CSize docSize = GetDocument()->GetDocumentSize();
int nMaxPage = max(1,(docSize.cy+m_nPaperHeight-1)/m_nPaperHeight));
pInfo->SetMaxPage(nMaxPage);
}
ISLab ICE HUFS
MFC Tutorial
337
OnBeginPrinting(2)
• CDC::SetDeviceCaps 함수를 이용하여 출력 용지의 높이
를 구함
• 프린트 중에 사용할 GDI 리소스(펜, 폰트, 브러쉬등)를
할당해 두는 일을 하는 곳
– 페이지 출력시마다 리소스 할당을 하지 않기 위해
– 즉, 프린트 작업에 들어가기에 앞서 전체적으로 필요한 GDI 리소
스를 할당
– OnEndPrinting에서 이 리소스들을 제거
ISLab ICE HUFS
MFC Tutorial
338
GetDeviceCaps의 인자
HORZRES
VERTRES
HORSIZE
VERTSIZE
LOGPIXELSX
LOGPIXELSY
NUMCOLORS
TECHNOLOGY
현재 선택된 출력용지의 폭을 픽셀 단위로 알고자 할 때
현재 선택된 출력용지의 높이를 픽셀 단위로 알고자 할 때
현재 선택된 출력용지의 폭을 밀리미터 단위로 알고자 할 때
현재 선택된 출력용지의 높이를 밀리미터 단위로 알고자 할때
현재 프린터의 수평방향의 DPI(Dot Per Inch)를 알고자 할 때
현재 프린터의 수직방향의 DPI(Dot Per Inch)를 알고자 할 때
프린터가 지원하는 색상의 수를 리턴한다. 흑백이면 2
현재 디바이스컨텍스트가 나타내는 출력장치가 무엇인지를
돌려준다. 예로 프린터의 경우에는 DT_RASPRINTER가
리턴될 것이다.
DT_PLOTTER
: 백터 플로터
DT_RASDISPLAY : 래스터 디스플레이
DT_RASPRINTER : 래스터 프린터
DT_RASCAMERA : 래스터 카메라
....
ISLab ICE HUFS
MFC Tutorial
339
OnEndPrinting
• 본 예제에서는 할당한 리소스들이 없으므로
OnEndPrinting에서 할 일이 없음
void CObeditView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo*
/*pInfo*/)
{
}
ISLab ICE HUFS
MFC Tutorial
340
OnPrepareDC 함수의 수정
void CObeditView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
if (pInfo == NULL)
{
CScrollView::OnPrepareDC(pDC, pInfo);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetViewportExt(m_zoomRatio, m_zoomRatio);
pDC->SetWindowExt(100, 100);
}
else
{
pDC->SetViewportOrg(0, -(pInfo->m_nCurPage-1)*m_nPaperHeight);
}
}
ISLab ICE HUFS
MFC Tutorial
341
OnPrepareDC에서의 주의점
• 인자로 넘어오는 CDC 클래스의 오브젝트에 대한 포인터
에 대하여 출력을 할 경우
– 윈도우 출력의 경우 : 출력이 나감
– 프린터 출력의 경우 : 출력이 안 나감
– 프린터 출력시에는 OnPrepareDC의 호출이 끝난 다음에야 새 페
이지의 출력을 프린터 드라이버에 알리는 CDC::StartPage를 호출
하기 때문. 그 전에 호출한 것은 아무런 소용이 없다.
• 두번째 인자 pInfo
– NULL : 화면 출력
– NULL이 아님 : 프린트 출력. 이때 프린트 쪽의 원점을 뒤로 이동
하여 다음 페이지 출력
– pInfo->m_nCurPage : 현재 출력이 나갈 페이지의 번호를 가리킴
ISLab ICE HUFS
MFC Tutorial
342
SetViewportOrg를 이용한 페이지의 출력
전체 편집문서
1. N 페이지만
프린트로 출력이
나가야한다.
2. 출력원점의
보정없이 OnDraw를
호출하면 항상
1 페이지가 출력된다.
종이의 원점에
전체편집문서의
원점이 바로 대응
되기 때문이다.
3. 종이의 출력원점을
전체편집문서의 원점과
맞추어주기위해 그만큼
뒤로 이동하고
OnDraw를 호출한다.
그러면 1페이지부터
N-1 페이지까지의
출력은 종이밖으로
출력되기 때문에
무시된다.
1 페이지
N 페이지
출력용지
ISLab ICE HUFS
MFC Tutorial
343
편집 문서의 수정
• 출력 용지를 늘리기위해
CObeditDoc::CObeditDoc()
{
m_sizeDoc = CSize(1500, 5000);
m_AppName = _T(“도형편집기”);
}
ISLab ICE HUFS
MFC Tutorial
344
Mapping Mode 변경
• MM_TEXT로 출력시 출력 결과가 너무 작고, 프린터 기종
마다 크기가 다르므로
void CObeditView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
if (pInfo == NULL)
{
CScrollView::OnPrepareDC(pDC, pInfo);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetViewportExt(m_zoomRatio, m_zoomRatio);
pDC->SetWindowExt(100, 100);
}
else
{
pDC->SetMapMode(MM_LOMETRIC);
pDC->SetViewportOrg(0, -(pInfo->m_nCurPage-1)*m_nPaperHeight);
}
}
ISLab ICE HUFS
MFC Tutorial
345
출력 용지 페이지 수 계산
void CObeditView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
{
m_nPaperHeight = pDC->GetDeviceCaps(VERTRES);
OnPrepareDC(pDC, pInfo);
CPoint pt(m_nPaperHeight, m_nPaperHeight);
pDC->DPtoLP(&pt);
CSize docSize = GetDocument()->GetDocumentSize();
int nMaxPage = max(1, (docSize.cy + pt.y - 1) / pt.y);
pInfo->SetMaxPage(nMaxPage);
}
• GetDiviceCaps(VERTSIZE)를 호출하면 1 밀리미터 단위의 값이 넘
어옴. MM_LOMETRIC은 0.1 밀미미터 단위의 값임
– 오차가 크므로 픽셀 단위의 값을 구한 다음 DPtoLP를 이용하여
오차를 없앰
ISLab ICE HUFS
MFC Tutorial
346
프린터로 아무것도 출력이 안되는 이유
+Y
-X
+X
출력원점
-Y
출력용지
ISLab ICE HUFS
MFC Tutorial
347
OnPrepareDC의 수정
void CObeditView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
if (pInfo == NULL)
{
CScrollView::OnPrepareDC(pDC, pInfo);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetViewportExt(m_zoomRatio, m_zoomRatio);
pDC->SetWindowExt(100, 100);
}
else
{
pDC->SetMapMode(MM_LOMETRIC);
pDC->SetMapMode(MM_ANISOTROPIC);
CSize size = pDC->GetViewportExt();
pDC->SetViewportExt(size.cx, -size.cy); // 반대방향으로 뒤집음
pDC->SetViewportOrg(0, -(pInfo->m_nCurPage-1)*m_nPaperHeight);
}
}
ISLab ICE HUFS
MFC Tutorial
348
MFC에서의 미리보기 구조
• MFC에서는 기본적인 프린터 출력루틴만 제대로 만들어
졌다면 미리보기는 자연스럽게 구현이 된다.
• 차이점
– 미리보기는 윈도우로 출력되기 때문에 프린터 출력과는 달리
WM_PAINT를 처리할 수 있어야 한다.
– 사용자의 입력을 기다렸다가 페이지를 출력한다.
• CPreviewDC
– 두개의 DC를 사용
• 프린터 DC를 흉내낸 DC
• 출력이 실제로 표시되는 윈도우를 나타내는 DC
ISLab ICE HUFS
MFC Tutorial
349
CPreviewView 클래스
• CPreviewView 클래스
– 메인 프레임의 자식 윈도우로 존재
• CPrintInfo의 m_bPreview가 TRUE이면 미리보기 중
ISLab ICE HUFS
MFC Tutorial
350
미리보기 창에 출력
void CObeditView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
{
m_nPaperHeight = pDC->GetDeviceCaps(VERTRES);
OnPrepareDC(pDC, pInfo);
CPoint pt(m_nPaperHeight, m_nPaperHeight);
pDC->DPtoLP(&pt);
CSize docSize = GetDocument()->GetDocumentSize();
int nMaxPage = max(1, (docSize.cy + pt.x - 1)/pt.x);
pInfo->SetMaxPage(nMaxPage);
분리자
두 페이지 모드일
때 나갈 문자열
CString tempString;
tempString.Format("총 %d 페이지 중 %%d 페이지\n총 %d 페이지 중 %%d-%%d 페이
지",nMaxPage, nMaxPage);
pInfo->m_strPageDesc = tempString;
}
한 페이지 모드일
때 나갈 문자열
ISLab ICE HUFS
MFC Tutorial
351
ISLab ICE HUFS
분리 윈도우
목차
• 분리 윈도우
• 동적 분리 윈도우
• 정적 분리 윈도우
ISLab ICE HUFS
MFC Tutorial
353
정적 동적 분리 윈도우(1)
동적 분리 윈도우
정적 분리 윈도우
ISLab ICE HUFS
MFC Tutorial
354
정적 동적 분리 윈도우(2)
ISLab ICE HUFS
MFC Tutorial
355
분리 윈도우의 구현
• CSplitterWnd 클래스를 이용
– 다음 클래스의 member data로 존재
• CFrameWnd
• CMDIChildWnd
ISLab ICE HUFS
MFC Tutorial
356
동적 분리 윈도우의 구현
class CChildWnd : public CMDIChildWnd
{
DECLARE_DYNCREATE(CChildFrame)
public:
CChildFrame();
// Attributes
public:
CSplitterWnd m_wndSplitter;
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
// {{AFX_VIRTUAL(CChildFrame)
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
....
ISLab ICE HUFS
MFC Tutorial
357
자식 윈도우 생성시
• 최대 4개의 동적 분리 윈도우 생성 가능
BOOL CChildFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext*
pContext)
{
return m_wndSplitter.Create(this, 2, 2, CSize(10, 10), pContext);
}
분리 윈도
우의 행
갯수
분리 윈도
우의 열
갯수
동적 분리
윈도우의
창의
최소 크기
ISLab ICE HUFS
MFC Tutorial
358
분리 윈도우의 크기 변경
• 프로그램에서 변경시
– SetColumnInfo,SetRowInfo 함수를 이용하여 크기 변경
void
void
void
void
GetRowInfo( int row, int& cyCur, int& cyMin );
GetColumnInfo( int col, int& cxCur, int& cxMin );
SetRowInfo( int row, int cyIdeal, int cyMin );
SetColumnInfo( int col, int cxIdeal, int cxMin );
ISLab ICE HUFS
MFC Tutorial
359
pContext
struct CCreateContext
{
m_pNewViewClass
m_pCurrentDoc
m_pNewDocTemplate
m_pLastView
m_pCurrentFrame
//
//
//
//
//
//
생성하고자 하는 새로운 뷰의 CRuntimeClass
새로 생성한 뷰가 연관된 이미 존재하는 도큐먼트 객체
새로운 MDI 프레임 윈도우의 생성과 연관된
도큐먼트 템플릿
이미 존재하는 뷰
현재 생성하고 있는 프레임 윈도우
ISLab ICE HUFS
MFC Tutorial
360
다른 윈도우에 갱신이 안 되는 경우
ISLab ICE HUFS
MFC Tutorial
361
OnLButtonUp 코드 수정
void CObeditView::OnLButtonUp(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DPtoLP(&point);
m_pCurDrawObject->SetEndPoint(point);
m_pCurDrawObject->DrawObject(&dc);
ReleaseCapture();
CObeditDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDoc->m_objectList.AddTail(m_pCurDrawObject);
pDoc->SetModifiedFlag(TRUE);
pDoc->UpdateAllViews(this);
}
}
자신의 문서 내용을 출력하고 있는 모든 뷰에게 내용을
다시 그리라고 하는데 사용하는 함수
ISLab ICE HUFS
MFC Tutorial
362
UpdateAllViews
• CDocument 클래스의 멤버 함수
• 자신의 문서 내용을 출력하고 있는 모든 뷰에게 내용을
다시 그리라고 하는데 사용
• void UpdateAllViews(CView* pSender, LPARAM lHint = 0L,
CObject* pHint = NULL);
– pSender : 도큐먼트를 변경한 뷰, NULL이면 모든 뷰 갱신
– lHint : 변경 정보
– pHint : 변경과 관계된 객체에 대한 포인터
• CView 클래스의 OnUpdate 함수 호출
ISLab ICE HUFS
MFC Tutorial
363
OnUpdate
• UpdateAllView는 각 뷰 클래스의 OnUpdate 함수 호출
– 각각의 OnUpdate 함수는 Invalidate를 호출하여 윈도우 영역 전
체를 다시 그린다.
– 이를 방지하기 위해 수정해야 한다. 즉 OnUpdate에 갱신된 정보
를 포함하여 이 정보에 따라 그림을 수정해야 함
• 예제에서 OnUpdate가 불리는 경우
– 새로운 객체를 삽입하였을 때 객체 삽입을 알려주어야 할 때
– 배율 설정시에 모든 뷰에 배율이 변경되었다는 것을 알려주어야
할때
ISLab ICE HUFS
MFC Tutorial
364
분리 윈도우의 배율의 불일치
ISLab ICE HUFS
MFC Tutorial
365
OnUpdate 함수 정의
void CObeditView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
if (pSender == this)
return;
switch(lHint)
새로운 객체 추가
{
case 1 :
{
CClientDC dc(this);
OnPrepareDC(&dc);
((CDrawObject *)pHint)->DrawObject(&dc);
break;
}
한 뷰에서 다른
case 2 :
뷰로 배율을 전파
{
SetZoomFactor(((CObeditView *)pSender)->m_zoomRatio);
Invalidate();
break;
}
}
}
ISLab ICE HUFS
MFC Tutorial
366
UpdateAllViews 호출 수정(1)
void CObeditView::OnLButtonUp(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DPtoLP(&point);
m_pCurDrawObject->SetEndPoint(point);
m_pCurDrawObject->DrawObject(&dc);
ReleaseCapture();
삽입된 객체
CObeditDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDoc->m_objectList.AddTail(m_pCurDrawObject);
pDoc->SetModifiedFlag(TRUE);
pDoc->UpdateAllViews(this, 1, m_pCurDrawObject);
}
}
객체 사입
ISLab ICE HUFS
MFC Tutorial
367
UpdateAllViews 호출 수정(2)
void CObeditView::OnViewZoom()
{
CZoomDlg zoomDlg(this);
zoomDlg.m_editZoom = m_zoomRatio;
if (zoomDlg.DoModal() != IDOK)
return;
m_zoomRatio = zoomDlg.m_editZoom;
SetZoomFactor(zoomDlg.m_editZoom);
GetDocument()->UpdateAllViews(this, 2);
Invalidate();
}
배율 변경
ISLab ICE HUFS
MFC Tutorial
368
CMyToolBar::OnHScroll 수정
void CMyToolBar::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
int nMin, nMax;
m_zoomScroll.GetScrollRange(&nMin, &nMax);
int nOldPos, nCurPos = m_zoomScroll.GetScrollPos();
nOldPos = nCurPos;
switch(nSBCode)
....
// set zoom ratio to view window
CMDIChildWnd* pChildFrame = (CMDIChildWnd *)
(((CMDIFrameWnd *)AfxGetMainWnd())->MDIGetActive());
CObeditView *pView = (CObeditView *)pChildFrame->GetActiveView();
pView->SetZoomFactor(nCurPos);
pView->GetDocument()->UpdateAllViews(pView, 2);
pView->Invalidate();
}
배율 변경
ISLab ICE HUFS
MFC Tutorial
369
정적 분리 윈도우
• 프레임 클래스의 OnCreateClient 함수를 오버라이드 해서
구현
• 서로 다른 뷰를 가지도록 만든다.
ISLab ICE HUFS
MFC Tutorial
370
OnCreateClient 함수
BOOL CMyFrame::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext)
{
// 먼저 가로로 두 개의 정적윈도우를 만들 것임을 알린다.
if (!m_wndSplitter.CreateStatic(this, 1, 2);
return FALSE;
// 첫번째 정적 윈도우를 생성한다. 이 윈도우는 템플릿에 등록된 뷰 클래스이다.
if (!m_wndSplitter.CreateView(0, 0, pContext->m_pNewViewClass,
CSize(130, 50), pContext))
return FALSE;
// 두번째 정적 윈도우를 생성한다. 이 윈도우는 CInputView 클래스이다.
if (!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CInputView),
CSize(0, 0), pContext))
return FALSE;
// 두번째 뷰를 활성화한다.
SetActiveView((CView*)m_wndSplitter.GetPane(0, 1);
return TRUE;
}
ISLab ICE HUFS
MFC Tutorial
371
세개의 정적 분리 윈도우 생성
ISLab ICE HUFS
MFC Tutorial
372
세 개의 정적 분리윈도우의 구현
if (!m_wndSplitter1.CreateStatic(this, 1, 2))
return FALSE;
if (!m_wndSplitter1.CreateView(0, 0, RUNTIME_CLASS(CFileTreeView),
CSize(100,100), pContext))
return FASLE;
if (!m_wndSplitter2.CreateStatic(&m_wndSplitter1, 2, 1, WS_CHILD |
WS_VISIBLE | WS_BORDER, m_wndSplitter1.IdFromRowCol(0,1)))
return FALSE;
if (!m_wndSplitter2.CreateView(0, 0, RUNTIME_CLASS(CListView),
CSize(100, 150), pContext))
return FALSE;
if (!m_wndSplitter2.CreateView(1, 0, RUNTIME_CLASS(CTextView),
CSize(100, 120), pContext))
return FALSE;
SetActiveView((CView*)m_wndSplitter2.GetPane(0, 0));
ISLab ICE HUFS
MFC Tutorial
373
ISLab ICE HUFS
MFC 디버깅 매크로와
예외 처리
목차
•
•
•
•
메시지 출력
ASSERT 매크로
오브젝트의 유효성 검사
예외 처리
ISLab ICE HUFS
MFC Tutorial
375
컴파일 옵션
• Debug 모드
– _DEBUG
• Release 모드
– NODEBUG
ISLab ICE HUFS
MFC Tutorial
376
디버그 모드로 수행
ISLab ICE HUFS
MFC Tutorial
377
디버깅 모드로 수행
•
•
•
•
•
한 문장씩 수행
함수 안으로 들어가 수행
수행중인 함수밖으로
커서 위치까지 수행
Call Stack
ISLab ICE HUFS
MFC Tutorial
378
TRACE 매크로
• 디버그 창으로 메시지 출력
• 디버그 모드로 컴파일할 때만 수행
TRACE(“Sample TRACE Output : %d == 0x%x\n”, i, i);
ISLab ICE HUFS
MFC Tutorial
379
ASSERT 매크로
• 어떤 조건을 검사하여 거짓이면 그 위치(파일 이름과 행
번호)를 출력하는데 사용
• 주로 프로그램 개발 기간 중에 함수의 인자로 들어온 값
이 맞게 들어왔는지의 여부를 판단하는데 사용
• 디버그 모드로 컴파일 시에만 수행
ASSERT(prt != NULL);
ISLab ICE HUFS
MFC Tutorial
380
VERIFY 매크로
• ASSERT 매크로와 동일
• 단, 디버그 모드가 아닌 Release 모드로 컴파일 시에도 수
행
VERIFY(LoadAccelTable(hWnd, “MainWnd”));
ISLab ICE HUFS
MFC Tutorial
381
오브젝트의 유효성 검사
• CObject 클래스의 후손에만 적용
• AssertValid
– 현재 오브젝트의 데이터멤버가 올바른 값을 갖고 있는지의 여부
를 검사
• Dump
– 현재 오브젝트의 데이터멤버를 출력하는데 사용
• 디버그 모드에서만 수행
– _DEBUG
ISLab ICE HUFS
MFC Tutorial
382
AssertValid
class CHorzLine : public CObject
{
CPoint m_ptStart, m_ptEnd;
....
#ifdef _DEBUG
void AssertValid() const;
void Dump(CDumpContext& dc) const;
#endif
};
void CHorzLine::AssertValid() const
{
CObject::AssertValid(); // 먼저 선조 클래스의 유효성을 검사한다.
ASSERT(m_ptStart.y == m_ptEnd.y);
}
ISLab ICE HUFS
MFC Tutorial
383
Dump
void CHorzLine::Dump(CDumpContext& dc) const
{
CObject::Dump(dc); // 먼저 선조클래스의 데이터멤버를 호출한다.
dc << “X : “ << (WORD)m_ptStart.x << “ Y : “ << (WORD)m_ptStart.y
<< “\n”;
dc << “Y : “ << (WORD)m_ptEnd.x << “ Y : “ << (WORD)m_ptEnd.y
<< “\n”;
}
void f()
{
CHorzLine* pLine = new CHorzLine;
....
#ifdef _DEBUG
pLine->Dump(afxDump);
#endif
....
afxDump는 CDumpContext
타입의 전역 변수. 출력이
윈도우의 Debug 탭으로 출
력
ISLab ICE HUFS
MFC Tutorial
384
예외처리
체크 되어야
ISLab ICE HUFS
MFC Tutorial
385
ISLab ICE HUFS
공통 컨트롤(Common Control)
목차
•
•
•
•
•
•
•
Common Control의 종류
Control Message 처리
Animation Control
Progress Control
Slider Control
List Control
Tree Control
ISLab ICE HUFS
MFC Tutorial
387
Common Control의 종류(1)
• CAnimateCtrl
• CHeaderCtrl
• CHotKeyCtrl
• CImageList
• CListCtrl
ISLab ICE HUFS
MFC Tutorial
388
Common Control의 종류(2)
• CProgressCtrl
• CRichEditCtrl
– OLE 복합문서 컨테이너
ISLab ICE HUFS
MFC Tutorial
389
Common Control의 종류(3)
• CSliderCtrl
• CSpinButtonCtrl
• CStatusBarCtrl
• CTabCtrl
ISLab ICE HUFS
MFC Tutorial
390
Common Control의 종류(4)
• CToolBarCtrl
• CToolTipCtrl
• CDragListBox
• CCheckListBox
ISLab ICE HUFS
MFC Tutorial
391
Common Control의 종류(5)
• CTreeCtrl
ISLab ICE HUFS
MFC Tutorial
392
Common Control
• Common contorl의 code는 윈도우의
system\COMCTL32.DLL에 있다.
–
–
–
–
각 컨트롤에 대한 윈도우 프로시저
각 컨트롤을 위한 윈도 클래스를 등록하는 코드가 포함
등록 코드는 DLL이 로드될 때 호출
다이얼로그를 초기화할 때 프로그램에서는 다이얼로그 리소스에
서 기호 클래스 이름을 사용해서 DLL에 있는 윈도 프로시저를 연
결
– 이렇게 함으로써 프로그램에서는 컨트롤의 윈도를 소유하게 되
지만, 코드는 DLL에 존재
• 공통 컨트롤은 Class Wizard가 멤버 변수를 제공하지 않
음
• 공통 컨트롤들로부터 통지 메시지들을 매핑하는 일에는
Class Wizard를 이용할 수 있다.
ISLab ICE HUFS
MFC Tutorial
393
Common Control의 사용
• Common control 역시 컨트롤이기 때문에 dialog box에서
사용할 수 있다.
• 보통 윈도우의 자식 윈도우로 존재할 수 있다.
ISLab ICE HUFS
MFC Tutorial
394
Dialog Box에서 사용(1)
Progress Control
Slider Control
List Control
Spin Control
Hotkey Control
Tree Control
Tap Control
Animation Control
ISLab ICE HUFS
MFC Tutorial
395
Dialog Box에서 사용(2)
• Resource view에 있는 control palette 이용
• 없는 것은 데이터 멤버로 만들어 놓은 다음
WM_INITDIALOG 메시지가 왔을 때 Create 같은 멤버함
수를 이용해 직접 생성
• Class wizard를 이용해 dialog box template에 해당하는
dialog class 생성
• Add Member Variable 버튼을 택하여 common control에
해당하는 데이터 멤버를 만듦
– 강제적으로 Category가 CONTROL이 된다.
ISLab ICE HUFS
MFC Tutorial
396
일반윈도우의 자식윈도우로 사용시
• 각 common control 클래스의 오브젝트를 정의
• 각 컨트롤의 Create 함수를 이용해 컨트롤 생성
• Common control을 dialog template에 만들어 놓으면 알아서 생성되
기 때문에 직접 common control 클래스의 Create 멤버함수를 불러줄
필요가 없다.
class CMyView : public CView
{
....
CProgressCtrl m_progressBar;
....
};
int CMyView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
....
m_progressBar.Create(...);
....
ISLab ICE HUFS
MFC Tutorial
397
Notification Message 처리
• Control은 자신에게 무슨 일이 발생하면 부모 윈도우에게
알려준다.
– Control이 dialog box에서 사용된 경우라면 이 때 부모윈도우는
dialog box가 된다.
ISLab ICE HUFS
MFC Tutorial
398
Notification Message
• WM_COMMAND
– 원래의 window control들이 이용
– 표준 32비트 wParam, lParam 메시지 파라미터는 common
control이 부모에게 보내는 정보를 위해 사용하기에는 부적절
• WM_NOTIFY
– wParam은 control ID
– lParam은 control에 의해 운영되는 NMHDR 구조체 포인터이거나
이를 포함하는 더 큰 구조체
ISLab ICE HUFS
MFC Tutorial
399
NMHDR
typedef struct tagNMHDR {
HWND hwndFrom;
// 메시지를 보내는 control handle
UINT idFrom;
// 메시지를 보내는 control ID
UINT code;
// control-특성적인 notification code
} NMHDR;
• code로 들어오는 notification code에는 모든 common
control에 공통되는 것과 common control에 따라 달라지
는 것 두 종류가 존재
ISLab ICE HUFS
MFC Tutorial
400
공통되는 Notification Code
NM_CLICK
NM_DBCLICK
NM_RCLICK
NM_RDBCLICK
NM_RETURN
NM_SETFOCUS
NM_KILLFOCUS
NM_OUTOFMEMORY
컨트롤을
컨트롤을
컨트롤을
컨트롤을
컨트롤이
경우
컨트롤에
컨트롤이
메모리가
좌측
좌측
우측
우측
입력
마우스 버튼으로 클릭했을 때
마우스 버튼으로 더블 클릭했을 때
마우스 버튼으로 클릭했을 때
마우스 버튼으로 더블 클릭했을 때
포커스를 갖고 있을 때 리턴키를 친
입력 포커스가 갈 때
입력 포커스를 잃을 때
부족해서 하던 일을 끝내지 못할 때
ISLab ICE HUFS
MFC Tutorial
401
다양한 Notification Code Structure
• 툴팁 컨트롤
– NMHDR 스트럭처만을 그대로 이용
• 트리뷰 컨트롤
– 한 항목을 선택하면 TVN_SELCHANGING라는 알림코드를 갖는다.
WM_NOTIFY 메시지 발생. 이때 lParam은 NM_TREEVIEW 스트럭
처를 갖는다.
typedef struct _NM_TREEVIEW
{
NMHDR hdr;
UINT action;
TV_ITEM itemNew;
TV_ITEM itemOld;
POINT ptDrag;
} NM_TREEVIEW;
ISLab ICE HUFS
MFC Tutorial
402
Message Map에서의 Notification Message
• ON_NOTIFY 매크로 사용
– ON_NOTIFY(wNotifyCode, ctrlID, memberFn)
– ctrlID를 공통 컨트롤 ID로 갖는 공통컨트롤로부터
wNotifyCode라는 알림코드가 오면 memberFn이라는 처리
함수를 불러달라는 것
–
void memberFn(NMHDR* pNotifyStruct, LRESULT* result);
공통 컨트롤에
따라 달라진다.
처리 결과를 돌려준다.
처리했으면 0을 리턴
ISLab ICE HUFS
MFC Tutorial
403
Message Map Macro
• ON_NOTIFY_RANGE, ON_NOTIFY_EX,
ON_NOTIFY_EX_RANGE
– 동일한 종류의 여러 control로부터 오는 notification code를 처
리하고자 할 때
– 매번 처리함수를 따로 만들지 않고 하나의 처리함수를 정의해 사
용
ISLab ICE HUFS
MFC Tutorial
404
Notification Code 처리 예
• List control에서 사용자가 선택하는 항목이 달라질 때
BEGIN_MESSAGE_MAP(....)
....
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LISTCTRL, OnListCtrlClick)
....
END_MESSAGE_MAP()
void CCmmCtrlView::OnListCtrlClick(NMHDR* pNotifyStruct, LRESULT* result)
{
NM_LISTVIEW* pListView = (NM_LISTVIEW *)pNotifyStruct;
// 자신의 용도에 맞게 적절히 처리한다.
....
적절한 타입으로
*result = 0;
캐스팅 하여 사용
}
ISLab ICE HUFS
MFC Tutorial
405
Message Reflection
• Notification message를 부모 윈도우로 보냈을 때 처리가
안 되었다면 이를 다시 컨트롤로 보내 자체에서 처리가
되도록 하는 기능
• MFC 4.0에서 새로 제공해주는 기능
• 부모 윈도우의 의존성에서 벗어나 나름대로의 동작 방식
을 더 가질 수 있게 됨
• Message Reflection의 경우 컨트롤 자체의 message map
에 등록해야
– ON_NOTIFY_REFLECT 매크로 사용
ON_NOTIFY_REFLECT(wNotifyCode, memberFn)
ISLab ICE HUFS
MFC Tutorial
406
예제
•
•
•
•
프로젝트 이름 : CmmCtrl
SDI
데이터베이스 옵션은 주지 않음
Toolbar, status bar, 프린트 관련 옵션도 선택 않음
ISLab ICE HUFS
MFC Tutorial
407
메뉴 구성
Common Control
Animate
Image List
Slider
Progress
Tree
List
-----------Exit
Help
ID_COMM_ANIMATE
ID_COMM_IMAGE
ID_COMM_SLIDER
ID_COMM_PROGRESS
ID_COMM_TREE
ID_COMM_LIST
ISLab ICE HUFS
MFC Tutorial
408
Control ID 생성
// CmmCtrlView.cpp
#define
#define
#define
#define
#define
IDC_ANIMATE
IDC_PROGRESS
IDC_SLIDER
IDC_LISTCTRL
IDC_TREECTRL
200
201
202
203
204
//
//
//
//
//
Animation control ID
Progress control ID
Slider control ID
List control ID
Tree control ID
• Resource Symbol을 이용해도 됨
ISLab ICE HUFS
MFC Tutorial
409
컨트롤 멤버데이터 정의
• CCmmCtrlView 클래스에 정의
CAnimateCtrl
CImageList
CImageList
CSliderCtrl
CProgressCtrl
CListCtrl
CTreeCtrl
HTREEITEM
m_wndAnimateCtrl;
// Animation control
m_wndImageList;
// Image list 1
m_wndSmallImageList;
// Image list 2
m_wndSliderCtrl;
// Slider control
m_wndProgressCtrl;
// Progress control
m_wndListCtrl;
// List control
m_wndTreeCtrl;
// Tree control
m_treeRoot;
// Tree control에서 사용된다.
// 루트 항목을 가리킨다.
BOOL m_bListCtrl; // List control의 생성여부
BOOL m_bTreeCtrl; // Tree control의 생성여부
BOOL m_bSlider;
// Slider control의 생성여부
ISLab ICE HUFS
MFC Tutorial
410
남아있는 객체 삭제를 위한 함수
void CCmmCtrlView::CheckWnd()
{
if (m_bListCtrl)
// List control이 있으면 없앤다.
{
m_wndImageList.DeleteImageList();
m_wndSmallImageList.DeleteImageList();
m_wndListCtrl.DestroyWindow();
m_bListCtrl = FALSE;
}
else if (m_bTreeCtrl)
// Tree control이 있으면 없앤다.
{
m_wndImageList.DeleteImageList();
m_wndTreeCtrl.DestroyWindow();
m_bTreeCtrl = FALSE;
}
else if (m_bSlider)
{
m_wndSliderCtrl.DestroyWindow();
m_bSlider = FALSE;
}
}
ISLab ICE HUFS
MFC Tutorial
411
CCmmCtrlView의 생성자/소멸자 변경
CCmmCtrlView::CCmmCtrlView()
{
m_bListCtrl = FALSE;
m_bTreeCtrl = FALSE;
m_bSlider = FALSE;
}
CCmmCtrlView::~CCmmCtrlView()
{
CheckWnd();
}
ISLab ICE HUFS
MFC Tutorial
412
Animation Control
•
•
•
•
AVI 파일을 디스플레이
오디오가 있는 파일은 지원안 함
즉 하나의 Video Stream만 있는 avi file 만 지원
오디오를 지원하는 클래스 : OLE 컨트롤 중 마이크로소
프트 멀티미디어 컨트롤
ISLab ICE HUFS
MFC Tutorial
413
ID_COMM_ANIMATE
void CCmmCtrlView::OnCommAnimate()
{
CheckWnd();
// 이 함수의 용도는 앞에서 설명하였다.
// AVI 파일을 입력받기 위한 다이얼로그를 띄운다.
CFileDialog dlg( TRUE,_T("AVI"),_T("*.AVI"),
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
_T("Animation (*.AVI)|*.AVI|"));
if (dlg.DoModal() != IDOK) // 사용자가 취소한 경우는
return;
// 그대로 끝낸다.
CString strFileName = dlg.GetPathName(); // AVI 파일 이름을 저장한다.
CRect rectAnimateCtrl;
GetClientRect(&rectAnimateCtrl); //뷰의 위치를 얻어둔다.
// 애니메이트 컨트롤을 생성한다.
m_wndAnimateCtrl.Create(WS_CHILD|WS_VISIBLE|WS_BORDER|ACS_CENTER,
rectAnimateCtrl, this, IDC_ANIMATE);
m_wndAnimateCtrl.Open(strFileName);
InvalidateRect(NULL);
UpdateWindow();
m_wndAnimateCtrl.Play(0,0xFFFF,1);
//
}
ISLab ICE HUFS
MFC Tutorial
414
Animation Control의 속성
ACS_CENTER
애니메이션 컨트롤의 중앙에서 AVI 파일을 플레이
한다. 이 스타일이 주어지지 않으면 AVI 파일의
크기에 맞춰 애니메이션 컨트롤의 크기가 변경된다
위의 예에서 바로 이 스타일을 사용하였다.
ACS_TRANSPARENT
AVI 파일의 배경색 대신에 원래 애니메이션 컨트롤
의 자리에 있던 배경색을 사용한다.
ACS_AUTOPLAY AVI 파일이 오픈됨과 동시에 플레이되도록 하며
플레이가 계속 반복되도록 한다.
ISLab ICE HUFS
MFC Tutorial
415
CAnimateCtrl의 멤버 함수
Open
Play
Seek
Stop
Close
AVI 파일이나 리소스를 읽어들여 첫 프레임을 윈도우에 표시한다.
AVI 클립을 플레이한다.
첫번째 인자와 두번째 인자가 플레이할 프레임을 지칭
시작 프레임일 경우 0을 마지막 프레임일 경우 -1(0xFFFF)
마지막 인자는 반복횟수
AVI 클립의 지정된 프레임을 윈도우에 표시한다.
AVI 클립의 표시를 중단한다.
오픈된 AVI 클립을 닫아 버린다.
ISLab ICE HUFS
MFC Tutorial
416
Animation Control의 Notification Code
ACN_START
ACN_STOP
AVI 클립의 플레이가 시작되었음을 알린다.
AVI 클립의 플레이가 다 끝났음을 알린다.
• WM_COMMAND 메시지 발생
• ON_CONTROL 매크로 사용
ISLab ICE HUFS
MFC Tutorial
417
Notification Code 처리함수
BEGIN_MESSAGE_MAP(CCmmCtrlView, CView)
//{{AFX_MSG_MAP(CCmmCtrlView)
ON_COMMAND(ID_COMM_ANIMATE, OnCommAnimate)
ON_COMMAND(ID_COMM_IMAGE, OnCommImage)
....
//}}AFX_MSG_MAP
ON_CONTROL(ACN_STOP, IDC_ANIMATE, OnAnimateStop)
END_MESSAGE_MAP()
void CCmmCtrlView::OnAnimateStop()
{
AfxMessageBox("AVI 방영(?)이 끝났습니다.");
m_wndAnimateCtrl.Close();
m_wndAnimateCtrl.DestroyWindow();
InvalidateRect(NULL);
}
ISLab ICE HUFS
MFC Tutorial
418
Image List
• Mask bitmap
• 윈도우가 아님
• BOOL Create(int cx, int cy, BOOL bMask, int nInitial, int
nGrow);
– cx, cy ; 픽셀 단위로 각 이미지의 크기
– bMask : mask image를 사용할 것인지의 여부
– nInitial : 처음 이미지 리스트가 생성될 때 이미지 리스트에 들어
갈 이미지의 개수
– nGrow : 이미지 리스트의 크기가 변할 때 쓰이는 단위
ISLab ICE HUFS
MFC Tutorial
419
ID_COMM_IMAGE(1)
void CCmmCtrlView::OnCommImage()
{
CheckWnd();
m_wndImageList.Create(32, 32, TRUE, 2, 2);
CBitmap bitmap, bitmap2, bitmap3, bitmap4, bitmap5;
bitmap3.LoadBitmap(IDB_BITMAP3); // Load mask bitmap
bitmap.LoadBitmap(IDB_BITMAP1);
m_wndImageList.Add(&bitmap, (CBitmap *)&bitmap3);
bitmap2.LoadBitmap(IDB_BITMAP2);
m_wndImageList.Add(&bitmap2, (CBitmap *)&bitmap3);
CClientDC dc(this);
CPoint pt;
for(int i = 0;i < m_wndImageList.GetImageCount();i++)
{
pt.x = 100 + 32*i;
pt.y = 100;
m_wndImageList.Draw(&dc, i, pt, ILD_NORMAL);
ISLab ICE HUFS
MFC Tutorial
420
ID_COMM_IMAGE(2)
pt.y += 50;
m_wndImageList.Draw(&dc, i, pt, ILD_BLEND50);
pt.y += 50;
m_wndImageList.Draw(&dc, i, pt, ILD_BLEND25);
}
m_wndImageList.DeleteImageList();
}
IDB_BITMAP1
IDB_BITMAP2
IDB_BITMAP3
ISLab ICE HUFS
MFC Tutorial
421
Image List의 멤버 함수(1)
GetImageCount
SetBkColor
GetBkColor
GetImageInfo
DeleteImageList
Add
Remove
Replace
Extraction
Read
Write
Image list에 들어있는 image의 개수
Image list의 image의 배경색을 설정. Mask
image list의 경우에는 CLR_NONE을 주면 Mask를
갖고 그리기 때문에 원래 배경이 보존된다
현재 image list의 image의 배경색을 얻어온다
현재 image list의 image에 대한 정보를 얻음
Image list를 삭제한다
새로운 image를 image list에 추가한다.
Image list에서 image를 삭제한다.
Image list에서 한 image를 다른 image로 변경
Image list의 image를 icon handle로 만들려는
경우에 사용
Image를 파일에서 읽어 image list에 추가
Image를 image list에서 읽어 파일에 추가
ISLab ICE HUFS
MFC Tutorial
422
Image List의 멤버 함수(2)
Draw
SetOverlayImage
Image list의 image를 윈도우 위에 출력한다.
Image list의 image를 overlay image list에
추가한다. Image list 당 4개까지의 image를
overlay mask로 사용할 수 있다.
ISLab ICE HUFS
MFC Tutorial
423
Draw 함수
BOOL Draw(CDC* pdc, int nImage, POINT pt, UINT nStyle);
IDL_NORMAL
IDL_TRANSPARENT
IDL_BLEND50
IDL_BLEND25
IDL_OVERLAYMASK
Image list에 지정된 배경색을 갖고 이미지를
출력한다. Mask image list의 경우에는 배경이
보존된 채 출력이 이루어진다.
지정된 배경색에 관계없이 배경을 유지한 채 image를
출력하는데 마스크된 image에만 적용 가능한 옵션
주어진 image가 선택되었음을 나타내기 위해 시스템
하이라이트 색상으로 혼합한 다음에 출력한다.
주어진 image가 입력포커스를 갖고 있음을 나타내며
출력한다.
주어진 image를 그리고 그 위에 이 스타일과 함께
지정된 overlay mask를 그린다. Overlay mask
지정은 INDEXTOOVERLAYMASK macro를 통해 이루
어진다. 연산자를 이용해 이 스타일과 함께 지정해준다.
ISLab ICE HUFS
MFC Tutorial
424
ID_COMM_PROGRESS(1)
void CCmmCtrlView::OnCommProgress()
{
CheckWnd();
InvalidateRect(NULL);
CRect rect;
// Progress control의 위치를 지정한다
rect.left = rect.top = 100;
rect.right = 400; rect.bottom = 150;
// Progress control을 생성한다
m_wndProgressCtrl.Create(WS_CHILD|WS_VISIBLE|WS_BORDER,rect,
this,IDC_PROGRESS);
m_wndProgressCtrl.SetRange(0, 100);
// 진행범위를 지정한다.
m_wndProgressCtrl.SetPos(0);
// 초기위치를 지정한다
ISLab ICE HUFS
MFC Tutorial
425
ID_COMM_PROGRESS(2)
for(int i = 1;i <= 10; i++)
{
::Sleep(100);
// 0.1초간 쉰다.
m_wndProgressCtrl.SetPos(i*10); // 10만큼씩 진행한다.
}
AfxMessageBox("Progress Bar의 끝에 도달했군요.");
m_wndProgressCtrl.DestroyWindow();
InvalidateRect(NULL);
}
ISLab ICE HUFS
MFC Tutorial
426
Progress Control의 멤버함수
SetRange
SetPos
OffsetPos
SetStep
StepIt
Progress
Progress
Progress
Progress
Progress
bar의
bar의
bar의
bar의
bar의
범위값을 지정하고 그에 맞추어 다시 그림
현재 위치를 지정하고 그에 맞추어 다시 그림
현재 위치를 주어진 값만큼 보정하고 다시 그림
진행 단위를 지정한다. StepIt 함수에서 사용한다.
현재 위치를 SetStep에서 지정된 값만큼 진행시킨다.
ISLab ICE HUFS
MFC Tutorial
427
Slider Control
• 불연속적인 값이나 어떤 범위의 값을 입력받고자 할 때
• WM_HSCROLL(혹은 WM_VSCROLL)로 특이하게
notification code를 발생시킨다.
ISLab ICE HUFS
MFC Tutorial
428
ID_COMM_SLIDER
void CCmmCtrlView::OnCommSlider()
{
CheckWnd();
InvalidateRect(NULL);
CRect rect;
rect.SetRect(100, 100, 300, 200);
m_wndSliderCtrl.Create(WS_VISIBLE|WS_CHILD
|TBS_HORZ|TBS_BOTH|TBS_AUTOTICKS, rect, this, IDC_SLIDER);
m_wndSliderCtrl.SetTicFreq( 2 ); // Set the interval of tick count
m_wndSliderCtrl.SetLineSize( 2 ); // Set the size of line movement
m_wndSliderCtrl.SetPageSize( 4 ); // Set the size of page movement
m_wndSliderCtrl.SetRange( 0, 12, TRUE );
m_wndSliderCtrl.SetPos(0);
}
ISLab ICE HUFS
MFC Tutorial
429
Slider Control의 윈도우 스타일
TBS_HORZ
TBS_VERT
TBS_AUTOTICKS
TBS_NOTICKS
TBS_BOTTOM
TBS_TOP
TBS_RIGHT
수평 slider control을 만든다. 이것이 디폴트이다.
수직 slider control을 만든다.
지정된 슬라이더 범위 내의 각 단위값 마다 눈금을 붙이다. 만일 이
스타일이 이용된 경우에는 SetTic, SetTicFreq와 같은 멤버함수를 이용해
눈금의 위치를 지정할 수 있다.
눈금이 없는 슬라이더를 만든다.
슬라이더의 하단에 눈금을 표시한다. TBS_TOP 스타일과 함께 사용되면
위아래 모두에 눈금을 붙일 수 있다. TBS_BOTTOM과 TBS_TOP 스타일은
수평 슬라이더에만 적용 가능하다.
수평 슬라이더의 상단에 눈금을 붙인다.
수직 슬라이더의 우단에 눈금을 붙인다. TBS_LEFT 스타일과 함께
사용되면 오른쪽, 왼쪽 모두에 눈금을 붙인다.
ISLab ICE HUFS
MFC Tutorial
430
TBS_LEFT
TBS_BOTH
TBS_ENABLESELRANGE
수직 슬라이더의 좌단에 눈금을 붙인다.
수평 슬라이더이면 위아래에 눈금을 붙이고 수직
슬라이더이면 왼쪽, 오른쪽에 눈금을 붙인다.
이 스타일을 주면 영역을 선택하는 것이
가능하다. 선택 영역의 시작과 끝 눈금이
삼각형 모양의 눈금으로 변하고 그 사이의
영역이 하이라이트된다.
ISLab ICE HUFS
MFC Tutorial
431
CSliderCtrl의 멤버 함수(1)
SetRange
SetRangeMin
SetRangeMax
GetRangeMax
GetRangeMin
GetRange
GetLineSize
SetLineSize
GetPageSize
SetPageSize
GetPos
SetPos
Slider control의 양끝값을 설정한다.
Slider control의 최소값을 설정한다.
Slider control의 최대값을 설정한다.
Slider control의 최대값을 얻어온다.
Slider control의 최소값을 얻어온다.
Slider control의 양끝값을 얻어온다.
Slider control의 라인 크기를 얻어온다. TB_LINEUP,
TB_LINEDOWN의 발생 시 이동량을 얻어오는 것이다.
Slider control의 라인 크기를 설정한다.
Slider control의 페이지 크기를 얻어온다. TB_PAGEUP,
TB_PAGEDOWN의 발생시 이동량을 얻어오는 것이다.
Slider control의 페이지 크기를 결정한다.
Slider control의 슬라이더 위치를 얻어온다.
Slider control의 슬라이더 위치를 새로 설정한다.
ISLab ICE HUFS
MFC Tutorial
432
CSliderCtrl의 멤버 함수(2)
GetTic
GetTicPos
SetTic
SetTicFreq
ClearTics
주어진 눈금의 위치를 얻어온다.
주어진 눈금이 위치한 좌표를 얻어온다.
눈금이 생길 위치를 지정한다.
눈금이 생길 위치를 위치 단위로 지정한다. 예로 들면 2로
지정하면 0, 2, 4...의 위치에 눈금이 생긴다.
Slider control에서 모든 눈금을 제거한다.
ISLab ICE HUFS
MFC Tutorial
433
Slider Control의 Notification Code
TB_TOP
TB_BOTTOM
TB_LINEDOWN
TB_LINEUP
TB_PAGEDOWN
TB_PAGEUP
TB_THUMBPOSITION
TB_THUMBTRACK
TB_ENDTRACK
HOME 키를 눌렀을 때
END 키를 눌렀을 때
VK_RIGHT이나 VK_DOWN 키를 눌렀을 때
VK_LEFT나 VK_UP 키를 눌렀을 때
마우스로 슬라이더의 오른쪽을 누르거나 PgDn 키
를 눌렀을 때
마우스로 슬라이더의 왼쪽을 누르거나 PgUp 키를
눌렀을 때
TB_THUMBTRACK의 끝에 따라와 슬라이더의
드래깅이 끝났음을 알린다.
사용자가 슬라이더를 드래그하면 그 때 계속적으로
발생한다.
각 notification code에 뒤이어 항상 발생한다.
ISLab ICE HUFS
MFC Tutorial
434
Slider Control의 WM_HSCROLL 처리
BEGIN_MESSAGE_MAP(CCmmCtrlView, CView)
//{{AFX_MSG_MAP(CCmmCtrlView)
....
//}}AFX_MSG_MAP
ON_CONTROL(ACN_STOP, IDC_ANIMATE, OnAnimateStop)
ON_WM_HSCROLL()
END_MESSAGE_MAP()
void CCmmCtrlView::OnHScroll( UINT nSBCode, UINT nPos, CScrollBar*
pScrollBar )
{
int nCurPos = ((CSliderCtrl *)pScrollBar)->GetPos();
if (nCurPos==((CSliderCtrl *)pScrollBar)->GetRangeMax() &&
nSBCode==TB_ENDTRACK)
{
AfxMessageBox("Slider의 끝에 도달했군요.");
m_wndSliderCtrl.DestroyWindow();
InvalidateRect(NULL);
}
}
ISLab ICE HUFS
MFC Tutorial
435
List View Control
• 리스트의 한 아이템이 여러 항목으로 구성될 수 있다.
• 항목의 일부로 비트맵이 들어갈 수 있다.
• 각 항목의 제목을 나타내기 위해 헤더(Header) 컨트롤이
라는 것을 내부적으로 사용할 수 있다.
• 항목마다 사용되는 아이콘을 따로 리스트로 유지하는데
앞서 살펴 본 image list를 사용하는 것이다.
ISLab ICE HUFS
MFC Tutorial
436
List View Control의 타입
아이콘뷰
스몰아이콘뷰
리스트뷰
리포트뷰
LVS_ICON 스타일을 지정하면 된다. 각 항목은 아이콘과
그 밑의 레이블로 구성된다. 각 항목은 드래깅으로 다른
위치에 갖다놓을 수 있다.
LVS_SMALLICON 스타일을 지정하면 된다. 각 항목은
16X16 아이콘과 그 오른쪽의 레이블로 구성된다. 각 항목
은 드래깅으로 다른 위치에 갖다 놓을 수 있다.
LVS_LIST 스타일을 지정하면 된다. 각 항목은 서브 항목별
로 정렬되어 디스플레이된다.
LVS_REPORT 스타일을 지정하면 된다.
LVS_NOCOLUMNHEADER 스타일이 명시되지 않으면
헤더 컨트롤이 사용되어 레이블과 각 서브 항목의 타이틀을
표시할 수 있다. 리스트뷰에서와 마찬가지로 각 항목들은
서브 항목별로 정렬되어 디스플레이된다.
ISLab ICE HUFS
MFC Tutorial
437
List View Control의 윈도우 스타일
LVS_BUTTON
LVS_EDITLABELS
Icon view에서 아이콘을 버튼처럼 디스플레이 되도록 한다.
각 항목의 레이블이 편집 가능하도록 한다.
부모 윈도우는 LVN_ENDLABELEDIT 알림코드를
처리할 수 있어야 한다.
LVS_ICON
List control을 아이콘뷰로 생성할 것을 지정한다
LVS_LIST
List control을 리스트뷰로 생성할 것을 지정한다
LVS_REPORT
List control을 리포트뷰로 생성할 것을 지정한다
LVS_SMALLICON
List control을 스몰아이콘뷰로 생성할 것을 지정
LVS_NOCOLUMNHEADER
List control을 리포트뷰로 만들 때 header control을 사용하지
말것을 지정
LVS_SORTASCENDING
List control의 항목을 오름차순으로 정렬
LVS_SORTDESCENDING
List control의 항목을 내림차순으로 정렬
LVS_SINGLESEL
단지 하나의 항목만이 선택가능 하도록 한다. 원래
디폴트는 여러 항목이 선택 가능하다.
LVS_NOSCROLL
항목들이 윈도우 영역의 크기를 넘어가도 스크롤이
안되도록 한다.
ISLab ICE HUFS
MFC Tutorial
438
CListCtrl 클래스의 주요 멤버 함수(1)
InsertColumn
DeleteColumn
InsertItem
GetItem
SelItem
DeleteItem
DeleteAllItems
HitTest
EnsureVisible
Scroll
EditLabel
GetBkColor
SetBkColor
GetImageList
새로운 컬럼을 삽입한다.
컬럼을 하나 삭제한다.
새로운 항목을 하나 삽입한다.
항목의 속성을 얻어온다.
항목에 부항목을 붙이는 등의 속성변경 작업을 한다.
항목 하나를 삭제한다.
모든 항목을 삭제한다.
주어진 위치에 어떤 항목이 있는지 알아낸다.
주어진 항목이 보이도록 만든다.
내용을 스크롤시킨다.
항목 텍스트의 편집이 가능하도록 한다.
배경색을 얻어온다.
배경색을 설정한다.
사용되는 아이콘리스트를 얻어온다.
ISLab ICE HUFS
MFC Tutorial
439
CListCtrl 클래스의 주요 멤버 함수(2)
SetImageList
GetItemCount
GetStringWidth
사용되는 icon list를 지정한다.
항목수를 얻어온다.
주어진 문자열을 표시하는데 필요한 최소한의 컬럼폭을
돌려준다.
GetColumnWidth 리스트뷰와 리포트뷰의 컬럼폭을 얻어온다.
SetColumnWidth 리스트뷰와 리포트뷰의 컬럼폭을 설정한다.
GetItemText
리스트뷰의 특정항목의 레이블이나 부항목의 텍스트를
얻어온다.
SetItemText
리스트뷰의 특정항목의 레이블이나 부항목의 텍스트를
설정한다.
ISLab ICE HUFS
MFC Tutorial
440
ID_COMM_LIST(1)
void CCmmCtrlView::OnCommList()
{
CheckWnd();
CRect rect;
GetClientRect(&rect);
// 리스트 컨트롤을 리포트뷰로 생성한다.
m_wndListCtrl.Create(LVS_REPORT| WS_VISIBLE | WS_CHILD, rect,
this, IDC_LISTCTRL);
// 16X16 이미지리스트를 만든다.
m_wndSmallImageList.Create(16,16, FALSE, 1, 2);
m_wndSmallImageList.Add(((CCmmCtrlApp *)AfxGetApp())>LoadIcon(IDI_ICON1));
m_wndSmallImageList.Add(((CCmmCtrlApp *)AfxGetApp())>LoadIcon(IDI_ICON2));
m_wndListCtrl.SetImageList(&m_wndSmallImageList, LVSIL_SMALL);
ISLab ICE HUFS
MFC Tutorial
441
ID_COMM_LIST(2)
// 리스트 컨트롤의 헤더를 초기화한다.
LV_COLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvc.fmt = LVCFMT_CENTER;
// 첫 번째 칼럼을 만든다.
lvc.pszText = (LPTSTR)_T("회사이름
");
lvc.cx = m_wndListCtrl.GetStringWidth(lvc.pszText) + 15;
lvc.iSubItem = 0;
m_wndListCtrl.InsertColumn(0, &lvc);
// 두 번째 칼럼을 만든다.
lvc.pszText = (LPTSTR)_T("제품이름
");
lvc.cx = m_wndListCtrl.GetStringWidth(lvc.pszText) + 15;
lvc.iSubItem = 1;
m_wndListCtrl.InsertColumn(1, &lvc);
ISLab ICE HUFS
MFC Tutorial
442
ID_COMM_LIST(3)
// 세 번째 칼럼을 만든다.
lvc.pszText = (LPTSTR)_T("가격
");
lvc.cx = m_wndListCtrl.GetStringWidth(lvc.pszText) + 15;
lvc.iSubItem = 2;
m_wndListCtrl.InsertColumn(2, &lvc);
// 네 번째 칼럼을 만든다.
lvc.pszText = (LPTSTR)_T("수량
");
lvc.cx = m_wndListCtrl.GetStringWidth(lvc.pszText) + 15;
lvc.iSubItem = 3;
m_wndListCtrl.InsertColumn(3, &lvc);
// 첫 번째 항목을 리스트컨트롤에 붙인다.
int nActualIndex;
LV_ITEM lvItem;
lvItem.mask = LVIF_TEXT | LVIF_IMAGE;
lvItem.state = lvItem.stateMask = 0;
lvItem.iImage = lvItem.lParam = 0;
ISLab ICE HUFS
MFC Tutorial
443
ID_COMM_LIST(4)
lvItem.iItem = m_wndListCtrl.GetItemCount() + 1;
lvItem.iSubItem = 0;
lvItem.pszText = _T("삼성");
nActualIndex = m_wndListCtrl.InsertItem(&lvItem);
lvItem.mask = LVIF_TEXT;
lvItem.iImage = -1;
lvItem.iItem = nActualIndex;
lvItem.iSubItem = 1;
lvItem.pszText = _T("매직 스테이션");
m_wndListCtrl.SetItem(&lvItem);
lvItem.iItem = nActualIndex;
lvItem.iSubItem = 2;
lvItem.pszText = _T("2,500,000");
m_wndListCtrl.SetItem(&lvItem);
ISLab ICE HUFS
MFC Tutorial
444
ID_COMM_LIST(5)
lvItem.iItem = nActualIndex;
lvItem.iSubItem = 3;
lvItem.pszText = _T("3,000");
m_wndListCtrl.SetItem(&lvItem);
// 두 번째 항목을 리스트컨트롤에 붙인다.
lvItem.mask = LVIF_TEXT | LVIF_IMAGE;
lvItem.state = lvItem.stateMask = 0;
lvItem.iImage = lvItem.lParam = 0;
lvItem.iItem = m_wndListCtrl.GetItemCount() + 1;
lvItem.iSubItem = 0;
lvItem.pszText = _T("끝내기");
nActualIndex = m_wndListCtrl.InsertItem(&lvItem);
m_bListCtrl = TRUE;
}
ISLab ICE HUFS
MFC Tutorial
445
SetImageList
• 두번째 인자
– LVSIL_NORMAL 큰 아이콘을 갖는 image list
– LVSIL_SMALL
작은 아이콘을 갖는 image list
– LVSIL_STATE
상태를 나타내는 아이콘을 갖는 image list
ISLab ICE HUFS
MFC Tutorial
446
헤더
• LV_COLUMN을 초기화해서 InsertColumn 함수를 호출
typedef struct _LV_COLUMN {
UINT mask;
int fmt; // 정렬방식 : LVCFMT_LEFT, LVCFMT_RIGHT,
//
LVCFMT_CENTER
int cx;
LPSTR pszText;
int cchTextMax;
int iSubItem;
} LV_COLUMN
• mask
LVCF_FMT
LVCF_SUBITEM
LVCF_TEXT
LVCF_WIDTH
fmt 필드를 사용할 것이다
iSubItem 필드를 사용할 것이다.
pszText 필드를 사용할 것이다.
cx 필드를 사용할 것이다.
ISLab ICE HUFS
MFC Tutorial
447
항목
• LV_ITEM 스트럭처를 초기화 한 다음 InsertItem 함수 호
출
• 부항목은 InsertItem 함수의 리턴값(nActualIndex)을 갖
고 LV_ITEM 스트럭처를 초기화한 다음에 SetItem 함수
호출
• 원하는 부항목 수만큼 반복
ISLab ICE HUFS
MFC Tutorial
448
LV_ITEM(1)
typedef struct _LV_ITEM {
UINT mask;
int iItem;
int iSubItem;
UINT state;
UINT stateMask;
LPTSTR pszText;
int cchTextMax;
int iImage;
// index of the list view item’s icon
LPARAM lParam; // 32-bit value to associate with item
} LV_ITEM;
ISLab ICE HUFS
MFC Tutorial
449
LV_ITEM(2)
• mask
LVIF_TEXT
LVIF_IMAGE
LVIF_PARAM
LVIF_STATE
pszText 필드를 사용할 것이다.
iImage 필드를 사용할 것이다.
lParam 필드를 사용할 것이다.
state 필드를 사용할 것이다.
• iItem : list view control의 몇번째 항목인가
• iSubItem : 몇번째 부항목인가(0부터 시작)
• state : stateMask 필드와 같이 사용
– LVIS_CUT, LVIS_DROPHILITED, LVIS_FOCUSED,
LVIS_SELECTED
– 항목의 외양을 나타냄
ISLab ICE HUFS
MFC Tutorial
450
LV_ITEM(3)
• pszText : 항목의 텍스트
• cchTextMax : pszText 필드의 버퍼 크기
• iImage : image list의 아이콘의 인덱스(-1이면 사용안함)
– 만일 이 값이 I_IMAGECALLBACK 이면 디스플레이 할 순간에 부
모 윈도우로 LVN_GETDISPINFO notification message가 보내진
다.
ISLab ICE HUFS
MFC Tutorial
451
실행 모습
ISLab ICE HUFS
MFC Tutorial
452
List View의 Notification Code
LVN_BEGINDRAG
LVN_BEGINRDRAG
LVN_BEGINLABELEDIT
LVN_ENDLABELEDIT
LVN_DELETEITEM
LVN_KEYDOWN
LVN_COLUMNCLICK
LVN_DELETEALLITEMS
LVN_INSERTITEM
LVN_ITEMCHANGING
LVN_ITEMCHANGED
왼쪽 마우스버튼을 이용해 드래그 작업이 시작
할 때 발생한다.
오른쪽 마우스버튼을 이용해 드래그 작업이 시
작할 때 발생
레이블 편집이 시작될 때 발생
레이블 편집이 끝날 때 발생
항목이 삭제될 때 발생
키가 눌렸을 때 발생. 이는 리스트뷰 컨트롤이
입력 포커스를 갖고 있을 때만 발생
리스트뷰 컨트롤의 헤더가 클릭되었을 때 발생
모든 항목이 삭제되었을 때 발생
새로운 항목이 삽입되었을 때 발생
현재 선택된 항목이 다른 항목으로 변경될 때
현재 선택 항목이 다른 항목으로 변경된 다음
발생
ISLab ICE HUFS
MFC Tutorial
453
LVN_ITEMCHANGED 처리
BEGIN_MESSAGE_MAP(CCmmCtrlView, CView)
//{{AFX_MSG_MAP(CCmmCtrlView)
....
//}}AFX_MSG_MAP
ON_CONTROL(ACN_STOP, IDC_ANIMATE, OnAnimateStop)
ON_WM_HSCROLL()
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LISTCTRL, OnListCtrlClick)
END_MESSAGE_MAP()
void CCmmCtrlView::OnListCtrlClick(NMHDR * pNotifyStruct, LRESULT * result)
{
NM_LISTVIEW* pListView = (NM_LISTVIEW *)pNotifyStruct;
if (pListView->iItem == 1)
{
AfxMessageBox("끝이 눌렸습니다.");
}
*result = 0;
}
ISLab ICE HUFS
MFC Tutorial
454
Tree View Control
• 윈도우 스타일
TVS_HASLINES
TVS_LINESATROOT
TVS_HASBUTTONS
TVS_EdITLABELS
듦
각 항목간(부모 자식간)을 선으로 이어준다.
루트를 만들어 최상위 레벨의 항목들과 연결
시켜준다.
각 항목의 좌측에 버튼을 붙여준다.
Tree view control의 레이블을 편집 가능하게 만
ISLab ICE HUFS
MFC Tutorial
455
CTreeCtrl의 멤버함수(1)
InsertItem
DeleteItem
DeleteAllItems
Expand
SelectItem
EditLabel
HitTest
SortChildren
SortChildrenCB
EnsureVisible
GetCount
GetIndent
SetIndent
새로운 항목을 삽입한다.
항목 하나를 삭제한다.
모든 항목을 삭제한다.
주어진 항목의 자식 항목들을 모두 펼친다.
주어진 항목을 현재 선택 항목으로 만든다.
주어진 항목의 레이블을 편집 가능하게 만든다.
주어진 위치에 있는 항목의 핸들을 얻어온다.
주어진 항목의 자식 항목들을 정렬한다.
주어진 항목의 자식 항목들을 정렬한다. 따로 정렬함수를
제공해 주어야 한다.
지정된 항목이 트리뷰 컨트롤 내에서 보이도록 만든다.
항목의 총수를 얻어온다.
부모 항목과 자식 항목 간의 거리를 픽셀단위로 얻어온다.
부모 항목과 자식 항목 간의 거리를 픽셀단위로 설정한다.
ISLab ICE HUFS
MFC Tutorial
456
CTreeCtrl의 멤버함수(2)
GetImageList
SetImageList
ItemHasChildren
GetNextSiblingItem
GetPrevSiblingItem
GetParentItem
GetSelectedItem
GetRootItem
GetItem
SetItem
GetItemText
트리뷰 컨트롤과 관련된 이미지리스트를 얻어온다.
트리뷰 컨트롤과 관련된 이미지리스트를 설정한다.
주어진 항목이 자식 노드를 갖고 있는지 여부를
알려준다.
트리구조에서 주어진 항목과 같은 레벨의 다음 항
목을 얻어준다.
트리구조에서 주어진 항목과 같은 레벨의 이전 항
목을 얻어준다.
트리구조에서 주어진 항목의 부모 항목을 얻음
현재 선택된 항목이 무엇인지 알려준다.
루트항목이 무엇인지 알려준다.
주어진 트리뷰 항목의 속성을 돌려준다.
주어진 트리뷰 항목의 여타 속성을 설정한다.
주어진 트리뷰 항목의 텍스트를 돌려준다.
ISLab ICE HUFS
MFC Tutorial
457
CTreeCtrl의 멤버함수(3)
SetItemText
GetVisibleCount
GetItemImage
SetItemImage
GetItemRect
주어진 트리뷰 항목의 텍스트를 설정한다.
현재 트리뷰 컨트롤에서 보이는 항목의 수를 돌려
준다.
주어진 항목의 이미지가 무엇인지 알려준다.
주어진 항목의 이미지를 변경한다.
주어진 항목을 둘러싸는 사각형이 무엇인지 얻음
ISLab ICE HUFS
MFC Tutorial
458
ID_COMM_TREE(1)
void CCmmCtrlView::OnCommTree()
{
CheckWnd();
InvalidateRect(NULL);
CRect rect;
GetClientRect(&rect);
m_wndTreeCtrl.Create(TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS
| WS_VISIBLE | WS_CHILD, rect, this, IDC_TREECTRL);
m_wndImageList.Create(32, 32, FALSE, 1, 2);
m_wndImageList.Add(((CCmmCtrlApp*)AfxGetApp())->LoadIcon(IDI_ICON1));
m_wndImageList.Add(((CCmmCtrlApp*)AfxGetApp())->LoadIcon(IDI_ICON2));
m_wndImageList.Add(((CCmmCtrlApp*)AfxGetApp())->LoadIcon(IDI_ICON3));
m_wndTreeCtrl.SetImageList(&m_wndImageList, TVSIL_NORMAL);
TV_INSERTSTRUCT
tvs;
ISLab ICE HUFS
MFC Tutorial
459
ID_COMM_TREE(2)
memset(&tvs, 0, sizeof(TV_INSERTSTRUCT));
tvs.hParent = 0;
tvs.hInsertAfter = TVI_SORT;
tvs.item.iImage = 0;
tvs.item.iSelectedImage = 2;
tvs.item.pszText = _T("Tree Parent");
tvs.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
m_treeRoot = m_wndTreeCtrl.InsertItem(&tvs);
tvs.hParent = m_treeRoot;
tvs.hInsertAfter = TVI_SORT;
tvs.item.iImage = 1;
tvs.item.iSelectedImage = 2;
tvs.item.pszText = _T("Tree Child1");
tvs.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
m_wndTreeCtrl.InsertItem(&tvs);
ISLab ICE HUFS
MFC Tutorial
460
ID_COMM_TREE(3)
tvs.hParent = m_treeRoot;
tvs.hInsertAfter = TVI_SORT;
tvs.item.iImage = 1;
tvs.item.iSelectedImage = 2;
tvs.item.pszText = _T("Tree Child2");
tvs.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
m_wndTreeCtrl.InsertItem(&tvs);
m_bTreeCtrl = TRUE;
}
ISLab ICE HUFS
MFC Tutorial
461
SetImageList
• 두번째 인자
– TVSIL_NORMAL
– TVSIL_STATE
항목의 선택시와 보통 때의 모습만을 담고 있은 경우
선택 유무 말고 사용자 나름대로의 기준으로 항목 상태
를 지정하려는 경우
IDI_ICON1
IDI_ICON2
IDI_ICON3
ISLab ICE HUFS
MFC Tutorial
462
실행모습
ISLab ICE HUFS
MFC Tutorial
463
TV_INSERTSTRUCT
typedef struct _TV_INSERTSTRUCT {
HTREEITEM hParent;
// 지금 삽입되는 항목의 부모 항목이 무엇인가
// 나타내는 핸들이 들어가는 곳
// InsertItem 함수를 이용해 항목을 하나 추가
// 하면 그 항목의 핸들이 리턴되는데 그 값이
// hParent와 hInsertAfter 필드에서 사용된다
// 값이 0이거나 TVI_ROOT이면 루트 항목이 됨
HTREEITEM hInsertAfter; // 어느 항목 뒤에 삽입될 것인지 그 항목을 지정
// 여기서 위치는 hParent 필드가 가리키는 항목
// 의 자식 항목에서의 위치를 말함
//
TVI_FIRST 첫번째 항목으로 삽입
//
TVI_LAST
마지막 항목으로 삽입
//
TVI_SORT
삽입되는 항목을 알파벳 순으로
//
정렬하여 삽입한다.
TV_ITEM
item;
} TV_INSERTSTUCT, FAR *LPTV_INSERTSTRUCT;
ISLab ICE HUFS
MFC Tutorial
464
TV_ITEM(1)
typedef struct _TV_ITEM {
UINT mask;
HTREEITEM hItem;
UINT state;
UINT stateMask;
LPSTR pszText;
int cchTextMax;
int iImage;
int iSelectedImage;
int cChildren;
LPARAM lParam;
} TV_ITEM, FAR *LPTV_ITEM;
ISLab ICE HUFS
MFC Tutorial
465
TV_ITEM(2)
• mask
–
–
–
–
–
–
–
TVIF_CHILDREN
TVIF_HANDLE
TVIF_IMAGE
TVIF_PARAM
TVIF_SELECTEDIMAGE
TVIF_STATE
TVIF_TEXT
cChildren 필드를 사용한다.
hItem 필드를 사용한다.
iImage 필드를 사용한다.
lParam 필드를 사용한다.
iSelectedImage 필드를 사용한다.
state, stateMask 필드를 사용한다.
pszText, cchTextMax 필드를 사용한다.
• hItem : 이 스트럭처가 나타내고 있는 항목
– 새로운 항목의 삽입 시에는 0을 지정해야
ISLab ICE HUFS
MFC Tutorial
466
TV_ITEM(3)
• pszText : 항목에 들어갈 텍스트
– LPSTR_TEXTCALLBACK이면 항목의 디스플레이 책임은 부모 윈
도우가 진다. 이때 부모 윈도우에게 TVN_SETDISPINFO 메시지가
넘어간다.
• cchTextMax : pszText 필드가 가리키는 버퍼의 크기
ISLab ICE HUFS
MFC Tutorial
467
TV_ITEM(4)
• iImage : 정상상태에 있을 때에 해당하는 이미지(이미지
리스트에서의 인덱스)
• iSelectedImage : 선택상태에 있을 때에 해당하는 이미지
• cChildren : 자식 항목을 가질 것인지 여부를 지정
– 0 : 자식 항목이 없음
– 1 : 자식 항목이 있음
• lParam : 이 항목과 관련해서 따로 저장하고 싶은 32비트
값을 지정할 때 사용
ISLab ICE HUFS
MFC Tutorial
468
트리뷰의 알림 메시지
TVN_BEGINDRAG
TVN_BEGINRDRAG
TVN_BEGINLABELEDIT
TVN_ENDLABELEDIT
TVN_DELETEITEM
TVN_ITEMEXPANDING
TVN_ITEMEXPANDED
TVN_KEYDOWN
TVN_SELCHANGING
TVN_SELECTED
왼쪽 마우스버튼을 이용해 드래그 작업이 시작할
때 발생한다.
오른쪽 마우스 버튼을 이용해 드래그 작업이 시작
할 때 발생한다.
레이블 편집이 시작될 때 발생
레이블 편집이 끝날 때 발생
항목이 삭제될 때 발생
항목 하나가 펼쳐져야 함을 알리기 위해 발생
항목 하나가 펼쳐졌음을 알리기 위해 발생
키가 눌렸을 때 발생. 이는 트리뷰 컨트롤이 입력
포커스를 갖고 있을 때 발생한다.
현재 선택된 항목이 다른 항목으로 변경될 때 발생
현재 선택된 항목이 다른 항목으로 변경된 다음
발생
ISLab ICE HUFS
MFC Tutorial
469
NM_DBLCLK
BEGIN_MESSAGE_MAP(CCmmCtrlView, CView)
//{{AFX_MSG_MAP(CCmmCtrlView)
....
//}}AFX_MSG_MAP
ON_CONTROL(ACN_STOP, IDC_ANIMATE, OnAnimateStop)
ON_WM_HSCROLL()
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LISTCTRL, OnListCtrlClick)
ON_NOTIFY(NM_DBLCLK, IDC_TREECTRL, OnTreeCtrlDblClick)
END_MESSAGE_MAP()
void CCmmCtrlView::OnTreeCtrlDblClick(NMHDR * pNotifyStruct, LRESULT *
result)
{
HTREEITEM hItem = m_wndTreeCtrl.GetSelectedItem();
if (m_treeRoot == hItem)
AfxMessageBox("루트가 더블 클릭되었군요.");
*result = 0;
}
ISLab ICE HUFS
MFC Tutorial
470