Visual C++ Programming

Slides:



Advertisements
Similar presentations
YES C 제 1 장 C 언어의 개요 1/34 제 1 장 C 언어의 개요 문봉근. YES C 제 1 장 C 언어의 개요 2/34 제 1 장 C 언어의 개요 1.1 프로그램과 C 언어의 특징 1.2 C 언어의 프로그램 구성 1.3 비주얼 C++ 통합 환경 들어가기.
Advertisements

메시지 처리의 기본 개념 메시지 발생된 이벤트의 종류와 정보를 전달하는 일종의 상수 값 윈도우 프로그래밍 가장 중요한 것은 메시지를 처리하는 것 윈도우 시스템 Application 이벤트 발생 메시지 전송 메시지 처리 화면에 출력.
Computer Graphics 윈도우 프로그래밍 김 창 헌김 창 헌. Computer Graphics 2 윈도우 시스템  윈도우  스크린 위에서 독립적으로 움직일 수 있는 사각형 영역  윈도우 시스템  유저와 어플리케이션간의 그래픽 스크린을 통한 인터페이스 를.
CH5 디버그를 해보자 디버그 디버거 : 실행중인 응용 프로그램을 지정한 장소에서 정지하고, 그 시 점에서 변수, 메모리, 콜 스택의 내용을 참조하는것이 가능 Build -> Start Debug -> Go.
CH1 개발 효율이 높은 프로그램 구조
Visual C++ Programming Document/View Architecture
컴퓨터 공학 설계 및 실험 I MFC programming
2장. 윈도우즈 입출력 1/211 1.
3. C++와 객체지향 C++ 코딩 방법 객체 단위로 2 개의 파일 인터페이스 파일 구현파일
03장 영상처리를 위한 Visual C++ 디지털 영상 파일 포맷 MFC 응용 프로그램 마법사를 이용한 MFC 프로젝트 작성
컴퓨터 응용 및 실습 Part1. OOP&Java Programming data type Review
윈도우 운영체제와 윈도우 응용 프로그램의 특징을 이해한다.
C++ Espresso 제1장 기초 사항.
Lecture 2 MFC and Application Frameworks
제1장 윈도우 프로그래밍 1.1 윈도우 프로그래밍의 개념 1.2 윈도우 프로그램의 기본 구조
Visual C++ Programming Document/View Architecture 3
5장. 단축키와 비트맵 윈도우 프로그램에는 화면에서 사용자들의 입력을 받아 들이고 출력을 위한 코드 외 부분이 존재한다. 이 부분을 주로 리소스라고 부르고 이들은 주로 화면에 나타난다. 메뉴, 툴바, 비트맵, 단축키, 대화상자 등이 여기에 속한다. 이 부분들은 우리의 프로그램의.
윈도우의 화면 출력 원리를 이해한다. CDC 클래스를 이용한 화면 출력 기법을 배운다.
제 1 장 영상처리 기초.
2014 ITA 8월 강의 C Programming -1주차- C언어 기초 정대진 ( )
강좌명 : C++프로그래밍 (C++ Programming)
Lab 3 Guide: 교재 4장 대화상자 예제. - 프로파일 입력 ( 쪽)
MFC를 이용한 네트워크게임 졸업 프로젝트 담당 교수 : 김재형 교수님 김 성준 김 민기.
MFC 발전 과정과 주요 특징을 개괄적으로 이해한다.
윤 홍 란 MFC 기초 윤 홍 란
Windows Programming 시작하기
Internet Computing KUT Youn-Hee Han
2주 실습강의 Java의 기본문법(1) 인공지능연구실.
태양계 시뮬레이션 팀 명: 복학생 강유진 박지혜.
인스톨쉴드9 데브스튜디오 사용 매뉴얼 (VB6에서 개발후 배포프로그램 만들기)
졸업작품발표 타자 연습 프로그램 By.. Eunju 담당 교수 : 이형원 교수님 학번 : 이름 : 김은주.
Network Socket Programming
Microsoft Visual C++ 제 1편 입문편 5장. 샘플 프로그램의 사용자화
MFC Application Frameworks (AFX)
MFC 프로그래밍에 관한 팁 / Keyboard
Visual C++ Programming
2장 자바환경과 자바 프로그램 2.1 자바 개발 환경 2.2 자바 통합환경 2.3 자바 응용 프로그램과 애플릿 프로그램
Visual C++ Programming Output and File
Visual C++ Programming Common Controls
Computer Architecture
C++ 프로그래밍 년 2학기 전자정보공학대학 컴퓨터공학부.
Lecture 3 Graphics with GDI
ASP.NET Mobile Controls
C ++ 프로그래밍 시작.
1장. 프로그래밍 언어, C 프로그래밍.
김 정 석 Web Programming 김 정 석
C++ 개요 객체지향 윈도우즈 프로그래밍 한국성서대학교 유일선
운영체제 (Operating Systems)
Visual Basic 기초 1 목표: 컴퓨터기반제어에 관련된 학습을 하기 전에 Visual Basic의 기초를 살펴본다.
1주차: 프로그래밍언어란 무엇인가? C 언어란? C 프로그래밍을 위한 준비
쉽게 풀어쓴 C언어 Express 제4장 변수와 자료형 C Express.
adopted from KNK C Programming : A Modern Approach
컴퓨터의 기초 제 2강 - 변수와 자료형 , 연산자 2006년 3월 27일.
소프트웨어 공학 (Software Engineering)
제 2장 어휘구조와 자료형 토 큰 리 터 럴 주 석 자 료 형 배 열 형.
컴퓨터공학실습(I) 3주 인공지능연구실.
Chapter3 : 객체지향의 개념 3.1 객체지향(object-oriented)과
Chap02 객체 지향 개념 2.1 객체지향(object-oriented)과 절차지향(procedural-oriented)
Lab 9 Guide: 인터넷 프로그래밍 예제 * 일대일 채팅 프로그램 (교재 27장, 쪽)
Chapter 02. 소프트웨어와 자료구조.
C언어 개론.
3장,4장 발표 서정우.
제 7장 이벤트.
Windows 프로그래밍 환경 및 MFC의 구조
컴퓨터 계측 및 실습 C++ 기초 영남대학교 기계공학부.
C.
MFC 응용 프로그램 구조 두 개의 윈도우로 구성된 일반적인 MFC 프로그램 프레임 윈도우
C++ 언어의 특징
MFC 기초 윈도우 응용프로그램 개발 간략한 역사 Microsoft Foundation Classes
제 4장 Visual C++ COM 컴파일러.
Presentation transcript:

Visual C++ Programming 숭실대학교 정보과학대학원 김상일 hava@shinbiro.com

C++ 의 특징 C++ C 함수  연산자의 다중정의 참조자, 클래스 함수, 포인터 구조체, 공용체 풍부한 연산자  C++은 1980년 미국 벨 연구소의 Bjarne Stroustrup 박사에 의해 개발  1980년 발표 당시에는 “C with class” 라는 이름으로 발표  “C++”라는 이름은 1983년부터 사용되기 시작 함수  연산자의 다중정의 참조자, 클래스 함수, 포인터 구조체, 공용체 풍부한 연산자 ⊙ 객체지향 프로그래밍 ⊙ C C++

C++ 의 특징 Bjarne Stroustrup

C++ 의 특징 예약어 기능 class new delete friend inline operator this private protected public virtual 클래스를 정의  선언 메모리 영역을 할당 메모리 영역을 해제 클래스를 다른 클래스  함수의 ”친구”로 선언 인라인 함수를 정의  선언 연산자를 다중정의 해당 클래스 객체 자신을 가리키는 포인터 클래스의 비공개 멤버를 선언 클래스의 보호 멤버를 선언 클래스의 공개 멤버를 선언 클래스의 가상 함수를 선언

C++ 의 특징  I/O 스트림  기존의 표준 C stream인 stdin, stdout, stderr, stdprn 외에도 C++에서는 cout, cin등의 지정된 stream들이 있어 이 stream과 insertor(<<), extractor(>>)함수를 이용한 입출력 방식을 주로 사용.  Insertor(<<)함수를 이용한 출력  cout stream과 insertor함수를 사용할 경우에는 iostream.h 파일을 include 해야 한다. C C++ #include <stdio.h> void main(void) { printf(“Hello World!\n”); } #include <iostream.h> cout << “Hello World!\n”;

C++ 의 특징  변수선언  변수 사용 위치에서 선언하고 선언과 동시에 그 값을 초기화  #include<iostream.h> void main() { int hap=0; for(int i=0; i<=100; i++) hap += i; cout << hap << “\n”; } 상수를 알아서 찾아줌  데이터 항목을 하나 이상 표시 #include<iostream.h> void main(void) int my_int = 5; float my_float = 5.333; cout << "The value of my_int is : " << my_int << ”\n"; cout << "The value of my_float is : " << my_float << ”\n"; }

C++ 의 특징  전역 식별 연산자(::) (Global Scope Resolution Operator) :: 변수명칭 :: 변수명칭 해당 변수는 전역변수임을 의미 #include<iostream.h> int suja=123; void main() { int suja=10; cout << suja << ”\n"; cout << ::suja << ”\n"; }

C++ 의 특징  Extractor(>>)함수를 이용한 입력  cin stream과 extractor함수를 사용할 경우에는 iostream.h 파일을 include 해야 한다.  키보드로 부터 데이터를 입력 #include<iostream.h> void main(void) { int my_int; float my_float; cin >> my_int; cin >> my_float; cout << “my_int = “ << my_int << “\nmy_float = “ << my_float << “\n”; }

C++ 의 특징  new와 delete 연산자 #include<stdio.h> void main(void) { int *i; i = malloc(sizeof(int)); *i = 10; printf(“%d”, *i); free(i); } #include<iostream.h> int *i = new int; //int *i = new int[10]; i=10; // 10개의 배열을 동적으로 할당 cout << i; delete i;

Enumerator  열거형 정의 및 선언법  정의 : 사용자가 정의하는 특별한 명칭을 갖는 정수들의 집합체를 말한다.  선언법 enum [태그명] {열거요소, 열거요소,…}; 예) enum color { black, blue, green, cyan, red }; ( 형틀 정의 ) enum color screen; ( 변수 정의 ) enum color { black, blue, green, cyan, red } screen; enum은 열거형을 나타내는 예약어이다. color은 열거형의 tag명 black, blue, green, cyan, red는 열거요소 screen이라는 열거형은 black, blue, green, cyan, red로 구성된다. 그 외의 요소를 갖게 되면 에러 발생

Enumerator  열거형 선언자  선언자 변수, 배열, 포인터, 함수 등이 올 수 있다.  선언자 변수, 배열, 포인터, 함수 등이 올 수 있다.  일반변수 enum color rainbow; /* color형을 가질 수 있는 변수 */  배열 enum color rainbow[10]; /* 배열의 요소가 color형 변수 */  포인터 변수 enum color rainbow, *rp; rp = &rainbow; /* color형 변수의 주소를 가리키는 color형 포인터 변수 rp */  열거형을 돌려주는 함수 enum color rain(); /* color형을 돌려주는 함수 */

Enumerator  열거형의 특징 ◐ 열거 요소는 내부적으로 정해진 상수로 표현된다. 예) enum color { black, blue, green, cyan, red }; black=0, blue=1, green=2, cyan=3, red=4 ◐ 열거 요소에 부여하는 정수는 임의적이어도 된다. 예) enum color { black=5, blue, green=15, cyan, red=25 }; black=5, blue=6 green=15, cyan=16, red=25로 처리된다. ◐ 열거형 변수에 열거형에 해당하는 정수를 대입할 수 있다. 예) enum color { black=5, blue, green=15, cyan, red=25 } screen; screen=6; /* 열거 요소의 정수값으로 치환 가능 */ screen=25; ◐ 열거형 상수는 기억영역을 확보하지 않는다. 예) enum color { black, blue, green, cyan, red }; black++, &blue, --green ( X ) /* 변수가 아니고 상수이기 때문 */

typedef  typedef와 #define과의 차이점 ◐ 표현상의 순서에 차이가 있다. 예) #define INTEGER int typedef int INTEGER; ◐ #define은 구문표현의 변화이지만, typedef는 의미상의 변화이다. #define INTEGER int 위 선언문은 전처리기가 처리하고 나면 없어지고, INTEGER는 모두 int로 바뀌어서 컴파일된다. ◐ 열거형과 typedef을 이용하여 소스를 작성하면 더욱 보기 쉽고 이해하기 쉬운 프로그램을 작성할 수 있다.

Reference  레퍼런스 방식의 함수호출  C++는 기본적으로 파라미터를 값(value)이 아닌 레퍼런스로 보내도록 함수를 설정해 준다.  파라미터의 명칭은 &를 선언하기만 하면 된다. #include<iostream.h> void load_a(char &the_char); // C : void load_a(char *the_char); void main() { char my_char='z'; load_a(my_char); // C : load_a(&my_char); cout << my_char << ”\n"; } void load_a(char &the_char) // C : void load_a(char *the_char) the_char = 'a'; // C : *the_char = 'a';

C++ 의 특징 void func(int inja1=1, inja2=100)  함수의 내정인자 { 함수의 실제내용; } #include <iostream.h> void func(int a=10, int b=20, int n=5) { for(int i=a; i<=b; i+=n) // a  b 사이의 정수를 n간격으로 표시 cout << i; cout << “\n”; } void main() func(); // func(10, 20, 5)와 동일 func(5); // func(5, 20, 5)와 동일 func(5, 30); // func(5, 30, 5)와 동일 func(30, 40, 2);

객체지향 프로그래밍(Object-Oriented Programming)  객체지향 프로그래밍(OOP)은 구조적 프로그래밍(Structured Programming)의 개발 이래로 소프트웨어 기술 발전 사에서 매우 큰 혁명으로 여겨지고 있다. OOP에 관한 여러 가지 정의와 해석이 존재하지만, 일반적으로 추상화(Data Abstraction), 상속성(Inheritance) 및 다형성(Polymorphism)등이 그 주요 특성으로 알려져 있다.  데이터 추상화 (Data Abstraction)  OOP에서는 데이터와 그 데이터를 처리하는 함수(Function)들이 하나의 독립된 객체에 캡슐화(Encapsulation)되어있다. 즉, OOP에서는 데이터 추상화를 클래스라 불리우는 코드 단위로 사용하여 표현하는데, 하나의 클래스는 유사한 속성과 기능을 가지는 여러 개의 객체들을 나타낸다.  클래스가 단순한 데이터 구조(Data Structure)와 다른 점은 필요한 데이터 구조의 정의뿐 아니라, 이 데이터 구조 위에서 작동하는 프로그램 코드, 즉, 함수들도 함께 가지고 있다는 점이다.  데이터 추상화는 여러 장점이 있지만, 무엇보다도 한 객체가 가지고 있는 데이터나 값은 그 객체만이 검색, 수정할 수 있다는 점이다.  이를 정보 감춤(Information Hiding)이라고 표현하는데, 이런 식으로 개발된 프로그램은 모듈간의 간섭이 없어 나중에 코드를 수정하거나 추가할 때 유리하다.

객체지향 프로그래밍(Object-Oriented Programming)  상속성 (Inheritance)  OOP에서는 새로운 클래스를 정의할 때, 이미 만들어 놓은 클래스의 속성(데이터의 구조와 함수들의 정의)을 상속 받고 필요한 부분만 추가할 수 있는데, 이를 클래스의 상속성이라 한다.  이때 새로 생긴 클래스는 Sub-Class, 이전의 모태가 된 클래스를 Super-Class라 한다.  상속성을 사용하면 유사한 클래스들 간의 공통된 속성을 하나의 Super-Class에 정의하여 Sub-Class가 공유할 수 있으므로 전체 코드 크기도 줄고 프로그램 구성도 간단해진다.  C프로그래머들이 C++프로그래밍을 접할 때 이 상속성을 설계하는데 종종 어려움을 겪는데, 이는 주어진 문제를 객체지향적으로 분석 (Object-Oriented Analysis)하는 연습을 통하여 해결할 수 있다.

객체지향 프로그래밍(Object-Oriented Programming)  다형성(Polymorphism)  대부분의 구조적 프로그래밍 언어에서는 하나의 함수가 하나의 기능을 가진다.  그러나 OOP에서는 하나의 함수가 사용되는 상황(Context)에 따라서 여러 가지 기능을 가질 수 있다.  즉, 클래스의 상속성 구조에서 여러 개의 클래스 사이에 동일한 이름의 함수들이 정의될 수 있고, 각 함수의 기능(Behavior)은 소속된 클래스의 성격과 용도에 맞게 세분화 될 수 있다.  예로서 그래픽 어플리케이션에서 원, 사각형, 자유형 등 여러 가지 그림 객체를 움직이는 MOVE라는 함수를 생각할 수 있다.  이때 OOP에서는 하나의 MOVE라는 이름의 함수를 종류별로 정의하고, 각 형태의 그림 객체마다 이를 옮기는 최적의 방법으로 각 함수를 정의할 수 있다.

객체 (Object)  소프트웨어에 대한 객체지향적 시각  객체 + 객체 = 프로그램  데이터 + 함수 = 객체  정의  특정 데이터와 관련된 함수들을 가지는 프로그램 모듈  실세계 영역에 있는 정보, 물건, 사물, 개체, 개념 등을 표현함  객체 = 속성(Attributes) + 행위(Behaviors) = 변수(Variables) + 함수(Methods)  자동차  객체의 특징  캡슐화 (Encapsulation)  정보은폐 (Information Hiding)

캡슐화 (Encapsulation)  특정 데이터와 관련된 함수들을 한 덩어리로 묶는다.  문제영역의 개념화 및 추상화를 효과적으로 지원함.  C++ 의 캡슐화 장치 class Point { int xPosition; int yPosition; colorType color; public: void move(int x, int y); void setColor(colorType c);  } 데이터 관련 함수들

정보 은폐 (Information Hiding)  캡슐내부의 정보를 외부에 감추는 것을 의미한다.  캡슐화는 관련된 것들 주변에 캡슐을 씌우는 것.  처리하려는 데이터 구조와 함수에 사용된 알고리즘 등을 외부에서 직접 접근하지 못하도록 한다.  캡슐화 그 자체가 캡슐 안의 내용들이 외부에 보이지 않는 것을 의미 하지는 않는다.  콘택600  인터페이스  외부 객체들이나 프로그램들이 접근할 수 있는 데이터와 함수들을 정의하여  외부에서 이 인터페이스를 통해서 정보를 검색하거나 함수를 실행하도록 한다.

setColor (colorType); 정보 은폐 (Information Hiding)  C++ 의 인터페이스 장치 class Point { int xPosition; int yPosition; colorType color; public: void move(int x, int y); void setColor(colorType c);  } 관련된 함수들 데이터 xPosition: 10 yPosition: 20 color: blue move (int, int); setColor (colorType);  외부 인터페이스 블랙박스

객체 (Object)  정의  객체란 캡슐화와 정보은폐의 개념을 프로그램에서 효과적으로 사용할 수 있도록 한 장치임.  객체의 조건  상태(State)를 가져야 한다.  행위(Behavior) 를 가져야 한다.  고유의 식별자(Identity)를 가져야 한다.

복합 객체 (Composite Object)  한 객체가 다른 객체들을 포함하고 있는 경우  작은 객체를 조합하여 보다 큰 객체로 조립해 가는 과정  Point and Circle  class Point { int xPosition, yPosition; public: void move(int x, int y); }  class Circle { Point center; int radius; void move(int x, int y) { center.xPosition += x; // Error center.yPosition += y; // Error center.move(x, y); // Okay }}

메시지 (Message)  객체 접근 방법  한 객체는 다른 객체에게 메시지를 보내어 교류한다.  메시지 교환 (Massage Passing)  메시지 교환 (Message Passing)은 객체들 사이에 정보를 교환할 수 있는 유일한 수단이다.  한 객체가 다른 객체의 함수를 부르는 과정을 메시지 교환(Message Passing) 이라고 한다.  메시지 형태  수신객체, 함수명, 함수의 Arguments  수신객체는 이 메시지를 받을 객체를 나타낸다.  <receiver>.<operation_name> <arguments>  myPoint.move(10, 5); myPoint.setcolor (blue);

클래스 (Class)  개념  클래스는 객체의 타입(Object Type)이다.  정의  클래스는 유사한 객체들이 갖는 공통된 데이터와 함수들을 정의한 객체의 기본 규격(Specification)이다.  유사한 객체들의 타입을 정의한다.  인스턴스(Instance)  어떤 클래스에서 생성된 객체 혹은 한 클래스에 속하는 각각의 객체.  한 클래스에 속한 모든 객체들은 같은 종류의 데이터와 함수들을 가진다.  생성된 각 객체는 클래스에서 정의된 변수들에 대한 메모리를 할당 받는다.

클래스 (Class)  직원 클래스 char *name; positionType position; int salary; class Employee { char *name; positionType position; int salary; phoneNumberType phoneNumber;  public: void promote(positionType newPosition); void changeSalary(int newSalary); }  Employee YoungHee(); 혹은 Employee* YoungHee = new Employee();

상속 (Inheritance)  개념  한 클래스가 여러 종류의 서브 클래스로 세분화된다.  그래픽 클래스는 선, 다각형, 원 등으로 세분화  학생 클래스는 학부학생과 대학원생등으로 세분화  기존의 클래스 위에 필요한 데이터와 함수들을 추가하여 새로운 클래스를 만드는 경제적인 방법.  재사용성 증대  용어(Terminology)  슈퍼 클래스 (Super class, Base class)  서브 클래스 (Subclass, Derived class, Extended class)  클래스 상속 구조 (Class Inheritance Hierarchy)

상속 (Inheritance)  대학 인사관리 시스템 Person Employee Staff Temporary Faculty Student  class Student : public Person{…}

다중 상속 (Multiple Inheritance)  다중 상속  한 클래스가 여러 개의 슈퍼클래스를 가지는 경우  여러 슈퍼 클래스들로부터의 재사용  class Graduate : public Student, public Faculty{…} Person Employee Staff Temporary Faculty Student Graduate Visiting Faculty Temp.Staff UnderGrad

추상 클래스 (Abstract Class)  서브 클래스들의 공통된 특성을 추출하여 묘사하기 위한 클래스  Printer Software  모든 종류의 프린터가 공통으로 가지는 특성을 추상클래스에 정의  변수 : 프린터의 상태, 속도  함수 : print();  프린트마다 인쇄하는 방법이 다르므로 이 추상 클래스 안에서는 Print라는 함수를 완전히 구현할 수 없다.  실제 구현은 여러 서브클래스에서 각 프린터 종류에 맞게 하면 된다.

추상 클래스 (Abstract Class)  추상 클래스 ‘Printer’ (추상클래스) Printer 도트 매트릭스 프린터 레이저 잉크젯

다형성 (Polymorphism, 다양한 형태)  복수의 클래스가 하나의 메시지에 대해 각 클래스가 가지고 있는 고유한 방법으로 응답할 수 있는 능력.  별개로 정의된 클래스들이 같은 이름의 함수를 별도로 가지고 있어 하나의 메시지를 각기 다른 방법으로 해석 하여 필요한 함수를 수행할 수 있는 것을 말한다.  가상함수(Virtual Function)를 사용하여 구현  Compile time Polymorphism  함수, 연산자의 Overloading  Run time Polymorphism  가상함수를 이용한 함수의 Overriding

다형성 (Polymorphism)  Printer 함수의 다중정의 텍스트 파일 print(); 포맷 파일 그래픽 파일  파생클래스에서의 멤버 접근 권한 private protected public 항상 접근할 수 없다 private로 상속받으면 protected로 상속받으면 public로 상속받으면

Class Library  Template (템플릿)  템플릿은 임의의 데이터 유형에 재사용할 수 있는 범용 코드를 허용함으로써 클래스 계열이 컴파일러에 의해 어떻게 생성되는가를 정의하는 역할을 한다.  템플릿은 컴파일할 때에 클래스 그룹들을 컴파일러가 어떻게 구성해야 하는 가를 정의하며, 필요할 때마다 특정 유형을 만드는 데 사용할 수 있는 범용 정의를 컴파일러가 만들도록 한다.  템플릿은 여러 개의 데이터 유형에 적용할 수 있는 범용 코드를 작성할 수 있기 때문에 작업을 더 쉽게 수행할 수 있다.  STL(Standard Template Library, 표준 템플릿 라이브러리)  STL은 뛰어난 융통성과 훌륭한 성능을 바탕으로 많은 곳에 적용할 수 있는 범용 데이터 구조와 알고리즘을 제공함으로써 완전히 재사용이 가능한 범용 프로그래밍을 가능하게 하고 있다.  마이크로소프트 비주얼 C++과 볼랜드 C++은 자신의 가장 최신 컴파일러 버전에 STL 버전들을 구현하고 있다.

“If you can dream it, you can do it” 꿈꿀 수 있다면, 달성이 가능하다

CHAPTER 1 마이크로소프트 윈도우와 Visual C++

CHAPTER 1  윈도우 그래픽 디바이스 인터페이스(GDI)  장치 독립적인 인터페이스를 제공.  사용자는 디바이스 컨텍스트(device context)라는 데이터 구조체를 참조하는 GDI 함수를 호출한다.  윈도우는 물리적인 장치에 디바이스 컨텍스트 객체를 맵핑하고, 적합한 입출력 명령을 보낸다.  리소스 기반 프로그래밍  리소스 파일에는 Bitmap, Icon, Menu, Dialog Box, String 등이 포함된다.

CHAPTER 1  윈도우에서 제공되는 리소스 데이터  Accelerator 사용자가 빠르게 명령을 호출할 수 있도록 해주는 단축키.  Bitmap 그래픽 이미지를 이진 파일의 형식으로 변환하여 사용되는 이미지.  Cursor 스크린 상에서 마우스의 현재 위치를 나타내 주는 3232 Pixel 크기의 비트맵.  Dialog Box  Font  Icon  Menu  String Table 스트링은 단순한 문자열들의 집합. 주로 메뉴, 다이얼로그 박스, 에러 메시지를 나타내기 위해 사용된다  User-defined Resource 프로그래머가 응용 프로그램에 지원하기 위해 자신만의 독특한 데이터를 정의한 것을 말한다.

CHAPTER 1  프로그램 코드 *.c OR *.cpp  리소스 데이터 *.rc  리소스 데이터는 응용 프로그램 안에서 공통적으로 사용되는 정적 데이터들의 집합.  리소스 편집기(App Studio)를 사용하여 프로그램에 필요한 리소스 데이터를 작성한다.  *.rc 리소스 컴파일러 Link *.EXE  리소스 데이터는 일반적으로 프로그램의 .EXE 파일에 포함되어 있지만, 보통의 프로그램 데이터 세그먼트에 존재하지 않고 별도의 장소에 보관된다.  리소스 데이터는 필요로 할 때만 메모리에 적재된다.  대부분의 리소스 데이터는 읽기 전용 데이터이다.  Visual C++의 요소(Components)  개발시스템  C스타일의 Win32 프로그램을 작성하는 방법.  C++과 MFC를 사용하는 방법.

CHAPTER 1 ◐ 도스상에서의 실행 파일 생성 과정 ◑ Source Code (Sample.cpp) C++ Compiler Object File (Sample.obj) Linker Executable Program (Sample.exe)

CHAPTER 1 ◐ 윈도우 상에서의 실행 파일 생성 과정 ◑ Developer Studio Linker Compiler Resource Compiler Source files Windows header Windows, runtime, and MFC libraries OBJ files Runtime header Executable (EXE) Resource file (RES) Bitmaps, icons, and other resources Resource.h Resource script file(RC) MFC header Resource compilation Code compilation

CHAPTER 1  Microsoft Developer Studio97과 구현과정  Project  서로 연관되어 있는 파일들의 집합  이 파일들이 컴파일과, 링크 과정을 거쳐 실행 가능한 프로그램이나 DLL로 만들어진다.  Make file  컴파일러 옵션, 링크 옵션 저장.  소스 파일간의 상호 연관성을 표현.  Visual C++ 4.0 : (.mak)  Visual C++ 5.0 : (.dsp)  기존의 프로젝트에 대한 작업  Developer Studio에서 워크 스페이스 파일(.dsw)을 열고난 후 작업.

CHAPTER 1 파일(확장자) 설명 APS BSC CLW DSP DSW MAK NCB OPT PLG CPP H 리소스 뷰 지원 소스 브라우저 정보 파일 클래스 위저드 지원 프로젝트 파일 * 워크 스페이스 파일 * 외부 메이크 파일 클래스 뷰 지원 워크스페이스 환경설정 보유 빌드 로그 파일 소스 파일 헤더 파일

CHAPTER 1  AppWizard (자동 코드 생성기)  VC++의 CASE(Computer-Aided Software Engineering) 도구  AppWizard (자동 코드 생성기)  프로그램의 틀을 자동적으로 생성해 주는 도구  AppStudio (Resource Editor, 리소스 편집기)  자원(Resource)들을 편집하는 도구  사용자 인터페이스 요소들(메뉴, 다이얼로그, 단축키 등)을 시각적으로 디자인할 수 있도록 도와 준다.  ClassWizard (자동 코드 생성기)  AppStudio에서 시각적으로 디자인된 요소들을 실제 프로그램 코드와 연결시키는 작업을 한다.  새로운 클래스를 정의한다.

CHAPTER 1  C/C++ Compiler  Visual C++ 컴파일러는 C 소스 코드와 C++ 소스 코드의 확장자에 따라, 프로젝트 파일에 설정된 소스 코드를 어떠한 방식으로 컴파일 할 것인가를 결정하기 때문에 C 구조로 작성된 C 소스 코드와 C++ 구조로 작성된 C++ 소스 코드를 모두 컴파일 할 수 있다.  Resource Compiler  RC파일을 컴파일해서 링커시에 필요한 .res 파일을 생성한다.  .rc : 텍스트 파일  .res : 이진파일  Linker  링커는 컴파일러로 만들어진 .obj 파일과 .res 파일을 읽고, LIB 파일과 결합하고, DLL 과 연결시켜 EXE 파일을 작성한다.

CHAPTER 1  Debugger  중단점(BreakPoint)을 설정하여 해당 부분에 멈추거나, 한 문장씩 코드를 실행하며 값들을 추적해 볼 수 있다.  디버깅하기 위해서는 컴파일러, 링커 옵션에서 디버깅 정보를 생성 해내도록 설정해야 한다.  Debug 모드 프로그램 코드를 생성하고 이것을 실행 파일로 만드는 Build 과정에서 디버깅 정보가 실행 파일에 포함되도록 한다. 그러나 실행 파일에 디버깅 정보가 포함되기 때문에 실행 파일이 원래보다 크게 생성된다.  Release 모드 일반적으로 정상적으로 실행될 수 있는 프로그램을 완성하기 전까지는 디버깅을 해야 하므로 Debug 모드에서 빌드 과정을 수행하고, 완전한 프로그램이 완료되었을때는 Release 모드로 전환하여 실행 파일을 생성한다.

CHAPTER 1  Source Browser  파일 수준이 아닌 클래스나 함수 수준에서 어플리케이션을  윈도우 진단 도구 (Windows Diagnostic Tools)  Spy++ : 윈도우 메시지를 감시 DevStudio\Vc\bin\Spyxx.exe  MFC Tracer : 응용 프레임워크 진단 매크로 DevStudio\Vc\bin\Tracer.exe  Source Browser  파일 수준이 아닌 클래스나 함수 수준에서 어플리케이션을 분석하거나 편집할 수 있다.  Definitions and References (정의와 참조)  Call Graph/Caller Graph (함수의 호출관계도)  Derived Class Graph/Base Class Graph (클래스 계층도)  File Outline (파일 개요)

CHAPTER 1  Online Help  Developer Studio 97에는 HTML에 기초를 둔 도움말 시스템이 내장되어 있다.  설명서 방식 : Help - Contents를 선택하면 Workspace window가 InfoView모드로 전환된다.  Topic별 방식 : Help - Search를 선택하면주제와 항목이 표시된다.  단어별 방식 : Help - Search - Query tab - 단어입력  F1이용 : 커서를 원하는 함수, 클래스 이름으로 이동해서 F1키를 누른다.

CHAPTER 1  컴포넌트 갤러리(Component Gallery)  서로 다른 프로젝트간에 소프트웨어 컴포넌트를 공유할 수 있다.  ActiveX 컨트롤 Visual C++ 4.0 : OLE Control(OCX)  C++ 소스 모듈 리소스나 소스파일을 추가할 수 있다.  Developer Studio 컴포넌트 프로젝트에 특정 기능을 추가할 수 있는 툴을 포함하고 있다.  Microsoft Foundation Class Library 버전 4.21  어플리케이션 프레임워크를 정의하는 라이브러리.  ActiveX Template Library(ATL)  MFC와는 분리된 ActiveX 컨트롤을 생성하기 위한 툴.

MFC (Microsoft Foundation Class)  Microsoft가 자체적으로 개발한 윈도우용 C++ 프로그램 라이브러리 C++ Application MFC Windows API ◐ 윈도우 API를 캡슐화한 MFC ◑

MFC (Microsoft Foundation Class)  장점  효율성(Efficiency)  안전성(Safety)  확장성(Extensibility) 새로운 기능이나 객체 안에 내용의 추가가 쉽도록 만들자는 개념  재사용성(Reusability) 이미 개발된 코드를 다른 필요한 곳에 부품처럼 재사용이 가능하도록 하여 소프트웨어의 생산성을 향상시킴  유지보수성(Maintainability) 프로그램에 에러가 발생하거나 새로운 운용 환경에 적응시킬 때, 혹은 시스템의 기능을 개선하고자 하는 등 프로그램에 변경이 가해져야 하는 경우, 프로그램을 수정하기 용이한 정도  이식성(Portability) 서로 다른 기종 간에 호환성이 실현되는 것으로서 그 보다는 좀더 강한 의미. 프로그램 등의 변동 없이 바로 어느 한 기종에서 다른 기종으로 옮겨서 사용하는 것이 가능한 것. 어느 한 컴퓨터 환경에서 다른 컴퓨터 환경으로 옮겨 갈 때 변경의 정도가 적을수록 이식성이 높은 것이다.

MFC  윈도우와 관련된 클래스  Window management : 윈도우 관리  Graphic Device Interface(GDI) : 그래픽 장치 인터페이스  Multiple Document Interface(MDI) : 다중 문서 인터페이스  Menus : 메뉴  Dialog boxes : 대화상자  Windows controls : 윈도우 컨트롤  Windows common dialogs : 윈도우용 일반 다이얼로그  OLE(Object Linking & Embedding) : 오브젝트 연결과 삽입  Application services : 어플리케이션 서비스

MFC  일반적인 목적의 클래스  Run-Time Type Information : 실행 타입 정보  Object Persistence : 객체 보존성  Collection Classes : 집합체 클래스  Strings : 문자열  Files : 파일  Time and Date : 시간과 날짜  Exception Handling : 예외 처리

MFC  구조적인 클래스  Commands : 명령 관련 클래스들  Documents and Views : 도큐먼트와 뷰  Printing and Print Preview : 프린트와 프린트 미리 보기  Dialog Data Exchange and Validation(DDX/DDV) : 다이얼로그 데이터 교환, 확인  Context-Sensitive Help : 도움말

MFC  비주얼 클래스  Form View : 형태 뷰  Edit View : 편집 뷰  Scrolling View : 스크롤 뷰  Splitter Window : 분할 뷰  Toolbars and Status bar : 툴 바와 상태 바  Dialog Bar and other Control Bars : 다이얼로그 바와 다른 컨트롤 바  VBX Controls : VBX 컨트롤

MFC  데이터 베이스 클래스  Database Engine classes : 데이터베이스 엔진 클래스  Record Field Exchange(RFX) : 레코드 필드 교환  Record View : 레코드 뷰  OLE 클래스  Visual Editing servers : 비주얼 편집 서버  Visual Editing containers : 비주얼 편집 컨테이너  Drag and Drop Structured Storage : 끌어다 놓기  OLE Automation servers : OLE 자동화 서버  OLE Automation clients : OLE 자동화 클라이언트

MFC  유저 인터페이스 클래스  Enhanced toolbars : 기능이 추가된 툴 바  Miniframe windows : 미니프레임 윈도우  Tabbed dialogs : 탭 다이얼로그(탭에 의해 포커스 이동)  Win32에 대한 지원  New Win32 APIs : Win32 API 함수들 지원  Multithreading : 멀티 Thread 관련된 클래스  Unicode support : 유니코드 지원  Shared 32-bit DLLs : 공유된 32비트 DLL

MFC  MFC 3.1과 3.2에서 포함된 내용  Windows 95 Common Controls : 윈도우 95 컨트롤  Simple MAPI : 단순한 MAPI  Windows Sockets : 윈도우 소켓  Swap-tuned DLL versions : 최적화된 DLL 지원  MFC 4.0에 포함된 내용  Containment of OLE Controls : OLE 컨트롤  DAO(Data Access Objects) : MFC 자체 데이터베이스 엔진  Simplified Windows 95 Common Controls : 간단한 윈도우95 공통 컨트롤  Windows 95 Common Dialogs : 윈도우95 일반 다이얼로그  Thread synchronization Objects : 스레드 동기화 오브젝트

◐ MFC 클래스 라이브러리 마인드 맵(Mind Map) ◑ CView ◐ MFC 클래스 라이브러리 마인드 맵(Mind Map) ◑ CObject CCmdTarget CGdiObject CDC CScrollView CFormView CRecordView CEditView CWinApp CDocTemplate CFrameWnd CWnd CSingleDocTemplate CMultiDocTemplate CClientDC CWindowDC CPaintDC CMetaFileDC CPen CBrush CFont CBitmap CPalette CRgn GetEditControl GetPrinterFont GetSelectedText SetPrinterFont SetTabStops 

MFC  기본 클래스(CObject)  거의 대부분의 클래스가 이 클래스로부터 파생되었다.  기본 클래스는 데이터를 직렬화(Serialize)하고 Run-time 클래스 정보를 얻어내거나 Debugging시에 출력 진단의 역할을 담당한다.  윈도우 어플리케이션 구조 클래스  MFC에서 중요한 클래스들은 모두 포함되어 있다.  CWinApp, CWnd, CDocument, CView 등이 있다.  윈도우 어플리케이션 프로그램의 뼈대 역할을 하면서 기본적인 기능을 수행한다. 1. 윈도우 어플리케이션 클래스  CWinApp : 윈도우 어플리케이션 오브젝트를 생성시키는 기본 클래스. 어플리케이션 프로그램을 초기화 시키고, 실행하거나 종료하는 기능을 한다.

MFC  윈도우 어플리케이션 구조 클래스 2. 명령 관련(Command-Related) 클래스  CCmdTarget : 윈도우 메시지를 받고, 응답하는 오브젝트 클래스들의 기본클래스  CCmdUI : 메뉴 또는 컨트롤바와 같은 오브젝트를 업데이트 하는데 쓰인다. 예) 오브젝트의 상태 변경(enable/disable, check/uncheck) 3. 도큐먼트와 뷰 클래스  CDocTemplate : 도큐먼트 템플릿에 대한 기본 클래스  CSingleDocTemplate : SDI 도큐먼트 템플릿  CMultiDocTemplate : MDI 도큐먼트 템플릿  CDocument : 어플리케이션이 지정한 도큐먼트의 기본(Base) 클래스 사용자의 도큐먼트들은 이CDocument 클래스로부터 상속받아 사용한다.  CView : 도큐먼트 안에 있는 데이터를 뷰를 통하여 화면에 보일 수 있도록 하는 클래스 사용자의 View들은 이CView 클래스로부터 상속받아 사용한다.  CPrintInfo : 프린트 관련 정보들을 저장하고 다루는 구조체  CCreateContext : CCreateContext는 도큐먼트, 뷰, 프레임 윈도우, 도큐먼트 템플릿에 대한 포인터를 지정하고 있는 구조체

◐ Visual Object Class Mind Map ◑ MFC CStatic CComboBox CObject CCmdTarget CMenu CDC CGdiObject CDialog CEdit CFrameWnd CControlBar CWnd CView ◐ Visual Object Class Mind Map ◑ CClientDC CWindowDC CPaintDC CMetaFileDC CPen CBrush CFont CBitmap CPalette CRgn CFormView CScrollView CEditView CMDIFrameWnd CMDIChildWnd CToolBar CStatusBar CDialogBar CFileDialog CColorDialog CFontDialog CPrintDialog CFindReplaceDialog CButton CListBox CSplitterWnd CVBControl CScrollBar

MFC  Visual Objects 관련 클래스 1. CWnd 클래스  CWnd : 모든 윈도우에 대한 기본 클래스로서 기본적인 SDK 함수들을 MFC에 맞도록 캡슐화(Encapsulation)시켜 놓았다.  CFrameWnd : 메인 프레임에 관한 윈도우 클래스 CMDIFrameWnd : MDI 프로그램에서 사용되는 메인 프레임 윈도우 클래스 CMDIChildWnd : MDI 프로그램의 자식(Child) 윈도우 클래스 2. CView 클래스  CView : 도큐먼트 안에 있는 데이터를 화면에 출력하는 역할을 하는 클래스  CScrollView : CView의 기본 특성 외에 화면 스크롤이 가능한 뷰이다.  CFormView : 다이얼로그 리소스에 기반 하여 쉽고 빠르게 구현할 수 있는 클래스 다이얼로그 리소스 안에 출력 형태가 정의되어 있다.  CEditView : 텍스트 편집,단어 검색,치환 그리고 스크롤을 자체적으로 해결한 뷰 간단한 텍스트 에디터를 만드는데 편리한 클래스이다.

MFC  Visual Objects 관련 클래스 3. 다이얼로그 (Dialog) 클래스  CDialog : 다이얼로그 클래스들에 대한 기본(Base) 클래스  모달(Modal) 다이얼로그  모드리스(Modeless) 다이얼로그 MFC가 제공하는 기본 다이얼로그는 모달 다이얼로그이다.  CDataExchange : 다이얼로그 박스에 대한 초기화와 타당성(validation) 정보를 제공한다.  CFileDialog : 파일을 열거나 저장, 디렉토리 찾아가기 등의 일을 하는 표준 다이얼로그 클래스  CPrintDialog : 파일을 프린트하거나 프린트 옵션을 지정하는 표준 다이얼로그 클래스  CFontDialog : 폰트를 선택, 글자 크기와 속성을 지정하는 표준 다이얼로그 클래스  CColorDialog : 색상을 선택하기 위한 표준 다이얼로그 클래스  CFindReplaceDialog : 문자를 검색, 지정한 문자열로 치환하는 표준 다이얼로그 클래스

MFC  Visual Objects 관련 클래스 4. 제어 (Control) 클래스  CStatic : 윈도우나 다이얼로그 박스의 어느 위치에 고정된 텍스트  CButton : 다이얼로그 박스에서 흔히 볼 수 있는 체크 박스나 라디오 버튼  CEdit : 편집이 가능한 박스  CListBox : 여러 아이템을 박스 안에 나열해서 표현, 한 아이템을 선택하는 것이 가능한 박스  CComboBox : 에디트 컨트롤과 리스트 박스로 구성된 박스  CControlBar : 제어바에 대한 기본 클래스  CStatusBar : 윈도우 하단에 있는 상태바에 대한 클래스  CScrollBar : 윈도우 우측이나 좌측에 있는 스크롤바에 대한 클래스  CToolBar : 윈도우 상단에 위치한 작은 비트맵 버튼들과 관련된 클래스  CDialogBar : 모드리스 다이얼로그 박스에 관련된 클래스  CVBControl : 비주얼베이직에서 사용되던 VBX를 제어할 수 있는 클래스  CSplitterWnd : 여러 개의 틀로 나뉘어질 수 있는 윈도우를 제어하는 클래스

MFC  Visual Objects 관련 클래스 5. 메뉴 (Menu) 클래스  CMenu : 응용 프로그램에서 메뉴와 팝업 메뉴를 쉽게 구현할 수 있도록 작성된 클래스 6. 디바이스 컨텍스트 (Device-Context) 클래스  CDC : 디바이스 컨텍스트에 대한 기본 클래스 화면 출력과 프린터와 같은 비화면 출력을 다룰 수 있는 함수들이 있다.  CPaintDC : 윈도우의 화면 출력에 사용된다. 주로 OnPaint()에 의해 사용된다. 이 클래스를 생성할 때 자동적으로 BeginPaint가 실행되고 소멸될 때에 EndPaint가 실행된다.  CClientDC : 윈도우의 클라이언트 영역에 화면 출력한다.  CWindowDC : 전체 윈도우에 대한 화면 출력 클래스. 클라이언트 영역뿐만 아니라 메인 프레임 영역에도 적용 가능하다.  CMetaFileDC : 윈도우 메타파일에 대한 클래스 ◐ 메타파일 : 그래픽 이미지를 생성해 낼 수 있는 GDI명령들이 저장된 파일. 이미지를 BMP나 PCX와 같이 통째로 저장하는 것이 아니고 그래픽 명령으로 저장되어 있기 때문에 크기가 작고, 수정이 쉽다.

MFC  Visual Objects 관련 클래스 7. Drawing(그리기) Object 클래스  CGdiObject : GDI 객체들의 기본 클래스  CBitmap : 비트맵을 생성하고, 출력, 변경시키기 위한 클래스  CBrush : 브러시를 선택하고 속성을 조절할 수 있는 클래스  CFont : 폰트를 선택하고 속성을 조절할 수 있는 클래스  CPalette : 출력장치와 응용 프로그램간 팔레트를 조절할 수 있는 클래스  CPen : 펜을 선택하고 속성을 조절할 수 있는 클래스  CRgn : 다각형 또는 타원을 그릴 수 있도록 조절하는 클래스

◐ 일반 목적(General Purpose) Class Mind Map ◑ MFC 독립 클래스들 CObject CException CFile CByteArray CWordArray CDWordArray CPtrArray CObArray CStringArray CUIntArray CPtrList COblist CStringList CArchiveException CFileException CMemoryException CNotSupportedException CResourceException CUserException CStdioFile CMemFile CMapPtrToWord CMapPtrToPtr CMapStringToOb CMapStringToPtr CMapStringToString CMapWordToOb CMapWordToPtr CArchive CPoint CDumpContext CSize CRuntimeClass CString CMemoryState CTime CRect CTimeSpan ◐ 일반 목적(General Purpose) Class Mind Map ◑

MFC  일반 목적 클래스와 독립적 클래스 1. 파일 처리와 관련된 클래스  CFile : 2진 파일들에 대한 프로그램 인터페이스를 제공한다.  CMemFile : 메모리를 파일처럼 쓸 수 있도록 하는 프로그램 인터페이스 제공  CStdioFile : 일반적인 텍스트 파일을 다룰 수 있는 프로그램 인터페이스 제공  CArchive : CFile과 같이 사용되어 데이터 객체에 대한 Serialization을 구현하는데 중요한 인터페이스 제공 2. 진단 (Diagnostics)  CDumpContext : 메모리의 내용을 통째로 보이도록 하는 클래스  CMemoryState : 메모리 사용에 대한 체크를 할 수 있도록 하는 클래스  CRuntimeClass : 런타임 시 어떤 객체의 클래스 관련 정보를 정확하게 아는데 사용

MFC  일반 목적 클래스와 독립적 클래스 3. 예외 처리 (Exceptions) : 치명적인 에러 발생 시에 컴퓨터가 멈추는 일을 막는다.  CException : 여러 가지 예외 처리들에 대한 기본 클래스  CArchiveException : 데이터 기록에 대한 예외 처리 클래스  CFileException : 파일에 관련된 예외 처리 클래스  CMemoryException : 메모리 고장에 관한 예외 처리 클래스  CNotSupportedException : 지원되지 않는 특성을 호출하였을 때 발생하는 예외처리  CResourceException : 윈도우 리소스를 메모리에 로딩 하는 데 실패할 경우  CUserException : 사용자가 정의할 수 있는 클래스. 예외 처리에 들어가기 전에 문제가 무엇인지를 윈도우에게 알려야 한다. 4. 집합체(Collections) 관련 클래스  배열 관련 클래스  CByteArray : BYTE형태의 원소들을 배열로 저장  CDWordArray : 더블 워드 형태의 원소들을 배열로 저장  CObArray : CObject에서 파생된 클래스 또는 CObject 클래스 그 자체에 대한 포인터를 배열로 저장  CPtrArray : 함수(void) 포인터를 배열로 저장  CStringArray : CString 객체를 배열로 저장  CWordArray : WORD 형태의 원소들을 배열로 저장  CUIntArray : UINT 형태의 원소들을 배열로 저장

MFC  일반 목적 클래스와 독립적 클래스 4. 집합체(Collections) 관련 클래스  링크드 리스트 관련 클래스  COblist : CObject에서 파생된 클래스 또는 CObject 클래스 그 자체에 대한 포인터를 링크드 리스트 형태로 저장  CPtrList : 함수(void) 포인터를 링크드 리스트로 저장  CStringList : CString 객체를 링크드 리스트로 저장  객체간의 맵핑 클래스  CMapPtrToWord : 함수(void)포인터를 WORD 형태의 데이터로 맵핑시킨다.  CMapPtrToPtr : 함수(void)포인터를 함수 포인터에 맵핑하는데 사용된다.  CMapStringToOb : CString객체를 CObject 포인터로 맵핑한다.  CMapStringToPtr : CString객체를 CObject void 포인터로 맵핑한다.  CMapStringToString : CString객체를 CString 객체로 맵핑한다.  CMapWordToOb : WORD 형태의 데이터를 CObject 포인터로 맵핑한다.  CMapWordToPtr : WORD 형태의 데이터를 함수 포인터에 맵핑한다.

MFC  일반 목적 클래스와 독립적 클래스 5. 기타 독립 클래스 : MFC 전체에 걸쳐 광범위하게 사용되는 클래스이다.  CPoint : 점에 관한 클래스  CSize : 크기에 관한 클래스  CRect : 영역에 관한 클래스  CString : 문자열에 관한 클래스  CTime : 절대적 시간을 다루는 클래스  CTimeSpan : 상대적 시간을 다루는 클래스

MFC  매크로와 전역 변수  이 부분은 클래스에 관련된 부분은 아니지만 MFC 코드를 이해하는데 필요한 요소이기 때문에 어떤 내용들이 포함되어 있는지 알아야 한다.  DevStudio\Vc\mfc\include\<afx.h> 1. 데이터 형 (Data Types)  윈도우 SDK 시절부터 데이터 형을 새롭게 정의하였는데 일반적으로 많이 쓰는 데이터형에 대해서 알아야 한다.  MFC에 새롭게 정의된 데이터 타입 POSITION : MFC의 Collection 클래스에서 사용되는 원소들의 위치 지정에 사용되는 데이터형 LPCRECT : RECT 구조체에 대한 32비트 포인터

Data Types 데이터 타입 의미  DevStudio\Vc\include\Windef.h BOOL BYTE WORD UINT DWORD LONG LPVOID COLORREF BSTR LPSTR LPCSTR WNDPROC WPARAM, LPARAM LRESULT 논리 데이터 형(TRUE또는 FALSE) 8 비트 unsigned형 정수 16 비트 unsigned형 정수 32 비트 unsigned형 정수 32 비트 unsigned형 정수 or 세그먼트:오프셋 주소 32 비트 signed형 정수 32비트 타입 지정이 없는 포인터 색상(color)을 표현하는 32비트 데이터 형 32비트 문자형 포인터 32비트 문자열 포인터 32비트 문자열 상수 포인터 윈도우 함수에 대한 32비트 포인터 윈도우 함수 또는 Callback 함수의 인수로 넘겨주기 위한 32 비트 데이터 형 윈도우 함수 또는 Callback 함수에 결과로 되돌아온 32 비트 데이터 형  DevStudio\Vc\include\Windef.h

Data Types 의미 hIcon hCursor hBrush hWnd hMenu hInstance hFont hBitmap hPalette hPen hTask hDlg hDC hRgn 아이콘을 가리키는 핸들 커서(마우스 포인터)를 가리키는 핸들 브러시를 가리키는 핸들 윈도우를 가리키는 핸들 메뉴 또는 팝업 메뉴를 가리키는 핸들 윈도우 응용 프로그램의 인스턴스를 가리키는 핸들 텍스트 글꼴을 가리키는 핸들 DIB 이미지 정보를 포함하고 있는 메모리 영역을 가리키는 핸들 색 팔레트(테이블)를 가리키는 핸들 선의 종류를 지정하는데 사용하는 펜을 가리키는 핸들 독립적으로 실행하고 있는 작업을 가리키는 핸들 대화 상자를 가리키는 핸들 장치 컨텍스트를 가리키는 핸들 창의 클립(clip) 영역을 가리키는 핸들 핸들의종류  MFC를 사용해서 프로그래밍할 때는 일반적으로 핸들이 필요하지 않다. 이유는 MFC가 응용 프로그램 프레임워크에 포함되어 있는 기본적인 윈도우 객체에 액세스하는 데 사용할 수 있는 다른 방법을 제공하기 때문이다.

MFC  매크로와 전역 변수 2. Run-Time Object Model Service  매크로 DECLARE_DYNAMIC, DECLARE_DYNCREATE, DECLARE_SERIAL, IMPLEMENT_DYNAMIC, IMPLEMENT_DYNCREATE, IMPLEMENT_SERIAL, RUNTIME_CLASS 3. 진단 서비스 (Diagnostic Services)  MFC는 디버깅을 쉽게 할 수 있도록 여러 가지 진단 서비스를 갖추고 있다.  전역 변수는 afx로 시작, 전역 함수는 Afx로 시작한다.  매크로 : ASSERT, ASSERT_VALID, DEBUG_NEW, TRACE, VERIFY  전역 변수 : afxDump, afxMemDF, afxTraceEnabled, afxTraceFlags  전역 함수 : AfxCheckMemory, AfxDump, AfxEnabledMemoryTracking, AfxlsMemoryBlock, AfxlsValidAddress, AfxlsValidString, AfxSetAllocHook, AfxDoForAllClasses

MFC  매크로와 전역 변수 4. 예외 처리 (Exception Processing)  프로그램이 실행될 때 예외 상황(시스템이 비정상적이 되거나 치명적인 메모리 에러, 파일검색 에러 등)을 처리하기 위하여 사용한다.  매크로 TRY, CATCH, AND_CATCH, END_CATCH, THROW, THROW_LAST  전역 함수 AfxThrowArchiveException, AfxThrowFileException, AfxThrowMemoryException, AfxThrowNotSupportedException, AfxThrowResourceException, AfxThrowUserException, AfxAbort(종료) 5. CString 형식지정 및 메시지 박스 출력  이 함수들은 보통 메시지 박스에 나타날 문자열을 다루기 위하여 사용된다.  전역 함수 : AfxFormatString1, AfxFormatString2, AfxMessageBox

MFC  매크로와 전역 변수 6. 메시지 맵 (Message Maps)  매크로  메시지 맵 선언과 정의에 관련된 매크로 DECLARE_MESSAGE_MAP // 선언 BEGIN_MESSAGE_MAP, END_MESSAGE_MAP // 정의  메시지 맵핑과 관련된 매크로 ON_COMMAND, 0N_CONTROL, ON_MESSAGE, ON_VBXEVENT ON_REGISTERED_MESSAGE, ON_UPDATED_COMMAND_UI

MFC  매크로와 전역 변수 7. 어플리케이션 프로그램의 정보 및 관리  전역 함수 AfxGetApp, AfxGetAppName, AfxGetInstanceHandle,AfxGetMainWnd, AfxGetResourceHandle, AfxRegisterWndClass, AfxRegisterVBEvent, AfxSetResourceHandle 8. 표준 명령어와 윈도우 ID  표준 명령어 ID : ID로 시작하는 매크로 예) ID_FILE_OPEN : 메뉴에 있는 파일 열기 명령어에 대한 ID  윈도우 ID (윈도우의 내부 처리를 위한 표준 명령어에 대한 ID) : AFX_ID로 시작하는 매크로  DevStudio\Vc\mfc\include\<afxres.h>

MFC  매크로와 전역 변수 9. 헝가리언 표기법(Hungarian Notation)  변수들을 정의할 때 데이터형을 알아보기 쉽도록 접두어를 붙여 표기하는 것. 전치사 의미 a ai b by c cb cr cx, cy dw f fn h i l Array Integer Array Boolean Unsigned Char(Byte) Char Count of bytes Color Reference Value Short(count of x, y length) Unsigned long(dword) Flag(On/Off) Function Handle Integer Long lp lpfn lpsz m n np p psz s sz tm w x, y Long Pointer Function Pointer String Pointer Data member of a class Short or Int Near Pointer Pointer String 0 terminated String(NULL) Text Metric Unsigned Int(Word) Short(x, y coordinate)

MFC  헝가리언 표기법 변수명 설명 hWndMain alDice lpszText cdwPixels Main이라는 창(Wnd)을 가리키는 핸들(h) Dice라고 하는 long정수의 배열(a) Text라고 하는 NULL 종료 문자열(sz)을 가리키는 포인터(lp) 이중 단어(dw) 유형이며, 계수를 위해서 사용하는 Pixels라고 하는 이름의 변수

CObject로 부터 파생되지 않은 MFC 하위 시스템들  OLE 클래스  단순 데이터 유형 클래스  지원 클래스  동기화 클래스  유형이 있는 템플릿 클래스  OLE클래스  OLE는 응용 프로그램이 훌륭한 일을 할 수 있도록 하는 강력한 새로운 기술이다.  OLE를 사용하면, 편집할 수 있는 다중 응용 프로그램 OLE 문서와 OLE 개체를 만들 수 있다.  OLE를 사용하여 응용 프로그램간에 마우스로 끌어다 떨어뜨리는 복사 기능을 제공 하거나 OLE 자동화를 통해 또 다른 응용프로그램을 제어할 수도 있다.  OLE 데이터 유형을 캡슐화한 COle로 시작하는 OLE클래스들도 있다.

CObject로 부터 파생되지 않은 MFC 하위 시스템들  point나 rect같은 공통 Win32 API 데이터 유형을 캡슐화 한다. 클래스 의미 CImageList COleVariant COleCurrency COleDateTime COleDateTimeSpan 일련의 비트맵을 저장하고 쌓아두는 데 사용한다. 리스트 컨트롤과 트리 컨트롤에서도 사용하고 있다. CURRENCY는 고정 소수점 산술 유형으로 소수점 전에 15자리가 있고, 그 뒤에 4자리가 있다. 날짜와 시간 값을 나타내는 OLE 자동화 유형 DATE에 대한 포장기이다. 두 개의 COleDateTime 값 사이의 시간차와 같이 일수로 측정된 시간 간격을 나타낸다. 데이터를 여러 유형으로 저장할 수 있는 OLE 자동화 유형이다. CPoint CRect CString 표준 SDK RECT 구조에서 찾을 수 있는 사각형 영역의 좌표를 포장한다. 표준 SDK POINT 구조에서 발견할 수 있는 (x,y)좌표 쌍을 포장한다. 거리와 상대적 위치, 또는 순서쌍 등을 포장한다. CSize CTime CTimeSpan 문자 문자열을 포장하고 있으며, 문자열을 처리하는데 사용하는 많은 유용한 메소드와 연산자를 제공하고 있다. 절대적 시간과 날짜 값을 포장하고 있다. 상대적 시간과 날짜 값을 포장하고 있다.

CObject로 부터 파생되지 않은 MFC 하위 시스템들  지원 클래스  사용자 인터페이스 개체를 갱신하고 메뉴와 명령 단추를 활성화하고 비활성화하는 등과 같은 동작들을 수행하는 데 사용하는 CCmdUI를 포함하고 있다.  CWaitCursor 클래스는 단순히 커서를 모래 시계 모양으로 변경하는 역할을 한다.  CRectTracker 클래스는 크기 조정 핸들을 사용하여 화면의 항목들을 움직이고 크기를 변경할 수 있게 한다.  동기화 클래스  스레드 행동의 동기를 맞추어 주는 Win32 객체들을 C++ 객체로 포장하기 위한 네 개의 MFC 클래스가 있다.  CSemaphore  CMutex  CCriticalSection  CEvent  유형이 있는 템플릿 클래스들  유형이 있는 템플릿 클래스는 공통으로 사용하는 프로그래밍 상황에서 많이 유용하게 사용하고 있으며, CObject로부터 파생된 콜렉션 유형보다 더 낫다.

MFC  MFC 프로그램 작성 방법 ① 프로그램이 필요로 하는 기능을 명시화해야 한다. ② 그 사양을 바탕으로 기능에 맞는 클래스들이 무엇인지를 찾아내야 한다. ③ 코딩에 들어간다. ④ 디버깅과 테스팅 ⑤ 문서화와 도움말 작업

CHAPTER 2 MFC 라이브러리 어플리케이션 프레임워크

CHAPTER 2  어플리케이션 프레임워크 (Application Framework)  어플리케이션 생성을 위해서 필요한 모든 것을 제공해 주는 객체지향 소프트웨어 요소들의 집합.  어플리케이션 프레임워크와 클래스 라이브러리  클래스 라이브러리  어플리케이션에서 사용될 수 있는 관련 C++ 클래스들의 집합.  어플리케이션 프레임워크 (Application Framework)  클래스 라이브러리를 모아 놓은 특수한 집합체  MFC 이전의 AFX  응용 프로그램 틀(Application Framework)을 AFX라고 불렀다.  AFX란 이름은 1994년 초반에 마이크로소프트에서 사용이 중단되었다.

CHAPTER 2  메시지 처리(Message Processing)  도스용 프로그램 : 사용자의 입력을 받기 위해서 운영체제를 호출.  윈도우용 프로그램 : 운영체제가 보내 주는 메시지를 처리.  프로그램을 실행시키면, 윈도우는 WinMain() 함수를 호출한다.  MFC에서는 WinMain()을 감추고, 메시지 처리를 구조화 시킬 수 있는 CWinApp를 제공한다.  WM_의 접두어로 시작하는 식별자를 사용한다.  WM_LBUTTONDOWN (마우스의 왼쪽 버튼이 눌려졌다는 것을 의미)  메시지들을 다루기 위한 대부분의 코딩은 어플리케이션 프레임 워크가 알아서 한다.

CHAPTER 2  메시지 구조  typedef struct tagMSG { typedef struct tagPOINT { LONG x; // 화면 좌표 LONG y; // 화면 좌표 } POINT; // 중첩 구조  메시지 구조  typedef struct tagMSG { HWND hwnd; // 메시지를 꺼낼 창의 핸들 UINT message; // 메시지 값 WPARAM wParam; // 메시지에 대한 추가적인 정보 LPARAM lParam; // 메시지에 대한 추가적인 정보 DWORD time; // 메시지가 대기열에 들어온 시간 POINT pt; // 메시지가 전달되었을 때 커서의 화면 좌표 }MSG;  hwnd - 이 인수가 0(NULL)이면, 메시지 대기열에 있는 모든 메시지들을 꺼내게 된다.  message - 각 윈도 메시지는 WINDOWS.H에 매크로로 정의되어 있는 특정 값을 갖고 있다.

CHAPTER 2  시스템 정의 메시지  윈도우는 시스템 정의 메시지를 해당 중심 창 프로시저에 보냄으로써 응용 프로그램과 통신한다.  각 시스템 정의 메시지는 고유의 번호로된 식별자를 갖고 있으며, 이에 해당되는 식별자 매크로 정의를 갖고 있다. 접두사 메시지 분류 BM CB DM EM LB SBM WM 단추 컨트롤 메시지 콤보 박스 컨트롤 메시지 기본 누름 단추 컨트롤 메시지 편집 컨트롤 메시지 목록 상자 컨트롤 메시지 이동 표시줄 컨트롤 메시지 일반 창 메시지

CHAPTER 2  사용자 정의 메시지 메시지 유형 값의 범위 시스템 정의 메시지(제1부) 사용자 정의 내부 메시지 시스템 정의 메시지(제2부) 사용자 정의 외부 메시지 0x0000-0x03FF 0x0400-0x7FFF 0x8000-0xBFFF 0xC000-0xFFFF  응용 프로그램 객체 데이터를 얻기 위한 전역 MFC 함수 함수 의미 AfxGetApp AfxGetAppName AfxGetInstanceHandle AfxGetResourceHandle CWinApp 객체에 대한 포인터를 반환한다. 응용 프로그램의 이름을 담고 있는 문자열에 대한 포인터를 반환한다. 현재의 응용 프로그램 인스턴스에 대한 핸들을 반환한다. 이 핸들은 AfxWinInit()내에서 주 스레드를 초기화할 때 설정된다. 응용 프로그램 자원에 대한 핸들을 반환한다. 이 핸들은 AfxWinInit()내에서 주 스레드를 초기화할 때 설정된다.

CHAPTER 2  메시지 전달 방식  윈도우의 모든 동작은 마우스의 왼쪽 버튼이 눌려졌다거나, 키보드가 눌려졌다거나 하는 등의 어떤 특정 사건에 대해서 응답하는 방식으로 이루어져 있다.  Message Event 방식 또는 Message Driven 방식  이벤트들을 보관하는 큐  Hardware Event Queue  System Queue  응용 큐  메시지  어떤 특정 이벤트에 의해서 발생된 관련 정보.

CHAPTER 2 ◐ 메시지 전달과정 ◑  핸들 (Handle) 방식 메시지 발생 하드웨어 이벤트 큐 프로그램 메시지 루프 ◐ 메시지 전달과정 ◑  핸들 (Handle) 방식  윈도우는 각각의 객체들을 식별하기 위해서 핸들을 사용한다.  HWND (윈도우에 대한 핸들)  HICON (아이콘에 대한 핸들)  HMENU (메뉴에 대한 핸들)

CHAPTER 2  인스턴스 (Instance) 방식  인스턴스란? 프로그램의 복사본을 말하며, 각각의 복사본을 구별하기 위해 인스턴스 핸들을 이용한다.  각각의 다른 프로그램이 여러 개 실행되었거나, 동일한 프로 그램이 여러 개 실행되었을 경우, 윈도우는 여러 개의 프로그램을 실행시키기 위해 각각의 프로그램에 인스턴스 라는 핸들을 부여한다.  하드웨어 장치와 독립된 처리 방식  윈도우는 거의 대부분이 하드웨어 장치와 독립적으로 작동한다.  하드웨어와 독립적인 장치를 지원해 줄 수 있는 디바이스 드라이버를 내장하고 있다.

CHAPTER 2 ◐ 메시지 처리 방식 ◑ NOTEPAD 메시지 루프 PBRUSH 메시지 루프 입력에 대한 처리 WRITE 메시지 루프 시스템 큐 NOTEPAD 응용 큐 WRITE 응용 큐 PBRUSH 응용 큐 키보드에서 A키 입력 하드웨어 장치 Windows Windows 응용 프로그램

CHAPTER 2  메시지 식별자  메시지가 프로그램에서 사용될 때는 부호 없는 정수형의 값에 불과하다. 윈도우는 이러한 부호 없는 정수형의 값을 특정 사건(사용자 입력)에 대한 기호로서 인식한다.  프로그램에서 이러한 메시지에 대한 부호 없는 정수형의 값들을 이용할 때, 일반적으로 통일성을 갖기 위해 WM_의 접두어로 시작하는 식별자를 사용한다.  WM_LBUTTONDOWN (마우스의 왼쪽 버튼이 눌려졌다는 것을 의미)  WM_DESTROY ( 윈도우를 파괴한다는 것을 의미)  메시지 식별자는 WINDOWS.H 에 정의되어 있다.  메시지 핸들러  메시지 핸들러는 특정 이벤트가 발생했을 때 프로그램 객체로부터 통지(notification)를 받아들이는 역할을 한다.  전달된 메시지가 올바른 종류이고, 해당 작업에 맞는 것일 경우에만 메시지 핸들러가 구동된다.  메시지 핸들러에서 처리되는 메시지 유형  윈도우 메시지  컨트롤 통지 메시지  명령 메시지

CHAPTER 2  윈도우 메시지  윈도우에 의해 응용 프로그램에 전달된다.  보통 WM_ 접두사로 시작하는 메시지들이다.  예외, WM_COMMAND - MFC에서 특별한 상태를 갖는다.  컨트롤 통지 메시지  자식 윈도우가 부모 윈도우에 보내는 WM_COMMAND 메시지들을 포함하고 있다.  컨트롤은 특정 통지 코드가 내장되어 있는 WM_COMMAND메시지를 종종 발생시킨다.  통지 코드는 때때로 미리 정의되어 있는 MFC 메시지 처리 메커니즘에 맵핑될 수 있다.  그러면 통지를 위한 윈도우의 메시지 핸들러가 이에 맞게 동작하게 된다.  표준 윈도우 컨트롤은 보통 명령과 통지 메시지를 둘다 전송하지만, MFC가 보통 명령 메시지는 클래스 메소드로 싸기 때문에 응용 프로그램에서는 통지 메시지만 처리하면 된다.  명령 메시지  명령 메시지는 메뉴나 도구모음 단추와 같은 사용자 인터페이스로부터의 WM_COMMAND 통지 메시지를 포함하고 있다.

CHAPTER 2 ◐ 윈도우의 하드웨어 장치 운영방식 ◑ Windows application program GDI.EXE USER.EXE KERNEL.EXE DISPLAY.DRV KEYBOARD.DRV PRINTER.DRV MOUSE.DRV SOUND.DRV SYSTEM.DRV COMM.DRV MS-DOS file I/O Memory management RS-232 HardWare Display(Crt Monitor) Keyboard Mouse Sound HardWare Timer HardWare Printer

CHAPTER 2  객체 구성 요소들  동적 연결 라이브러리 (DLL)  비주얼 베이직 확장 (VBX)  OLE 컨트롤 확장 (OCX)  동적 연결 라이브러리  실행시(Run-time)에 로드되는 라이브러리를 말한다.  여러 개의 프로세스가 사용할 수 있는 함수들의 라이브러리를 갖고 있는 실행 파일이다.  코드 내의 함수 호출이 실행될 때에 동적으로 DLL내의 실제 코드와 연결되기 때문에 동적 연결이라고 부른다.  프로그램의 모듈성을 향상시킬 수 있다.  DLLs 테스트를 분리해서 수행한다.  사용자가 직접 DLLs을 만들 수 있다.  윈도우도 USER32.DLL, GDI32.DLL, KERNEL32.DLL과 같은 DLL들의 집합으로 이루어져 있다.  이들 세 DLL은 Win32 응용 프로그램 인터페이스(API)의 핵심을 이루고 있다.

CHAPTER 2  비주얼 베이직 확장 (VBX)  VBX는 프로그램 개발 동안 시각적으로 처리할 수 있도록 연결된 추가 함수들을 가진 특수 구조의 DLL이다.  VBX는 임의의 윈도우 프로그램이나 여러 언어에서 사용할 수 있다.  16비트 윈도우 프로그램에서만 사용할 수 있다.  OLE 컨트롤 확장 (OCX)  VBX 구조의 기능과 OLE2.0의 강력한 기능을 조합한 혼성체이다.  윈도우 개발 도구에 통합된 인터페이스를 제공하고 있다.  하나의 원본 파일로부터 16비트 버전과 32비트 버전을 둘 다 컴파일할 수 있다.  윈도우 응용 프로그래밍 인터페이스(API)  프로그래머가 다른 프로그램을 만들 때 사용할, 한 프로그램(또는 관련 있는 일련의 프로그램들) 내의 함수 호출들을 모아 놓은 것이다.  함수의 내부 구조는 알 필요가 없으며, 함수의 프로토타입과 반환 값만 알면 된다.

CHAPTER 2  Win16 어플리케이션 프로그래밍 인터페이스(API)  Win16 버전들은 (.EXE) 확장명을 갖고 있지만, 이들은 모두 실제로 DLL이며 스스로 실행될 수는 없다.  Win32 어플리케이션 프로그래밍 인터페이스(API)  16비트 인자들이 상당수 32비트로 바뀌었다.  Win32 API 에는 새로운 함수들이 추가되었다. Win16 API Win32 API 의미 USER.EXE GDI.EXE KRNL386.EXE USER32.DLL GDI32.DLL KERNEL32.DLL USER 구성 요소는 메시지와 메뉴, 커서, 통신, 타이머를 포함한 윈도우 관리에 책임을 지고 있으며, 윈도우를 나타내는 것이 아닌 이를 제어하는 것과 관련된 대부분의 다른 함수들을 갖고 있다. GDI 구성 요소는 그래픽 장치 인터페이스이다. 이는 윈도우 메타파일과 비트맵, 장치 컨텍스트, 그리고 글꼴을 포함한 사용자 인터페이스와 그래픽을 그리는 것을 처리한다. KERNEL 구성 요소는 윈도우의 심장부 역할을 하는 메모리와 작업, 자원 관리의 저차원 기능을 처리한다.

CHAPTER 2  윈도우 메시징  클래스 요약 클래스 이름 설명 메시지맵 매크로 CCmdTarget CCmdUI 윈도우 메시지를 C++ 멤버함수에 연결(map)시켜주는 매크로 커맨드 메시지를 받는 모든 객체에 대한 기초 클래스 사용자 인터페이스 객체를 갱신하는 것을 도와준다. (예, 사용 가능하게 하거나 사용할 수 없게 한다.)

CHAPTER 2  MFC 커맨드 메시지 전달 CMDIFrameWnd 1. Active CMDIChild 2. {itself} 3. CWinApp CDialog 1. {itself} 2. Owner CWnd CMDIChildWnd 1. Active CView CView 2. CDocument CDocument 2. CDocTemplate Command Message

CHAPTER 2  메시지 맵(Message Map)  메시지 맵이란? 윈도우 메시지를 C++ 멤버함수에 연결(map)시켜 주는 매크로이다.  메시지 맵을 사용하게 되면, 부피가 커지는 vtable을 피할 수 있다.  메시지 맵 메커니즘  BEGIN_MESSAGE_MAP(CMyFrame, CMyFrameWnd) ON_WM_PAINT() ON_WM_LBUTTONDOWN() END_MESSAGE_MAP()  ON_MessageName(ID, ClassMethod) 자기 자신의 클래스 해당클래스의 기초클래스를 지정 메시지를 보낸 쪽의 식별자 메시지를 처리할 클래스 메소드의 이름

CHAPTER 2  메시지 맵 항목  명령 메시지 핸들러  차일드 윈도우 통지 메시지 핸들러  윈도우 메시지 핸들러  명령 메시지 핸들러  메뉴를 선택하거나 키보드 가속기를 사용하는 것과 같은 사용자의 행동에 의해 발생된 WM_COMMAND 메시지들을 처리한다.  WM_COMMAND 메시지는 ON_COMMAND 메시지 맵 항목들을 가진 여러 응용 프로그램 구성 요소에 의해 처리된다.  ON_COMMAND(ID, ClassMethod)  해당 메시지 핸들러 메소드는 클래스 선언에 놓이게 된다. afx_msg void ClassMethod(); 메시지를 보낸 쪽의 식별자 메시지를 처리할 클래스 메소드의 이름

CHAPTER 2  차일드 윈도우 통지 메시지 핸들러  차일드 윈도우의 통지 메시지를 처리하는 역할을 한다.  차일드 윈도우 통지 메시지 다섯 가지 유형  범용 컨트롤 핸들러  단추(Button) 핸들러  콤보(Combo) 박스 핸들러  편집(Edit) 컨트롤 핸들러  목록(List) 상자 핸들러  범용 컨트롤 통지 핸들러 ON_CONTROL (wNotifyCode, ID, ClassMethod) 처리할 메시지나 명령 컨트롤의 식별자 클래스에 정의된 메시지 핸들러 메소드

CHAPTER 2  차일드 윈도우 통지 메시지 핸들러  단추 컨트롤 통지 핸들러 ON_BN_*EVENT* (ID, ClassMethod)  ON_BN_*EVENT*는 미리 정의된 BN_*(단추 통지) 메시지 매크로 중 어느 하나를 나타낸다. ON_BN_CLICKED ON_BN_DISABLE ON_BN_DOUBLECLICKED ON_BN_HILITE ON_BN_PAINT ON_BN_UNHILITE 단추 컨트롤의 식별자 클래스에 대한 메시지 핸들러 메소드

CHAPTER 2  차일드 윈도우 통지 메시지 핸들러  콤보 상자 컨트롤 통지 핸들러 ON_CBN_*EVENT* (ID, ClassMethod)  ON_CBN_*EVENT*는 미리 정의된 CBN_*(콤보 상자 통지) 메시지 매크로 중 어느 하나를 나타낸다. ON_CBN_CLOSEUP ON_CBN_KILLFOCUS ON_CBN_DBLCLK ON_CBN_SELCHANGE ON_CBN_DROPDOWN ON_CBN_SELENDCANCEL ON_CBN_EDITCHANGE ON_CBN_SELENDOK ON_CBN_EDITUPDATE ON_CBN_SETFOCUS ON_CBN_ERRSPACE 콤보 상자 컨트롤의 식별자 클래스에 대한 메시지 핸들러 메소드

CHAPTER 2  차일드 윈도우 통지 메시지 핸들러  편집 컨트롤 통지 핸들러 ON_EN_*EVENT* (ID, ClassMethod)  ON_EN_*EVENT*는 미리 정의된 EN_*(편집 통지) 메시지 매크로 중 어느 하나를 나타낸다. ON_EN_CHANGE ON_EN_MAXTEXT ON_EN_ERRSPACE ON_EN_SETFOCUS ON_EN_HSCROLL ON_EN_UPDATE ON_EN_KILLFOCUS ON_EN_VSCROLL 편집 상자 컨트롤의 식별자 클래스에 대한 메시지 핸들러 메소드

CHAPTER 2  차일드 윈도우 통지 메시지 핸들러  목록 상자 컨트롤 통지 핸들러 ON_LBN_*EVENT* (ID, ClassMethod)  ON_LBN_*EVENT*는 미리 정의된 LBN_*(목록 상자 통지) 메시지 매크로 중 어느 하나를 나타낸다. ON_LBN_DBLCLK ON_LBN_ERRSPACE ON_LBN_KILLFOCUS ON_LBN_SELCANCEL ON_LBN_SELCHANGE ON_LBN_SETFOCUS 목록 상자 컨트롤의 식별자 클래스에 대한 메시지 핸들러 메소드

CHAPTER 2  MFC가 제공하지 않는 윈도우 메시지 핸들러 정의하기  Win32가 제공하는 윈도우 메시지는 모두 ON_MESSAGE() 매크로를 사용하여 핸들러를 정의할 수 있다.  예를 들어, WM_SETREDRAW 메시지에 대한 미리 정의된 MFC 메시지 핸들러는 존재하지 않는다.  이 메시지에 대한 핸들러를 만들려면, ON_MESSAGE() 메시지 맵 항목을 다음과 같이 정의한다. ON_MESSAGE(WM_SETREDRAW, OnSetReDraw)  클래스 선언에 OnSetReDraw() 메시지 핸들러를 선언한다. afx_msg LRESULT OnSetReDraw(WPARAM wParam, LPARAM lParam);  wParam과 lParam인수는 MSG 구조의 멤버들과 동일한데, 이들의 값은 처리중인 메시지에 따라 달라진다.

CHAPTER 2  사용자 정의 메시지 핸들러  사용자가 정의한 메시지 맵 항목은 다음 둘 중의 하나의 부류에 속한다.  사용자 정의 내부 항목  사용자 정의 외부 항목  사용자 정의 내부 메시지 맵 항목 ON_MESSAGE (MessageMacro, ClassMethod)  클래스 선언에 ClassMethod() 메시지 핸들러를 선언한다. afx_msg LONG ClassMethod (UINT, LONG); 처리할 메시지의 매크로 값 클래스를 위해 정의된 메시지 핸들러 메소드

CHAPTER 2  사용자 정의 메시지 핸들러  사용자 정의 외부 메시지 맵 항목 ON_REGISTERED_MESSAGE (MessageMacro, ClassMethod)  클래스 선언에 ClassMethod() 메시지 핸들러를 선언한다. afx_msg LONG ClassMethod (UINT, LONG);  메시지와 메시지 핸들러의 대응 예 처리할 메시지의 매크로 값 클래스를 위해 정의된 메시지 핸들러 메소드 메시지 메시지 맵 메시지 핸들러 WM_PAINT WM_LBUTTONDOWN WM_CHAR ON_WM_PAINT() ON_WM_LBUTTONDOWN() ON_WM_CHAR() void OnPaint() void OnLButtonDown(UINT nFlags, CPoint point) void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

CHAPTER 2  어플리케이션 프레임워크 예제  헤더파일(.h) // 어플리케이션 클래스 class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); }; // 프레임 윈도우 클래스 class CMyFrame: public CMainFrame CMyFrame(); protected: afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnPaint(); DECLARE_MESSAGE_MAP() 클래스들은 MFC에서 사용하고 있는 코드 관례를 따르기 위해 항상 대문자 C로 시작한다. 클래스 선언에서 메시지 핸들러를 구별하기 위한 표시 “afx_msg”로 표시된 두 함수는 MFC 라이브러리 메시지 전달 체계를 통해 전달되는 메시지를 처리한다.

CHAPTER 2  어플리케이션 구현파일(.cpp) #include <afxwin.h> // 기초 클래스가 선언된 MFC 라이브러리 헤더 파일 #include “myapp.h” CMyApp theApp; // 단 하나만 존재하는 CMyApp 객체 BOOL CMyApp::InitInstance() { m_pMainWnd = new CMyFrame(); m_pMainWnd -> ShowWindow(m_nCmdShow); m_pMainWnd -> UpdateWindow(); return TRUE; } BEGIN_MESSAGE_MAP (CMyFrame, CFrameWnd) ON_WM_PAINT() ON_WM_LBUTTONDOWN() END_MESSAGE_MAP()

CHAPTER 2  어플리케이션 구현파일 CMyFrame::CMyFrame() { Create(NULL, “MYAPP Application”); } void CMyFrame::OnPaint() CPaintDC dc(this); dc.TextOut(0, 0, “Hello, world!”); void CMyFrame::OnLButtonDown(UINT nFlags, CPoint point) TRACE(“Entering CMyFrame::OnLButtonDown - %lx, %d, %d\n”, (long)nFlags, point.x, point.y);

CHAPTER 2  WinMain() 함수  어플리케이션 내부에 숨겨져 있다.  CMyAPP 클래스  CMyApp::InitInstance() 멤버 함수  어플리케이션의 메인 프레임 윈도우를 구성하고, 출력하는데 필요한 함수를 호출  CWinApp::Run() 멤버 함수  CWinAPP에 상속된 함수  메시지 루프를 만든다.  CMyFrame 클래스  이 클래스의 객체는 어플리케이션의 메인 프레임 윈도우를 나타낸다.  CFrameWnd의 Create() 멤버 함수를 호출하면 실제 윈도우가 만들어진다.

CHAPTER 2  CMyFrame::OnLButtonDown() 함수  WM_LBUTTONDOWN() 메시지를 처리하는 함수  CMyFrame::Onpaint() 함수  WM_PAINT() 메시지를 처리하는 함수  어플리케이션 실행 순서  어플리케이션 실행 WinMain() 함수 호출 CWinApp로 부터 파생된 클래스의 어플리케이션 전역 객체를 찾는다. InitInstance() 멤버 함수를 호출 Run() 멤버 함수를 호출  어플리케이션 종료(Shutdown)  CMyFrame 객체 소멸 Run() 에서 메시지 루프를 빠져 나온다 WinMain() 함수를 끝낸다 CMyApp 객체 소멸

CHAPTER 2  Sequence of Execution  응용 프로그램 초기화 과정에서 WinMain()이 응용 프로그램 객체의 InitApplication()과 InitInstance() 메소드를 호출한다.  WinMain()이 Run() 메소드를 호출할 때, 응용 프로그램의 메시지 펌프가 시작되고, 응용 프로그램의 실행이 끝나면 WinMain()이 응용 프로그램 객체의 ExitInstance() 메소드를 호출한다.  CWinApp is derived from CWinThread.  Represents the main thread of execution for your application.  In recent versions of MFC, the InitInstance, Run, ExitInstance, and OnIdle member functions are actually in class CWinThread. WinMain Initializes current instance of the application Standard function supplied by framework Runs the message loop and OnIdle Cleans up after the application InitInstance ExitInstance Run calls

CHAPTER 3 AppWizard 사용하기 “Hello, World!”

CHAPTER 3  도큐먼트와 뷰(Documents and Views)  도큐먼트 기초 클래스  도큐먼트 기초 클래스 코드는 File메뉴의 Open및 Save메뉴 아이템과 상호작용한다.  파생된 도큐먼트 클래스는 도큐먼트 객체의 데이터를 실질적으로 읽고 쓰는 일을 한다.  뷰 기초 클래스  프레임 윈도우 내에 포함된 클라이언트 영역의 윈도우를 나타낸다.  파생된 뷰 클래스는 자신과 연결된 도큐먼트 클래스와 밀접하게 작용하며 어플리케이션의 화면 출력과 프린터 I/O을 수행한다.

CHAPTER 3 Document View Part of document currently visible  도큐먼트/뷰 구조

CHAPTER 3  뷰(View)  사용자 관점  사용자가 크기를 변경하고 이동하고 닫을 수 있는 정상적인 윈도우.  프로그래머 관점  MFC 라이브러리 CView 클래스에서 파생된 C++ 객체.  MFC 라이브러리 뷰 클래스 코드  헤더파일(H)  구현파일(CPP)  단일 도큐먼트 인터페이스(SDI) 와 다중 도큐먼트 인터페이스(MDI)  SDI 어플리케이션  하나의 윈도우만 가지고 있다.  한 번에 하나의 도큐먼트만이 로드된다.  Notepad  MDI 어플리케이션  다수의 차일드(child) 윈도우를 가지고 있다.  각 차일드 윈도우는 별도의 도큐먼트를 갖는다.  Word, 아래아한글(Hangul)

CHAPTER 3  OnDraw() 멤버 함수  CView 클래스의 가상 멤버 함수  뷰 윈도우가 다시 그려질 때마다 어플리케이션 프레임워크에 의해서 호출.  프로그램 내의 함수가 윈도우의 데이터를 변경시키는 경우  뷰에 상속된 멤버 함수 Invalidate() (또는 InvalidateRect())를 호출하여 윈도우에 변경된 사실을 알려주어야 한다.  Invalidate()가 호출된 후에 OnDraw() 함수가 호출된다.  CView::OnDraw  virtual void OnDraw( CDC* pDC ) = 0;  Parameters  pDC 디바이스 컨텍스트에 대한 포인터

BOOL / TextOut  bool declarators;  This keyword is an integral type.  A variable of this type can have values true and false.  !false == true !true == false  if (expres1) statement1; If expres1 is true, statement1 is always executed; if expres1 is false, statement1 is never executed.  CDC::TextOut  virtual BOOL TextOut( int x, int y, LPCTSTR lpszString, int nCount );  BOOL TextOut( int x, int y, const CString& str );  Parameters  x 텍스트가 시작하는 x좌표(논리 단위).  y 텍스트가 시작하는 y좌표(논리 단위).  lpszString 출력하는 텍스트 문자열에 대한 포인터.  nCount lpszString 파라미터에 의해 가리키는 문자열에 있는 문자의 수.  str 출력하는 텍스트 문자열을 포함하는 CString 오브젝트에 대한 참조.

SelectStockObject(내장객체 중의 하나를 디바이스 컨텍스트에 선택)  virtual CGdiObject* SelectStockObject(int nIndex);  Parameters 종류 의미 BLACK_BRUSH DKGRAY_BRUSH GRAY_BRUSH HOLLOW_BRUSH LTGRAY_BRUSH NULL_BRUSH WHITE_BRUSH BLACK_PEN NULL_PEN WHITE_PEN ANSI_FIXED_FONT ANSI_VAR_FONR DEVICE_DEFAULT_FONT OEM_FIXED_FONT SYSTEM_FONT SYSTEM_FIXED_FONT DEFAULT_PALETTE 검정색 브러시 검정 회색 브러시 회색 브러시 투명한 브러시 밝은 회색 브러시 널 브러시 흰색 브러시 검정색 펜 널 펜 흰색 펜 ANSI 고정 시스템 폰트 ANSI 가변 시스템 폰트 디바이스 의존(Device-dependent) 폰트 OEM 의존 고정 폰트 시스템 폰트 (메뉴, 다이얼로그박스 컨트롤, 텍스트) 고정폭(Fixed-width) 시스템 폰트 (Win3.0 이전 버전) 기본 색상 팔레트(Default color palette)

Ellipse  About Ellipses - 현재의 펜과 현재의 브러쉬로 타원 내부를 채운다. An ellipse is a closed curve defined by two fixed points (f1 and f2) such that the sum of the distances (d1 + d2) from any point on the curve to the two fixed points is constant. Ellipse d1 d2   f1 f2 Bounding rectangle  BOOL Ellipse(int x1, int y1, int x2, int y2);  BOOL Ellipse( LPCRECT lpRect);  Parameters  lpRect 타원의 경계 사각형의 좌표를 포함하는 RECT 구조체나 CRect 객체에 대한 포인터  사각형의 높이 : y2 - y1  사각형의 폭 : x2 - x1.

CHAPTER 3  Visual C++를 이용한 프로그램 작업 순서  The visual design step  The code-writing step 항목 내용  프로젝트의 설계  기본 골격의 작성  리소스 편집  프로그램 코드 기술  컴파일(Debug)  실행, 디버깅  컴파일(Release) 프로그램 동작과 윈도의 외관을 결정한다. AppWizard를 이용한다. ResourceView를 이용한다. ClassWizard를 이용한다. 디버그 정보가 있는 실행 파일을 만든다. 문제가 생긴 부분을 디버거로 알아낸다. 완성된 버전의 실행 파일을 만든다.

CHAPTER 3  진단 매크로(Diagnostic Macros)를 가능한 상태로 만들기  TRACE 매크로 - 프로그램 상태를 모니터링 한다.  이 매크로를 사용하기 위해서는 트레이싱이 가능한 상태로 설정되 어야 한다(디폴트로 설정되어 있다).  TRACER 유틸리티(…\Vc\bin\Tracer.exe)를 실행하여 Enable tracing을 체크한다.  TraceEnabled = 1  프리컴파일 헤더(Precompiled Headers) 이해하기  AppWizard는 프로젝트를 생성할 때에 스위치 설정과 프리컴파일 헤더를 위한 파일들을 만들어 준다.  자동 프리컴파일 헤더  /Yx 스위치를 사용해서 활성화 된다.  데이터 베이스 파일에 컴파일 결과를 저장한다.  수동 프리컴파일 헤더  /Yc, /Yu 스위치에 의해서 활성화 된다.

CHAPTER 3  프리컴파일 헤더(Precompiled Headers) 이해하기  소스 파일 StdAfx.cpp에는 한 문장만이 포함된다.  #include “StdAfx.h” // 다른 헤더 파일을 포함시키는 역할을 한다.  #include문  #include <afxwin.h> // MFC 핵심 표준 구성요소들  #include <afxext.h> // MFC 확장 클래스  #include <afxole.h> // MFC OLE compound document를 사용  #include <afxdisp.h> // Automation 또는 ActiveX 컨트롤을 사용  #include <afxtempl.h> // 템플릿 기반 콜렉션 클래스를 사용(p519)  #include <afxcmn.h> // MFC 공통 컨트롤  #include <afxdlgs.h> // MFC 대화 상자  #include <afxres.h> // MFC 자원  프로그램을 실행시키는 두 가지 방법  Developer Studio에서 직접 실행 : Ctrl + F5  Debugger 에서 실행 : F5

CHAPTER 3 ◐ Visual C++ 프리컴파일 헤더 처리과정 ◑ /Yc “stdafx.h” /Yu “stdafx.h” #include “afxwin.h” #include “afxext.h” StdAfx.h #include “stdafx.h” StdAfx.cpp #include “myprog.h” myprog.cpp StdAfx.pch /Yc “stdafx.h” /Yu “stdafx.h” /Fp “path” sets path for this file ◐ Visual C++ 프리컴파일 헤더 처리과정 ◑

CHAPTER 3 ◐ Hello World의 흐름 ◑ 프레임워크의 처리 개발자와 AppWizard가 기술한 코드 시간의 흐름 이후 메시지 루프를 계속한다 CWinApp::CWinApp 여러가지 초기화 CMainFrame::OnCreate CHelloView::OnDraw CView::OnPaint CHelloApp::CHelloApp CHelloApp::InitInstance 도큐먼트 템플릿의 작성 윈도우 생성 InitInstance InitApplication Run 메시지루프 WinMain CHelloApp theApp; 어플리케이션의 객체정의

성공의 A B C Ability(능력) Brain(두뇌) Challenge(도전)

CHAPTER 4 기본적인 이벤트 처리, 맵핑 모드, 스크롤 뷰

CHAPTER 4  OnKeyDown(), OnLButtonDown()  윈도우 이벤트가 발생할 때 어플리케이션 프레임워크가 호출하는 멤버 함수  이름이 On으로 시작되는 함수  OnKeyDown(), OnLButtonDown()  어플리케이션 프레임워크에 의해서 호출되는 함수들은 대부분 가상 함수가 아니기 때문에 프로그래밍 단계가 더 필요하다.  어플리케이션 프레임워크에 자신의 메시지 핸들러 함수의 코드를 연결하기 위해서는 메시지 맵 구조가 필요하다.  메시지 맵 CHAPTER 2 참조  사용자가 마우스 왼쪽 버튼을 누른다. 윈도우는 WM_LBUTTONDOWN 메시지를 해당 윈도우에 보낸다. 프로그램이 WM_LBUTTONDOWN 메시지를 처리한다.  헤더 파일  함수 원형을 선언  구현 파일  함수를 어플리케이션 프레임워크와 연결해 주는 메시지 맵 매크로를 작성

CHAPTER 4  <함수의 원형 선언부분, 헤더파일> 마우스 버튼 + 다른 키  <함수의 원형 선언부분, 헤더파일> afx_msg void OnLButtonDown(UINT nFlags, CPoint point);  afx_msg는 이 함수가 메시지 맵 함수의 원형임을 알려준다.  <멤버함수 구현부분, 소스파일> void CMyView::OnLButtonDown(UINT nFlags, CPoint point) { // 이벤트 처리코드… }  OnLButtonDown() 함수를 어플리케이션 프레임워크와 연결해 주는 메시지 맵  <클래스 선언부분, 헤더파일> DECLARE_MESSAGE_MAP()  <코드구현 부분, 소스파일> BEGIN_MESSAGE_MAP(CMyView, CView) ON_WM_LBUTTONDOWN END_MESSAGE_MAP() 프로그램 윈도우의 작업 영역에서 마우스의 x, y 위치를 전달(상대좌표)

CHAPTER 4  WM_XXX 메시지와 대응하는 MFC 함수 프로토타입 메시지 함수 프로토타입 WM_CHAR WM_CREATE WM_LBUTTONDOWN WM_DESTROY WM_LBUTTONUP WM_MOUSEMOVE WM_PAINT WM_SIZE afx_msg void OnChar(UINT, UINT. UINT) afx_msg int OnCreate(LPCREATESTRUCT) afx_msg void OnLButtonDown(UINT, CPoint) afx_msg void OnDestroy() afx_msg void OnLButtonUp(UINT, CPoint) afx_msg void OnMouseMove(UINT, CPoint) afx_msg void OnPaint() afx_msg void OnSize(UINT, int, int)

CHAPTER 4  뷰 상태 저장하기 - 클래스 데이터 멤버가 필요하다.  rectEllipse  CRect 클래스 객체로 타원의 주변 사각형을 저장.  m_nColor  타원의 색상값을 저장하는 정수.  뷰 클래스 데이터 멤버 초기화  CMyView::CMyView() : m_rectEllipse(0, 0, 200, 200) {…}  MFC 라이브러리의 클래스 데이터 멤버의 이름은 m_ 으로 시작한다.  무효화 사각형(Invalidate Rectangle)  다시 그려져야 할 영역들을 포함하고 있는 최소한의 사각형  OnLButtonDown() InvalidateRect() WM_PAINT 메시지를 생성 OnDraw() 호출 Invalidate Rectangle 파라 미터를 접근

CHAPTER 4  윈도우에서 경계선, 캡션바, 메뉴바, 툴바 등이 차지하는 부분을 제외한 영역.  윈도우 클라이언트 영역(Client Area)  윈도우에서 경계선, 캡션바, 메뉴바, 툴바 등이 차지하는 부분을 제외한 영역.  GetClientRect() : 클라이언트 영역의 크기를 알 수 있다.  클라이언트 영역 외부에서는 그리기를 수행할 수 없다.  CRect, CPoint, CSize  DevStudio\Vc\mfc\include\<afxwin.h>에 정의 (60, 137, 171, 212 line)  상속받는 데이터 멤버  CRect left, top, right, bottom  CPoint x, y  CSize cx, cy  포인트가 사각형 내에 존재하는지 검사하는 방법  if(m_rectEllipse.PtInRect(point)) { //포인트가 사각형 내에 있을 때 처리할 부분 }

CHAPTER 4  포인트가 타원 내에 존재하는지 검사하는 방법  타원에 대응하는 CRgn 클래스의 객체를 생성한 후, PtInRegion() 함수 사용  CRgn rgn; rgn.CreateEllipticRgnIndirect(m_rectEllipse); if(rgn.PtInRegion(point)) { //포인트가 타원 내에 있을 때 처리할 부분 }  CRect 클래스의 LPRECT 연산자  CWnd::InvalidateRect()  void InvalidateRect( LPCRECT lpRect, BOOL bErase = TRUE ); CRect에 LPRECT() 연산자가 중복정의 되어 있기 때문에 인자가 CRect 객체 가 되더라도 실제 LPRECT 변수를 써놓은 것과 동일하게 사용할 수 있다.  CRect rectClient; GetClientRect(rectClient); // 윈도우의 클라이언트 영역을 얻는다. 윈도우 내부의 타원이나 다각형 영역을 나타내는 특수한 영역 구조체를 생성한 후 이 구조체를 프로그램에 있는 C++ CRgn 객체에 연결한다.

CHAPTER 4  CWnd::Invalidate - 윈도우의 사용자 영역을 무효화한다.  NULL 사각형 포인터가 함수를 호출한다.  윈도우의 무효화 영역은 현재 갱신영역에 모인다.  갱신 영역은 윈도우가 WM_PAINT 메시지를 보내는 다음 번에 칠하는 윈도우의 영역이다.  윈도우는 갱신 영역이 비어 있지 않고 어플리케이션에 대해 대기한 그 이상의 메시지가 없을 때에만 윈도우에 칠하기 명령을 보낸다.  void Invalidate( BOOL bErase = TRUE );  CWnd::InvalidateRect - 특정 사각형을 무효화한다.  void InvalidateRect( LPCRECT lpRect, BOOL bErase = TRUE );  Parameters  lpRect 사용자 좌표로 무효화되는 사각형을 갖는 RECT 구조체나 CRect객체에 대한 포인터. NULL이면, 윈도우는 윈도우의 전체 사용자 영역을 무효화한다.  bErase 칠하기 전에 갱신 영역을 지워야 한다면 TRUE. 갱신 영역의 어떤 부분을 지우기 위해 마크되면 전체 갱신 영역이 지워진다. 영역은 윈도우에 WM_ERASEBKGND 메시지를 보내 지운다.

CHAPTER 4  Size  CSize Size() const;  폭(width)은 오른쪽 x 좌표에서 왼쪽 x 좌표를 뺀 것.  높이(height)는 하단의 y 좌표에서 상단의 y좌표를 뺀 것.  이 값들의 어느 것이나 사각형이 일반화되어 있지 않으면 음수가 된다.  예  CRect rect(1,1,5,7); CSize size; size = rect.Size(); // size는 4,6으로 설정된다.

CHAPTER 4  Rectangle  BOOL Rectangle(int x1, int y1, int x2, int y2);  BOOL Rectangle(LPCRECT lpRect);  Parameters  x1 사각형의 왼쪽 상단의 x좌표(논리단위)  y1 사각형의 왼쪽 상단의 y좌표(논리단위)  x2 사각형의 오른쪽 하단의 x좌표(논리단위)  y2 사각형의 오른쪽 하단의 y좌표(논리단위)  lpRect 사각형의 좌표(논리단위)를 포함하는 RECT 구조체나 CRect 객체에 대한 포인터

CHAPTER 4  WM_PAINT 메시지가 발생되는 경우  사용자가 윈도우를 옮기거나, 윈도우를 제거했을 때 발생한다.  사용자가 윈도우의 크기를 바꿀 때 발생한다.  응용 프로그램이 SendMessage() 함수를 호출하여 WM_PAINT 메시지를 발생시킬 수 있다.  응용 프로그램이 그것의 작업 영역의 일부를 스크롤하기 위하여 ScrollWindow()나, ScrollDC() 함수를 호출할 때 발생한다.  응용 프로그램이 강제적으로 WM_PAINT 메시지를 발생시키기 위해서 InvalidateRect()나, InvalidateRgn() 함수를 호출할 때 발생한다.  윈도우가 윈도우의 겹친 다이얼로그 박스나 메시지 박스를 제거할 때 발생한다.  메뉴가 나타났다가 없어질 때 발생한다.  커서가 작업 영역을 지나서 이동할 때 발생한다.  아이콘이 작업 영역을 지나서 드래그(Drag)될 때 발생한다.

CHAPTER 4  마우스 처리  클라이언트 영역 마우스 메시지  비 클라이언트 영역 마우스 메시지  클라이언트 영역 마우스 메시지  커서가 윈도우의 클라이언트 영역 내에 있을 때 시스템에 의해 계속 발생된다.  클라이언트 영역 마우스 메시지를 위해 MFC가 미리 정의한 메시지 맵 매크로 메시지 맵 매크로 의미 ON_WM_MOUSEMOVE() ON_WM_LBUTTONDBLCLK() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_MBUTTONDBLCLK() ON_WM_MBUTTONDOWN() ON_WM_MBUTTONUP() ON_WM_RBUTTONDBLCLK() ON_WM_RBUTTONDOWN() ON_WM_RBUTTONUP() 사용자가 마우스를 움직임 사용자가 왼쪽 마우스 버튼을 두 번 클릭함 사용자가 왼쪽 마우스 버튼을 클릭함 사용자가 왼쪽 마우스 버튼을 놓음 사용자가 가운데 마우스 버튼을 두 번 클릭함 사용자가 가운데 마우스 버튼을 클릭함 사용자가 가운데 마우스 버튼을 놓음 사용자가 오른쪽 마우스 버튼을 두 번 클릭함 사용자가 오른쪽 마우스 버튼을 클릭함 사용자가 오른쪽 마우스 버튼을 놓음

CHAPTER 4  마우스 처리 class CWnd : public CCmdTarget { protected:  마우스는 하나 또는 그 이상의 버튼을 가진 포인팅 디바이스(Pointing Device) 이다. 윈도우는 마우스가 어떤 동작을 할 때 그 동작에 해당하는 메시지를 발생 시킨다. 프로그램은 이 메시지를 받아서 그 메시지에 대한 처리만 해주면 된다.  WM_MOUSEMOVE 메시지 윈도우는 마우스가 특정 윈도우를 가지거나 움직일 때, 발생되는 메시지를 전달한다. 이때 윈도우는 이 메시지와 함께 마우스와 관련된 정보를 현재 입력 포커스(마우스 커서가 위치한 윈도우)를 가지고 있는 프로그램에 전달한다. 이러한 정보에는 프로그램 윈도우의 작업 영역에서의 마우스 커서 위치와 눌려진 마우스 버튼에 대한 것들이 포함된다.  CWnd 클래스에 protected 액세스 권한을 갖는 멤버 함수로 되어있다. class CWnd : public CCmdTarget { protected: afx_msg void OnMouseMove(UINT nFlags, CPoint point); : }

CHAPTER 4  OnMouseMove() 메시지 처리 함수의 nFlags 매개 변수에 전달되는 값 nFlags 값 의미 MK_CONTROL MK_LBUTTON MK_MBUTTON MK_RBUTTON MK_SHIFT Ctrl 키와 함께 마우스 버튼이 눌려졌다. 마우스의 왼쪽 버튼이 눌려졌다. 마우스의 가운데 버튼이 눌려졌다. 마우스의 오른쪽 버튼이 눌려졌다. Shift 키와 함께 마우스 버튼이 눌려졌다.  windows.h 에 #define으로 정의  void CMainFrame::OnMouseMove(UINT nFlags, CPoint point) { if(nFlags & MK_SHIFT) // Shift 키에 대한 처리 else if(nFlags & MK_LBUTTON) // 마우스의 왼쪽 버튼에 대한 처리 }

CHAPTER 4  마우스 버튼 메시지 class CWnd : public CCmdTarget Button Button Down Button Up Button DoubleClick 왼쪽 가운데 오른쪽 WM_LBUTTONDOWN WM_MBUTTONDOWN WM_RBUTTONDOWN WM_LBUTTONUP WM_MBUTTONUP WM_RBUTTONUP WM_LBUTTONDBLCLK WM_MBUTTONDBLCLK WM_RBUTTONDBLCLK class CWnd : public CCmdTarget { protected: // 메시지 핸들러 메소드 프로토타입 afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); afx_msg void OnMButtonDown(UINT nFlags, CPoint point); afx_msg void OnMButtonUp(UINT nFlags, CPoint point); afx_msg void OnMButtonDblClk(UINT nFlags, CPoint point); afx_msg void OnRButtonDown(UINT nFlags, CPoint point); afx_msg void OnRButtonUp(UINT nFlags, CPoint point); afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); }  CWnd 클래스에 protected 액세스 권한을 갖는 멤버 함수로 되어있다.

CHAPTER 4  마우스 캡쳐  응용 프로그램 창에서 사용자가 마우스 버튼을 누르게 되면, 윈도우 시스템은 그 창에 WM_*BUTTONDOWN 메시지 중의 하나를 보내게 된다 .  이와 같은 플래그를 설정하는 버튼 누름 메시지는 응용 프로그램이 동기를 벗어나지 않도록 이에 대응하는 버튼 놓음 메시지를 갖고 있어야 한다.  윈도우에서 사용자가 마우스 버튼을 누른 상태에서 윈도우 바깥쪽으로 마우스를 움직이고, 그 때 마우스 버튼을 놓게 되면, 윈도우의 동기가 맞지 않게 된다.  WM_*BUTTONDOWN 메시지가 윈도우 안에 있을 때 수신되었다 하더라도 WM_*BUTTONUP 메시지는 전혀 수신되지 않는다.  이유는, 마우스 버튼을 놓았을 때 커서가 윈도우 안에 존재하지 않기 때문이다.

CHAPTER 4  마우스 캡쳐  클래스 CMainFrame이 CFrameWnd로부터 파생된 프레임 윈도우 클래스라고 가정하면, 클라이언트 영역 마우스 버튼 클릭을 처리하기 위한 메시지 맵은 다음과 같이 만들 수 있다. BEGIN_MESSAGE_MAP (CMainFrame, CFrameWnd) ON_WM_LBUTTONDOWN() ON_WM_RBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_RBUTTONUP() ON_WM_MOUSEMOVE() END_MESSAGE_MAP()

CHAPTER 4  마우스 캡쳐  파생된 CMainFrame::OnLButtonDown() 메소드가 왼쪽 마우스 버튼을 눌렀을 때 BOOL 플래그를 설정한다면(m_bLMouseDown), 핸들러의 코드는 다음과 같은 형태가 된다.  void CMainWnd::OnLButtonDown (UINT nFlags, CPoint point) { m_bLMouseDown = TRUE; // 클래스 멤버 마우스 버튼 누름 플래그를 설정 CFrameWnd::OnLButtonDown (nFlags, point); // 상속된 핸들러를 호출 }  void CMainWnd::OnLButtonUp (UINT nFlags, CPoint point) m_bLMouseDown = FALSE;// 클래스 멤버 마우스 버튼 누름 플래그를 재설정 CFrameWnd::OnLButtonUp (nFlags, point); // 상속된 핸들러를 호출

CHAPTER 4  마우스 캡쳐  파생된 CMainFrame::OnLButtonDown() 메소드가 왼쪽 마우스 버튼을 눌렀을 때 BOOL 플래그를 설정한다면(m_bLMouseDown), 핸들러의 코드는 다음과 같은 형태가 된다.  void CMainWnd::OnLButtonDown (UINT nFlags, CPoint point) { m_bLMouseDown = TRUE; // 클래스 멤버 마우스 버튼 누름 플래그를 설정 CFrameWnd::OnLButtonDown (nFlags, point); // 상속된 핸들러를 호출 }  void CMainWnd::OnLButtonUp (UINT nFlags, CPoint point) m_bLMouseDown = FALSE;// 클래스 멤버 마우스 버튼 누름 플래그를 재설정 CFrameWnd::OnLButtonUp (nFlags, point); // 상속된 핸들러를 호출

CHAPTER 4  마우스 이벤트의 흐름이 윈도우의 클라이언트 영역 내에서만 발생하게 되면, 마우스 버튼 상태 플래그가 CMainWnd::OnLButtonDown() Set m_bLMouseDown = TRUE CMainWnd::OnMouseMove() 클라이언트 영역 내에서 마우스를 움직인다. CMainWnd::OnLButtonUp() Set m_bLMouseDown = FALSE  마우스 이벤트의 흐름이 윈도우의 클라이언트 영역 내에서만 발생하게 되면, 마우스 버튼 상태 플래그가 기본적으로 동기를 유지하게 된다.

CHAPTER 4  마우스 캡처하기  버튼 누름 메시지 핸들러 내에서 마우스를 캡처하고 버튼 놓음 메시지 핸들러에서 풀게 되면, 윈도우가 항상 동기를 유지함을 보장할 수 있다.  SetCapture() 아무런 인수도 받아들이지 않으며 현재의 SetCapture()를 호출하기 전에 모든 마우스 입력을 받아들인 CWnd 객체에 대한 포인터를 반환한다.  void CMainWnd::OnLButtonDown (UINT nFlags, CPoint point) { m_bLMouseButton = TRUE; // 클래스 멤버 마우스 누름 플래그 SetCapture(); // 마우스를 캡처 CFrameWnd::OnLButtonDown(nFlags, point); // 상속된 핸들러를 호출 }  void CMainWnd::OnLButtonUp (UINT nFlags, CPoint point) m_bLMouseButton = FALSE; // 클래스 멤버 마우스 누름 플래그 ReleaseCapture(); // 마우스 캡처를 푼다 CFrameWnd::OnLButtonUp(nFlags, point); // 상속된 핸들러를 호출

CHAPTER 4  비 클라이언트 영역 마우스 메시지  커서가 윈도우의 비 클라이언트 영역 내에 있을 때 계속해서 시스템에 의해 생성된다.  윈도우의 비 클라이언트 영역은 캡션 표시줄과 축소와 확대 단추, 닫기 단추, 시스템 메뉴 아이콘, 윈도우 틀 등으로 이루어져 있다.  비 클라이언트 영역 마우스 메시지를 위해 MFC가 미리 정의한 메시지 맵 매크로 메시지 맵 매크로 의미 ON_WM_NCMOUSEMOVE() ON_WM_NCLBUTTONDBLCLK() ON_WM_NCLBUTTONDOWN() ON_WM_NCLBUTTONUP() ON_WM_NCMBUTTONDBLCLK() ON_WM_NCMBUTTONDOWN() ON_WM_NCMBUTTONUP() ON_WM_NCRBUTTONDBLCLK() ON_WM_NCRBUTTONDOWN() ON_WM_NCRBUTTONUP() 사용자가 비 클라이언트 영역에서 마우스를 움직임 „ 왼쪽 마우스 버튼을 두 번 클릭함 „ 왼쪽 마우스 버튼을 클릭함 „ 왼쪽 마우스 버튼을 놓음 „ 가운데 마우스 버튼을 두 번 클릭함 „ 가운데 마우스 버튼을 클릭함 „ 가운데 마우스 버튼을 놓음 „ 오른쪽 마우스 버튼을 두 번 클릭함 „ 오른쪽 마우스 버튼을 클릭함 „ 오른쪽 마우스 버튼을 놓음

CHAPTER 4  메시지 핸들러 메소드 프로토타입 afx_msg UINT OnNcHitTest (CPoint point); afx_msg void OnNcLButtonDown (UINT nHitTest, CPoint point); afx_msg void OnNcLButtonUp (UINT nHitTest, CPoint point); afx_msg void OnNcLButtonDblClk (UINT nHitTest, CPoint point); afx_msg void OnNcMButtonDown (UINT nHitTest, CPoint point); afx_msg void OnNcMButtonUp (UINT nHitTest, CPoint point); afx_msg void OnNcMButtonDblClk (UINT nHitTest, CPoint point); afx_msg void OnNcRButtonDown (UINT nHitTest, CPoint point); afx_msg void OnNcRButtonUp (UINT nHitTest, CPoint point); afx_msg void OnNcRButtonDblClk (UINT nHitTest, CPoint point); afx_msg void OnNcMouseMove (UINT nHitTest, CPoint point);  nHitTest 매개 변수는 메시지가 전송되었을 때의 커서가 비 클라이언트 영역내의 어느 부분에 있었는지를 나타내는 히트-테스트 코드이다.  비 클라이언트 영역 마우스 메시지 핸들러에서 윈도우가 nHitTest 매개 변수 를 제공하기 때문에 자신의 프로그램에서 OnNcHitTest() 메소드를 재정의할 필요는 거의 없다.

CHAPTER 4 ◐ 물리적 좌표 시스템  GDI 좌표 시스템  물리적 좌표 시스템(장치좌표), 논리적 좌표 시스템(논리좌표)  물리적 좌표 시스템  비디오 화면과 같은 물리적 장치의 좌표계  화면의 창은 원점(0,0)이 화면 왼쪽 위에서 시작하며, 오른쪽으로 갈수록 x축의 값이 증가하고, 아래로 내려갈수록 y축의 값이 증가한다.  창의 오른쪽 아래는 화면의 오른쪽 아래에 해당된다.  비디오 화면의 실제 수는 현재의 비디오 해상도에 좌우된다.  일반적인 해상도 (640, 480), (800, 600), (1024, 768) 장치좌표 원점 (0,0) +X축 +Y축 ◐ 물리적 좌표 시스템

CHAPTER 4  GDI 좌표 시스템  윈도우는 그래픽 출력을 내보내기 전에 현재의 논리적 화면의 좌표를 물리적 장치에 맵핑한다.  GDI 함수들 각각은 논리적 좌표를 사용하고 있다.  맵핑 모드를 이용하여, 응용 프로그램이 GDI 그래픽 출력을 논리적 창에 보내면 GDI는 출력을 물리적 창이나 몇몇 다른 장치(프린터 등)에 맵핑한다.  실제 화면 크기를 픽셀 단위로 구하고자 할 때 GetSystemMetrics() 를 사용한다.  화면 너비를 구하고자 할 때 GetSystemMetrics(SM_CXSCREEN) 을 사용한다.  화면 높이를 구하고자 할 때 GetSystemMetrics(SM_CYSCREEN) 을 사용한다.

CHAPTER 4  맵핑 모드(Mapping Mode)  MM_TEXT 맵핑 모드  Fixed-Scale(고정 비율) 맵핑 모드  Variable-Scale (가변 비율) 맵핑 모드  MM_TEXT 맵핑 모드 ( 장치좌표 )  드로잉 단위 : Pixel  디바이스 좌표계와 거의 비슷하지만 CDC 클래스의 멤버 함수인 SetViewportOrg 와 SetWindowOrg 함수를 사용하여 원점을 바꿀 수 있다. void CMyView::OnDraw(CDC* pDC) { pDC -> SetMapMode(MM_TEXT); pDC -> SetWindowOrg(CPoint(100, 100)); pDC -> Rectangle(CRect(100, 100, 300, 300)); }  논리 좌표(100, 100) 은 장치 좌표(0, 0) 에 맵핑된다. CDC 클래스의 멤버 함수는 논리 좌표를 사용하므로 Rectangle() 함수는 논리 좌표의 원점을 기준으로 사각형을 그린다.(p118-119)

CHAPTER 4 ◐ 원점이 (100, 100) 으로 이동된 다음에 그려진 사각형 ◑ (0, 0) (100, 100) origin in logical coordinate space... ...maps to (0, 0) origin in device coordinate space This is the visible part of logical coordinate space This is what you would see on screen

CHAPTER 4  고정 비율(Fixed-Scale) 맵핑 모드  CDC::SetMapMode  virtual int SetMapMode(int nMapMode); Mapping Mode Logical Unit MM_HIENGLISH MM_LOENGLISH MM_HIMETRIC MM_LOMETRIC MM_TEXT(장치좌표) MM_TWIPS 0.001 inch 0.01 inch 0.01 mm 0.1 mm 1 device pixel(+X: 오른쪽 , +Y: 아래) a twip is 1/1440 inch, 1/20 of a point(a point is 1/72 inch)  Positive x is to the right; positive y is up.(p119)  가변 비율(Variable-Scale) 맵핑 모드 맵핑 모드 설명 MM_ISOTROPIC MM_ANISOTROPIC xy 축이 항상 1:1로 유지됨. xy 축의 scale factor 가 독립적으로 설정될 수 있다.  MM_ISOTROPIC, MM_ANISOTROPIC 는 현재의 창이나 뷰포트 설정을 변경하지 않는다. 단위나 방향, 비율을 변경하고자 할 때는 CDC::SetWindowExt() 와 CDC:: SetViewportExt() 메소드를 사용한다.

CHAPTER 4  맵핑 모드를 처리할 때 유용한 CDC 클래스 메소드 메소드 설명 GetViewportExt() GetViewportOrg() GetWindowExt() GetWindowOrg() ScaleWindowExt() ScaleViewportExt() SetViewportExt() SetViewportOrg() SetWindowExt() SetWindowOrg() 장치 컨텍스트의 뷰포트의 크기를 구한다. 장치 좌표계에서 뷰포트의 원점을 구한다. 장치 컨텍스트와 연관된 창의 크기를 구한다. 장치 컨텍스트와 연관된 창의 원점 좌표를 구한다. 장치 컨텍스트와 연관된 창의 확장 배율을 정한다. 뷰포트의 현재 확장 값들에 상대적으로 뷰포트 확장을 수정한다. 장치 컨텍스트의 확장을 설정한다. 장치 컨텍스트의 뷰포트 원점을 설정한다. 장치 컨텍스트와 연관된 창의 크기를 설정한다. 장치 컨텍스트와 연관된 창의 원점을 설정한다.  맵핑 모드를 처리할 때 유용한 CDC 클래스 메소드

CHAPTER 4  윈도우의 크기에 맞는 타원을 출력하는 OnDraw 함수  void CMyView::OnDraw(CDC* pDC) { CRect rectClient; GetClientRect(rectClient); pDC -> SetMapMode(MM_ANISOTROPIC); pDC -> SetWindowExt(1000, 1000); pDC -> SetViewportExt(rectClient.right, -rectClient.bottom); pDC -> SetViewportOrg(rectClient.right / 2, rectClient.bottom / 2); pDC -> Ellipse(CRect(-500, -500, 500, 500)); }  SetWindowExt, SetViewportExt 는 고정 비율 맵핑 모드인 경우, 인자값 들은 무시된다. 그러나, MM_ISOTROPIC 인 경우에는 그림을 그리기 전에 반드시 두 함수가 호출되어야 한다.  맵핑 모드는 OnDraw() 함수보다는 CView 클래스의 가상 함수 OnPrepareDC() 에서 설정하는 것이 낫다.

CHAPTER 4  MM_ANISOTROPIC  MM_ISOTROPIC 맵핑 모드에서 중앙에 그려진 타원 Client rectangle (-500, 0) (500, 0) (0, 500) (0, -500) Y축 x축 (0, 0)

CHAPTER 4  CDC::SetWindowExt - 윈도우의 수평과 수직 범위를 설정한다.  virtual CSize SetWindowExt(int cx, int cy); virtual CSize SetWindowExt(SIZE size);  Parameters  cx 윈도우의 수평범위 (logical units)  cy 윈도우의 수직범위 (logical units)  size 새로운 윈도우의 범위 (logical units) 를 포함하는 SIZE 구조체나 CSize 객체  CDC::SetViewportExt - 뷰포트의 수평과 수직 범위를 설정한다.  virtual CSize SetViewportExt(int cx, int cy); virtual CSize SetViewportExt(SIZE size);  cx 뷰포트의 수평범위 (device units)  cy 뷰포트의 수직범위(device units)  size 새로운 뷰포트 원점(device units)을 포함하는 SIZE 구조체나

CHAPTER 4  CDC::SetWindowOrg - 윈도우의 원점을 설정한다.  CPoint SetWindowOrg(int x, int y); CPoint SetWindowOrg(POINT point);  Parameters  x 새로운 윈도우 원점의 x 좌표 ( 논리단위)  y 새로운 윈도우 원점의 y 좌표 (논리단위)  point 새로운 윈도우 원점(논리단위)을 포함하는 POINT 구조체나 CPoint 객체  CDC::SetViewportOrg - 뷰포트의 원점을 설정한다.  virtual CPoint SetViewportOrg(int x, int y); virtual CPoint SetViewportOrg(POINT point);  x 새로운 뷰포트 원점의 x 좌표 (장치단위)  y 새로운 뷰포트 원점의 y 좌표 (장치단위)  point 새로운 뷰포트 원점(장치단위)을 포함하는 POINT 구조체나

CHAPTER 4  좌표계(Coordinate) 변환  좌표 시스템을 언제 사용할 것인가 결정할 수 있는 규칙  CDC 멤버 함수는 논리 좌표의 파라미터를 사용한다.  CWnd 멤버 함수는 장치 좌표의 파라미터를 사용한다.  Hit-Test는 장치 좌표에서 작동한다.  영역(Region)은 장치 좌표로 정의한다.  CRect::PtInRect() 등과 같은 함수들은 장치 좌표를 사용하여 작업한다.  장기간 유지될 값들은 논리 좌표 또는 물리 좌표에 저장한다.  좌표변환 함수들의 프로토타입 void LPtoDP(LPPOINT lpPoints, int nCount = 1) const; void LPtoDP(LPRECT lpRect) const; void LPtoDP(LPSIZE lpSize) const; void DPtoLP(LPPOINT lpPoints, int nCount = 1) const; void DPtoLP(LPRECT lpRect) const; void DPtoLP(LPSIZE lpSize) const;

CHAPTER 4  LPtoDP - 논리 좌표를 장치 좌표로 변환  Parameters  lpPoints - 변환되는 POINT 구조체나 CPoint 객체에 대한 포인터  nCount - 변환되는 위치의 수  lpRect - 변환되는 RECT 구조체나 CRect 객체에 대한 포인터  lpSize - 변환되는 SIZE 구조체나 CSize 객체에 대한 포인터  논리 좌표를 장치 좌표로 변환하는 공식  x비율인자 = x뷰포트 범위 / x윈도우 범위  y비율인자 = y뷰포트 범위 / y윈도우 범위  장치단위 x = 논리단위 x * x비율인자 + x원점 옵셋  장치단위 y = 논리단위 y * y비율인자 + y원점 옵셋  DPtoLP - 장치 좌표를 논리 좌표로 변환

CHAPTER 4  뷰 윈도우 스크롤 하기  CScrollView 클래스는 CView 클래스에서 파생되었으며, 스크롤바를 가지고 있다. 키보드에 의한 스크롤 기능은 제공되지 않으므로 직접 코드를 작성해야 한다.  윈도우는 실제 보이는 크기보다 훨씬 더 크다.  실제 보이는 부분을 뷰포트(Viewport)라고 한다.  뷰포트의 크기는 클라이언트 영역의 크기에 따라 달라진다.  스크롤바를 사용하여 뷰포트의 영역을 옮길 수 있다.  스크롤바  윈도우 자체는 스크롤바를 윈도우에 연결시키지 않는다.  CScrollView 클래스의 멤버 함수들은 스크롤바에 의해 뷰로 보내지는 WM_HSCROLL, WM_VSCROLL 메시지를 처리해 준다.  또 다른 스크롤 방식  라인수가 너무 많아 윈도우에 모두 포함시킬 수 없을 경우, 윈도우에 모든 라인을 포함시키지 않고, 화면에 보이는 만큼의 라인을 얻고 싶다면, 사용자가 CView 로 부터 파생하는 클래스를 작성해야 한다.

CHAPTER 4  CWnd::OnVScroll - 수직 스크롤 이벤트가 뷰에서 발생할 때 호출된다.  Parameters  afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);  Parameters nSBCode - 발생하는 스크롤 행위와 타입  SB_BOTTOM 아래로 스크롤  SB_TOP 위로 스크롤  SB_ENDSCROLL 스크롤의 끝  SB_LINEDOWN 한 라인 아래로 스크롤  SB_LINEUP 한 라인 위로 스크롤  SB_PAGEDOWN 한 페이지 아래로 스크롤  SB_PAGEUP 한 페이지 위로 스크롤  SB_THUMBPOSITION 절대 위치로 스크롤  SB_THUMBTRACK 스크롤 박스를 지정 위치로 드래그한다. nPos  SB_THUMBPOSITION or SB_THUMBTRACK 코드에 대한 현재 스크롤바 위치. 그렇지 않으면 사용되지 않는다. pScrollBar  알림 코드를 보내는 스크롤바 컨트롤. 이 파라미터는 스크롤바가 뷰에 속해 있으면 NULL이다.

CHAPTER 4  CWnd::OnHScroll - 수평 스크롤 이벤트가 뷰에서 발생할 때 호출된다.  Parameters  afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);  Parameters nSBCode - 발생하는 스크롤 행위와 타입  SB_LEFT 왼쪽으로 스크롤  SB_RIGHT 오른쪽으로 스크롤  SB_ENDSCROLL 스크롤의 끝  SB_LINELEFT 한 라인 왼쪽으로 스크롤  SB_LINERIGHT 한 라인 오른쪽으로 스크롤  SB_PAGELEFT 한 페이지 왼쪽으로 스크롤  SB_PAGERIGHT 한 페이지 오른쪽으로 스크롤  SB_THUMBPOSITION 절대 위치로 스크롤  SB_THUMBTRACK 스크롤 박스를 지정 위치로 드래그한다. nPos  SB_THUMBPOSITION or SB_THUMBTRACK 코드에 대한 현재 스크롤바 위치. 그렇지 않으면 사용되지 않는다. pScrollBar  알림 코드를 보내는 스크롤바 컨트롤. 이 파라미터는 스크롤바가 뷰에 속해 있으면 NULL이다.

CHAPTER 4  CScrollView::SetScrollSizes  void SetScrollSizes ( int nMapMode, SIZE sizeTotal, const SIZE& sizePage = sizeDefault, const SIZE& sizeLine = sizeDefault );  Parameters  nMapMode 현재 뷰의 맵핑 모드를 설정한다.  sizeTotal 스크롤 뷰의 전체 크기  sizePage 스크롤바 페이지를 나타내는 장치단위의 크기. 스크롤바 페이지는 사용자가 스크롤바 트랙 범위 내를 클릭할 때 이동된 거리이다.  sizeLine 스크롤바 라인을 나타내는 장치단위의 크기. 스크롤바 라인은 사용자가 스크롤바 트랙 범위 내를 클릭할 때 이동된 거리이다.

CHAPTER 4  OnInitialUpdate() 함수  뷰 윈도우가 완전히 생성된 후, OnDraw() 함수를 호출하기 직전에 프레임워크에 의해 첫번째로 호출되는 함수.  키보드 입력 받아들이기  키보드를 누르게 되면, 윈도우는 가상 키 코드와 함께 WM_KEYDOWN과 WM_KEYUP 메시지를 해당 윈도우에 보낸다. 윈도우에 이 메시지가 도착하기 전에, ANSI 문자세트가 눌려진 경우, 이 메 시지는 Shift 키가 눌려진 상태를 검사하여 WM_CHAR로 변환하게 된다. 커서키와 펑션키와 같은 키들은 코드값이 없으므로 변환되지 않는다. 이때 발생된 메시지들은 WM_KEYDOWN과 WM_KEYUP 메시지 만을 갖는다.  WM_CREATE 메시지  이 메시지는 윈도우가 뷰에 보내는 첫번째 메시지이다. 윈도우의 Create() 함 수가 호출되면 윈도우의 생성이 끝난 것이 아니므로, OnCreate() 함수내에서 는 윈도우 함수를 호출할 수 없다. 따라서 윈도우의 생성 후 초기화에 대한 함수는 OnInitialUpdate() 함수를 재정의(Override) 해서 사용해야 한다.

CHAPTER 4  WM_CLOSE 메시지  사용자가 시스템메뉴에서 [닫기]를 선택하거나, 부모 윈도우가 닫히게 되면 윈도우는 WM_CLOSE 메시지를 보내게 된다. 사용자는 OnClose() 함수를 재정의하여 윈도우를 받을 때 사용자에게 파일을 저장할 것인지 묻는 작업을 만들 수 있다. (OnClose() 에 처리하는 이와 같은 작업을 CDocument::SaveModified() 함수를 재정의하여 대신 사용할 수 있다.)  WM_QUERYENDSESSION 메시지  윈도우 95를 종료하게 될 때 실행중인 모든 어플리케이션에 WM_QUERYENDSESSION 메시지를 보낸다. WM_CLOSE 메시지 핸들러를 기술했다면, WM_QUERYENDSESSION 메시지 핸들러를 추가해야 한다.  WM_DESTROY 메시지  윈도우는 WM_CLOSE 메시지 후에 이 메시지를 보내고, OnDestroy() 함수가 호출된다. OnDestroy() 함수 내에서는 닫는 작업을 취소할 수 없다. 함수 내부에서 반드시 Base class 의 OnDestroy() 함수를 호출하도록 한다.  WM_NCDESTROY 메시지  이 메시지는 윈도우가 파괴되고 난 후 최종적으로 받게 되는 메시지이고 OnNcDestroy() 함수가 호출된다. 함수 내부에서 반드시 Base class 의 OnNcDestroy() 를 호출하도록 한다.

CHAPTER 4  키보드 처리  윈도우 시스템은 입력 포커스를 막 잃어버리거나 갖게 되는 윈도우에 대해 WM_KILLFOCUS와 WM_SETFOCUS 메시지들을 보내게 된다.  MFC는 이들 메시지를 미리 정의된 메시지 핸들러인 CWnd::OnSetFocus(), CWnd::OnKillFocus() 로 싸고 있다.  윈도우의 자식 컨트롤이 포커스를 얻게 되면, 이의 부모 윈도우에 대한 키보드 메시지들이 중단되며, 자식 컨트롤이 그 대신 메시지들을 얻게 된다.  어느 윈도우가 현재 포커스를 갖고 있는지 찾기 위해서는 CWnd::GetFocus() 메소드나 Win32 API 함수인 GetFocus() 를 호출하면 된다.

CHAPTER 4  키보드 메시지  윈도우 시스템은 입력 포커스를 갖고 있는 윈도우에게 사용자가 어떤 키들을 입력하고 있는지 알려 주기 위해 키보드 메시지들을 전송한다. 이들 메시지는 WM_KEYDOWN 과 WM_KEYUP이며, CWnd::OnKeyDown() 과 CWnd::OnKeyUp() 메시지 핸들러로 포장되어 있다.  Alt키를 제외하고는 모든 키가 WM_KEYDOWN과 WM_KEYUP 메시지를 보낸다  Alt키는 시스템 키로 WM_SYSKEYDOWN과 WM_SYSKEYUP 메시지를 보내는데, MFC는 이를 CWnd::OnSysKeyDown()과 CWnd::OnSysKeyUp() 메시지 핸들러로 포장하고 있다.  사용자가 Alt키를 누른 상태에서 다른 키를 누르게 되도 MFC는 CWnd::SysKeyDown() 핸들러 메소드를 호출한다.  MFC가 키보드 메시지를 위해 정의한 메시지 핸들러의 프로토타입 afx_msg void OnMessageHandler (UINT nChar, UINT nRepCnt, UINT nFlags)  nChar - 누르거나 손을 뗀 키  nRepCnt - 반복 횟수(키의 입력 횟수), 시스템 키의 경우 - 값은 1 다른 키의 경우 - 값은 0  nFlags - 스캔 코드와 키 전이 코드, 이전 키 상태, 키에 대한 컨텍스트 코드

CHAPTER 4  MFC 키보드 메시지 핸들러의 nFlags 매개 변수에서 사용한 비트 비트 값 의미 0-7 8 9-10 11-12 13 14 15 스캔 코드 : 키보드에서 발생한 8비트의 OEM 스캔 코드 값 확장 키 : 기능 키나 숫자 키패드에 있는 키와 같은 확장 키를 나타낸다. 1이면 확장 키, 0이면 일반 키 예약된 부분 : 사용하지 않음 예약된 부분 : 윈도우 시스템이 내부적으로 사용 컨텍스트 코드 : 키를 눌렀을 때 Alt키를 눌렀는지를 나타낸다. Alt키를 눌렀으면 1, 그렇지 않으면 0 이전 상태 : 키의 이전 상태를 나타낸다. 이전에 누른 상태였으면 1, 누르지 않은 상태였으면 0 전이 상태 : 키의 전이 상태를 나타낸다. 키를 누르고 있는 상태면 0, 원상 복구하고 있는 상태면 1

CHAPTER 4  MFC 키보드 메시지 핸들러에서 nFlags의 확장 키 비트에 의해 나타난 확장 키 키 위치 Alt 화살표 키 Ctrl Delete End Enter Home, Insert 키보드의 오른쪽 숫자 키 패드와 주 키보드 키 사이 한 곳에만 있음 두 개의 Enter 키 PageDown, PageUp 슬래시(/) 양쪽의 / 키

CHAPTER 4  가상 키 코드  대부분의 응용 프로그램이 확장 키 비트를 무시하고, 그 대신 가상 키 코드를 사용하고 있다.  윈도우 시스템이 자동으로 올바른 가상 키 코드를 결정하기 때문에 키들은 항상 올바른 스캔 코드 값과 일치하게 된다.  윈도우가 키보드 입력을 위해 사용하는 가상 키 코드 가상 키 코드 키보드의 키 VK_0 ~ VK_9 키보드 맨 위에 있는 0~9까지의 키 VK_A ~ VK_Z A~Z까지의 키 VK_ADD 숫자 키패드의 + 키 VK_BACK 백 스페이스 키 VK_CANCEL Ctrl + Break 조합

CHAPTER 4  윈도우가 키보드 입력을 위해 사용하는 가상 키 코드 가상 키 코드 키보드의 키 VK_CAPITAL CapsLock 키 VK_CLEAR Clear 키 (NumLock이 꺼져 있을 때의 숫자 키패드의 5번 키) VK_CONTROL Ctrl 키 VK_DECIMAL 숫자 키패드의 . 키 VK_DELETE Delete 키 VK_DIVIDE 숫자 키패드의 / 키 VK_DOWN 아래 화살표 키 VK_END End 키 VK_ESCAPE Esc 키 VK_F1~VK_F12 F1 ~ F12까지의 기능 키

CHAPTER 4  윈도우가 키보드 입력을 위해 사용하는 가상 키 코드 가상 키 코드 키보드의 키 VK_HOME Home 키 VK_INSERT Insert 키 VK_LEFT 왼쪽 화살표 키 VK_MENU Alt 키 VK_MULTIPLY 숫자 키패드의 * 키 VK_NEXT Page Down과 PgDn 키 VK_NUMLOCK NumLock 키 VK_NUMPAD0 ~ VK_NUMPAD9 숫자 키패드의 0 ~ 9까지의 키 VK_PAUSE Pause 키

CHAPTER 4  윈도우가 키보드 입력을 위해 사용하는 가상 키 코드 가상 키 코드 키보드의 키 VK_PRIOR Page Up과 PgUp 키 VK_RETURN 엔터 키 VK_RIGHT 오른쪽 화살표 키 VK_SCROLL Scroll Lock 키 VK_SHIFT Shift 키 VK_SNAPSHOT Print Screen 키 VK_SPACE 스페이스 바 VK_SUBTRACT 숫자 키패드이 - 키 VK_TAB 탭 키 VK_UP 위 화살표 키

CHAPTER 4  상태 변경 키와 토글 키의 상태를 감지  상태 변경 키 - Alt, Ctrl, Shift  토글 키 - CapsLock, Num Lock  Win32 API 함수 GetKeyState() 를 사용 - 현재의 키의 상태를 나타내는 BOOL 값을 반환한다.  모든 가상 키의 상태를 한번에 알 필요가 있을 경우에는 Win32 API 함수인 GetKeyboardState() 를 호출하면 된다.  BOOL bAltPressed = ::GetKeyState(VK_MENU); Alt키를 눌렀는지의 여부를 결정하는 역할을 한다.  BOOL bCapsLockOn = ::GetKeyState(VK_CAPITAL) & 0x01; 16진수 값 0x01을 비트 단위 AND 연산자(&)에 적용하여 밑의 부분의 비트를 추출하면 된다.

CHAPTER 4  문자 메시지  키보드 배치가 각 나라의 모국어의 특성에 따라 나라마다 다르기 때문에 코드 페이지와 문자 집합도 달라지게 된다.  WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP 메시지를 사용할 때 문제가 발생하게 된다.  윈도우는 Win32 API 함수 TranslateMessage() 를 호출하여 이들 네 개의 메시지를 WM_CHAR와 WM_SYSCHAR 메시지로 변환할 수 있도록 한다.  WM_CHAR 처리하기  ON_WM_CHAR() 메시지 맵 항목과 함께 사용해야 한다.  OnChar() 메소드 프로토타입과 인수들은 OnKeyDown()과 OnKeyUp() 과 같으나 nChar 문자는 OEM이 아닌 ANSI 문자이다.  afx_msg void OnChar (UINT nChar, UINT nRepCnt, UINT nFlags);  변환된 WM_CHAR 메시지는 항상 앞의 WM_KEYDOWN 메시지와 뒤의 WM_KEYUP 메시지 사이에 끼게 된다.

CHAPTER 4  윈도우에서 키보드 입력의 흐름 물리적 키보드 스캔 코드 윈도우 95와 논리적 키보드 키보드 드라이버 WM_KEYDOWN 메시지 WM_CHAR WM_KEYUP 물리적 키보드 논리적 키보드 스캔 코드

CHAPTER 4  키보드 핸들러 void CMainWnd::OnChar (UINT nChar, UINT nRepCnt, UINT nFlags) { CString msg = “WM_CHAR”; // 글자를 그림 ShowKeyInfo(msg, nChar, nRepCnt, nFlags); CFrameWnd::OnChar(nChar, nRepCnt, nFlags); // 상속한 핸들러를 호출 }

의식과 운명 의식이 바뀌면 사고가 바뀐다. 사고가 바뀌면 행동이 바뀐다. 행동이 바뀌면 습관이 바뀐다. 습관이 바뀌면 인격이 바뀐다. 인격이 바뀌면 운명이 바뀐다. -윌리암 제임스-

CHAPTER 5 그래픽 디바이스 인터페이스(GDI) 색상, 폰트

CHAPTER 5  디바이스 컨텍스트(Device Context)  디바이스 컨텍스트란?  물리적 장치(모니터, 프린터…)의 그리기 속성에 관한 정보를 가지고 있는 윈도우 자료구조체. - (물리적 장치의 논리적 버전)  논리적 장치의 예 - 메타파일 (장치와 독립적인 포맷으로 그림을 저장한 구조를 모아놓은 것)  Win32 API에서 제공하는 Device Context  화면 컨텍스트 - 비디오 화면에서 그래픽 동작을 지원한다.  정보 컨텍스트 - 장치 데이터의 검색을 제공한다.  메모리 컨텍스트 - 비트맵에서 그래픽 동작을 지원한다.  프린터 컨텍스트 - 프린터나 플로터에서 그래픽 동작을 지원한다.

CHAPTER 5  GDI (Graphic Device Interface)  DC는 장치를 나타내며, 응용 프로그램이 하드웨어에 직접 그리지 않아도 되도록 하는 추상 층을 제공하는 역할을 한다.  GDI는 윈도우 그래픽 함수 호출에 대응하여 적절한 장치 드라이버를 호출함으로써 이와 같은 추상 계층을 제공한다. 응용 프로그램 MFC Device Context 클래스 장치 드라이버 GDI 물리적 하드웨어 ◐ 하드웨어와 MFC 응용 프로그램 사이의 추상 계층들

CHAPTER 5  디바이스 컨텍스트(Device Context) 클래스  윈도우에서 수행된 모든 그리기 작업은 장치 컨텍스트에 대해 이루어진다.  C++ GDI 객체는 HDC 타입의 핸들로 정의되는 윈도우 디바이스 컨텍스트를 가지고 있다.  많은 디바이스 컨텍스트 클래스는 CDC 에서 파생된다. CObject CMetaFileDC CWindowDC CDC CPaintDC CClientDC ◐ MFC 장치 컨텍스트 클래스의 계층

CHAPTER 5  디바이스 컨텍스트 (Device Context) 클래스  DevStudio\Vc\mfc\include\<Afxwin.h> 클래스 이름 설명 CDC CClientDC CPaintDC CWindowDC CMetaFileDC 윈도우 디바이스 컨텍스트를 캡슐화한다. (605라인) 윈도우의 사용자 영역에 대한 디바이스 컨텍스트를 캡슐화한다. (1032라인) WM_PAINT 메시지에 응답하여 BeginPaint 와 EndPaint 함수를 캡슐화하는 것을 제외하고는 CDC와 동일하다. (1069라인) 윈도우의 전체 영역에 대한 디바이스 컨텍스트를 캡슐화한다. (1053라인) 메타파일에 대해 디바이스 컨텍스트를 캡슐화한다.  디스플레이 컨텍스트 클래스 - CClientDC와 CWindowDC  윈도우의 클라이언트 영역은 경계선, 캡션바, 메뉴바 등을 제외한 영역이다.  CClientDC 객체를 만들게 되면 이 클라이언트 영역의 좌상단이(0, 0) 좌표에 해당하게 된다.  뷰 윈도우는 프레임윈도우의 차일드 윈도우이다.  CWindowDC 는 윈도우 비클라이언트 영역의 좌상단이 (0, 0) 좌표가 된다.

CHAPTER 5  기반 클래스 - CDC  장치 컨텍스트 객체를 정의한다.  화면, 프린터, 창의 클라이언트 영역에 그릴 수 있는 메소드들을 제공한다.  모든 그래픽 출력은 CDC가 제공하는 클래스 메소드들을 사용해야 한다. 클래스 멤버 설명 m_hDC m_hAttribDC CDC 객체에 대한 출력 장치 컨텍스트. 출력을 만드는 대부분의 CDC GDI 호출은 이 멤버 DC를 사용한다. CDC 객체에 대한 특성 장치 컨텍스트. CDC객체로부터의 정보를 요청하는 대부분의 CDC GDI 호출은 이 멤버 DC를 사용한다. ◐ CDC 객체의 클래스 멤버  DC 설정  CDC::SetAttribDC() - m_hAttribDC(특성 장치 컨텍스트)를 설정  CDC::SetOutputDC() - m_hDC(출력 장치 컨텍스트)를 설정  DC 해제  CDC::ReleaseAttribDC() - m_hAttribDC를 반납  CDC::ReleaseOutputDC() - m_hDC를 반납

CHAPTER 5  CDC 객체를 만들고 사용하기  생성자인 CDC::CDC() 를 호출해야 한다.  세 가지 초기화 메소드 중의 하나를 호출해야 한다. ◐ CDC 객체의 초기화 메소드 초기화 메소드 설명 CreateDC() CreateIC() CreateCompatibleDC() 프린터와 같은 특정 장치에 대한 장치 컨텍스트를 만든다. 장치 컨텍스트를 만들지 않고 장치 정보에 액세스하기 위해 특정 장치에 대한 정보 컨텍스트를 생성한다. 기존의 장치 컨텍스트와 호환성이 있는 새로운 메모리 장치 컨텍스트를 만든다. 메모리 내에 그래픽 이미지를 준비하고자 할 때 보통 사용한다.

CHAPTER 5  CDC::CreateDC()  특정 장치에 대한 장치 컨텍스트를 만든다.  DC가 생성되면 TRUE를 반환, 생성되지 않으면 FALSE를 반환  virtual BOOL CreateDC( LPCTSTR lpszDriverName, LPCTSTR lpszDeviceName, LPCTSTR lpszOutput, const void* lpInitData );  CDC::CreateIC()  특정 장치에 대한 정보 컨텍스트를 만든다.  IC가 생성되면 TRUE를 반환, 생성되지 않으면 FALSE를 반환  virtual BOOL CreateIC( LPCTSTR lpszDriverName,  CDC::CreateCompatibleDC()  virtual BOOL CreateCompatibleDC( CDC* pDC );  pDC 매개 변수로 주어진 DC와 호환성이 있는 메모리 DC를 만든다.  매개 변수가 NULL인 경우에는 전체 비디오 화면과 호환성이 있는 메모리DC가 만들어진다.

CHAPTER 5  CreateDC()와 CreateIC() 메소드에 대한 매개변수 매개 변수 의미 lpszDriverName lpszDeviceName lpszOutput 확장자 없이 장치 드라이버의 파일 이름을 나타내는 CString이거나 NULL로 끝나는 문자열에 대한 포인터이다. 예) “EPSON” 지원할 특정 장치의 이름을 나타내는(보통은 프린터) CString이거나 NULL로 끝나는 문자열에 대한 포인터이다. 드라이버가 하나 이상의 장치를 지원할 경우에 이 매개 변수를 사용한다. 예) “EPSON FX-80” 물리적 파일이나 출력 포트에 대한 파일 이름이나 장치 이름을 나타내는 CString이거나 NULL로 끝나는 문자열에 대한 포인터이다. lpInitData 장치 드라이버에 대한 장치 관련 초기화 데이터를 담고 있는 DEVMODE 구조에 대한 포인터이다.  DEVMODE 구조를 사용하기 위해서는 PRINT.H 파일을 포함해야 한다.

CHAPTER 5  CDC 객체의 생성과 소멸  윈도우에서는 가능한 디바이스 컨텍스트를 제한하기 때문에, CDC 객체를 생성한 후, 객체의 사용이 모두 끝나면 반드시 해당 객체를 소멸해야 한다.  디바이스 컨텍스트 객체를 소멸하고, 윈도우 디바이스 컨텍스트를 해제하는 방법은 스택상에 객체를 생성하는 것이다. Void CMyView::OnLButtonDown(UINT nFlags, CPoint point) { CRect rect; CClientDC dc(this); // 스택상에 dc를 만든다. dc.GetClipBox(rect); // 클리핑 사각형을 얻는다. } // dc가 자동 해제된다.  CDC::GetDC 를 사용하여 디바이스 컨텍스트를 얻을 수도 있다. GetDC 를 사용하였을 경우에는 반드시 ReleaseDC 를 수행해야 된다. CDC* pDC = GetDC(); // dc 포인터 pDC -> GetClipBox(rect); // 클리핑 사각형을 얻는다. ReleaseDC(pDC); // 반드시 호출해야 한다. }  CDC 객체 포인터는 어플리케이션 프레임워크가 소멸시켜 주기 때문에 자신이 직접 소멸시키면 안된다. 클리핑(Clipping) 영역 : 윈도우가 그래픽 출력을 허용하는 영역

CHAPTER 5  CPaintDC  CPaintDC 객체는 창에 대한 그리기 표면을 나타낸다.  BeginPaint()  칠할 특정 창을 준비하며, PAINTSTRUCT란 특수 구조를 칠할 정보로 채운다.  화면 장치 컨텍스트에 대한 핸들을 반환한다.  EndPaint() - 특정 창의 칠하는 작업이 끝났음을 알린다.  CPaintDC 객체를 사용할 때 따라야 할 기본 단계 1. CPaintDC 객체를 만든다. 2. CPaintDC 객체에 그린다. 3. CPaintDC 객체를 제거한다.  CPaintDC 생성자는 BeginPaint() 함수를 호출한다.  CPaintDC 소멸자는 EndPaint() 함수를 호출한다.  스택에 디바이스 컨텍스트를 만든 경우 EndPaint() 함수는 자동으로 호출된다.  View 클래스는 CView::OnDraw() 메소드의 매개 변수로 CPaintDC 객체를 받는다

CHAPTER 5  디폴트 OnPaint는 적절한 디바이스 컨텍스트를 가지고 OnDraw를 호출하지만, 사용자가  CPaintDC  윈도우 프로시저에서의 C 코드 switch (msg) { case WM_PAINT: HDC hDC; PAINTSTRUCT paintstruct; hDC = BeginPaint (hWnd, &paintstruct); // hDC를 사용하여 그래픽 동작을 실행 EndPaint (hWnd, &paintstruct); return 0; }  CPaintDC  OnPaint() 메시지 핸들러에서 WM_PAINT 메시지에 대한 반응으로 타원 그리기 void CMainWnd::OnPaint() { // 칠하기 DC 만들기 CPaintDC dc(this); // DC에서 타원 그리기 CRect rc; GetClientRect(&rc); dc.Ellipse(rc); }  디폴트 OnPaint는 적절한 디바이스 컨텍스트를 가지고 OnDraw를 호출하지만, 사용자가 특정한 디스플레이를 필요로 할 경우 OnPaint에서 PaintDC의 객체를 만들어 사용한다. void CMyView::OnPaint() { CPaintDC dc(this); OnPrepareDC(&dc); dc.TextOut(0, 0, “for the display. Not the printer”); OnDraw(&dc); // 화면과 프린터에 공통되는 코드 }

CHAPTER 5  CClientDC  클라이언트 영역이나 창을 나타내는 장치 컨텍스트를 호출하고 제거한다.  Win32 API 함수 GetDC()  CClientDC 생성자로 부터 호출된다.  Win32 API 함수 ReleaseDC()  CClientDC 소멸자로 부터 호출된다.  CClientDC 객체는 DC가 제어하는 클라이언트 영역을 포함하는 윈도우의 핸들을 멤버 변수 m_hWnd에 저장한다.  CClientDC 객체를 생성하기 위해서 CWnd 객체를 매개변수로 생성자에 전달한다.  CClientDC::CClientDC // #include <afxwin.h>  CClientDC ( CWnd* pWnd );  Parameters  pWnd 디바이스 컨텍스트가 생성되는 CWnd 객체에 대한 포인터

CHAPTER 5  CClientDC  OnLButtonDown() 메시지 핸들러의 WM_LBUTTONDOWN 메시지에 void MainWnd::OnLButtonDown(UINT nFlags, CPoint point) { CClientDC dc(this); // 그림을 그릴 ClientDC를 생성 // DC에 다이아몬드를 그린다. CRect rc; GetClientRect(&rc); dc.MoveTo (0, (rc.bottom + rc.top) / 2); dc.LineTo ((rc.right + rc.left) / 2, 0); dc.LineTo (rc.right, (rc.bottom + rc.top) / 2); dc.LineTo ((rc.right + rc.left) / 2, rc.bottom); dc.LineTo (0, (rc.bottom + rc.top) / 2); }

CHAPTER 5  CWindowDC  클라이언트 영역과 비클라이언트 영역을 모두 포함한 전체 윈도우 표면을 나타내는 장치 컨텍스트를 호출하고 제거한다.  Win32 API 함수 GetDC()  CWindowDC 생성자로 부터 호출된다.  Win32 API 함수 ReleaseDC()  CWindowDC 소멸자로 부터 호출된다.  CWindowDC 객체는 DC가 나타내는 윈도우 영역의 핸들을 멤버 변수 m_hWnd에 저장한다.  CWindowDC 객체를 생성하기 위해서 CWnd 객체를 매개변수로 생성자에 전달한다.  CWindowDC::CWindowDC // #include <afxwin.h>  CWindowDC ( CWnd* pWnd );  Parameters  pWnd 디바이스 컨텍스트가 생성되는 CWnd 객체에 대한 포인터

CHAPTER 5  CWindowDC  OnRButtonDown() 메시지 핸들러의 WM_RBUTTONDOWN 메시지에 반응하여 CWindowDC 객체를 이용한 연속된 원 그리기 void MainWnd::OnRButtonDown(UINT nFlags, CPoint point) { CWindowDC dc(this); // 그림을 그릴 WindowDC를 생성 CRect rc; // 윈도우의 제목 표시줄에서, DC에 연속적으로 이어진 원을 그림 GetWindowRect(&rc); // 윈도우 제목 표시줄의 높이를 결정 int cyCaption = GetSystemMetrics (SM_CYCAPTION); // 원을 채워 넣을 사각형을 정의 CRect rcEllipse (0, 0, cyCaption, cyCaption); while (rcEllipse.right < rc.right); // 원을 그림 dc.Ellipse(rcEllipse); rcEllipse.left += cyCaption; rcEllipse.right += cyCaption; }

CHAPTER 5  CMetaFileDC  GDI 함수 호출을 기록하고 재작동하는 데 사용한다.  윈도우 메타파일 생성 2. CMetaFileDC::Create() 메소드를 호출한다. 3. CMetaFileDC 객체를 초기화한다.  CMetaFileDC::Create  BOOL Create( LPCTSTR lpszFilename = NULL );  Parameters  lpszFilename NULL로 끝나는 문자열에 대한 포인터. 생성할 메타파일이 존재한다면, 그 파일명을 지정하는 NULL 값의 문자열을 가리킨다. 미리 지정된 파일명이 없다면, 메소드는 새로운 메타파일을 메모리 안에 생성한다.

 SDK 그리기 도구의 데이터 유형과 MFC 그래픽 객체 클래스와의 관계 CHAPTER 5  그래픽(GDI) 객체 (DevStudio\Vc\mfc\include\<Afxwin.h>  CBitmap 481라인  CBrush 브러시는 색칠할 때 사용되는 픽셀의 비트맵 패턴을 정의한다. (418라인)  CFont 451라인  CPalette 색상을 맵핑하기 위한 인터페이스 (522라인)  CPen 선이나 경계선을 그리기 위해 사용되는 도구 (382라인)  CRgn 영역(Region)은 다각형과 타원의 결합된 지역 (556라인)  SDK 그리기 도구의 데이터 유형과 MFC 그래픽 객체 클래스와의 관계 SDK 그리기 도구 MFC 클래스 윈도우 데이터 유형 Bitmap Brush Font Palette Pen Rgn CBitmap CBrush CFont CPalette CPen CRgn hBitmap hBrush hFont hPalette hPen hRgn

CHAPTER 5 ◐ MFC 클래스 계층 구조에서  스택에 선언된 그래픽 객체는 객체가 그 범위를 벗어나게 되면 자동으로 CObject CBitmap CFont CGdiObject CPen CBrush ◐ MFC 클래스 계층 구조에서 각 그래픽 객체들의 위치 CRgn CPalette  스택에 선언된 그래픽 객체는 객체가 그 범위를 벗어나게 되면 자동으로 삭제된다.  포인터로 선언되고 새로운 연산자들을 할당 받은 그래픽 객체들은 DC를 이전 상태로 되돌릴 때에는 반드시 제거해야 한다.

CHAPTER 5  GDI 객체의 생성과 소멸  1단계 생성 : 생성자와 함께 객체를 생성하고, 초기화시킨다 (CPen 이나 CBrush 와 같은 클래스들)  2단계 생성 : 생성자는 객체를 생성하고, 함수를 사용하여 초기화시킨다. (CFont 나 CRgn 과 같은 클래스들)  void CMyView::OnDraw(CDC* pDC) { CPen myPen1(PS_DOT, 5, RGB(0, 0, 0)); // 1단계 생성 CPen myPen2; // 2단계 생성 if(myPen2.CreatePen(PS_DOT, 5, RGB(0, 0, 0))) // 여기에서 펜을 사용한다. }  GDI 객체 추적(Tracking)  객체를 추적하는 방법  원래의 GDI 객체를 보관해 놓고, 새로운 GDI 객체를 선택한 다음, 작업이 완료되었을 때 보관해 놓은 원래의 객체를 복구 시킨다.

CHAPTER 5  GDI 객체 추적(Tracking) void CMyView::OnDraw(CDC* pDC) { CPen newPen (PS_DASHDOTDOT, 2, (COLORREF) 0); // 폭이 2픽셀인 검정펜을 작성한다 CPen* pOldPen = pDC -> SelectObject(&newPen); // 펜을 선택한다 pDC -> MoveTo(10, 10); // 선을 그린다 pDC -> LineTo(110, 10); pDC -> SelectObject(pOldpen); // newPen 이 선택 해제된다.(선택을 종료한다) } // newPen 이 자동 소멸된다.  내장(stock) GDI 객체  윈도우는 많은 stock GDI 객체를 가지고 있다. 이러한 객체는 윈도우의 부분이기 때문에 객체를 제거할 필요가 없다. Stock GDI 객체를 선택함으로써 사용자가 만들어 놓은 GDI 객체의 선택을 제거할 수 있다.

CHAPTER 5  GDI 선택의 존속기간  어떠한 GDI 선택도 함수가 끝나고 난 후에는 유효하지 않으므로 디스플레이 디바이스 컨텍스트에 있어서는, 각 함수의 시작부분에서 새로운 디바이스 컨 텍스트를 얻어야 한다. 프린터나 메모리 버퍼와 같은 디바이스 컨텍스트에서는 윈도우 핸들을 보관 함으로써 존속기간을 지속시킬 수 있다.  윈도우의 컬러 맵핑(Color Mapping)  표준 VGA 카드는 4비트 컬러코드를 사용하며, 동시에 16가지 색상만을 사용할 수 있다.  윈도우의 색상은 각각 8비트의 RGB 값으로 표현된다.  색상을 사용하는 GDI 함수는 32bit COLORREF 인자를 받는다. (RGB 매크로를 사용하여 COLORREF 자료형으로 변환)  브러시에서는 디러링(dithering)된 색상을 사용할 수 있다. CBrush brush (RGB(128, 128, 192));  SetBkColor나 SetTextcolor 함수는 항상 디러링(dithering)된 색상을 사용할 수 없다.(근접한 순수색상이 표시된다.)

RGB Blue 0~255 Zero Green 0~255 Red 0~255  windows.h 파일에 정의  COLORREF RGB( // COLORREF : 데이터 type BYTE bRed, // red component of color BYTE bGreen, // green component of color BYTE bBlue // blue component of color );  RGB 매크로 정의  #define RGB (r, g, b) ((DWORD) (((BYTE) (r) | \ ((WORD) (g) << 8)) | (((DWORD) (BYTE) (b)) << 16)))  윈도우는 색상을 표현하기 위해 4byte를 사용  1byte 3byte 색상표현 일반적으로 사용하지 않는다. (윈도우 RGB 칼라와 16칼라 이상을 지원하는 비디오 디바이스에 대한 칼라 팔레트를 구분하기 위해 사용)  RGB 매크로로 표현할 수 있는 색상  256*256*256 = 16,777,216 color Blue 0~255 Zero Green 0~255 Red 0~255

RGB Green Blue Color 255 128 192 Black Cyan Red Magenta Yellow White 255 128 192 Black Cyan Red Magenta Yellow White Dark blue Dark green Dark cyan Dark red Dark magenta Dark yellow Dark gray Light gray

CHAPTER 5  CPen 클래스  CPen 객체는 윈도우 GDI 펜을 캡슐화하고 있다. 메소드 설명 CreatePen() CreatePenIndirect() FromHandle() GetExtLogPen() GetLogPen() 연산자 HPEN 특정 유형, 너비, 붓, 속성을 지닌 논리적인 펜을 생성하며, 이것을 CPen 객체에 붙인다. LOGPEN 구조에서 유형, 너비, 색상이 정의된 펜을 생성하고, 윈도우 HPEN으로부터 CPen 객체로 포인터를 반환한다. 펜의 기본적인 EXTLOGPEN 구조를 받는다. 펜의 기본적인 LOGPEN 구조를 받는다. 현재 CPen 객체에 첨부되어 있는 윈도우 펜의 핸들을 반환한다.

CHAPTER 5  CPen::CreatePen  BOOL CreatePen ( int nPenStyle, int nWidth, COLORREF crColor );  BOOL CreatePen ( int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount = 0, const DWORD* lpStyle = NULL );  Parameters  nPenStyle 펜의 스타일  nWidth 펜의 두께  crColor 펜에 대한 RGB 색상  pLogBrush LOGBRUSH 구조체에 대한 포인터  nStyleCount lpStyle 파라미터에 의해 가리키는 스타일의 길이를 기술한다.  lpStyle doubleword 값의 배열을 가리킨다.

CHAPTER 5  펜의 스타일 (DevStudio\Vc\include\<Wingdi.h> 1389라인)  PS_SOLID 실선  PS_DASH 긴 파선. 펜의 폭이 1일 때만 유효.  PS_DOT 짧은 파선. 펜의 폭이 1일 때만 유효.  PS_DASHDOT 1점 쇄선. 펜의 폭이 1일 때만 유효.  PS_DASHDOTDOT 2점 쇄선. 펜의 폭이 1일 때만 유효.  PS_NULL 투명  PS_INSIDEFRAME 실선. 프레임이나 바운딩 사각형(Rectangle, Ellipse)을 포함하는 객체에 대해 프레임내에 그리는 펜을 생성한다.  PS_USERSTYLE 사용자에 의해 제공되는 스타일 배열을 사용하는 펜  PS_ALTERNATE 모든 다른 픽셀을 설정하는 펜

CHAPTER 5  사용자 정의 빨간 대시 펜을 이용한 OnLButtonDown()  void CMainWnd::OnLButtonDown(UINT nFlags, CPoint point) { CClientDC dc(this); // 그림을 그릴 CClientDC를 생성 CPen penRed; // 빨간 대시를 그릴 펜을 생성 penRed.CreatePen(PS_DASH, 1, RGB(255, 0, 0)); // 장치 컨텍스트에서 새로운 펜을 지정하고, 이전에 존재하던 복구할 펜을 저장 후 제거 CPen* ppenOld; ppenOld = dc.SelectObject(&penRed); // DC에 다이아몬드를 그림 CRect rc; GetClientRect(&rc); dc.MoveTo (0, (rc.bottom + rc.top) / 2); dc.LineTo ((rc.right + rc.left) / 2, 0); dc.LineTo (rc.right, (rc.bottom + rc.top) / 2); dc.LineTo ((rc.right + rc.left) / 2, rc.bottom); dc.LineTo (0, (rc.bottom + rc.top) / 2); dc.SelectObject(ppenOld); // 처음의 상태대로 복구 (현재 상태는 제거) }

CHAPTER 5  CBrush 클래스  CBrush 객체는 윈도우 GDI 붓을 캡슐화하고 있다. 메소드 설명 CreateBrushIndirect() CreateDIBPatternBrush() CreateHatchBrush() CreatePatternBrush() CreateSolidBrush() CreateSysColorBrush() LOGBRUSH 구조에서 지정된 유형, 색상, 무늬를 지닌 붓을 생성하며, 이것을 CBrush 객체에 붙인다. 장치와 무관한 비트맵으로부터 지정된 무늬를 지닌 붓을 특정 빗금 무늬와 색상을 가진 붓을 생성하며, 이것을 CBrush 객체에 붙인다. 비트맵에 의해 지정된 무늬를 가진 붓을 생성하며, 이것을 CBrush 객체에 붙인다. 지정된 한가지 색상의 붓을 생성하며, 이것을 CBrush 객체에 붙인다. 기본 시스템 색상의 붓을 생성하며, 이것을 CBrush 객체에 붙인다. FromHandle() GetLogBrush() 연산자 HBRUSH 윈도우 HBRUSH로부터 CBrush 객체로 포인터를 반환한다. CBrush 객체로부터 기본적인 LOGBRUSH 구조를 받는다. CBrush 객체에 첨부되어 있는 윈도우 핸들을 반환한다.

CHAPTER 5  CBrush의 Constructor  CBrush();  CBrush(COLORREF crColor); // crColor - 붓의 색상  CBrush(int nIndex, COLORREF crColor); // nIndex - 붓의 무늬(해칭 패턴)  CBrush(CBitmap* pBitmap); // pBitmap - 붓의 무늬로서 사용할 비트맵을 포함하는 CBrush 객체에 대한 포인터  해칭(Hatching) 패턴의 종류 (DevStudio\Vc\include\<Wingdi.h> 1380라인) 해칭 패턴 의미 모양 HS_HORIZONTAL HS_DIAGCROSS HS_VERTICAL HS_BDIAGONAL HS_FDIAGONAL HS_CROSS 수평 해치 수직 해치 45’로 위 방향 (왼쪽에서 오른쪽)의 해칭 45’로 아래방향 수직과 수평 십자가의 해칭 45’로 된 십자가 해칭

CHAPTER 5  사용자 정의 파란색 원을 메울 빗금 무늬를 그릴 수 있는 붓을 이용한 OnPaint()메소드  void CMainWnd::OnPaint() { CPaintDC dc(this); // 페인트 DC를 생성 // 파란색의 왼쪽에서 오른쪽 아래의 빗금 무늬 붓 생성 CBrush br (HS_BFDIGONAL, RGB(0, 0, 255)); // 장치 컨텍스트에서 새로운 붓을 선택하고, // 이전에 존재하던 복구할 붓을 저장 후 제거 CBrush* pbrOld; pbrOld = dc.SelectObject(&br); // DC에 원 그리기 CRect rc; GetClientRect(&rc); dc.Ellipse(rc); dc.SelectObject(pbrOld); // 처음의 상태대로 복구 (현재 상태는 제거) }

CHAPTER 5  CFont 클래스  CFont 객체는 윈도우 GDI 글꼴을 캡슐화하고 있다. 메소드 설명  글꼴을 생성하는 것은 장치 컨텍스트에서 텍스트를 그리기 위해서이다. 메소드 설명 CreateFont() CreateFontIndirect() FromHandle() CreatePointFontIndirect() GetLogFont() CreatePointFont() 지정된 속성을 가진 CFont 객체 생성 LOGPEN 구조에 명시된 속성을 가진 CFont 객체 생성 윈도우 HFONT로부터 CFont 객체로 포인터를 반환한다. LOGFONT 구조에 명시된 속성을 가진 CFont 객체 생성. 글꼴의 높이는 논리적 단위 대신 포인트를 10등분한 단위로 측정 CFont 객체에 첨부된 기본적인 윈도우 GDI 글꼴 핸들을 반환 지정된 높이(포인트를 10등분 하여 측정)와 서체를 가진 CFont 객체 생성 operator HFONT() CFont 객체에 첨부된 논리적 글꼴에 대한 정보를 LOGFONT에 기록함

CHAPTER 5  CBitmap 클래스  비트맵은 그래픽 이미지, 그림이나 무늬를 결정짓는 픽셀들의 배열이다.  CPalette 클래스  팔레트는 색상 정보를 저장하는 윈도우 GDI 객체이다.  MFC는 윈도우 색상 팔레트를 CPalette 클래스 안에 캡슐화 했다.  CRgn 클래스  영역은 디스플레이 장치의 어느 구역 안에서 다각형이나 원형의 정보를 저장하는 윈도우 GDI 객체이다.  CRgn은 GDI 영역 객체를 캡슐화 한다.

CHAPTER 5  CRgn 클래스  영역을 생성하고 활용하는데 사용하는 CRgn 클래스 메소드 설명 CombineRgn() CopyRgn() CreateEllipticRgn() CreateEllipticRgnIndirect() CreateFromData() CreateFromPath() 두 개의 지정된 영역 객체의 결합체를 생성한다. CRgn 객체를 다른 쪽으로 복사한다. 원형의 구역을 가진 CRgn 객체를 생성한다. 원형의 구역을 가진 CRgn 객체를 생성하며, 이것을 소유하는 상자는 RECT 구조에서 정의한다. 지정된 영역과 기하학적으로 변형된 데이터들을 기초로 영역을 생성한다. 지정된 디바이스 컨텍스트로 선택한 경로를 기초로 영역을 생성한다. CreatePolygonRgn() CreatePolyPolygonRgn() CreateRectRgn() 다각형의 구역을 가진 CRgn 객체를 생성한다. 필요하다면 다각형의 맨 끝 꼭지점을 맨 처음 꼭지점에 연결함으로써 다각형의 영역은 자동으로 닫히게 된다. 일련의 닫힌 다각형들로 구성된 영역을 가진 CRgn 객체를 직사각형의 영역을 가진 CRgn 객체를 생성한다.

CHAPTER 5  CRgn 클래스  영역을 생성하고 활용하는데 사용하는 CRgn 클래스 메소드 설명 EqualRgn() CreateRectRgnIndirect() CreateRoundRectRgn() EqualRgn() FromHandle() GetRegionData() GetRgnBox() RECT 구조에 의해 정의된 직사각형의 영역을 가진 CRgn 객체를 생성한다. 둥근 모서리의 직사각형을 가진 CRgn 객체를 생성한다. 두 개의 CRgn 객체를 영역이 같은지를 결정하기 위하여 서로 비교한다. 윈도우 영역에 대한 핸들로부터 CRgn 객체로 포인터를 반환한다. 지정된 영역을 기술하는 데이터로 버퍼를 채운다. CRgn 객체를 포함하는 직사각형과 동일한 직사각형을 받는다. OffSetRgn() PtInRegion() RectInRegion() 지정한 위치로 CRgn 객체를 옮긴다. 영역 안에 지정된 지점이 있는지 확인한다. 영역의 경계선 안에 어떠한 지정된 직사각형의 부분이 존재하는지 확인한다. SetRectRgn() 연산자 HRGN 존재하는 CRgn 객체를 지정된 직사각형 영역으로 맞춘다. CRgn 객체 안의 윈도우 핸들을 반환한다.

CHAPTER 5  글꼴과 텍스트  TTF(TrueType Font) : 아무런 이미지의 질 저하 없이 가상적으로 임의의 크기로 조정할 수 있는 벡터 글꼴  서체(typeface) : 글자의 스타일과 텍스트의 시각적 모양을 나타낸다.  글꼴 : 특정 서체에 있는 같은 글자의 집합  포인트 : 글꼴 문자의 높이를 측정하기 위해 사용 1포인트 - 1/72인치  글꼴 특성  고정폭(단일 간격) : 모두 같은 폭을 갖는다.  가변폭 : 필요한 만큼의 공간만 갖는다.  윈도우에서 정의하는 글꼴 유형  래스터 글꼴(비트맵 글꼴)  벡터 글꼴 - 일련의 선 조각들로부터 구성된 글꼴  트루타입 글꼴 - 문자 윤곽을 정의하기 위해 선과 스플라인 곡선을 사용하는 글꼴

CHAPTER 5  글꼴 계열  모든 서체는 글꼴의 스타일을 나타내는 글꼴 계열로 그룹이 나누어져 있다.  DevStudio\Vc\include\<wingdi.h> 1073라인 ◐ 윈도우에서 제공하는 글꼴 계열 계열 이름 설명 FF_DECORATIVE FF_DONTCARE FF_MODERN FF_ROMAN FF_SCRIPT FF_SWISS 고상한 글꼴. 예) Viking Runes 세리프가 있거나 없는 단일 간격 글꼴. 단일 간격 글꼴은 보통 현대적인데, Pica, Elite, Courier New 등이 이에 속한다. 세리프가 있는 비례 글꼴을 의미한다. 예) Times New Roman 필기체 형태의 글꼴을 의미한다. 예) Script, Cursive 세리프가 없는 비례 글꼴을 의미한다. 예) Arial 글꼴에 관한 정보가 전혀 필요하지 않을 때 사용하는 일반적인 계열 이름

CHAPTER 5  논리적 글꼴은 글꼴의 속성(굵은 글자체, 이탤릭체, 밑줄, 크기 ...)을 정의한다.  LOGFONT Structure(논리적 글꼴 구조)  장치 컨텍스트에서 사용하기 위해 논리적 글꼴을 만들 때 사용한다.  논리적 글꼴은 글꼴의 속성(굵은 글자체, 이탤릭체, 밑줄, 크기 ...)을 정의한다.  글꼴을 사용하려면 먼저 장치 컨텍스트에 이를 선택해야 한다.  장치 컨텍스트에 선택되었으면, 논리적 글꼴이 물리적 글꼴이 된다.  typedef struct tagLOGFONT { LONG lfHeight; // 문자 셀이나 문자의 논리적 높이 LONG lfWidth; // 글꼴 내의 문자들의 평균 논리적 너비 LONG lfEscapement; // 폰트에 쓰여진 텍스트의 각 라인의 각도( 1/10도 ) LONG lfOrientation; // 각 문자의 기준선의 각도 ( 1/10도) LONG lfWeight; // 글꼴의 무게 (0-1000 사이) BYTE lfItalic; // TRUE 이면 이태릭체 BYTE lfUnderline; // TRUE 이면 밑줄 BYTE lfStrikeOut; // TRUE 이면 취소선 BYTE lfCharSet; // 글꼴의 문자 집합 BYTE lfOutPrecision; // 출력 정밀도. BYTE lfClipPrecision; // 클리핑 정밀도. 클리핑 경계에 있는 문자들을 처리하는 방법을 정의한다. BYTE lfQuality; // 출력 품질 BYTE lfPitchAndFamily; // 글꼴의 피치와 계열 CHAR lfFaceName[LF_FACESIZE]; // 32자로 제한된 문자열. 글꼴의 서체 이름을 나타낸다. } LOGFONT;

CHAPTER 5  글꼴 생성 메소드 설명 CreateFontIndirect() CreateFont() CreatePointFont() CreatePointFontIndirect() LOGFONT 구조에 의해 정의된 CFont 객체를 초기화한다. 지정한 높이와 서체를 갖는 CFont 객체를 초기화한다. LOGFONT 구조에 정의된 대로 CFont 객체를 초기화한다. 글꼴 높이는 논리적 단위 대신에 1/10 포인트를 사용한다. 명시한 특성을 가진 CFont 객체를 초기화한다.

CHAPTER 5  글꼴 표시하기  트루타입 글꼴에서 맵핑 모드는 별로 중요하지 않으며, 단지 글꼴의 크기를 지정해주면 된다.  화면에서의 논리적 인치와 물리적 인치 인덱스 설명 값 HORZSIZE VERTSIZE HORZRES VERTRES LOGPIXELSX LOGPIXELSY 밀리미터(mm) 단위의 물리적 화면 폭 밀리미터(mm) 단위의 물리적 화면 높이 픽셀 단위의 화면 폭 래스터(raster) 라인 단위의 화면 높이 논리 인치당 수평 도트 수 논리 인치당 수직 도트 수 320 240 640 480 96  MM_HIMETRIC 또는 MM_TWIPS와 같은 고정된 맵핑 모드를 사용할 경우, 디스플레이 드라이버는 물리적 화면 크기를 사용해서 맵핑을 한다.

CHAPTER 5  맵핑 모드를 논리 트윕으로 설정하는 코드 (p155)  pDC->SetMapMode(MM_ANISOTROPIC); pDC->SetWindowExt(1440, 1440); pDC->SetViewportExt(pDC->GetDeviceCaps(LOGPIXELSX), pDC->GetDeviceCaps(LOGPIXELSY));  MM_TWIPS 맵핑 모드  12포인트 크기  tmheight - 295  tmInternalLeading - 55  Netheight(폰트의 순수높이) - 240

CHAPTER 5  문자 높이 계산하기(p154)  CDC의 멤버함수인 GetTextMetrics() 의 폰트 높이 측정 파라미터  tmHeight descender 와 diacritic 을 포함하는 폰트의 전체 높이  tmExternalLeading diacritic과 이전라인의 descender 사이의 거리  Diacritic 구별자  tminternalLeading  Netheight 순수 높이  Descender 하행문자  Character의 전체크기  tmHeight + tmExternalLeading  폰트의 크기 (=Netheight, 순수높이)  tmHeight - tmInternalLeading  ascending letter : ascender ( x의 높이보다 위로 나오는 부분, 上行문자 ) ex) b, d, f, h  descending letter : descender ( x의 높이보다 아래로 나오는 부분, 下行문자 ) ex) g, j, p, q, y

CHAPTER 5  BOOL GetTextMetrics(LPTEXTMETRIC lpMetrics) const; The TEXTMETRIC structure contains basic information about a physical font. All sizes are given in logical units.  CDC::GetTextMetrics  BOOL GetTextMetrics(LPTEXTMETRIC lpMetrics) const; typedef struct tagTEXTMETRIC { /* tm */ int tmHeight; int tmAscent; int tmDescent; int tmInternalLeading; int tmExternalLeading; int tmAveCharWidth; int tmMaxCharWidth; int tmWeight; BYTE tmItalic; BYTE tmUnderlined; BYTE tmStruckOut; BYTE tmFirstChar; BYTE tmLastChar; BYTE tmDefaultChar; BYTE tmBreakChar; BYTE tmPitchAndFamily; BYTE tmCharSet; int tmOverhang; int tmDigitizedAspectX; int tmDigitizedAspectY; } TEXTMETRIC; // 문자 높이 (ascent + descent) // 기준선 위의 문자 // 기준선 아래의 문자 // tmHeight 안쪽의 나머지 공간 // 텍스트 행간의 나머지 공간 // 글꼴 문자의 평균 너비 // 폭이 가장 긴 글꼴 문자의 너비 // 글꼴의 무게 // 0이 아닐 때 이탤릭 글꼴 // 0이 아닐 때 밑줄 글꼴 // 0이 아닐 때 취소선이 있는 글꼴 // 첫번째 글꼴 문자의 문자 값 // 마지막 글꼴 문자의 문자 값 // 기본 대체 문자 // 단어 분리 포맷을 위한 문자 값 // 글꼴 피치와 글꼴 군에 대한 정보 // 글꼴의 문자 집합 // 비어 있는 나머지 너비 // 대상 장치의 수평 면 // 대상 장치의 수직 면

CHAPTER 5  CFont::CreateFont - 폰트를 생성하여 CFont 객체에 붙인다.  BOOL CreateFont( int nHeight, int nWidth, int nEscapement, int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline, BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision, BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily, LPCTSTR lpszFacename );  CDC::GetTextExtent  현재 폰트를 사용하여 기술한 문자열의 높이와 폭(논리 단위)을 계산한다.  CSize GetTextExtent( LPCTSTR lpszString, int nCount ) const;  CSize GetTextExtent( const CString& str ) const;  Return Value 문자열의 크기(논리단위)를 포함하는 CSize object.  Parameters  lpszString 계산되는 크기에 대한 텍스트 문자열에 대한 포인터  nCount lpszString 파라미터에 의해 가리키는 문자열의 길이(바이트)  str 계산되는 크기에 대한 텍스트 문자열을 포함하는 CString 객체에 대한 참조

CHAPTER 5  CDC::GetDeviceCaps() - 화면 수치들을 리턴해 준다.  int GetDeviceCaps( int nIndex ) const;  Parameters  DRIVERVERSION 디바이스 드라이버 버전; for example, 0x100 for 1.0.  TECHNOLOGY 디바이스 기술(technology).  HORZSIZE 물리적인 디스플레이 폭 (밀리미터).  VERTSIZE 물리적인 디스플레이 높이(밀리미터).  HORZRES 디스플레이의 폭 (픽셀).  VERTRES 디스 플레이의 높이(in raster lines).  LOGPIXELSX 디스플레이 폭의 논리 인치마다의 픽셀 수  LOGPIXELSY 디스플레이 높이의 논리 인치마다의 픽셀 수  BITSPIXEL 각 픽셀에 대한 색상 비트의 수  PLANES 색상 판의 수  NUMBRUSHES 디바이스 특정 브러시의 수  NUMPENS 디바이스 특정 펜의 수  NUMFONTS 디바이스 특정 폰트의 수  NUMCOLORS 디바이스 색상 표에 있는 엔트리의 수  ASPECTX 라인 그리기에 사용되는 디바이스 픽셀의 상대 폭  ASPECTY 라인 그리기에 사용되는 디바이스 픽셀의 상대 높이  ASPECTXY 라인 그리기에 사용되는 디바이스 픽셀의 대각선의 폭  PDEVICESIZE PDEVICE 내부 데이터 구조체의 크기  CLIPCAPS 디바이스의 클리핑 성능  SIZEPALETTE 시스템 팔레트에 있는 엔트리의 수  NUMRESERVED 시스템 팔레트에 있는 예비된 엔트리의 수  COLORRES 픽셀마다의 디바이스의 실제 색상 해상도  RASTERCAPS 값은 디바이스의 래스터 성능을 나타낸다.  CURVECAPS 디바이스의 곡선 성능  LINECAPS 디바이스가 지원하는 라인 성능  POLYGONALCAPS 디바이스가 지원하는 다각형 성능  TEXTCAPS 디바이스가 지원하는 텍스트 성능

CHAPTER 5  CDC::GetTextFace  현재 폰트에 대한 서체 이름을 널로 끝나는 문자열로 얻는다.  int GetTextFace( int nCount, LPTSTR lpszFacename ) const;  int GetTextFace( CString& rString ) const;  Parameters  nCount lpszFacename 파라미터에 의해 가리키는 버퍼의 크기  lpszFacename 서체 이름이 넣어지는 버퍼에 대한 포인터  rString 서체 이름이 넣어지는 CString에 대한 참조

CHAPTER 5  CDC::SetBrushOrg  현재의 브러시 원점을 설정한다.  디바이스 컨텍스트에 대한 기본 브러시 원점은 0, 0이다.  브러시는 8 x 8픽셀 비트맵으로 표시되기 때문에, 브러시 원점의 x와 y좌표는 0에서 7까지의 범위이다.  CPoint SetBrushOrg( int x, int y );  CPoint SetBrushOrg( POINT point );  Parameters  x 새로운 브러시 원점의 x 좌표 ( 장치 단위, 0 - 7 )  y 새로운 브러시 원점의 y 좌표 ( 장치 단위, 0 - 7 )  point 새로운 브러시 원점( 장치 단위 )을 포함하는 POINT 구조체나 CPoint 객체

CHAPTER 5  EX05A 의 프로그램 요소들  OnPrepareDC 에 맵핑 모드를 설정  ShowFont Private 멤버 함수  CFont::CreateFont 함수호출  첫번째 인자 : 폰트의 높이  두번째 인자 : 폰트의 너비 두번째 인자를 0으로 설정하면, 폰트디자이너가 정의한 비율로 설정된다.  마지막 인자 : 폰트의 이름  첫번째 인자가 음수 : 문자의 크기(tmHeight - tmInternalLeading)를 설정 양수 : 셀의 크기(tmHeight)가 된다.

CHAPTER 5  OnDraw() 함수의 구성요소  fontTest1 : 디폴트 너비로 선택된 트루타입 폰트 Arial  fontTest2 : 디폴트 너비로 선택된 폰트 Courier  fontTest3 : 범용(generic) Roman 폰트  fontTest4 : LinePrinter 가 기술되었지만, 이 폰트는 디스플레이 하기위한 윈도우 폰트가 아니기 때문에 FF_MODERN 이라고 기술해 준 부분을 가지고 트루타입 Courier New 폰트를 선택한다.

CHAPTER 5  EX05C 의 프로그램 요소들  OnPrepareDC 에 맵핑 모드를 설정  ShowFont Private 멤버 함수  CFont::CreateFont 함수호출  첫번째 인자 : 폰트의 높이  두번째 인자 : 폰트의 너비 두번째 인자를 0으로 설정하면, 폰트디자이너가 정의한 비율로 설정된다.  마지막 인자 : 폰트의 이름  첫번째 인자가 음수 : 문자의 크기(tmHeight - tmInternalLeading)를 설정 양수 : 셀의 크기(tmHeight)가 된다.

CHAPTER 5  Win32 에서 사용되는 커서 Value Description IDC_APPSTARTING IDC_ARROW IDC_CROSS IDC_IBEAM IDC_ICON IDC_NO IDC_SIZE IDC_SIZEALL IDC_SIZENESW IDC_SIZENS IDC_SIZENWSE IDC_SIZEWE IDC_UPARROW IDC_WAIT Standard arrow and small hourglass Standard arrow Crosshair Text I-beam Windows NT only:Empty icon Slashed circle Windows NT only:Four-pointed arrow Same as IDC_SIZE Double-pointed arrow pointing northeast and south Double-pointed arrow pointing north and south Double-pointed arrow pointing northwest and south Double-pointed arrow pointing west and east Vertical arrow Hourglass

무릎 꿇고 있는 나무 로키산맥 해발 3천미터 높이에 수목 한계선인 지대가 있습니다. 이 지대의 나무들은 매서운 바람으로 인해 곧게 자라지 못하고 ‘무릎 꿇고 있는 모습’을 한 채 있어야 합니다. 이 나무들은 열악한 조건이지만 생존을 위해 무서운 인내를 발휘하며 지냅니다. 그런데 세계적으로 가장 공명이 잘 되는 명품 바이올린은 바로 이 ‘무릎 꿇고 있는 나무’로 만든다고 합니다. 아름다운 영혼을 갖고 인생의 절묘한 선율을 내는 사람은 아무런 고난 없이 좋은 조건에서 살아온 사람이 아니라 온갖 역경과 아픔을 겪어온 사람입니다.

CHAPTER 6 모달 다이얼로그와 윈도우95 공통 컨트롤

CHAPTER 6  모달(Modal) 다이얼로그와 모드리스(Modeless) 다이얼로그  모달(Modal) 다이얼로그 다이얼로그 박스가 닫히기 전에는 어플리케이션의 다른 기능을 사용할 수 없다.  모드리스(Modeless) 다이얼로그 다이얼로그 박스가 화면에 출력된 상태에서도 어플리케이션의 다른 기능을 사용할 수 있다.  윈도우 공통 컨트롤 (DevStudio\Vc\mfc\include\<Afxcmn.h>)  CAnimateCtrl, CHotKeyCtrl, CImageList, CListCtrl, CProgressCtrl, CRichEditCtrl, CSliderCtrl, CSpinButtonCtrl, CStatusBarCtrl CTabCtrl, CToolBarCtrl, CToolTipCtrl, CTreeCtrl  공통 컨트롤은 모두 COMMCTRL.DLL에 저장되어 있다. Ctrl 접미사를 가진 컨트롤 클래스들은 Win32 운영 체제에서만 사용할 수 있는 새로운 공통 컨트롤 클래스들이다.

CHAPTER 6  애니메이트 컨트롤 (CAnimateCtrl)  윈도 AVI(Audio Video Interleaved) 영화 파일을 상영하는 윈도우이다.  AVI 파일은 보통 영화의 프레임을 구성하는 일련의 정적 비트맵 이미지들을 디지털 소리와 엮어 합성한 것이다.  애니메이션 컨트롤은 소리를 지원하지 않는다.  핫 키 컨트롤 (CHotKeyCtrl)  핫 키 컨트롤 또는 키보드 가속기는 사용자가 특정 행동을 수행하거나 몇몇 명령을 보낼 수 있는 키 조합을 의미.  핫 키 컨트롤은 사용자가 자신의 핫 키를 정의할 수 있도록 하는 윈도우이다.  이미지 목록 컨트롤 (CImageList)  0부터 시작하는 비트맵 이미지의 배열이다.  Win32는 이미지를 만들고, 추가하고, 삭제하고, 교체하고, 합하고, 잡아 끌고, 소멸할 수 있는 함수들을 제공한다.

CHAPTER 6  목록 보기 컨트롤 (CListCtrl)  아이콘과 텍스트의 레이블의 조합으로 이루어진 항목들의 목록을 나타낸다.  진행 표시자 컨트롤 (CProgressCtrl)  응용 프로그램이 특정 행동의 진행 과정을 보여주는 표준화된 방법을 제공.  리치 에디트 컨트롤 (CRichEditCtrl)  사용자가 텍스트를 입력하고 편집할 수 있을 뿐만 아니라 텍스트에 여러 가지 방법으로 서식을 지정할 수도 있다.  문자와 문단의 서식 지정과 OLE지원, 다양한 글꼴을 동시에 사용할 수 있다.  트랙바 컨트롤 (CSliderCtrl)  최소값과 최대값 사이의 선택된 범위의 값을 제공한다.  스핀 버튼 컨트롤 (CSpinButtonCtrl)  스크롤 위치나 컨트롤에 표시되는 수와 같이 어떤 값을 증가하거나 감소하는데 사용되는 한 쌍의 화살표 버튼

CHAPTER 6  상태 표시줄 컨트롤 (CStatusBarCtrl)  사용자가 다음에 무엇을 해야 하고 특정 동작의 상태가 무엇인지를 알 수 있도록 도와 주는 정보를 나타낸다.  탭 컨트롤 (CTabCtrl)  하나의 대화 상자나 창에 여러 개의 페이지를 설정할 수 있다.  도구 모음 컨트롤 (CToolBarCtrl)  한 줄의 단추들을 담고 있는 컨트롤 표시줄의 한 유형이다.  단추들은 단추 이미지를 담고 있는 비트맵으로부터 만들어진다.  도구 모음 단추는 마우스가 이 위로 지나갈 때 도구 설명(Tooltip)을 나타낼 수 있다.  트리 보기 컨트롤 (CTreeCtrl)  항목들의 계층을 나타낸다.  트리 내의 각 항목은 텍스트 문자열은 물론 이와 관련된 비트맵을 갖고 있다.

CHAPTER 6  도구 설명 컨트롤(CToolTipCtrl)  어플리케이션에서 툴바 버튼이나 다른 도구의 사용 기능을 한 라인으로 기술하여 텍스트를 표시하는 작은 팝업 윈도우.  체크 리스트 박스(CCheckListBox)  체크 박스가 리스트에 있는 각 항목의 옆에 나타나고, 사용자는 선택된 항목의 체크 박스를 체크하거나 해제할 수 있다.  이동 리스트 박스(CDragListBox)  리스트 상자에 있는 파일 이름과 문자열과 같이 항목을 이동(drag)할 수 있게 해 준다. 이 기능을 갖는 리스트 박스는 프로젝트에 있는 경로 이름이나 파일들과 같이 알파벳보다는 다른 순서로 분류되어 있는 항목에 유용하다.  CHeaderCtrl  텍스트의 칼럼 위에 나타나는 크기를 조정할 수 있는 버튼.

CHAPTER 6  리소스와 컨트롤  다이얼로그는 일종의 윈도우이다.  다이얼로그 윈도우와 CView 윈도우의 차이점  다이얼로그 윈도우는 다이얼로그 구성요소와 레이아웃을 포함하고 있는 리소스를 사용한다.  다이얼로그 컨트롤  Edit Control(Text Box), Button, List Box, Combo Box, Static Text(Label), Tree View, Progress Indicator, Slider  다이얼로그 컨트롤은 CWnd 포인터나 인덱스 번호에 의해서 참조될 수 있다.  컨트롤은 사용자의 행동에 반응하여 부모 다이얼로그(Parent Dialog)에 메시지를 보낸다.

CHAPTER 6  모달(Modal) 다이얼로그 프로그래밍  기존의 프로젝트에 새 다이얼로그 추가 1. 다이얼로그 에디터를 이용하여 다이얼로그를 작성한다. 2. ClassWizard를 사용하여 CDialog에서 파생된 다이얼로그 클래스를 만든다. 3. ClassWizard를 사용하여 데이터 멤버를 만든다. (Exchange Function은 ClassWizard가 만들어준다.) 4. ClassWizard를 사용하여 이벤트를 발생시키는 컨트롤의 메시지 핸들러를 만든다. 5. OnInitDialog 함수 안에 특정한 컨트롤들의 초기화를 시켜주는 코드와 메시지 핸들러의 코드를 작성한다. (사용자가 다이얼로그를 닫을 때는 CDialog의 가상함수인 OnOK() 가 수행되도록 한다.) 6. 뷰 클래스안에서 다이얼로그를 보여주는 부분을 작성한다. 모달 다이얼로그를 만들때는 DoModal() 함수를 사용한다. DoModal() 함수는 사용자가 다이얼로그를 닫을 때 리턴된다.

CHAPTER 6  Progress Indicator 컨트롤(CProgressCtrl)  Progress Indicator를 초기화하기 위해서는 OnInitDialog 함수 내에서 SetRange와 SetPos 멤버함수를 사용한다. 메시지 핸들러 내에서 SetPos 함수를 사용하여 진척정도를 조정할 수 있다. ( 0 - 100 사이의 범위를 갖는다. ) 메소드 설명 void SetRange(int nLower, int nUpper); int SetPos( int nPos ); int OffsetPos( int nPos ); int SetStep( int nStep ); int Steplt(); 진행 표시자의 범위를 설정한다. 진행 표시자의 현재 위치를 설정한다. 진행 표시자의 현재 위치에서 nPos만큼 증가시킨다. 진행 표시자의 증가되는 양을 설정한다.(디폴트 10) 설정된 Step 만큼 현재 위치를 증가시킨다.

CHAPTER 6  Progress Indicator 컨트롤(CProgressCtrl) 매개변수 설명 dwStyle rect nParentWnd 그 컨트롤에 대한 창 스타일을 설정한다. 이것은 일반적인 창 스타일의 어떠한 조합도 가능하다. 컨트롤의 크기와 위치를 지정하는 직사각형 그 컨트롤의 부모 창에 대한 포인터 nID 트리 보기 컨트롤과 통신하기 위해 부모 창에서 사용하는 컨트롤 ID

CHAPTER 6  트랙바 컨트롤(CSliderCtrl)  트랙바 컨트롤은 슬라이더라고도 불리며, 사용자가 아날로그값을 설정할 수 있도록 해준다. 컨트롤의 범위를 크게 설정하면, 트랙바의 움직임이 연속적인 것처럼 보인다. 범위를 작게 설정하면, 트랙바는 불연속적으로 움직인다. 트랙바는 WM_HSCROLL 이나 WM_VSCROLL 메시지를 맵핑시킬 필요가 없기 때문에, 스크롤바보다는 구현하기가 쉽다.  CSliderCtrl 메시지에 대한 두 개의 메시지 맵 항목 매시지 맵 항목 설명 ON_WM_HSCROLL ON_WM_VSCROLL 화살표 버튼을 눌렀을 때 TBS_HORZ 를 갖는 슬라이더 컨트롤에 의해 발생된다. 화살표 버튼을 눌렀을 때 TBS_VERT(기본설정) 를 갖는

CHAPTER 6  슬라이더 컨트롤을 위해 정의된 창 스타일(트랙바 컨트롤,Track Bar Styles-TBS) 스타일 매크로 설명 TBS_AUTOTICKS TBS_BOTH TBS_BOTTOM TBS_ENABLESELRANGE TBS_HORZ 허용하는 값 범위 내에서 각 증가에 따라 슬라이더 눈금 표시를 준다. 눈금 표시는 SetRange() 메소드를 호출함으로써 자동으로 생성된다. 슬라이더 컨트롤의 방향(수평,수직)에 관계없이 슬라이더 컨트롤의 양쪽 면에 눈금 표시를 한다. 수평 슬라이더 컨트롤의 아래에 눈금 표시를 한다. 선택된 범위의 시작점과 끝점을 가리키는 삼각형 모양의 슬라이더 눈금 표시를 준다. 슬라이더 방향을 수평으로 한다.(기본값)  슬라이더 컨트롤을 위해 정의된 창 스타일(트랙바 컨트롤,Track Bar Styles-TBS) TBS_NOTICKS 슬라이더가 눈금 표시를 가지지 못하게 한다. TBS_RIGHT 수직 슬라이더 컨트롤의 오른쪽 면에 눈금 표시를 한다. TBS_LEFT 수직 슬라이더 컨트롤의 왼쪽 면에 눈금 표시를 한다. TBS_TOP 수평 슬라이더 컨트롤의 위에 눈금 표시를 한다. TBS_VERT 슬라이더 방향을 수직으로 한다.

CHAPTER 6  OnHScroll()과 OnVScroll() 메소드에서 슬라이더 컨트롤이 사용하는 통지 코드 통지 코드 설명 TB_PAGEUP TB_LINEUP TB_BOTTOM TB_LINEDOWN TB_THUMBPOSITION 사용자가 슬라이더의 위쪽, 또는 왼쪽 채널을 클릭하거나, PageUp키를 눌렀다. 사용자가 키보드의 상향 화살표나 좌향 화살표를 눌렀다. 사용자가 키보드에서 End키를 눌렀다. 사용자가 키보드의 하향 화살표나 우향 화살표를 눌렀다. 사용자가 슬라이더를 드래그하다가(TB_THUMBTRACK) 왼쪽 마우스 버튼에서 손을 뗐다. 절대 위치로 스크롤한다. 현재 위치는 nPos에 제공된다.  OnHScroll()과 OnVScroll() 메소드에서 슬라이더 컨트롤이 사용하는 통지 코드 TB_PAGEDOWN 사용자가 슬라이더의 아래쪽, 또는 오른쪽 채널을 클릭하거나, PageDown키를 눌렀다. TB_THUMBTRACK 사용자가 슬라이더를 드래그했다. TB_ENDTRACK 사용자가 키를 떼어 어떤 가상 키 코드(WM_KEYUP)를 보내도록 한다. 화면 이동(scrolling)이 중단된다. TB_TOP 사용자가 키보드에서 Home키를 눌렀다.

CHAPTER 6  속성을 다루는 CSliderCtrl 클래스 메소드 메소드 설명 슬라이더 컨트롤의 채널 크기를 얻는다. void GetChannelRect( LPRECT lprc ) const; 슬라이더 컨트롤의 채널 크기를 얻는다. int GetLineSize( ) const; 슬라이더 컨트롤의 행 크기를 얻는다. UINT GetNumTics( ) const; 슬라이더 컨트롤의 눈금 표시 수를 얻는다. int GetPageSize( ) const; 슬라이더 컨트롤의 페이지 크기를 얻는다. int GetPos() const; 슬라이더의 현재 위치를 얻는다. void GetRange(int& nMin,int& nMax) const; 슬라이더에 대한 최대 및 최소 위치를 얻는다. int GetRangeMax( ) const; 슬라이더의 최대 위치를 얻는다. int GetRangeMin( ) const; 슬라이더의 최소 위치를 얻는다. void GetSelection(int& nMin,int& nMax) const; 현재의 선택 범위를 얻는다. void GetThumbRect(LPRECT lprc) const; 슬라이더 컨트롤의 버튼 크기를 얻는다. int GetTic( int nTic ) const; 지정된 눈금 표시의 위치를 얻는다.

CHAPTER 6  속성을 다루는 CSliderCtrl 클래스 메소드 메소드 설명 DWORD* GetTicArray( ) const; 슬라이더 컨트롤에 대한 눈금 표시 위치들의 배열을 얻는다. int GetTicPos( int nTic ) const; 클라이언트 좌표 내에서 지정된 눈금 표시의 위치를 얻는다. int SetLineSize( int nSize ); 슬라이더 컨트롤의 행 크기를 설정한다. int SetPageSize( int nSize ); 슬라이더 컨트롤의 페이지 크기를 설정한다. void SetPos( int nPos ); 슬라이더의 현재 위치를 설정한다. void SetRange( int nMin, int nMax, BOOL bRedraw = FALSE ); 슬라이더에 최대 및 최소 위치를 설정한다. void SetRangeMax( int nMax, 슬라이더의 최대 위치를 설정한다. void SetRangeMin( int nMin, 슬라이더의 최소 위치를 설정한다. void SetSelection(int nMin,int nMax); 슬라이더의 선택 범위를 설정한다. BOOL SetTic( int nTic ); 지정된 눈금 표시의 위치를 설정한다. void SetTicFreq( int nFreq ); 슬라이더 컨트롤이 증가할 때 눈금 표시의 빈도수를 설정한다.

CHAPTER 6  연산을 다루는 CSliderCtrl 클래스 메소드 메소드 설명 void VerifyPos( ); void ClearSel(BOOL bRedraw = FALSE); 슬라이더 컨트롤에서 현재의 선택을 지워 버린다. void ClearTics(BOOL bRedraw = FALSE); 슬라이더 컨트롤에서 현재의 눈금 표시를 제거한다. void VerifyPos( ); 슬라이더 컨트롤의 위치가 0인지 검사한다.  예 눈금의 빈도수를 설정 m_pSlider1->SetTicFreq(8); m_pSlider2->SetTicFreq(8); 페이지 크기를 설정 m_pSlider1->SetPageSize(8); m_pSlider2->SetPageSize(8); 행 크기를 설정 m_pSlider1->SetLineSize(1); m_pSlider2->SetLineSize(1);

CHAPTER 6  스핀 버튼 컨트롤(CSpinButtonCtrl)  스핀 컨트롤 바로 앞에 위치한 에디트 컨트롤은 스핀 버튼의 버디(buddy)라고 한다. 버디에서 정수값을 사용한다면, ClassWizard를 사용하여 에디트 컨트롤의 integer 데이터 멤버를 추가하기만 하면 된다. 스핀 컨트롤의 속성에서 Auto Buddy와 Set Buddy Integer 속성을 설정해야 한다. OnInitDialog() 함수에서 SetRange() 와 SetAccel() 멤버 함수를 사용하여 범위와, 가속 정도를 설정할 수 있다. 만약 정수가 아닌 값을 에디트 컨트롤에 표시하려면, WM_VSCROLL 과 WM_HSCROLL 메시지를 맵핑한 후, GetPos() 과 GetBuddy() 를 사용해야 한다.  스핀 버튼 컨트롤 메시지에 대한 메시지 맵 항목 메시지 맵 항목 설명 ON_WM_HSCROLL ON_WM_VSCROLL ON_EN_UPDATE 화살표 단추를 누를 때 UDS_HORZ 스타일을 가지는 스핀 컨트롤에 의해 전송된다. 화살표 단추를 누를 때 UDS_VERT 스타일을 가지는 문자가 변할 때 편집 컨트롤에 의해 전송된다.

CHAPTER 6  스핀 버튼 컨트롤(CSpinButtonCtrl) 클래스 메소드 메소드 설명 void SetRange(int nLower, int nUpper); int SetPos( int nPos ); BOOL SetAccel( int nAccel, UDACCEL* pAccel ); int SetBase( int nBase ); CWnd* SetBuddy(CWnd* pWndBuddy); 스핀버튼의 범위를 설정한다. 스핀버튼의 현재위치를 설정한다. 스핀버튼의 가속정도를 설정한다. 스핀버튼에 대한 기반을 설정한다. 스핀버튼에 대한 버디 윈도우를 설정한다.  스핀 버튼 컨트롤(CSpinButtonCtrl) 클래스 메소드 int GetPos() const; CWnd* GetBuddy() const; 스핀버튼의 현재위치값을 리턴한다. 현재 버디 윈도우의 포인터를 리턴한다. UINT GetAccel( int nAccel, UDACCEL* pAccel ) const; UINT GetBase( ) const; 스핀버튼의 가속정도를 얻는다. 스핀버튼에 대한 현재 기반을 얻는다. void GetRange( int &lower, int &upper ) const; 스핀버튼의 범위를 얻는다.

CHAPTER 6  스핀 버튼 컨트롤(CSpinButtonCtrl)을 위해 정의된 창 스타일 스타일 매크로 설명 UDS_ALIGNLEFT UDS_ALIGNRIGHT UDS_ARROWKEYS UDS_AUTOBUDDY UDS_HORZ 스핀 버튼을 버디의 왼쪽 끝에 정렬한다. 스핀 버튼을 버디의 오른쪽 끝에 정렬한다. 키보드에서 화살표키를 누를 때, 컨트롤의 현재 위치를 증가시키고 감소시킨다. z 순서에서 이전의 창을 선택함으로써 자동으로 버디를 선택한다. 스핀 버튼의 화살표를 좌우 화살표로 한다.  스핀 버튼 컨트롤(CSpinButtonCtrl)을 위해 정의된 창 스타일 UDS_SETBUDDYINT 현재 위치가 변할 때 버디의 문자를 설정하도록 컨트롤에게 말한다. 문자는 현재 위치가 10진수나 16진수 문자열로 바뀌어 나타난다. UDS_WRAP 현재 위치가 감기도록 한다. 최대값 이상의 값은 이동(scroll)범위의 최소값으로 다시 시작하도록 감기고, 그 반대도 마찬가지이다. UDS_NOTHOUSANDS 모든 세자리 십진수 사이에 천자리 구분자를 하지 못하게 한다.

CHAPTER 6  목록 상자 컨트롤(CListBox)  단일 선택 목록 상자 - 한 번에 하나의 항목만을 선택할 수 있다.  다중 선택 목록 상자 - 여러 개의 항목을 선택할 수 있다.

CHAPTER 6  CListBox 컨트롤 창 스타일 (DevStudio\Vc\include\winuser.h) LBS_DISABLENOSCROLL 스타일 매크로 설명 목록 상자가 스크롤이 필요할 만큼의 충분한 항목을 가지고 있지 않을 때 수직 이동 표시줄을 사라지게 하는 대신 작동만 되지 않도록 한다. LBS_EXTENDEDSEL 목록 상자에서 마우스와 특별한 키의 조합을 사용하여 여러 개의 항목을 선택할 수 있도록 허락한다. LBS_HASSTRINGS 문자열 항목을 담고 있는 자신이 직접 그린 목록 상자를 지정한다. 그 목록 상자는 문자열들에 대한 메모리 할당을 책임진다. GetText()로 추출할 수 있는 특정한 항목의 문자 LBS_MULTICOLUMN 수평 이동 표시줄과 함께 여러 개의 열을 갖도록 목록 상자를 지정한다. SetColumnWidth()를 이용하여 열의 너비(수)를 설정할 수 있다. LBS_MULTIPLESEL 사용자가 항목을 한 번 클릭하거나 두 번 클릭을 할 때마다 문자열 항목을 선택, 또는 선택 취소를 한다. LBS_NOINTEGRALHEIGHT 윈도우는 대개 목록 상자가 충분하지 않으면, 일부 항목들은 출력 하지 못하게 목록 상자의 크기를 잡는다. 이 매크로는 생성할 때 부분 항목들을 볼 수 있도록 정확히 목록 상자의 크기를 잡는다. LBS_NOREDRAW 목록 상자는 변경이 있을 때 다시 그리기를 하지 않는다. WM_SETREDRAW 메시지를 보냄으로써 언제라도 이 스타일을 변경할 수 있다.

CHAPTER 6  CListBox 컨트롤 창 스타일 LBS_NOSEL 스타일 매크로 설명 LBS_NOTIFY 목록 상자가 보일 수는 있지만, 선택할 수 없는 항목들을 포함하고 있음을 가리킨다. LBS_NOTIFY 목록 상자는 사용자가 목록 항목을 한 번 클릭하거나 두 번 클릭할 때 부모 창에게 입력 메시지를 보낸다. LBS_OWNERDRAWFIXED 목록 상자의 부모 창이 그 내용을 그리는 데 책임을 가지며, 목록의 항목을 모두 같은 높이로 그리도록 지정한다. LBS_OWNERDRAWVARIABLE 항목을 모두 다른 높이로 그리도록 지정한다. LBS_SORT 목록 상자의 문자열을 알파벳순으로 정렬한다. LBS_STANDARD 이 스타일은 네 개의 스타일 비트의 조합이다. LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER. 이 목록 상자는 그 주위에 경계선을 그리고, 목록 내의 문자열들을 알파벳순으로 정렬하고, 사용자가 목록 항목을 한 번 클릭하거나 두 번 클릭할 때 부모 창에게 입력 메시지를 보낸다. LBS_USETABSTOPS 문자열 항목을 그릴 때 탭 문자들을 확장하도록 목록 상자에게 알려 준다. 기본 탭 위치는 32다이얼로그 단위 LBS_WANTKEYBOARDINPUT 사용자가 키를 누를 때 WM_VKEYTOITEM 및 WM_CHARTOITEM 메시지를 목록 상자의 부모 창에게 보냄으로써 응용 프로그랭에게 키보드 입력을 처리할 수 있도록 한다.

CHAPTER 6  CListBox 메시지에 대한 메시지 맵 항목 메시지 맵 항목 설명 ON_LBN_DBLCLK ON_LBN_ERRSPACE ON_LBN_KILLFOCUS ON_LBN_SELCANCEL ON_LBN_SELCHANGE ON_LBN_SETFOCUS 사용자가 목록 상자에 있는 항목을 두 번 클릭할 때 LBS_NOTIFY 스타일을 가지는 목록 상자가 이 메시지를 부모 창에게 보낸다. 목록 상자가 충분한 메모리를 할당할 수 없다. 이 메시지는 목록 상자가 입력 포커스를 잃어 버릴 때 발생한다. 현재 선택된 목록 상자 항목이 취소되었을 때 LBS_NOTIFY 스타일을 가지는 목록 상자가 이 메시지를 부모 창에게 보내다. 목록 상자에서 다른 항목을 선택할 때 LBS_NOTIFY 스타일을 가지는 목록 상자가 이 메시지를 부모 창에게 보낸다. 선택이 CListBox::SetCurSel() 클래스 메소드에 의해 변경되었다면, 통보 메시지는 전송되지 않는다. 다중 목록 상자의 경우 선택이 바뀌지 않는다 하더라도 사용자가 화살표를 누를 때는 이 통보 메시지가 전송된다. 이 메시지는 목록 상자가 입력 포커스를 얻을 때 발생한다.

CHAPTER 6  CListBox 클래스 메소드  단일 선택 목록 상자 메소드  범용 메소드  단일 선택 목록 상자 메소드  int GetCurSel( ) const; 현재 선택된 목록 상자 항목에 대한 색인(0을 기반으로 한 색인)을 얻는다.  int SetCurSel( int nSelect ); 목록 상자 문자열을 선택한다.  다중 선택 목록 상자 메소드  문자열에만 해당하는 메소드  위 네 가지 메소드들의 가능한 반환값  LB_ERRSPACE(-2) : 목록 상자가 항목을 저장할 만큼 충분한 메모리가 없을 때  LB_ERR(-1) : 목록 상자가 어떤 다른 오류를 만났을 때  LB_OKAY(0) : 모든 것이 예상대로 진행되었을 때  가상 메소드

CHAPTER 6  범용 CListBox 클래스 메소드 메소드 설명 int GetCount( ) const; int GetHorizontalExtent( ) const; DWORD GetItemData ( int nIndex ) const; void* GetItemDataPtr int GetItemHeight 목록 상자에 있는 항목의 개수를 얻는다. 목록 상자의 수평 스크롤 너비(픽셀 단위)를 얻는다. 목록 상자 항목과 관련이 있는 32비트 값을 얻는다. 목록 상자 항목에 대한 포인터를 얻는다. 목록 상자에 있는 항목들의 높이를 얻는다. LCID GetLocale( ) const; 목록 상자에 대한 지역 식별자(LCID, Locale identifier)를 얻는다. int GetSel( int nIndex ) const; 목록 상자 항목의 선택 상태를 얻는다. int GetItemRect( int nIndex, LPRECT lpRect ) const; 목록 상자 항목의 경계 직사각형을 얻는다. int GetText( int nIndex, LPTSTR lpszBuffer ) const; void GetText( int nIndex, CString& rString ) const; 목록 상자 문자열을 버퍼로 복사한다. int GetTextLen 목록 상자 문자열의 길이(바이트 단위)를 반환한다.

CHAPTER 6  범용 CListBox 클래스 메소드 메소드 설명 int GetTopIndex( ) const; UINT ItemFromPoint (CPoint pt, BOOL& bOutside ) const; void SetColumnWidth ( int cxWidth ); void SetHorizontalExtent ( int cxExtent ); int SetItemData( int nIndex, DWORD dwItemData ); 포인트에 가장 가까운 목록 상자 항목 색인을 결정하고 반환한다. 다중 열을 가지는 목록 상자의 열 너비를 설정한다. 목록 상자의 수평 스크롤 너비(픽셀 단위)를 설정한다. 목록 상자 항목과 관련이 있는 32비트 값을 설정한다. int SetItemHeight ( int nIndex, UINT cyItemHeight ); 목록 상자에 있는 항목들의 높이를 설정한다. LCID SetLocale ( LCID nNewLocale ); 목록 상자에 대한 지역 식별자(LCID)를 설정한다. int SetItemDataPtr ( int nIndex, void* pData ); 목록 상자 항목에 대한 포인터를 설정한다. void SetTabStops( ); BOOL SetTabStops( const int& cxEachStop ); BOOL SetTabStops( int nTabStops, LPINT rgTabStops ); 목록 상자 탭 멈춤 위치를 설정한다. int SetTopIndex ( int nIndex ); 목록 상자에서 맨 먼저 보이는 항목의 색인(0을 기반으로 한 색인)을 얻는다. 목록 상자에서 맨 먼저 보이는 항목의 색인(0을 기반으로 한 색인)을 설정한다.

CHAPTER 6  다중 선택 ListBox 메소드 메소드 설명 int GetAnchorIndex( ) const; int GetCaretIndex( ) const; int GetSelCount( ) const; int GetSelItems( int nMaxItems, LPINT rgIndex ) const; SelItemRange() 다중 선택 목록 상자에서 포커스 직사각형을 갖는 항목의 색인을 얻는다. 다중 선택 목록 상자에서 현재 선택된 항목의 수를 얻는다. 현재 선택된 모든 다중 선택 목록 상자 항목들의 색인을 정수 배열 버퍼에 넣는다. 다중 선택 목록 상자에서 범위 내에 있는 항목들의 선택 상태를 전환한다. int SetCaretIndex( int nIndex, BOOL bScroll = TRUE ); 다중 선택 목록 상자에서 지정된 색인에 해당하는 항목에 포커스 직사각형을 설정한다. int SetSel( int nIndex, BOOL bSelect = TRUE); 다중 선택 목록 상자에서 항목의 선택 상태를 전환한다. void SetAnchorIndex ( int nIndex ); 다중 선택 목록 상자에서 확장된 선택의 시작 항목을 설정한다. 다중 선택 목록 상자에서 현재 anchor item의 색인을 얻는다.

CHAPTER 6  문자열에 해당하는 메소드 메소드 int AddString( LPCTSTR lpszItem ); 설명 int AddString( LPCTSTR lpszItem ); int DeleteString( UINT nIndex ); int Dir( UINT attr, LPCTSTR lpszWildCard ); int FindString( int nStartAfter, LPCTSTR lpszItem ) const; int FindStringExact( int nIndexStart, LPCTSTR lpszFind ) const; 목록 상자에서 문자열을 지운다. 현재 디렉토리에서 파일 이름을 목록 상자에 추가한다. 목록 상자에서 문자열을 찾는다. 지정된 찾는 문자열과 일치하는 첫번째 문자열을 목록 상자에서 찾는다. void ResetContent( ); 목록 상자로부터 모든 항목들을 지운다. int SelectString( int nStartAfter, LPCTSTR lpszItem ); 단일 선택 목록 상자에서 문자열을 찾아 선택한다. int InsertString ( int nIndex, LPCTSTR lpszItem ); 문자열을 목록 상자의 지정된 색인에 삽입한다. (nIndex : -1, 리스트의 끝에 문자열 추가) 문자열을 목록 상자에 추가한다.

CHAPTER 6  가상 메소드 ( 재정의 가능) 메소드 설명 이 메소드를 재정의함으로써 문자열을 가지지 않는 virtual int CharToItem ( UINT nKey, UINT nIndex ); virtual int CompareItem ( LPCOMPAREITEMSTRUCT lpCompareItemStruct ); virtual void DeleteItem ( LPDELETEITEMSTRUCT lpDeleteItemStruct ); virtual void DrawItem ( LPDRAWITEMSTRUCT lpDrawItemStruct ); virtual void MeasureItem ( LPMEASUREITEMSTRUCT lpMeasureItemStruct ); 정렬된 자신이 직접 그린 목록 상자에서 새로운 항목의 위치를 얻기 위해 MFC에 의해 호출된다. 사용자가 정렬된 자신이 직접 그린 목록 상자에서 새로운 항목을 지울 때 MFC에 의해 호출된다. 자신이 직접 그린 목록 상자를 다시 그려야 할 때가 결정되었을 때 MFC에 의해 호출된다. 자신이 직접 그린 목록 상자가 목록 상자의 크기를 알아내기 위해 생성되었을 때 MFC에 의해 호출된다. virtual int VKeyToItem 이 메소드를 재정의함으로써 LBS_WANTKEYBOARDINPUT 스타일 비트 설정을 가지는 목록 상자에 대해 사용자 정의 WM_KEYDOWN 메시지 다루기를 제공한다. 이 메소드를 재정의함으로써 문자열을 가지지 않는 자신이 직접 그린 목록 상자에 대해 사용자 정의 WM_CHAR 메시지 다루기를 제공한다.

CHAPTER 6  리스트 컨트롤(CListCtrl, 목록 보기 컨트롤)  텍스트와 이미지를 포함하는 리스트를 원할 경우, 리스트 컨트롤을 사용한다.  항목들은 0 부터 시작하는 정수 인덱스값을 갖는다.  리스트 컨트롤이나 트리컨트롤 모두 이미지 리스트(CImageList)라고 하는 공통 컨트롤 요소에서 생성된 그래픽 이미지를 불러온다.  사용자는 아이콘이나 비트맵으로 만들어진 이미지 리스트를 만들어 리스트 컨트롤에 이미지 리스트의 포인터를 넘겨준다.

CHAPTER 6  CListCtrl이 지원하는 네 종류의 보기 보기 설명 아이콘 보기 작은 아이콘 보기 목록 보기 자세히 보기 LVS_ICON 창 스타일로 지정되므로 항목들이 최대 크기의 아이콘으로 출력되며, 아래에 이름표를 가진다. 사용자가 항목을 목록 보기 창의 어떤 위치로든 옮길 수 있다. LVS_SMALLICON 창 스타일로 지정되므로 항목들이 작은 크기의 아이콘으로 출력되며, 오른쪽에 이름표를 가진다. 사용자가 항목을 LVS_LIST 창 스타일로 지정되므로 항목들이 작은 크기의 아이콘으로 출력되며, 오른쪽에 이름표를 가진다. 항목들이 열을 기준으로 정렬되고 고정된다. 다른 목록 보기 위치로 옭길 수 없다. LVS_REPORT 창 스타일로 지정되며, 각 줄에 하나의 항목이 출력되며, 열에 정보를 가진 채 나란히 정렬된다. 왼쪽 열에는 작은 아이콘과 이름표가 나타난다. 나머지 열에는 응용프로그램 관련 하위 항목이 들어간다. 각 열은 LVS_NOCOLUMNHEADER 창 스타일이 지정되어 있지 않으면 Win32 머리글 공통 컨트롤을 사용한다.

CHAPTER 6  CListCtrl을 위해 정의된 창 스타일 스타일 매크로 설명 LVS_ALIGNLEFT 항목들이 아이콘 보기와 작은 아이콘 보기에서 왼쪽으로 정렬된다. LVS_ALIGNTOP 항목들이 아이콘 보기와 작은 아이콘 보기에서 그 컨트롤의 위에서부터 왼쪽으로 정렬된다. LVS_AUTOARRANGE 항목들이 아이콘 보기와 작은 아이콘 보기에서 자동으로 정렬된다. LVS_EDITLABELS 항목문자가 적절한 위치에서 편집될 수 있도록 허락한다. LVS_ICON 아이콘 보기 LVS_LIST 리스트(목록)보기 LVS_NOCOLUMNHEADER 자세히 보기에서 열 머리글이 출력되지 않는다. LVS_NOLABELWRAP 아이콘 보기에서 항목 문자가 하나의 줄에 출력된다. LVS_NOSCROLL 스크롤이 작동되지 않게 한다.

CHAPTER 6  CListCtrl을 위해 정의된 창 스타일 스타일 매크로 설명 LVS_REPORT LVS_NOSORTHEADER 열 머리글이 버튼으로서의 기능을 하지 않는다. LVS_OWNERDRAWFIXED 자세히 보기에서 원하는 때에 부모 창에게 항목을 그릴 수 있게 한다. LVS_REPORT 자세히 보기 LVS_SHAREIMAGELISTS 이미지 목록을 다중 목록 보기 컨트롤에서 사용할 수 있게 한다. LVS_SINGLESEL 한 번에 단 하나의 항목만이 선택될 수 있게 한다. LVS_SMALLICON 작은 아이콘 보기 LVS_SORTASCENDING 항목 테스트를 기준으로 오름차순으로 항목들을 정렬한다. LVS_SORTDESCENDING 항목 테스트를 기준으로 내림차순으로 항목들을 정렬한다.

CHAPTER 6  CListCtrl이 사용하는 윈도우 공통 컨트롤 창 스타일 스타일 매크로 설명 CCS_BOTTOM 컨트롤은 부모 창의 클라이언트 영역 바닥에 줄을 맞추며, 부모 창의 클라이언트 영역의 너비에 자신의 크기를 맞춘다. CCS_NODIVIDER 컨트롤의 맨 위에서 두 개의 픽셀 하이라이트가 그려지는 것을 막는다. CCS_NOHILITE 컨트롤의 맨 위에서 한 개의 픽셀 하이라이트가 그려지는 것을 막는다. CCS_NOMOVEV 컨트롤이 WM_SIZE 메시지에 반응하여 스스로 크기를 재조정하거나 수평 방향으로 움직이도록 한다. 수직으로는 움직이지 못하게 한다. CCS_NOPARENTALIGN 부모 창의 맨 위나 아래 바닥에 자동으로 줄이 맞춰지는 것을 막는다. CCS_NORESIZE 컨트롤이 생성하거나 크기를 재조정할 때 지정된 너비와 높이를 사용하게 한다. CCS_TOP 컨트롤은 부모 창의 클라이언트 영역 맨 위에 줄을 맞추며, 부모 창의 클라이언트 영역의 너비에 자신의 크기를 맞춘다.

CHAPTER 6  이미지 목록과 리스트 컨트롤  리스트 항목에서 사용하는 아이콘은 이미지 목록으로 저장된다.  큰 아이콘 목록 LVS_ICON 목록 보기 스타일에서 사용하는 최대 크기의 아이콘 이미지를 담고 있는 이미지 목록  작은 아이콘 목록 LVS_ICON 목록 보기 스타일을 갖지 않는 작은 크기의 아이콘 이미지를  상태 아이콘 목록 항목의 아이콘 옆에 나타날 수 있는 상태 이미지를 담을 수 있는 이미지 목록. 이 이미지는 보통 어떤 응용 프로그램에 특정 상태를 표시하는 데 사용한다.

CHAPTER 6  리스트 컨트롤 항목과 하위 항목  리스트 컨트롤(CListCtrl)  리스트 컨트롤은 항목의 목록을 가진다.  아이콘  이름표  현재 상태  응용 프로그램에 의해 정의된 값  리스트 컨트롤(CListCtrl)  LV_ITEM 구조체 typedef struct _LV_ITEM { UINT mask; // 유효한 데이터인지, 채워야 할 필요가 있는지 가리키는 비트 플래그 집합 int iItem; // 0에서 시작하여 번호를 매기는 인덱스를 가지는 항목 int iSubItem; // 1에서 지작하여 번호를 매기는 인덱스를 가지는 하위항목 UINT state; // 항목의 현재 상태 UINT stateMask; // 유효한 상태 멤버 비트를 지정한다. LPSTR pszText; // 구조가 항목 속성을 지정할 때 항목 문자를 포함하고 있는 문자열에 대한 포인터 int cchTextMax; // pszText가 가리키고 있는 버퍼의 크기 int iImage; // 아이콘 보기와 작은 아이콘 이미지 목록에서 항목 아이콘의 인덱스 LPARAM lParam; // 항목과 연관 있는 응용 프로그램에서 정의한 32비트 값 } LV_ITEM;

CHAPTER 6  LV_ITEM mask 멤버에서 사용하는 비트 플래그  리스트 컨트롤 통보 메시지 값 설명 LVIF_TEXT pszText 멤버가 유효하다. LVIF_IMAGE iImage 멤버가 유효하다. LVIF_PARAM lParam 멤버가 유효하다. LVIF_STATE state 멤버가 유효하다. LVIF_DI_SETITEM 윈도우는 요청이 있는 항목 정보를 저장해야 한다.  리스트 컨트롤 통보 메시지  대부분의 윈도우 공통 컨트롤과 마찬가지로 리스트 컨트롤은 자신의 부모 창에게 WM_NOTIFY 통보 메시지를 보낸다.  이 메시지들은 리스트 컨트롤의 부모 클래스에서 메시지 핸들러를 씀으로써 잡고 처리할 수 있다. ( DevStudio\Vc\include\Commctrl.h )

CHAPTER 6  리스트 컨트롤을 위해 정의된 통보 메시지 메시지 맵 항목 설명 LVN_BEGINDRAG 왼쪽 마우스 버튼을 포함하는 끌어서 놓기 작업이 시작된다. LVN_BEGINLABELEDIT 이름표 편집 작업이 시작된다. LVN_BEGINRDRAG 열을 클릭했다. LVN_COLUMNCLICK 오른쪽 마우스 버튼을 포함하는 끌어서 놓기 작업이 시작된다. LVN_DELETEALLITEMS 사용자가 컨트롤의 모든 항목을 지웠다. LVN_DELETEITEM 사용자가 컨트롤의 한 항목을 지웠다. LVN_ENDLABELEDIT 이름표 편집 작업이 끝난다. LVN_GETDISPINFO 새로운 항목을 삽입했다. LVN_INSERTITEM 목록 보기 항목을 출력하거나 정렬할 때 필요한 정보를 제공해 달라는 부모 창의 요청 LVN_ITEMCHANGED 항목을 변경했다. 항목을 변경하고 있다. LVN_ITEMCHANGING LVN_KEYDOWN 키를 눌렀다. LVN_PEN 펜 윈도우(펜과 디지타이저 타블렛을 가진 시스템)에서 사용된다. LVN_SETDISPINFO 부모 창에게 항목에 대한 출력 정보를 갱신하게 한다.

CHAPTER 6  리스트 컨트롤 사용하기 1. 이미지 목록 붙이기 2. 자세히 보기를 위한 열 추가하기 3. CListCtrl 객체에 항목 추가하기 4. WM_NOTIFY 메시지를 처리하기 위해 상속한 OnChildNotify() 메소드 재정의하기  이미지 목록 붙이기  생성하는 리스트 컨트롤이 LVS_ICON 스타일을 사용하면, 리스트 항목에 대한 이미지 목록을 필요로 한다.  출력할 리스트에 대한 이미지 목록을 생성하기 위해서는 CImageList 클래스를 사용한다.  컨트롤에서 사용하는 모든 이미지 목록에 대한 CListCtrl::SetImageList() 를 호출한다.

CHAPTER 6  자세히 보기를 위한 열 추가하기  보통 사용자에게 열의 크기를 재조정할 수 있게 하기 위해 머리글 공통  자세히 보기를 위한 열 추가하기  보통 사용자에게 열의 크기를 재조정할 수 있게 하기 위해 머리글 공통 컨트롤(CHeaderCtrl)을 사용한다. 1. LV_COLUMN 구조를 초기화 2. InsertColumn() 메소드를 호출하여 원하는 각 열을 생성  LV_COLUMN 구조 typedef struct _LV_COLUMN { UINT mask; // 유효한 데이터 멤버를 지정한다. int fmt; // 열 정렬 식별자(LVCFMT_CENTER, LVCFMT_LEFT, LVCFMT_RIGHT) int cx; // 열의 너비(단위 : 픽셀) LPTSTR pszText; // 열 머리글 문자열에 대한 포인터 int cchTextMax; // pszText가 가리키는 문자 수 int iSubItem; // 하위 항목의 인덱스 } LV_COLUMN;

CHAPTER 6  LV_COLUMN mask 멤버의 가능한 값 값 설명 LVCF_FMT fmt 멤버가 유효하다. LVCF_SUBITEM iSubItem 멤버가 유효하다. LVCF_TEXT pszText 멤버가 유효하다. LVCF_WIDTH cx 멤버가 유효하다.

CHAPTER 6  리스트 컨트롤 클래스 메소드 메소드 CImageList* SetImageList 설명 CImageList* SetImageList ( CImageList* pImageList, int nImageList); CImageList* GetImageList ( int nImageList ) const; int GetItemCount(); 리스트 뷰 컨트롤에 이미지 리스트를 할당한다. 리스트 뷰 아이템에 그려진 이미지 리스트의 핸들값을 리턴한다. 리스트 뷰 컨트롤의 아이템 개수를 리턴한다. BOOL SetColumnWidth( int nCol, int cx); 컬럼의 너비를 설정한다. int GetItemText( int nItem, int nSubItem, LPTSTR lpszText, int nLen ) const; CString GetItemText ( int nItem, int nSubItem) const; 현재 선택한 아이템의 텍스트를 리턴한다. BOOL SetColumn ( int nCol, const LV_COLUMN* pColumn); 리스트 뷰 컨트롤의 컬럼 속성을 설정한다.

CHAPTER 6  리스트 뷰 컨트롤의 Operation Operation 설명 InsertItem DeleteItem DeleteAllItem FindItem SortItems Scroll RedrawItems Update Arrange InsertColumn 리스트 뷰 컨트롤에 아이템을 추가한다. 컨트롤의 모든 아이템을 제거한다. 컨트롤의 아이템을 제거한다. 특정한 문자를 포함하는 아이템을 찾는다. 어플리케이션에서 정의된 비교함수를 사용하여 정렬한다. 리스트 뷰 컨트롤을 스크롤한다. 리스트 뷰 컨트롤의 아이템을 다시 그린다. 컨트롤이 특정한 아이템을 다시 그리도록 한다. 그리드에 아이템을 배치한다. 리스트 뷰 컨트롤에 새로운 컬럼을 추가한다.

CHAPTER 6  트리 컨트롤(CTreeCtrl)  리스트 뷰 컨트롤이나 트리 컨트롤 모두 같은 이미지 리스트를 사용하고 같은 공지 메시지를 공유하지만, 아이템을 식별하는 방법은 다르다. 트리 컨트롤은 정수 인덱스를 사용하는 대신에 HTREEITEM 핸들을 사용 한다. 아이템을 추가하기 위해서는 InsertItem() 을 사용한다. 그러나 우선 아이템을 식별하는 TV_INSERTSTRUCT 구조체를 만들어야 한다.  TV_INSERTSTRUCT 구조체 typedef struct _TV_INSERTSTRUCT { HTREEITEM hParent; HTREEITEM hInsertAfter; TV_ITEM item; } TV_INSERTSTRUCT;

CHAPTER 6  트리 컨트롤(CTreeCtrl)  TV_ITEM 구조체 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;

CHAPTER 6  트리 컨트롤(CTreeCtrl)을 위해 정의된 창 스타일 ( DevStudio\Vc\include\Commctrl.h ) 스타일 매크로 설명 TVS_HASLINES TVS_LINESATROOT TVS_HASBUTTONS TVS_EDITLABELS TVS_SHOWSELALWAYS TVS_DISABLEDRAGDROP 자식 항목은 그들을 대응되는 부모 항목과 연결하는 선을 가지고 있다. 트리는 각각의 부모 항목 왼편에 단추를 가진다. 자식 항목은 그들을 트리의 루트에 연결하는 선을 가지고 있다. 트리 보기 항목 이름표는 편집할 수 없다. 선택된 항목은 트리 보기 항목이 입력 포커스를 잃어 버렸다 하더라도 선택된 채 남아 있을 것이다. 트리 보기 컨트롤에게 TVN_BEGINDRAG 알림 메시지를 보내지 못하게 한다.

CHAPTER 6  트리 통보 메시지 ( DevStudio\Vc\include\Commctrl.h ) 통보 설명 TVN_BEGINDRAG 끌어서 놓기 작업이 시작됐다. TVN_BEGINLABELEDIT 적절한 이름표 편집을 시작했다. TVN_BEGINRDRAG 오른쪽 마우스 버튼을 사용하여 끌어서 놓기 작업을 시작했다. TVN_DELETEITEM 지정된 항목이 지워졌다. TVN_ENDLABELEDIT 적절한 이름표 편집이 끝났다. TVN_GETDISPINFO 트리 컨트롤이 항목을 출력하기 위해 필요로 하는 정보를 얻는다. TVN_ITEMEXPANDED 부모 항목의 자식 항목 목록이 확장되거나 없어졌다. TVN_ITEMEXPANDING 부모 항목의 자식 항목 목록이 확장되거나 없어지려고 한다. TVN_KEYDOWN 키를 아래로 눌렀다. TVN_SELCHANGED 현재 선택이 한 항목에서 다른 항목으로 변경되었다. TVN_SELCHANGING 선택이 한 항목에서 다른 항목으로 변경되려고 한다. TVN_SETDISPINFO 항목에 유지되는 정보를 갱신한다.

CHAPTER 6  트리 컨트롤 (CTreeCtrl) 클래스 메소드 메소드 설명 CImageList* SetImageList( CImageList* pImageList, int nImageListType ); CImageList* GetImageList ( UINT nImage ); HTREEITEM GetSelectedItem(); BOOL SetItem( TV_ITEM* pItem ); BOOL SetItem( HTREEITEM hItem, UINT nMask, LPCTSTR lpszItem, int nImage, int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam ); 트리 뷰 컨트롤에 이미지 리스트를 할당한다. 트리 뷰 아이템에 그려진 이미지리스트의 핸들값을 리턴한다. 선택한 아이템의 핸들값을 리턴한다. 트리 뷰의 아이템을 설정한다. UINT GetItemState( HTREEITEM hItem, UINT nStateMask ) const; 아이템의 상대값을 리턴한다. CString GetItemText ( HTREEITEM hItem) const; 아이템의 텍스트를 리턴한다.

CHAPTER 6  CTreeCtrl 매개변수 설명 dwStyle rect nParentWnd 그 컨트롤에 대한 창 스타일을 설정한다. 이것은 일반적인 창 스타일과 트리 스타일의 어떠한 조합도 가능하다. 컨트롤의 크기와 위치를 지정하는 직사각형 그 컨트롤의 부모 창에 대한 포인터 nID 트리 보기 컨트롤과 통신하기 위해 부모 창에서 사용하는 컨트롤 ID

CHAPTER 6  아이콘(Icon)  Small Icon : 16 x 16 픽셀  Large Icon : 32 x 32 픽셀  각 아이콘 마다 두 개의 분리된 비트맵이 있다.  색상 이미지를 위한 비트맵 : 픽셀당 4비트  마스크(mask)를 위한 모노크롬 비트맵 : 픽셀당 1비트  마스크 비트 0(FALSE) : 불투명한(opaque) 색  마스크 비트 1(TRUE) : 이미지 색상 : 검정색(0) - 투명 이미지 색상 : 흰색(0xF) - 픽셀 위치에 배경 색상이 반전

CHAPTER 6  CWnd::GetDlgItem  지정한 자식 윈도우 포인터나 핸들을 리턴한다.  보통 이 함수는 다이얼로그에 있는 컨트롤을 얻는데 사용된다.  CWnd* GetDlgItem(int nID) const; void CWnd::GetDlgItem(int nID, HWND* phWnd) const;  Return value  첫번째 형식의 함수는 지정 자식 윈도우에 대한 포인터를 리턴하거나 자식 윈도우가 존재하지 않으면 NULL  Parameters  nID 얻을 자식 윈도우 또는 컨트롤의 ID  phWnd 지정 자식 윈도우 핸들로 채워지는 HWND에 대한 포인터

CHAPTER 6  CComboBox::InsertString  그 위치에 있는 현재 항목을 아래로 이동하고 주어진 인덱스에 새로운 항목을 삽입한다.  이런 방식으로 문자열을 삽입하는 것은 CBS_SORT 스타일이 설정되어 있으면 다른 분류 옵션을 중복시킨다.  int InsertString( int nIndex, LPCTSTR lpszString );  Parameters  nIndex 새로운 문자열이 있는 인덱스 -1 : 리스트의 끝에 문자열이 추가된다.  lpszString 콤보박스에 삽입되는 null로 끝나는 문자열  CListBox::InsertString  그 위치에 있는 현재 항목과 그 아래에 있는 다른 항목들을 아래로 이동하여 주어진 인덱스에 새로운 항목을 삽입한다.  이런 방식으로 문자열을 삽입하는 것은 LBS_SORT 스타일이 설정되어 있으면  int InsertString( int nIndex, LPCTSTR lpszItem );  Return Value 성공하면 새로 삽입된 항목의 인덱스, 아니면 LB_ERR 또는 LB_ERRSPACE  lpszItem 리스트박스에 삽입되는 null로 끝나는 문자열

CHAPTER 6  CWnd::SetScrollRange  CScrollBar::SetScrollRange  특정 스크롤바의 스크롤 범위를 설정한다.  void SetScrollRange( int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = TRUE );  Parameters  nBar SB_HORZ 수평 스크롤바를 변경 SB_VERT 수직 스크롤바를 변경  nMinPos 최소로 가능한 스크롤 값  nMaxPos 최대로 가능한 스크롤 값  bRedraw 스크롤바를 다시 그려야 한다면 TRUE, 그렇지 않으면 FALSE  CScrollBar::SetScrollRange  void SetScrollRange( int nMinPos, int nMaxPos, BOOL bRedraw = TRUE );  nMinPos 최소 스크롤바 위치  nMaxPos 최대 스크롤바 위치  bRedraw 스크롤바를 다시 그려야 한다면 TRUE, 그렇지 않으면 FALSE

CHAPTER 6  CDialog::DoModal  virtual int DoModal( );  Return vlaue 다이얼로그 윈도우가 생성될 수 없으면 -1, 에러가 발생하면 IDABORT이거나 성공하면 EndDialog에 전달되는 값.  EndDialog에 전달되는 값 취소 버튼 : IDCANCEL, 확인 버튼 : IDOK  CDialog::OnOK  확인(OK) 버튼을 누를 때 호출된다.  이 함수의 기본적인 클래스의 구현은 데이터 교환과 확인을 수행하고 IDOK의 파라미터로 EndDialog를 호출하여 다이얼로그를 파괴한다.  OnOK는 모달 다이얼로그에서만 사용된다.  모덜리스 다이얼로그에서 확인 버튼을 넣으려면, 이 함수를 중복하고 그 내에서 DestroyWindow를 호출해야 한다.  virtual void OnOK( );

CHAPTER 6  CDialog::OnCancel  취소 버튼(IDCANCEL)을 누를 때 호출된다.  이 함수의 기본적인 클래스의 구현은 IDCANCEL의 파라미터로 EndDialog를 호출하여 다이얼로그를 파괴한다.  OnCancel은 모달 다이얼로그에서만 사용된다.  모덜리스 다이얼로그에서 취소 버튼을 넣으려면, 이 함수를 중복하고 그 내에서 DestroyWindow를 호출해야 한다.  virtual void OnCancel();  CDialog::EndDialog  모달 다이얼로그를 파괴하기 위하여 호출된다.  EndDialog는 다이얼로그를 즉시 파괴하지 않고, 현 메시지 핸들러가 완료된 다음에 파괴하기 위하여 플래그를 설정한다.  EndDialog는 CDialog객체를 삭제하지 않고, 단순히 관련된 윈도우를 파괴한다.  virtual EndDialog( int nResult );  Parameters  nResult 다이얼로그를 표시하는 데 호출되는 DoModal 함수에 의해 리턴되는 정수

CHAPTER 6  CWnd::DoDataExchange  다이얼로그의 컨트롤과 데이터를 교환  virtual void DoDataExchange( CDataExchange* pDX);  Parameters  pDX CDataExchange 객체에 대한 포인터  CWnd::GetScrollPos  지정 스크롤바의 현재 위치를 얻는다.  현재 위치는 스크롤바의 현재 스크롤 범위에 따른 상대적인 값이다.  int GetScrollPos( int nBar ) const;  nBar 스크롤바의 현재 위치 SB_HORZ 수평 스크롤바의 현재 위치를 얻는다. SB_VERT 수직 스크롤바의 현재 위치를 얻는다.  CScrollBar::GetScrollPos  스크롤바의 현재 위치를 얻는다.  int GetScrollPos( ) const;

CHAPTER 6  CScrollBar::SetScrollPos  스크롤바의 현재 위치를 설정한다.  int SetScrollPos( int nPos, BOOL bRedraw = TRUE );  Parameters  nPos 스크롤 박스의 새로운 위치  bRedraw TRUE는 새로운 위치를 반영하기 위하여 자동으로 스크롤바를 다시 그리게 한다. FALSE는 스크롤바 디스플레이를 갱신하지 않는다.  CScrollBar::GetScrollRange  현재 스크롤바 범위를 리턴한다.  void GetScrollRange( LPINT lpMinPos, LPINT lpMaxPos ) const;  lpMinPos 최소 스크롤바 위치를 받는 정수의 주소  lpMaxPos 최대 스크롤바 위치를 받는 정수의 주소

CHAPTER 6  CDC::SetBkColor  디바이스 컨텍스트의 현재 배경 색상을 기술한 RGB 색상 값으로 설정한다.  virtual COLORREF SetBkColor( COLORREF crColor );  Parameters  crColor 새로운 배경 색상의 RGB 값  CImageList::SetBkColor  이미지를 칠할 때 사용되는 배경 색상을 설정한다.  COLORREF SetBkColor( COLORREF cr );  cr 배경 색상  CListCtrl::SetBkColor  컨트롤의 현재 배경 색상을 설정한다.  BOOL SetBkColor( COLORREF cr );  cr 배경 색상을 기술하는 값

CHAPTER 6  CDC::GetBkColor  디바이스 컨텍스트에 대한 현재 배경의 RGB 값을 얻는다.  COLORREF GetBkColor( ) const;  CImageList::GetBkColor  이미지를 칠하는 데 사용되는 현재 배경을 얻는다.  CListCtrl::GetBkColor  컨트롤의 현재 배경 색상을 얻는다.

CHAPTER 6  CWnd::OnCtlColor  WM_CTLCOLOR 메시지에 대한 핸들러 함수  이 메시지는 컨트롤의 배경을 칠할 때 사용되는 브러시를 얻기 위하여 보통 자식 컨트롤에 의해 부모에 전달된다.  afx_msg HBRUSH OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor);  Parameters  pDC 컨트롤을 그리는데 사용되는 디바이스 컨텍스트에 대한 포인터  pWnd 컨트롤에 대한 포인터  nCtlColor 컨트롤의 타입 CTLCOLOR_BTN 버튼 컨트롤 CTLCOLOR_DLG 다이얼로그 박스 CTLCOLOR_EDIT 편집 컨트롤 CTLCOLOR_LISTBOX 리스트 박스 컨트롤 CTLCOLOR_MSGBOX 메시지 박스 CTLCOLOR_SCROLLBAR 스크롤바 컨트롤 CTLCOLOR_STATIC 정적 컨트롤

CHAPTER 6  CWnd::SetDlgItemText  특정 자식 윈도우의 윈도우 텍스트를 특정 텍스트 문자열로 설정한다.  void SetDlgItemtext( int nID, LPCTSTR lpszString );  Parameters  nID 윈도우 텍스트가 설정되는 자식 윈도우 ID  lpszString 새로운 윈도우 텍스트를 포함하는 null로 끝나는 문자열 버퍼에 대한 포인터  CWnd::SetWindowText  윈도우에 텍스트를 설정한다.  윈도우의 캡션(제목) 바에 윈도우 텍스트를 표시한다.  void SetWindowText( LPCTSTR lpszString );  lpszString 새로운 윈도우 텍스트로 사용되는 null로 끝나는 문자열에

CHAPTER 6  CWnd::GetWindowText  현재 윈도우 캡션(제목)의 텍스트를 얻는다.  int GetWindowText( LPCTSTR lpszStringBuf, int nMaxCount ) const;  void GetWindowText( CString& rString ) const;  Parameters  lpszStringBuf null로 끝나는 윈도우에 있는 문자 버퍼에 대한 포인터  nMaxCount lpszStringBuf에 의해 가리키는 버퍼의 크기  rString 윈도우 텍스트로 채워지는 CString에 대한 참조  CWinApp::LoadIcon  아이콘 리소스를 로드한다.  HICON LoadIcon( LPCTSTR lpszResourceName ) const;  HICON LoadIcon( UINT nIDResource ) const;  lpszResourceName MAKEINTRESOURCE 매크로를 사용하면 발생되는 아이콘 리소스의 이름  nIDResource 아이콘에 대한 리소스 ID

CHAPTER 6  CListCtrl::SetImageList  컨트롤에 항목을 표시하는 데 사용되는 이미지 리스트를 설정한다.  CImageList* SetImageList( CImageList* pImageList, int nImageList );  Parameters  pImageList 새로운 이미지 리스트  nImageList 이미지 리스트 타입 LVSIL_NORMAL 큰 이미지를 포함하는 이미지 리스트 LVSIL_SMALL 작은 이미지를 포함하는 이미지 리스트 LVSIL_STATE 상태 이미지를 포함하는 이미지 리스트  CListCtrl::GetItemText  항목이나 관련 서브 항목으로부터 기술한 텍스트를 얻는다.  int GetItemText( int nItem, int nSubItem, LPTSTR lpszText, int nLen ) const;  CString GetItemText( int nItem, int nSubItem ) const;  nItem 항목의 인덱스  nSubItem 얻는 텍스트의 서브 항목의 인덱스  lpszText 항목 텍스트를 받는 버퍼의 주소  nLen lpszText에 의해 기술되는 텍스트 버퍼의 길이

CHAPTER 6  CListCtrl::InsertItem - 새로운 항목을 컨트롤에 삽입한다.  int InsertItem( const LV_ITEM* pItem );  int InsertItem( int nItem, LPCTSTR lpszItem );  int InsertItem( int nItem, LPCTSTR lpszItem, int nImage );  int InsertItem( UINT nMask, int nItem, LPCTSTR lpszItem, UINT nState, UINT nStateMask, int nImage, LPARAM lParam );  Parameters  pItem 새로운 항목을 기술하는 LV_ITEM 구조체에 대한 포인터  nItem 항목이 삽입되는 곳의 인덱스  lpszItem 새로운 항목의 라벨을 포함하는 문자열에 대한 포인터  nImage 새로운 항목의 이미지의 인덱스나 항목이 콜백 항목이면 I_IMAGECALLBACK  nMask 어느 속성이 설정되는가를 나타내는 마스크 플래그  nState 항목 상태 플래그  nStateMask 어느 nState비트가 설정되는가를 나타내는 마스크 플래그  nImage 이미지 리스트에 있는 항목의 이미지 인덱스  lParam 이 항목에 관련되는 프로그래머가 제공하는 32비트 데이터

CHAPTER 6 Object Property Setting EX06B Dialog ID IDD_DIALOG1 Caption Windows Common Controls Dialog Static ID IDC_STATIC Caption Progress Caption Trackbar 1 Trackbar Style/Point Bottom/Right Static ID IDC_STATIC_TRACK1 Caption Static Caption Trackbar 2 Tick marks, Auto ticks Static ID IDC_STATIC_TRACK2 Caption Buddy Edit ID IDC_BUDDY_SPIN1 Style Read-only EX06B

CHAPTER 6 Object Property Setting EX06B Spin Style Auto buddy Static ID IDC_STATIC Caption Spin Static ID IDC_STATIC Caption List Control List Control ID IDC_LISTVIEW1 Style Single selection Show selection always Style/View List More Styles Border Static ID IDC_STATIC_LISTVIEW1 Caption Current Selection Static ID IDC_STATIC Caption Tree Control Tree Control ID IDC_TREEVIEW1 Style Has buttons, Has lines Lines at root, Border Static ID IDC_STATIC_TREEVIEW1 Caption Current Selection EX06B

CHAPTER 7 모덜리스 다이얼로그와 윈도우 공통 다이얼로그

CHAPTER 7  공통 다이얼로그  CFileDialog, CFontDialog, CColorDialog, CPrintDialog  이 클래스들은 COMDLG32.DLL 이 지원한다.  모덜리스 다이얼로그  모달 다이얼로그와 모덜리스 다이얼로그는 동일한 기초 클래스 CDialog 에서 파생된다.  모덜리스 다이얼로그 생성하기 모달 다이얼로그 모덜리스 다이얼로그 사용되는 생성자 윈도우를 만들기 위해 사용되는 함수 리소스 템플릿 ID를 파라미터로 하는 생성자 CDialog::DoModal() 디폴트 생성자 (파라미터 없음) CDialog::Create() (리소스 템플릿 ID를 파라미터로 함)

CHAPTER 7  사용자 정의메시지  다이얼로그는 뷰클래스의 멤버함수를 곧바로 부를 수 있지만, 이 경우에는 다이얼로그와 뷰를 반드시 연결해야만 한다. 그러나 보다 나은 방법은  사용자가 메시지를 만들어 뷰에 보내고, 뷰 클래스에서 이 메시지를 받아 해당 처리를 하도록 한다. CWnd::SendMessage() CWnd::PostMessage() 보낸 메시지의 처리가 모두 된 후에야 비로소 리턴 메시지 큐에 메시지를 추가하고 바로 리턴하여 다음 코드를 수행  다이얼로그 소유권(Ownership)  다이얼로그를 팝업(Pop-up) 스타일로 설정했다면, 다이얼로그는 뷰의 클라 이언트 영역으로 제한되지 않는다.  다이얼로그의 오너(Owner)는 뷰 윈도우가 아니라 어플리케이션의 메인프레임 윈도우이다.

CHAPTER 7  SendMessage()와 PostMessage()의 차이점  A윈도우 (메시지를 보내는 윈도우) ① pW->SendMessage(WM_MYMSG, 0, 0); AfxMessageBox(“전송완료 1”); ② pW->PostMessage(WM_MYMSG, 0, 0); AfxMessageBox(“전송완료 2”);  B윈도우 (메시지를 받는 윈도우) LONG CMyView::OnMyMsg(WPARAM wParam, LPARAM lParam) 복잡한 계산 처리 루틴 return 0L; ① B윈도우에서 메시지 처리가 다 된 후에 리턴 ② B윈도우에서 메시지 처리와는 상관없이 단지 메시지 큐에 해당 메시지만을 추가하고 바로 리턴하여 다음 코드인 AfxMessageBox(“전송완료 2”)를 수행

CHAPTER 7  SendMessage  특정 윈도우에 메시지를 보낸다.  보내지는 메시지는 즉시 전달된다.  LRESULT SendMessage(UINT message, WPARAM wParam=0, LPARAM lParam=0);  Parameters  message 보내지는 메시지  wParam 메시지 특정 부가 정보  lParam 메시지 특정 부가 정보  PostMessage  어플리케이션의 메시지 큐에 메시지를 포스트한다.  메시지가 포스트될 때, 큐에 있는 이미 다른 메시지들의 뒤에 넣어지고 나중 어느 시점에서 어플리케이션에서 받게 된다.  PostMessage는 메시지가 처리되는 것을 기다리지 않는다.  BOOL PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0);  message 포스트되는 메시지  wParam 메시지 특정 부가 정보  lParam 메시지 특정 부가 정보

CHAPTER 7  모달 다이얼로그와 모덜리스 다이얼로그의 차이점  CDialog::DoModal()로 생성된 모달 다이얼로그에서 CDialog::OnOK() 함수나 CDialog::OnCancel() 함수를 호출하면 결과적으로 CDialog::EndDialog() 함수가 호출되어 다이얼로그가 소멸된다.  CDialog::Create()로 생성된 모덜리스 다이얼로그 경우에는 EndDialog() 대신에 DestroyWindow() 함수를 호출해서 다이얼로그 윈도우를 소멸시킨다.  DestroyWindow() 함수를 호출해서 다이얼로그 윈도우를 소멸하는 이유  이렇게 재정의 하지 않으면 Enter키나 ESC키를 눌렀을 경우 EndDialog()를 호출하게 된다.

CHAPTER 7  윈도우 공통 다이얼로그 클래스 목적 CColorDialog CFileDialog CFindReplaceDialog CPageSetupDialog CFontDialog CPrintDialog 사용자가 색상을 선택하거나 만들어낼 수 있게 한다. 사용자가 파일을 열거나 저장하게 해준다. 사용자가 한 문자열을 다른 문자열로 대체하게 해준다. 사용자가 페이지 번호 파라미터를 입력하게 해준다. 사용자가 사용가능한 폰트의 리스트에서 하나의 폰트를 선택하게 해준다. 사용자가 프린터를 설정하고 문서 내용을 프린트하게 해준다.

CHAPTER 7  CFileDialog 클래스 직접 사용하기  CFileDialog dlg(TRUE, “bmp”, “*.bmp”); if(dlg.DoModal() == IDOK) { CFile file; VERIFY(file.Open(dlg.GetPathName(), CFile::modeRead)); }  첫 번째 파라미터 : TRUE(File Open 다이얼로그), FALSE(File Save 다이얼로그)  두 번째 파라미터 : “bmp” (디폴트 확장자)  세 번째 파라미터 : “*.bmp” (다이얼로그 파일 이름란에 출력될 문자열)  CFileDialog::GetPathName() : 선택된 파일의 전체 경로를 저장하는 CString 객체를 리턴한다.

CHAPTER 7  중첩(nested) 다이얼로그  Win32는 하나의 다이얼로그를 다른 다이얼로그 내에 “중첩시키는” 방법으로 여러 다이얼로그를 마치 하나처럼 보이게 할 수 있다.  중첩 다이얼로그를 만들기 위해서는 일반적으로 그룹 박스 컨트롤 (차일드 윈도우 ID : stc32=0x045f)을 포함한 다이얼로그 리소스 템플릿을 만들고, 기초 클래스(CFileDialog)에서 새로운 클래스를 유도한다.  그리고 ClassWizard를 이용해서 템플릿의 새로운 컨트롤에 대한 메시지들을 맵핑한다.

CHAPTER 7  파일 다이얼로그 캡션바에 아이콘 추가  BOOL CSpecialFileDialog::OnInitDialog() { CFileDialog::OnInitDialog(); HICON hIcon = AfxGetApp() -> LoadIcon(IDI_ICON1); GetParent() -> SetIcon(hIcon, TRUE); // Large Icon 설정 GetParent() -> SetIcon(hIcon, FALSE); // Small Icon 설정 return TRUE; }

CHAPTER 7 EX07A EX07B Object Property Setting Caption Edit1 Dialog ID IDD_DIALOG1 Border Modeless Dialog Dialog Frame Style Popup Static Text IDC_STATIC EX07A Object Property Setting GroupBox ID Stc32=0x045f Button Dialog IDC_DELETE Caption Delete all matching files IDD_FILESPECIAL Style Border Child None EX07B

허물을 덮어주세요 어느 화가가 알렉산드로스 대왕의 초상화를 부탁받고 고민에 빠졌습니다. 왜냐하면 대왕의 이마에는 추하기 짝이 없는 상처가 있었기 때문입니다. 화가는 대왕의 상처를 그대로 화폭에 담고 싶지 않았습니다. 대왕의 자랑스러움에 손상을 입히고 싶지 않았기 때문입니다. 그러나 상처를 그리지 않는다면 그 초상화는 진실한 것이 되지 못하므로 화가 자신의 신망은 여지없이 땅에 떨어질 것입니다. 화가는 고민끝에 한 가지 방법을 생각해 냈습니다. 대왕이 이마에 손을 대고 쉬고 있는 모습을 그려야겠다고 생각한 것입니다. 타인의 상처를 보셨습니까? 그의 허물을 가려줄 방법을 생각해봐야 하지 않을까요? 사랑은 허다한 허물을 덮는다고 합니다.

CHAPTER 8 ActiveX 컨트롤 사용하기

CHAPTER 8  ActiveX 컨트롤과 일반 윈도우 컨트롤  ActiveX 컨트롤 소프트웨어 모듈  일반 컨트롤  일반 컨트롤이나 윈도우95 공통 컨트롤은 다이얼로그의 차일드 윈도우이다.  MFC의 클래스인 CEdit 나 CTreeCtrl 과 같은 형태로 표시된다.  클라이언트 프로그램은 이러한 컨트롤의 차일드 윈도우를 생성하는 일을 담당한다.  일반 컨트롤은 BN_CLICKED 과 같은 통보 명령 메시지(Notification Command Message)를 다이얼로그에 보낸다.  만일 사용자가 에디트 컨트롤에서 텍스트를 얻으려면 CWnd::GetWindowText() 함수를 호출할 수 있다.

CHAPTER 8  ActiveX 컨트롤과 일반 윈도우 컨트롤  윈도우 컨트롤  별도의 DLL로 존재  일반 컨트롤  “CUSTOM Control” - 프로그래머가 만드는 컨트롤  자신의 부모 윈도우에게 WM_COMMAND 통보 메시지를 보내고 부모 윈도우로부터 사용자 정의 메시지를 받는다.

CHAPTER 8  ActiveX 컨트롤과 일반 컨트롤의 유사점  다이얼로그에 ActiveX 컨트롤을 삽입할 경우 컨트롤 식별자가 나타난다.  다이얼로그가 아닌 윈도우에 삽입할 경우  부모 윈도우의 WM_CREATE 핸들러에서 ActiveX 컨트롤을 표현하는 클래 스의 Create() 멤버 함수를 호출하면 된다.  ActiveX 컨트롤을 포함하는 윈도우를 컨테이너(container)라고 부른다.  ActiveX 컨트롤과 일반 컨트롤의 차이점 - 속성과 메소드  속성(Properties) - 정수 인덱스와 대응하는 기호 이름  클라이언트 프로그램에서는 지정된 인덱스로 속성을 얻을 수 있고, 고유한 리턴값을 수용한다.  생성된 Dialog Data Exchange(DDX) 코드는 ActiveX 컨트롤의 속성과 클라이언트 클래스의 데이터 멤버간의 데이터를 교환한다.

CHAPTER 8  ActiveX 컨트롤과 일반 컨트롤의 차이점 - 속성과 메소드  메소드(Methods) - 함수와 유사하다. 기호 이름, 파라미터, 리턴값 등을 갖는다.  일반 컨트롤 - 컨테이너에 WM_통보 메시지를 보낸다.  ActiveX 컨트롤 - “이벤트”를 생성한다.  “이벤트”는 ActiveX 컨트롤이 호출하는 컨테이너 함수이다.  “이벤트”는 ActiveX 컨트롤에 값을 리턴하지 않는다.  ActiveX 컨트롤 설치하기  Project 메뉴 - Add To Project 선택 - Component And Controls 선택 - Registered ActiveX Controls 선택 - Calendar Control 8.0 선택 - Insert  ActiveX 컨트롤은 클라이언트 프로그램이 특별한 익스포트(exported)된 함수를 호출할 때 자기 자신을 등록한다.

CHAPTER 8  ActiveX 컨트롤의 ClassWizard C++ 래퍼(wrapper) 클래스  이 클래스는 CWnd 클래스로부터 유도되며, 모든 속성과 메소드에 대한 멤버 함수를 갖고 있다.  동적으로 ActiveX 컨트롤 인스턴스를 생성하는데 사용할 수 있는 생성자를 갖는다.  unsigned long CCalendar::GetBackColor() { unsigned long result; InvokeHelper(DISPID_BACKCOLOR, DISPATCH_PROPERTYGET, VT_I4, (void*)&result, NULL); return result; }

CHAPTER 8  ActiveX 컨트롤에 AppWizard 지원  AppWizard 의 Step3 - ActiveX Control 옵션 체크되면 AppWizard는 어플리케이션 클래스의 InitInstance() 멤버 함수에 다음의 라인을 추가한다.  AfxEnableControlContainer(); // Ex08a.cpp  #include <afxdisp.h> // MFC OLE automation classes, StdAfx.h  기존 프로젝트에 ActiveX 컨트롤을 추가하려면 두 라인만 추가하면 된다.  다이얼로그 클래스 데이터 멤버와 래퍼(wrapper) 클래스 사용법  CDialog::OnInitDialog() CWnd::UpdateData(FLASE)를 호출하여 다이얼로그 클래스의 데이터 멤버값을 읽어들인다.  CDialog::OnOK() CWnd::UpdateData(TRUE)를 호출하여 다이얼로그 클래스의 데이터 멤버에 값을 저장한다.  ActiveX 컨트롤 속성에 데이터 멤버를 추가하고, 버튼 핸들러에서 Value 속성값을 얻어야 할 경우 버튼 핸들러에서 UpdateData(FALSE)를 호출하면 다이얼로그의 모든 컨트롤로부터 모든 속성값을 읽게 되어 시간을 낭비하게 된다.  다이얼로그 데이터 멤버의 사용을 피하고, 래퍼(wrapper) 클래스의 Get 함수를 호출하는 것이 더욱 효율적이다.

CHAPTER 8  ClassWizard 와 컨테이너 다이얼로그  템플릿에 한 개 이상의 ActiveX 컨트롤이 포함되면 ClassWizard를 이용해서 데이터 멤버와 이벤트 핸들러 함수를 추가할 수 있다.  다이얼로그 함수 내에서 속성을 변경할 경우  ActiveX 컨트롤을 위한 래퍼(wrapper) 클래스의 객체를 데이터 멤버로 추가해야 한다.  Calendar 컨트롤의 래퍼(wrapper) 클래스로 CCalendar 클래스가 있고, 다이얼로그 클래스에 m_calendar 데이터 멤버가 있을 경우 Value 속성값을 얻는 방법 COleVariant var = m_calendar.GetValue();

CHAPTER 8  ClassWizard 와 컨테이너 다이얼로그  DDX_OCShort(pDX, ID_CALENDAR1, 0x11, m_sCalDay);  다이얼로그를 생성하여 출력 CMyDialog dlg; dlg.m_sCalDay = 5; dlg.DoModal();  DDX 코드는 컨트롤이 출력되기 전에 멤버 함수로부터 속성값을 설정하는 일을 담당한다.  DDX 코드는 사용자가 OK 버튼을 클릭할 때 속성값으로부터 데이터 멤버를 설정한다.  Visual C++ 5.0의 버그로 인해 ClassWizard는 Calendar컨트롤을 포함한 많은 컨트롤들의 속성을 정확히 감지하지 못한다.  ClassWizard가 컨트롤의 속성을 정확히 탐지해도 모든 속성에 대해 데이터 멤버를 생성할 수 없다. 특히 Calendar의 Value 속성과 같은 VARIANT 형 속성에 대해서는 DDX 함수가 존재하지 않는다. 이런 속성에 대해서는 래퍼(wrapper) 클래스를 사용해야 한다. Day 속성의 정수 인덱스 (디스패치ID)

CHAPTER 8  CWnd::GetSafeHwnd  CWnd 객체와 현재 관련된 윈도우 핸들을 리턴한다.  NULL CWnd를 호출한다 해도 안전(safe)하기 때문에 GetSafeHwnd라 부른다.  HWND GetSafeHwnd( ) const;  Return Value  CWnd 객체와 현재 관련된 윈도우 핸들  CWnd가 NULL이거나 윈도우에 관련된 핸들이 없으면 NULL

CHAPTER 8  DDX_Text : 편집박스에 데이터를 교환하는 데 사용된다.  void AFXAPI DDX_Text( CDataExchange* pDX, int nIDC, BYTE& value );  void AFXAPI DDX_Text( CDataExchange* pDX, int nIDC, short& value );  void AFXAPI DDX_Text( CDataExchange* pDX, int nIDC, int& value );  void AFXAPI DDX_Text( CDataExchange* pDX, int nIDC, UINT& value );  void AFXAPI DDX_Text( CDataExchange* pDX, int nIDC, long& value );  void AFXAPI DDX_Text( CDataExchange* pDX, int nIDC, DWORD& value );  void AFXAPI DDX_Text( CDataExchange* pDX, int nIDC, CString& value );  void AFXAPI DDX_Text( CDataExchange* pDX, int nIDC, float& value );  void AFXAPI DDX_Text( CDataExchange* pDX, int nIDC, double& value );  void AFXAPI DDX_Text( CDataExchange* pDX, int nIDC, COleCurrency& value );  void AFXAPI DDX_Text( CDataExchange* pDX, int nIDC, COleDateTime& value );  Parameters  pDX CDataExchange(데이터 교환) 객체의 포인터.  nIDC 교환이나 확인이 발생하는 컨트롤의 리소스 ID  value 컨트롤에 입력된 데이터 (dialog box, form view, or control view)

CHAPTER 8  DDX 전역함수 함수 설명 DDX_CBIndex() DDX_CBString() DDX_Check() DDX_Control() DDX_LBIndex() DDX_LBString() 콤보 박스 컨트롤과 INT 데이터 멤버 사이의 INT 데이터의 흐름을 관리한다. 콤보 박스의 편집 컨트롤과 CString 데이터 멤버 사이의 CString 데이터의 흐름을 관리한다. 체크 박스 컨트롤과 INT 데어터 멤버 사이의 INT 데이터의 흐름을 관리한다. 서브클래스 컨트롤과 CWnd 데이터 멤버 사이의 데이터 흐름을 관리한다. 목록 상자 컨트롤과 INT 데이터 멤버 사이의 INT 데이터의 흐름을 관리한다. 목록 상자의 편집 컨트롤과 CString 데이터 멤버 사이의 DDX_LBStringExact() 목록 상자의 편집 컨트롤과 대화상자, 폼 View, Control View 객체의 CString 데이터 멤버 사이의 CString 데이터의 흐름을 관리한다. DDX_Radio() 라디오 컨트롤 그룹과 INT 데이터 멤버 사이의 INT 데이터의 DDX_Scroll() 이동 표시줄 컨트롤과 INT 데이터 멤버 사이의 INT 데이터의 DDX_Text() 편집 컨트롤과 CString 데이터 멤버 사이의 INT, UINT, LONG, DWORD, CString , FLOAT, DOUBLE 데이터의 흐름을 관리한다.

CHAPTER 8  DDV (데이터 유효성 검사, Dialog Data Validation)  이 함수들은 전형적으로 유효성 검사시 일어난 문제점을 알리는 메시지 상자를 나타내고, 문제가 일어난 컨트롤에 포커스를 맞춘다.  사용자가 입력한 데이터가 유효하지 않거나 받아들일 수 있는 범위를 벗어났을 때 예외를 발생시킨다.  컨트롤의 DDV 함수의 호출은 DDX 함수를 호출한 후에 일어나야 한다. 메소드 설명 DDV_MaxChars() 특정 값의 매개 변수와 연결된 컨트롤에서 문자의 개수가 지정된 값을 초과하지 않았는지를 확인한다. DDV_MinMaxByte() 컨트롤의 BYTE 값이 지정된 최소, 최대값 사이에 있는지 확인한다. DDV_MinMaxDouble() 컨트롤의 DOUBLE 값이 지정된 최소, 최대값 사이에 있는지 확인한다. DDV_MinMaxDWord() 컨트롤의 DWORD 값이 지정된 최소, 최대값 사이에 있는지 확인한다. DDV_MinMaxFloat() 컨트롤의 FLOAT 값이 지정된 최소, 최대값 사이에 있는지 확인한다. DDV_MinMaxInt() 컨트롤의 INT 값이 지정된 최소, 최대값 사이에 있는지 확인한다. DDV_MinMaxLong() 컨트롤의 LONG 값이 지정된 최소, 최대값 사이에 있는지 확인한다. DDV_MinMaxUnsigned() 컨트롤의 UINT 값이 지정된 최소, 최대값 사이에 있는지 확인한다.

CHAPTER 8  CDataExchange 클래스  CDataExchange 객체의 포인터 ( CDataExchange* pDX )가 DDX 와 DDV에 필요한 컨텍스트 정보를 제공한다. 메소드 설명 Fail() DDV의 유효성 검사가 실패했을 때 호출된다. 입력 포커스는 전단계의 활성화된 컨트롤에 위치하고 예외가 발생된다. PrepareCtrl() DDX나 DDV를 위해 컨트롤(편집 컨트롤 제외)을 준비한다. PrepareEditCtrl() DDX나 DDV를 위한 특정 편집 컨트롤을 준비한다.  CDataExchange가 제공하는 두 개의 전역 데이터 멤버  m_bSaveAndValidate : DDX와 DDV의 방향을 결정하는 BOOL Flag Flag - FALSE : DDX를 데이터 멤버 값으로 대화 컨트롤을 초기화하는데 사용한다. TRUE : DDV를 데이터 값을 검증하고 대화 컨트롤 값으로부터 데이터 멤버값을 설정하는데 사용한다.  m_pDlgWnd : 데이터 교환이 일어나는 대화 상자나 창의 포인터.  CDataExchange 전역함수

CHAPTER 8  DDX_OCColor  DDX_Control  void AFXAPI DDX_OCColor( CDataExchange* pDX, int nIDC, DISPID dispid, OLE_COLOR& value );  Parameters  pDX 데이터 교환 객체에 대한 포인터  nIDC 연결하는 컨트롤의 리소스 ID  dispid 컨트롤 속성의 디스패치(dispatch) ID  value 다이얼로그 박스, 폼 뷰 또는 컨트롤 뷰 객체에서 데이터가 교환되었을 때 멤버 변수에 대한 참조  DDX_Control  MFC 컨트롤 객체(CStatic, CEdit, CComboBox)를 윈도우 컨트롤에 연결하는 데 사용된다.  한번 붙으면, 클래스를 사용하여 컨트롤을 액세스하고 조정할 수 있다.  void AFXAPI DDX_Control( CDataExchange* pDX, int nIDC, CWnd& rControl );  pDX 데이터 교환 객체에 대한 포인터  nIDC 연결하는 컨트롤의 리소스 ID  rControl 기술한 컨트롤에 연결되는 MFC 컨트롤 객체에 대한 참조

CHAPTER 8  COleDateTime::Format  문자열에 대한 sprintf 함수이다.  CString Format( DWORD dwFlags = 0, LCID lcid = LANG_USER_DEFAULT );  CString Format( LPCTSTR lpszFormat ) const;  CString Format( UINT nFormatID ) const;  Parameters  dwFlags LOCALE_NOUSEROVERRIDE Use the system default locale settings, rather than custom user settings. VAR_TIMEVALUEONLY Ignore the date portion during parsing. VAR_DATEVALUEONLY Ignore the time portion during parsing.  lcid Indicates locale ID to use for the conversion.  lpszFormat sprintf에 전달되는 서식 문자열 %D Total days in this COleDateTime %H Hours in the current day %M Minutes in the current hour %S Seconds in the current minute %% Percent sign  nFormatID sprintf에 전달되는 서식 문자열에 대한 문자열 리소스 ID

CHAPTER 8  Form at a time string %a Abbreviated weekday name %A Full weekday name %b Abbreviated month name %B Full month name %c Date and time representation appropriate for locale %d Day of month as decimal number (01 - 31) %H Hour in 24-hour format (00 - 23) %I Hour in 12-hour format (01 - 12) %j Day of year as decimal number (001 - 366) %m Month as decimal number (01 - 12) %M Minute as decimal number (00 - 59) %p Current locale's A.M./P.M. indicator for 12-hour clock %S Second as decimal number (00 - 59) %U Week of year as decimal number, with Sunday as first day of week (00 - 51) %w Weekday as decimal number (0 - 6; Sunday is 0) %W Week of year as decimal number, with Monday as first day of week (00 - 51) %x Date representation for current locale %X Time representation for current locale %y Year without century, as decimal number (00 - 99) %Y Year with century, as decimal number %z, %Z Time-zone name or abbreviation; no characters if time zone is unknown %% Percent sign

CHAPTER 8  Event Sink Maps When an embedded OLE control fires an event, the control's container receives the event using a mechanism, called an "event sink map," supplied by MFC. This event sink map designates handler functions for each specific event, as well as parameters of those events. For more information on event sink maps, see the article ActiveX Control Containers in Visual C++ Programmer's Guide. Event Sink Maps  BEGIN_EVENTSINK_MAP Starts the definition of an event sink map.  DECLARE_EVENTSINK_MAP Declares an event sink map.  END_EVENTSINK_MAP Ends the definition of an event sink map.  ON_EVENT Defines an event handler for a specific event.  ON_EVENT_RANGE Defines an event handler for a specific event fired from a set of OLE controls.  ON_EVENT_REFLECT Receives events fired by the control before they are handled by the control's container.  ON_PROPNOTIFY Defines a handler for handling property notifications from an OLE control.  ON_PROPNOTIFY_RANGE Defines a handler for handling property notifications from a set of OLE controls.  ON_PROPNOTIFY_REFLECT Receives property notifications sent by the control before they are handled by the control's container.

CHAPTER 8  ON_EVENT  ON_EVENT( theClass, id, dispid, pfnHandler, vtsParams ) Parameters  theClass The class to which this event sink map belongs.  id The control ID of the OLE control.  dispid The dispatch ID of the event fired by the control.  pfnHandler Pointer to a member function that handles the event. This function should have a BOOL return type, and parameter types that match the event's parameters (see vtsParams). The function should return TRUE to indicate the event was handled; otherwise FALSE.  vtsParams A sequence of VTS_ constants that specifies the types of the parameters for the event. These are the same constants that are used in dispatch map entries such as DISP_FUNCTION. Remarks  Use the ON_EVENT macro to define an event handler function for an event fired by an OLE control.  The vtsParams argument is a space-separated list of values from the VTS_constants.  One or more of these values separated by spaces (not commas) specifies the function's parameter list.  specifies a list containing a short integer followed by a BOOL.

CHAPTER 8  EVENT_CUSTOM  EVENT_CUSTOM( pszName, pfnFire, vtsParams ) Parameters  pszName The name of the event.  pfnFire The name of the event firing function.  vtsParams A space-separated list of one or more constants specifying the function's parameter list. Remarks  Use the EVENT_CUSTOM macro to define an event-map entry for a custom event.  The vtsParams parameter is a space-separated list of values from the VTS_ constants.  One or more of these values separated by spaces (not commas) specifies the function's parameter list.  specifies a list containing a short integer followed by a BOOL.

CHAPTER 8  EVENT_CUSTOM  The VTS_ contains and their meanings are as follows: Symbol Parameter Type VTS_I2 VTS_I4 VTS_R4 VTS_R8 VTS_COLOR VTS_CY VTS_DATE VTS_BSTR VTS_DISPATCH VTS_FONT VTS_HANDLE VTS_SCOPE VTS_BOOL short long float double OLE_COLOR CURRENCY DATE const char* LPDISPATCH IFontDispatch* HANDLE SCOPE BOOL VTS_VARIANT VTS_PVARIANT VTS_UNKNOWN VTS_OPTEXCLUSIVE VTS_PICTURE VTS_TRISTATE VTS_XPOS_PIXELS VTS_YPOS_PIXELS VTS_XSIZE_PIXELS VTS_YSIZE_PIXELS VTS_XPOS_HIMETRIC VTS_YPOS_HIMETRIC VTS_XSIZE_HIMETRIC VTS_YSIZE_HIMETRIC const VARIANT* VARIANT* LPUNKNOWN OLE_OPTEXCLUSIVE IPictureDisp* OLE_TRISTATE OLE_XPOS_PIXELS OLE_YPOS_PIXELS OLE_XSIZE_PIXELS OLE_YSIZE_PIXELS OLE_XPOS_HIMETRIC OLE_YPOS_HIMETRIC OLE_XSIZE_HIMETRIC OLE_YSIZE_HIMETRIC

사랑한다는 것은 그런 것. 어둡고 높은 계단을 함께 오르며 시린 손을 마주잡는 것. 가난의 고독 고독의 가난 세월이 가면 나이도 먹어가지만 함께 손잡았던 기억은 사라지지 않아 그런 것. 비탈길 돌계단에 함께 서 있었음을 오래오래 기억하는 것.

CHAPTER 9 메모리관리

CHAPTER 9  MFC의 메모리 관리  메모리 할당 - 스택 프레임(또는 스택, 또는 프레임)할당과 힙 할당 두 가지로 분류한다.  스택(Stack) 할당  함수에 대한 인수와 블록 내의 지역 변수를 갖고 있는 메모리 영역이다.  스택에서 할당할 경우에는 실제 메모리 블록에서 작업하게 된다.  컴파일러가 이들 항목에 대한 메모리를 자동으로 할당하게 되고, 함수가 호출될 때마다 스택이 만들어지게 된다.  스택 할당의 두 가지 주요 기능  프레임으로부터 지역 변수의 자동 할당. 큰 배열이나 데이터 구조도 포함된다.  자신의 범위를 벗어난 경우에는 지역 변수들이 자동으로 반납된다.  힙(Heap) 할당  프로세스가 할당하도록 예약된 메모리 영역이다.  힙에서 할당할 경우에는 메모리 블록에 대한 포인터를 사용한다.  메모리는 C나 C++의 메모리 할당 함수나 메소드, 연산자 중의 하나를 사용하여 동적으로 할당된다.  malloc(), free() 대신에 new와 delete를 사용하면, 메모리 유출의 자동 조사 기능을 포함한 MFC 메모리 관리 디버깅 기능을 이용할 수 있다.  할당할 수 있는 동적 메모리의 양은 시스템 내에서 사용할 수 있는 가상 메모리의 양에 의해서만 제한된다.

CHAPTER 9  메모리 관리  원하는 만큼의 메모리를 할당만 하면 된다.  세부적인 것은 윈도우가 알아서 해결한다.  일단, 프로그램이 실행되면 프로그램의 코드(코드 세그먼트)와 데이터(데이터 세그먼트)는 메모리상에 존재해야만 한다.  프로그램 인스턴스를 공유한다.  코드 세그먼트는 공유하고, 데이터 세그먼트는 따로 갖는다.  코드 세그먼트와 리소스(아이콘, 메뉴, 커서 등과 같은 윈도우가 기본적으로 제공하고 있는 자원)를 메모리에서 제거했다가, 필요한 경우에 다시 로드한다  분산된 유휴 메모리를 하나의 연속적인 메모리로 만든다.

CHAPTER 9  메모리의 내부  여러 번 실행된 어플리케이션은 하나의 코드부를 공유한다. 코드부 복사본 1 데이터부 복사본 2 복사본 3

CHAPTER 9 ◐ 윈도우의 유휴 메모리 관리 방식 ◑ Windows Pbrush Write Notepad MS-DOS Q Free Memory Windows Pbrush Write Notepad MS-DOS Pbrush를 삭제 Notepad를 이동 Q를 실행 Q

CHAPTER 9 ◐ Win95 가상 주소 공간 배치 ◑  32비트 메모리 페이징 4 Gigabytes 3 Gigabytes 가상 기계 관리자(VMM)와 가상 장치 드라이버와 같은 중요 윈도우 구성 요소들의 코드와 데이터를 찾을 수 있는 곳이다.  32비트 메모리 페이징 ◐ Win95 가상 주소 공간 배치 ◑ 예약된 시스템 활동 영역 (시스템에서 전용으로 사용, 응용 프로그램과 DLL은 액세스 할 수 없다.) 공유 활동 영역 윈도우 95의 모든 프로세스가 사용함 전용 활동 영역 현재 실행하고 있는 Win32 프로세스의 주소 공간 16-bit/MS-DOS 0 Megabytes 4 Megabytes 2 Gigabytes 3 Gigabytes 4 Gigabytes

CHAPTER 9  32비트 주소 공간과 윈도우 95 메모리 영역  16비트/MS 도스 호환 활동 영역  이전의 응용 프로그램과의 호환성을 제공한다.  TSR(램 상주) 프로그램과 MS 도스 장치 드라이버에서 사용한다.  Win32 프로세스는 16비트/MS 도스 호환 계를 읽거나 쓰기 위해 액세스 할 수 없다.  이 영역에 액세스하게 되면, 보통 프로세서 예외 상황이 발생한다.  전용 활동 영역  현재 실행중인 Win32 프로세스의 전용 주소 공간을 담고 있다.  다른 프로세스가 액세스하여 프로세스의 데이터를 망가뜨리는 것을 방지하기 위해 윈도우 95 메모리 관리자는 프로세스의 전용 주소 공간에 속하는 모든 메모리 페이지를 맵핑하고 있다.  공유 활동 영역  윈도우NT 에서는 존재하지 않는다.  모든 프로세스의 주소 공간에 맵핑된 구성 요소들을 담고 있다.  Win32가 사용하는 공통 시스템 DLL도 이 공유 활동 영역에서 찾을 수 있다. Win32 응용 프로그램은 공유계에서 메모리를 할당 받을 수 없고, 반드시 메모리 맵핑 파일을 사용해야 한다.

CHAPTER 9 ◐ Windows NT 가상 주소 공간 배치 ◑ 4 Gigabytes 2 Gigabytes 시스템 사용을 위해 예약된 공간 응용 프로그램이 사용할 수 있는 공간 0 Gigabytes 2 Gigabytes 4 Gigabytes 잘못된 메모리 쓰기 동작을 잡기 위해 사용하는 64KB 공간 시스템 사용을 위해 예약된 64KB 공간

CHAPTER 9  윈도우 95는 밑의 2GB만 완전히 보호한다. 위의 2GB는 덜 안전한 상태에 있는데, 이들 영역이 모든 프로세스들에 맵핑되어 있기 때문이다.  윈도우 NT는 전체 4GB 주소 공간을 완전히 다른 프로세스로부터 보호한다.  윈도우 95와 NT 메모리 관리자가 모두 메모리 페이징과 32비트 선형 주소를 사용하고 있지만, 4GB주소 공간은 서로 다르게 처리하고 있다.  메모리 맵핑 파일을 이용하면, 디스크의 파일을 메모리의 특정 범위 주소로 맵핑하여 파일을 메모리에서 직접 다룰 수 있다.  페이지 할당하기  Win32 API는 프로세스에 대한 새로운 페이지를 할당하기 위해 VirtualAlloc()과 MapViewOfFile() 두 개의 함수를 제공한다.

CHAPTER 9  VirtualAlloc()  응용 프로그램의 가상 주소 공간의 일련의 페이지들을 예약하거나  LPVOID VirtualAlloc( LPVOID lpAddress, // 예약하거나 사용할 공간의 주소 DWORD dwSize, // 공간의 크기 DWORD flAllocationType, // 할당 유형 DWORD flProtect // 액세스 보호 유형 );  Parameters  lpAddress 새 영역의 원하는 시작 주소. 인수가 NULL인 경우에는 시스템이 그 영역을 어디에 할당할지 결정하게 된다.  dwSize 원하는 새 영역의 크기(바이트 단위)  flAllocationType 할당 유형  flProtect 그 페이지가 가져야 할 액세스 보호 유형을 나타낸다.

CHAPTER 9  VirtualAlloc()에서 사용하는 할당 유형 플래그들 의미 PAGE_READONLY PAGE_READWRITE PAGE_EXECUTE PAGE_EXECUTE_READ PAGE_EXECUTE_READWRITE PAGE_GUARD PAGE_NOACCESS PAGE_NOCACHE 사용하고자 하는 페이지에 대해 읽기 전용 액세스를 명시 사용하고자 하는 페이지에 대해 읽기 쓸 수 있음을 명시 사용하고자 하는 페이지에 대해 실행할 수 있음을 명시 사용하고자 하는 페이지에 대해 읽고 실행할 수 있음을 명시 사용하고자 하는 페이지에 대해 읽고 쓰고 실행할 수 있음을 명시 이 영역 내의 페이지들이 가드 페이지가 됨을 명시 사용하고자 하는 페이지에 대한 모든 액세스를 막는다. 사용하고자 하는 페이지에 캐싱을 허용하지 않는다.  VirtualAlloc() 액세스 보호 플래그 MEM_COMMIT MEM_RESERVE MEM_TOP_DOWN 지정한 범위의 페이지에 대해 물리적 메모리를 할당한다. 프로세스의 가상 주소 공간에 예약하지만, 물리적 메모리를 할당하지는 않는다. 예약된 부분은 이를 반납할 때까지 메모리 할당시 사용할 수 없다. 가능한 가장 높은 주소에 메모리를 할당한다.

CHAPTER 9  가드 페이지  가드 페이지는 잘못된 메모리 액세스에 대해 한 번의 보호를 제공하는 역할을 한다.  가드 페이지 내의 주소를 프로그램이 액세스하려고 시도하면, 윈도가 STATUS_GUARD_PAGE 예외 상황을 발생시키게 되며, PAGE_GUARD를 없애게 된다.

CHAPTER 10 비트맵(Bitmaps)

CHAPTER 10  GDI 비트맵과 장치-독립적인 비트맵(DIB, device-independent bitmap)  GDI 비트맵 객체 - 윈도우의 GDI 모듈 내에서 관리되는 장치-의존적인 데이터 구조체를 갖는다.  DIB - 고유한 색상 정보를 포함하고 있어서 색상 팔레트 관리가 쉽고 프린트시 그레이 음영을 제어하기 쉽다.  Win32 API에 의해 직접 지원되는 포맷은 DIB 뿐이다.  컬러 비트맵(Color Bitmap)과 모노 비트맵(Monochrome Bitmap)  윈도우는 브러시 색상을 다룰 때와는 다른 방식으로 컬러 비트맵을 다룬다.  컬러 비트맵  4개의 컬러 플래인(color plane)이 있다.  각 컬러 플래인당 1비트씩을 조합하여 하나의 픽셀을 나타낸다.  비트맵 색상은 표준 16컬러로 제한된다.  윈도우는 비트맵에서 디더링(dithering)된 색상을 사용하지 않는다.  모노 비트맵  한 개의 컬러 플래인을 갖는다.  각 픽셀은 off(0, 검정색) 아니면 on(1, 흰색)인 단일 비트로 표현된다.

CHAPTER 10  GDI 비트맵 사용하기  “비트맵”은 화면상에 표시되거나 프린터로 출력되는 페이지 자체가 될 수 있기 때문에 비트맵을 디스플레이 디바이스 컨텍스트나 프린터 디바이스 컨텍스트로 직접 선택할 수 없다.  CDC::CreateCompatibleDC() 함수를 이용하여 “메모리 디바이스 컨텍스트”를 만들어 사용한다.  리소스로부터 GDI 비트맵 로드하기  비트맵을 쉽게 사용하는 방법  리소스로부터 비트맵을 로드한다.  리소스 컴파일러 - 디스크로부터 DIB를 읽어서 프로젝트의 RES 파일에 저장  링커 - DIB를 프로그램의 EXE 파일에 복사한다.  CDC::LoadBitmap() - DIB로 저장된 BMP 파일을 GDI 비트맵 형식으로 자동 변환해 준다.

CHAPTER 10  리소스로부터 GDI 비트맵 로드하기  Red Blocks 비트맵을 출력하는 OnDraw() 함수  void CMyView::OnDraw(CDC* pDC) { CBitmap bitmap; CDC dcMemory; bitmap.LoadBitmap(IDB_REDBLOCKS); dcMemory.CreateCompatibleDC(pDC); dcMemory.SelectObject(&bitmap); pDC->BitBlt(100, 100, 54, 96, &dcMemory, 0, 0, SRCCOPY); // CDC 소멸자는 dcMemory를 삭제한다. 비트맵이 선택 해제된다. // CBitmap 소멸자는 선택 해제된 비트맵을 삭제한다. }

CHAPTER 10  디스플레이 맵핑 모드의 효과  맵핑 모드 MM_LOENGLISH 에서의 비트맵은 보기 좋은 편은 아니다.  COLORONCOLOR를 파라미터로 이용하여 CDC::SetStretchBltMode() 함수를 호출하면 비트맵 모양이 보다 좋아 보인다.  비트 스트레칭  맵핑 모드가 MM_TEXT가 아닌 경우에도 Red Blocks 비트맵을 정확히 54x96 픽셀의 사각형이 되도록 하려면 BitBlt() 함수 대신 StretchBlt() 함수를 사용해야 한다.  CSize size(54, 96); pDC -> DPtoLP(&size); pDC -> StretchBlt(0, 0, size.cx, -size.cy, &dcDisplayMemory, 0, 0, 54, 96, SRCCOPY);  BitBlt()나 SetStretchBlt() 함수 호출에 있어서 GDI가 실제로 비트들을 축소 하거나 확대하는 경우, 디스플레이 갱신 속도는 느려지게 된다.

CHAPTER 10  비트맵의 전송  비트 블록 전송 (BBT : Bit Block Transfer, BitBlt)  비트맵 데이터를 한 곳에서 다른 곳으로 전송하려면, 비트들의 블록을 전송해야 한다.  비트 블록을 전송할 때에는 버퍼로 메로리 DC를 사용해야 한다.  CDC::BitBlt (비트 전송)  기술한 소스 컨텍스트에서 CDC 객체에 붙은 디바이스 컨텍스트에 비트맵을 복사한다. 디바이스 컨텍스트의 각각에 대한 논리 좌표 맵핑이 동일하지 않으면, BitBlt() 함수는 비트맵을 복사하기 위해 StretchBlt() 함수를 사용한다. (StretchBlt는 필요한 대로 비트맵을 확대하거나 축소한다.)  BOOL BitBlt( int x, // 대상 사각형의 왼쪽 상단의 x 좌표(논리 좌표) int y, // 대상 사각형의 왼쪽 상단의 y 좌표(논리 좌표) int nWidth, // 복사하는 비트맵의 폭(논리 단위) int nHeight, // 복사하는 비트맵의 높이(논리 단위) CDC* pSrcDC, // 소스 디바이스 컨텍스트에 대한 포인터 int xSrc, // 소스 비트맵의 왼쪽 상단의 x 좌표(논리 좌표) int ySrc, // 소스 비트맵의 왼쪽 상단의 y 좌표(논리 좌표) DWORD dwRop // 비트맵을 복사할 때 사용하는 래스터 처리 );

CHAPTER 10  CDC::StretchBlt (비트를 늘여서 맞추기)  BOOL StretchBlt( int x // 대상 사각형의 왼쪽 상단의 x 좌표(논리 단위) int y // 대상 사각형의 왼쪽 상단의 y 좌표(논리 단위) int nWidth // 대상 사각형의 폭(논리 단위) int nHeight // 대상 사각형의 높이(논리 단위) CDC* pSrcDC // 소스 디바이스 컨텍스트에 대한 포인터 int xSrc // 소스 사각형의 왼쪽 상단의 x 좌표(논리 단위) int ySrc // 소스 사각형의 왼쪽 상단의 y 좌표(논리 단위) int nSrcWidth // 소스 사각형의 폭(논리 단위) int nSrcHeight // 소스 사각형의 높이(논리 단위) DWORD dwRop // 비트맵을 복사할 때 사용하는 래스터 처리 );

CHAPTER 10  BLACKNESS 모든 출력을 검정색으로 한다.  래스터 연산(raster-operation, dwRop)  BLACKNESS 모든 출력을 검정색으로 한다.  DSTINVERT 대상 비트맵을 반대로 한다.  MERGECOPY AND 연산자를 사용하여 패턴과 원본 비트맵을 결합한다.  MERGEPAINT OR 연산자를 사용하여 원본 비트맵을 반전시킨 것을 대상 비트맵과 결합한다.  NOTSRCCOPY 원본 비트맵을 반전시킨 것을 대상 비트맵에 복사한다.  NOTSRCERASE OR 연산자를 사용하여 대상과 원본 비트맵의 결합한 것을 반대로 한다.  PATCOPY 패턴을 대상 비트맵에 복사한다.  PATINVERT XOR 연산자를 사용하여 대상 비트맵과 패턴을 결합한다.  PATPAINT OR 연산자를 사용하여 원본 비트맵을 반전시킨 것을 패턴과 결합한다. OR 연산자를 사용하여 이 처리의 결과를 대상 비트맵과 결합한다.  SRCAND AND 연산자를 사용하여 대상과 원본 비트맵의 픽셀을 결합한다.  SRCCOPY 원본 비트맵을 대상 비트맵에 복사한다.  SRCERASE 대상 비트맵을 반대로 하고, 그 결과를 AND 연산자를 사용하여 원본 비트맵과 결합한다.  SRCINVERT XOR 연산자를 사용하여 대상과 원본 비트맵의 픽셀을 결합한다.  SRCPAINT OR 연산자를 사용하여 대상과 원본 비트맵의 픽셀을 결합한다.  WHITENESS 모든 출력을 흰색으로 한다.

CHAPTER 10  BitBlt(비트 블록 전송), StretchBlt(비트를 늘여서 맞추기) 대상 장치 컨텍스트의 현재 확대 모드를 사용하고 있다.  이 모드는 CDC::StretchBltMode() 메소드를 사용하여 설정된다.  모든 장치 컨텍스트가 비트 블록 전송, StretchBlt() 비트 블록 전송을 지원하지는 않는다.  CDC::GetDeviceCaps() 메소드를 RASTERCAPS를 매개 변수로 전달하여 호출하고, 반환 값에 RC_BITBLT, RC_STRETCHBLT가 있는지 조사하면, DC에서 비트 블록 전송, StretchBlt 비트 블록 전송을 사용할 수 있는지 알 수 있다.  if((dc.GetDeviceCaps(RASTERCAPS) & RC_STRETCHBLT) == 0) { RC_BITBLT // 장치가 BitBlt, StretchBlt를 지원하지 않음 } else { // 장치가 BitBlt, StretchBlt를 지원함

CHAPTER 10  nStretchMode 새로운 확장 모드  CDC::SetStretchBltMode - 현재 비트맵 확장 모드를 설정한다.  int SetStretchBltMode( int nStretchMode );  Parameters  nStretchMode 새로운 확장 모드 Value Description BLACKONWHITE 1 COLORONCOLOR 3 HALFTONE 4 Performs a Boolean AND operation using the color values for the eliminated and existing pixels. If the bitmap is a monochrome bitmap, this mode preserves black pixels at the expense of white pixels. Deletes the pixels. This mode deletes all eliminated lines of pixels without trying to preserve their information. Maps pixels from the source rectangle into blocks of pixels in the destination rectangle. The average color over the destination block of pixels approximates the color of the source pixels. After setting the HALFTONE stretching mode, an application must call the Win32 function ::SetBrushOrgEx to set the brush origin. If it fails to do so, brush misalignment occurs. WHITEONBLACK 2 Performs a Boolean OR operation using the color values for the this mode preserves white pixels at the expense of black pixels. STRETCH_ANDSCANS STRETCH_DELETESCANS STRETCH_HALFTONE STRETCH_ORSCANS windows 95: Same as BLACKONWHITE windows 95: Same as COLORONCOLOR windows 95: Same as HALFTONE windows 95: Same as WHITEONBLACK

CHAPTER 10  CGdiObject::GetObject  CGdiObject 에 붙어있는 GDI 오브젝트에 대한 정보를 얻는다.  int GetObject( int nCount, LPVOID lpObject ) const;  Parameters  nCount 기술한 버퍼에 복사되는 바이트의 최대 수. 보통 버퍼에 의해 가리키는 오브젝트의 sizeof()  lpObject 오브젝트 정보가 넣어지는 버퍼에 대한 포인터. Object Buffer type CPen CBrush CFont CBitmap CPalette CRgn 일반 펜에 대해 LOGPEN. 확장 펜에 대해 EXLOGPEN LOGBRUSH LOGFONT BITMAP 논리 팔레트에 있는 엔트리의 수를 기술하는 WORD. 실제 팔레트 엔트리를 얻으려면 CPalette::GetPaletteEntries 를 사용 Not supported

CHAPTER 10  BitBlt의 전송 소스와 전송 대상의 좌표 지정 BitBlt(dx, dy, dw, dh, pSrcDC, sx, sy, rop); dh dw (dx, dy) (sx, sy) 전송대상의 디바이스 컨텍스트 전송소스의 (0, 0) 전송된다 (dx, cy) : 디바이스 컨텍스트의 어디로 전송되는 가를 지정한다. dw : 전송하는 비트맵의 폭 dh : 전송하는 비트맵의 높이 (sx, sy) : 디바이스 컨텍스트의 어디에서 전송하는 가를 지정한다.

CHAPTER 10  래스터 연산(Raster Operation) (DevStudio\Vc\include\wingdi.h) 논리 연산 의 미 SRCCOPY NOTSRCCOPY SRCPAINT SRCAND SRCINVERT SRCERASE dst = src 전송 소스의 패턴을 사용한다. dst = ~src dst = dst ^ src dst = dst | src dst = dst & src dst = ~dst & src 전송 소스의 패턴을 반전하여 사용한다. 전송 소스와 전송 대상의 패턴을 OR한다. 전송 소스와 전송 대상의 패턴을 AND한다. 전송 소스와 전송 대상의 패턴을 XOR한다. 전송 소스의 패턴을 전송 대상의 패턴에서 소거한다.

CHAPTER 10  래스터 연산(Raster Operation) 전송 소스의 패턴 (SRC) 전송 대상의 패턴 (DST) SRCCOPY NOTSRCCOPY SRCPAINT SRCAND SRCINVERT SRCERASE

CHAPTER 10  예제 EX10A  맵핑 모드가 MM_LOENGLISH로 설정된 스크롤 뷰에 리소스 기반 비트맵을 출력한다.  CGdiObject 클래스의 멤버 함수 GetObject()의 호출을 통해 비트맵 크기를 얻는다.  비트맵을 이용해서 화면 출력 향상하기  화면에서 매끄러운 움직임을 지원하기 위해 프로그램 자체 비트맵을 생성한다.  메모리 디바이스 컨텍스트에 선택된 비트맵을 그린다.  그려진 비트맵을 화면으로 옮긴다.

CHAPTER 10  예제 EX10B  원이 이동될 때 WM_MOUSEMOVE 메시지에 따라 원이 지워졌다가 다시 그려지기 때문에 화면이 깜박거리는 문제를 해결하기 위해 GDI 비트맵을 사용한다.  OnInitialUpdate()  디스플레이 장치와 호환이 되는 메모리 디바이스 컨텍스트와 비트맵을 만든다.  메모리 디바이스 컨텍스트와 비트맵은 디스플레이 디바이스 컨텍스트 dc와 호환되지만 메모리 디바이스 컨텍스트는 디스플레이 디바이스 컨텍스트와 일치하는 맵핑모드를 설정해야 한다.  OnPaint()  비트맵을 그리기 위해 메모리 디바이스 컨텍스트를 준비한다.  OnDraw()  메모리 디바이스 컨텍스트의 핸들을 전달한다.  메모리 디바이스 컨텍스트에서 디스플레이 디바이스 컨텍스트로 비트맵을 복사한다.

CHAPTER 10  무효화 사각형  InvalidateRect(rectOld, TRUE); InvalidateRect(rectNew, TRUE);  파라미터가 True(디폴트)이면 윈도우는 무효 사각형이 다시 그려지기전에 배경색을 지운다. 따라서 화면 깜박임이 발생하게 된다.  InvalidateRect(rectOld, FALSE); InvalidateRect(rectNew, FALSE);  파라미터가 False이면 무효 사각형 전체가 비트맵에 복사되기 때문에 배경을 지우지 않는다.

CHAPTER 10  DIB와 CDib 클래스  MFC에는 GDI 비트맵을 위한 클래스(CBitmap)는 있지만 DIB를 위한 클래스는 없다.  팔레트 프로그래밍에 관한 조언  윈도우에 단일 DIB를 출력하는 경우 논리적 팔레트(DIB에서 사용할 색상을 포함하는 GDI 객체)를 만든 다음 논리적 팔레트를 하드웨어 시스템 팔레트(비디오 카드가 출력할 수 있는 256색상 테이블)에 맵핑시켜야 한다. - realize  시스템 팔레트  사용자가 임의로 색을 지정하여 사용할 수 있는 색상 - 236개  고정된 색상 - 20개  배경 프로그램의 경우  시스템 팔레트는 변경되지 않은 상태에서 윈도우는 논리적 팔레트와 시스템 팔레트 간에 새로운 맵핑을 설정한다.

CHAPTER 10  팔레트 프로그래밍에 관한 조언  프로그램의 팔레트는 언제 리얼라이즈(realize) 해야 하나?  프로그램에서 팔레트를 리얼라이즈 하게 되면 자신의 메인 윈도우로 WM_PALETTECHANGED 메시지를 보낸다.  자신의 프로그램이 입력 포커스를 받게 되면 WM_QUERYNEWPALETTE 메시지가 보내진다.  프로그램에서는 이 두 개의 메시지에 대응하여 팔레트를 리얼라이즈 해야 한다.  이 팔레트 메시지들이 뷰 윈도우로 보내지는 것이 아니므로 메인 프레임 윈도우에서 이 메시지들을 맵핑한 다음 뷰에 통보해야 한다.  Win32 함수 RealizePalette()를 호출하여 리얼라이즈를 수행하기 전에 SelectPalette() 함수를 호출하여 디바이스 컨텍스트로 DIB의 논리적 팔레트를 선택해야 한다.  SelectPalette()의 파라미터 True - 어플리케이션이 전경 프로그램으로 실행되든지, 배경 프로그램으로 실행되든지 상관없이 항상 배경 팔레트로 처리된다. False - 어플리케이션이 전경 프로그램으로 실행되고 있는 경우 전경 팔레트로 처리. 어플리케이션이 배경 프로그램으로 실행되고 있는 경우 배경 팔레트로 처리.

CHAPTER 10  팔레트의 종류  하드웨어 팔레트 ( Hardware Palette ) - 그래픽 카드의 하드웨어 팔레트  시스템 팔레트 ( System Palette ) - 윈도우의 팔레트 매니저가 사용하는 팔레트  논리적 팔레트 ( Logical Palette ) - 어플리케이션에서 만들어진 팔레트 ( CPalette 클래스로 표현된다 )  리얼라이즈 (Realize)과정 논리적 팔레트를 시스템 팔레트로 맵핑하는 과정  전경(foreground)/배경(background) 프로그램과 전경/배경 팔레트  전경 프로그램 - 현재 활성화된 프로그램  전경 팔레트 - 전경 프로그램에 의해 리얼라이즈된 팔레트  팔레트 관련 메시지  WM_PALETTECHANGED 메시지 - 활성화된 프로그램의 리얼라이즈로 인해 시스템 팔레트가 변경되면 윈도우는 실행중인 모든 프로그램의 메인 윈도우로 이 메시지를 전달하여 변경된 시스템 팔레트에 맞게 자신의 영역을 다시 그리도록 한다.  WM_QUERYNEWPALETTE 메시지 - 비활성 프로그램이 입력 포커스를 받아 활성화 될 때 이 메시지를 활성화된 프로그램에 전달하여 리얼라이즈할 기회를 제공한다.

CHAPTER 10  정적 시스템 색상 인덱스 RGB 색상 색상 1 2 3 4 5 6 7 8 9 RGB(0, 0, 0) 검정 1 2 3 4 5 6 7 8 9 RGB(0, 0, 0) 검정 RGB(128, 0, 0) RGB(0, 128, 0) RGB(128, 128, 0) RGB(0, 0, 128) RGB(128, 0, 128) RGB(0, 128, 128) RGB(192, 192, 192) RGB(192, 220, 192) RGB(166, 202, 240) 어두운 검정 어두운 녹색 어두운 노랑 어두운 청색 어두운 보라 어두운 하늘색 밝은 회색 연한 녹색 하늘색 246 247 248 249 250 251 252 253 254 255 RGB(255, 251, 240) 크림색 RGB(160, 160, 164) RGB(128, 128, 128) RGB(255, 0, 0) RGB(0, 255, 0) RGB(255, 255, 0) RGB(0, 0, 255) RGB(255, 0, 255) RGB(0, 255, 255) RGB(255, 255, 255) 어두운 회색 중간 회색 빨강 녹색 노랑 파랑 보라 흰색

CHAPTER 10  논리적 팔레트  LOGPALETTE 구조 typedef struct tagLOGPALETTE { WORD palVersion; // 그 구조에 대한 윈도우 버전. 0x300 WORD palNumEntries; // 색상 항목의 수 PALETTEENTRY palPalEntry[1]; // 각 항목에 대한 사용 플래그를 명시하는 PALETTEENTRY 구조의 배열 } LOGPALETTE; typedef struct tagPALETTEENTRY { BYTE peRed; BYTE peGreen; BYTE peBlue; BYTE peFlags; // 팔레트 항목의 사용방법 } PALETTEENTRY;

CHAPTER 10  팔레트 항목을 사용할 방법을 정의하는 플래그 플래그 값 설명 PC_EXPLICIT 논리적 팔레트 항목의 하위 단어가 하드웨어 팔레트 인덱스임을 나타낸다. PC_NOCOLLAPSE 색상을 시스템 팔레트 내의 기존 색상에 맵핑하기보다는 시스템 팔레트 내의 미사용 항목에 위치하도록 한다. PC_RESERVED 논리적 팔레트 항목은 팔레트 애니메이션을 위해 사용하며, 다른 창이 컬러 맵핑하는 것을 막게 된다.

CHAPTER 10  CPalette 클래스 메소드 메소드 설명 AnimatePalette() 애니메이션 팔레트를 만들기 위해 논리적 팔레트 항목을 교체한다. CreateHalftonePalette() 장치 컨텍스트에 대한 하프톤 팔레트를 만들고 이를 CPalette 객체에 부착한다. CreatePalette() 윈도우 색상 팔레트를 만들고, 이를 CPalette 객체에 부착한다. FromHandle() GetEntryCount() GetNearestPaletteIndex() 기존의 윈도우 HPALETTE 팔레트 핸들로부터 CPalette 객체에 대한 포인터를 얻는다. 논리적 팔레트 내의 색상 항목의 수를 얻는다. 지정된 색상 값과 가장 가깝게 일치하는 논리적 팔레트 항목의 인덱스를 얻는다. GetPaletteEntries() 논리적 팔레트로부터 지정된 범위의 팔레트 항목을 얻는다. ResizePalette() CPalette 객체의 논리적 팔레트에 있는 색상 항목들의 수를 지정된 항목 수로 변경한다. SetPaletteEntries() CPalette 객체의 논리적 팔레트에 있는 특정 범위의 항목들에 대한 RGB 색상 값과 플래그를 설정한다.

CHAPTER 10  DIBs, 픽셀, 색상 테이블  DIB는 픽셀이라 불리는 요소들이 2차원 배열로 구성된 것이다. 구성된다.  1bpp(비트이미지) - Mono  4bpp - 16컬러  8bpp - 256컬러  16bpp (하이 컬러) - 65,536컬러  24bpp (트루 컬러) - 1,680만 컬러  bpp (bit per pixel)  DIB가 색상 테이블을 가지고 있지 않을 경우 Win32 함수 CreateHalftonePalette()가 리턴하는 팔레트를 사용한다.

CHAPTER 10  장치 종속 비트맵 (DDB : Device Dependent Bitmap)  하드웨어 팔레트에 의존하는 비트맵  BITMAP 구조 ( DevStudio\Vc\include\<Wingdi.h> 374라인) typedef struct tagBITMAP { LONG bmType; // 비트맵 유형 LONG bmWidth; // 비트맵의 너비 (픽셀 단위) LONG bmHeight; // 비트맵의 높이 (픽셀 단위) LONG bmWidthBytes; // 한 주사선에 대한 바이트 수 WORD bmPlanes; // 비트맵 내의 색상 면의 수 WORD bmBitsPixel; // 픽셀의 색상을 묘사하기 위해 필요한 비트들의 수 LPVOID bmBits; // 이미지 데이터를 형성하고 있는 문자 값의 배열에 대한 포인터 } BITMAP;

CHAPTER 10  장치 독립 비트맵 (DIB : Device Independent Bitmap)  팔레트의 RGB 색상 요소들을 DIB 이미지 내의 픽셀들로 맵핑하기 위해 사용하는 비트들의 배열을 담고 있다.  디스크의 파일 크기를 줄이기 위해 사용한 데이터 압축 도식을 나타내는 데이터 압축 식별자를 담고 있다.

CHAPTER 10  BMP 파일 내의 DIB의 구조 ( DevStudio\Vc\include\<Wingdi.h> 500라인) bfType = “BM” bfOffBits BITMAPFILEHEADER (BMP file only) biSize (구조체 크기<Byte>) biWidth (픽셀 단위의 비트맵 폭) biPlanes (픽셀 단위의 비트맵 높이) biPlanes=1 (대상 디바이스를 위한 컬러 플레인, 항상1) biBitCount (픽셀 당 비트수 1,4,8,16,24,32) biCompression (압축 타입 지정) biSizeImage (이미지 크기) biClrused (실제로 비트맵에 사용한 색상 테이블의 색상 인덱스 수) 모노 DIB 2개의 32비트 엔트리 4bpp DIB 16개 또는 그 이하의 32비트 엔트리 8bpp DIB 256개 또는 그 이하의 32비트 엔트리 이미지를 구성하는 실제 데이터 (픽셀은 행(row) 내의 열(column)에 의해 정렬된다. 행(row)은 4바이트 경계로 이루어진다. Color Table (색상 테이블) DIB Bit Image

CHAPTER 10  BMP 파일 내의 DIB의 구조  클립보드로부터 DIB를 얻는 경우 DIB의 BITMAPFILEHEADER가 존재하지 않는다. BITMAPINFOHEADER 구조체에서 색상 테이블을 계산할 수 있지만 색상 테이블에서 이미지를 계산할 수는 없다.  BITMAPINFOHEADER와 색상 테이블을 합친 BITMAPINFO 구조체  DevStudio\Vc\include\<Wingdi.h> 546라인 typedef struct tagBITMAPINFO{ BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[1]; } BITMAPINFO;

CHAPTER 10  DIB 액세스 함수  SetDlBitsToDevice  화면이나 프린터에 DIB를 직접 출력한다.  비트맵의 한 비트는 화면의 1픽셀이나 프린터의 1도트에 대응한다.  StretchDlBits  StretchBlt()와 유사한 방식으로 화면이나 프린터에 DIB를 직접 출력한다.  GetDlBits  할당한 메모리에 지정된 GDI 비트맵으로 부터 DIB의 비트를 구한다.  픽셀당 색상 비트의 수와 압축을 지정하여 DIB 포맷을 어느 정도 제어할 수 있다.  압축을 사용하는 경우 GetDlBits()를 두 번 호출하게 되는데, 한 번은 필요한 메모리를 계산하기 위해서 호출하고, 또 한 번은 DIB 데이터를 생성하기 위해 호출한다.  CreateDlBitmap  DIB로 부터 GDI 비트맵을 만든다.  다른 DIB 함수들처럼 파라미터로 디바이스 컨텍스트 포인터를 제공해야 한다.  CreateDlBSection  새로운 Win32 함수로 DIB 섹션이라는 특수한 DIB를 생성하고 GDI 비트맵 핸들을 리턴한다.  DIB의 메모리를 직접 접근해서 비트맵 핸들과 메모리 디바이스 컨텍스트를 가지고 GDI 함수들을 호출하여 DIB에 그리기를 할 수 있다.

CHAPTER 10  DIB 출력 퍼포먼스  최적화된 DIB 처리는 윈도우의 주요 기능이다.  16bpp/24bpp 비트맵을 출력하는 경우, 처리 속도는 매우 느리다.  분리된 8bpp GDI 비트맵을 만들고 나서 StretchBlt()를 호출하면 비트맵이 보다 빠르게 출력된다.  비트맵을 만들어 그리기(drawing)전에 팔레트를 리얼라이즈(Realize) 해야 한다.  BMP 파일에서 CDib 객체를 로딩(Loading)한 후 삽입할 코드 m_pDib -> UsePalette(&dc); m_hBitmap = m_pDib -> CreateBitmap(&dc); ::SelectObject(m_dcMem.GetSafeHdc(), m_hBitmap);  뷰 클래스의 OnDraw()에서 CDib::Draw() 대신 사용할 수 있는 코드 CSize sizeDib = m_pDib -> GetDimensions(); pDC -> StretchBlt( 0, 0, sizeDib.cx, sizeDib.cy, &m_dcMem, 0, 0, sizeToDraw.cx, sizeToDraw.cy, SRCCOPY);

CHAPTER 10  CBitmap 클래스 메소드 메소드 설명 SetBitmapBits() 비트맵의 비트들을 특정 비트 값으로 설정한다. SetBitmapDimension() 0.1mm 단위를 사용하여 비트맵의 너비와 높이를 지정한다. LoadOEMBitmap() 미리 정의된 윈도우 비트맵을 로드해서 CBitmap 객체에 부착한다. LoadMappedBitmap() 자원 데이터로부터 비트맵을 로드해서 색상을 현재의 시스템 색상으로 맵핑한다. LoadBitmap() 자원 데이터로부터 비트맵을 로드해서 CBitmap 객체에 부착한다. GetBitmapDimension() SetBitmapDimension() 메소드로 앞에서 설정된 비트맵의 너비와 높이를 구한다. GetBitmapBits() 비트맵의 비트들을 지정된 버퍼로 복사한다. GetBitmap() 특정 CBitmap 객체에 대한 포인터를 얻는다. FromHandle() 지정된 윈도우 비트맵 핸들로부터 CBitmap 객체에 대한 포인터를 얻는다. CreateDiscardableBitmap() 지정된 장치 컨텍스트와 호환성이 있는 버릴 수 있는 비트맵을 생성한다. CreateCompatibleBitmap() 지정된 장치 컨텍스트와 호환성이 있는 비트맵을 생성한다. CreateBitmapIndirect() BITMAP 구조에 정의된 너비와 높이, 비트 패턴을 갖는 비트맵을 생성한다. CreateBitmap() 지정된 너비와 높이, 비트 패턴을 갖는 장치 종속 메모리 비트맵을 생성한다.

CHAPTER 10  CBitmap::LoadBitmap  프로그램의 실행 파일에서 이름이 붙은 비트맵 리소스를 로드하여  BOOL LoadBitmap( LPCTSTR lpszResourceName );  BOOL LoadBitmap( UINT nIDResource );  Parameters  lpszResourceName 로드하는 비트맵 리소스의 이름을 포함하는 널로 끝나는 문자열에 대한 포인터.  nIDResource 로드하는 비트맵 리소스를 나타내는 정수.  CDC::CreateCompatibleDC  기술한 디바이스 컨텍스트에 호환되는 메모리 디바이스 컨텍스트를 생성한다.  virtual BOOL CreateCompatibleDC( CDC* pDC );  pDC 생성하는 디바이스 컨텍스트가 호환되는 디바이스 컨텍스트에 대한 포인터.

CHAPTER 10  CDC::GetSafeHdc  CDC에 현재 붙어 있는 윈도우 디바이스 컨텍스트 핸들을 리턴한다.  HDC GetSafeHdc( ) const;  Return Value CDC에 현재 붙어 있는 윈도우 디바이스 컨텍스트 핸들  CPoint::Offset  x, y좌표에 개별적인 값을 추가한다.  void Offset( int xOffset, int yOffset );  void Offset( POINT point );  void Offset( SIZE size );  Parameters  xOffset 위치의 x 좌표에 옵셋(offset)인 크기  yOffset 위치의 y 좌표에 옵셋(offset)인 크기  point CPoint 객체의 x, y 멤버에 의해 기술된 위치에 대한 옵셋 (POINT or CPoint) 의 크기  size CPoint 객체의 cx, cy 멤버에 의해 기술된 위치에 대한 옵셋 (SIZE or CSize) 의 크기 예) CPoint point(5,5); // 위치를 x=5, y=5로 초기화한다. point.Offset(4,3); // x좌표에 4, y좌표에 3을 추가한다.

CHAPTER 10  COMPLEXREGION 새로운 클리핑 영역은 오버랩 경계를 갖는다.  CDC::SelectClipRgn  디바이스 컨텍스트의 클리핑 영역을 기술한 영역으로 설정하거나 기술한 영역을 현재의 영역에 조합한다.  virtual int SelectClipRgn( CRgn* pRgn );  int SelectClipRgn( CRgn* pRgn, int nMode );  The region’s type  COMPLEXREGION 새로운 클리핑 영역은 오버랩 경계를 갖는다.  ERROR 디바이스 컨텍스트 또는 영역은 유효하지 않다.  NULLREGION 새로운 클리핑 영역이 비어 있다.  SIMPLEREGION 새로운 클리핑 영역은 오버랩 경계를 갖지 않는다.  Parameters  pRgn 새로운 클리핑 영역으로 사용하거나 현재 영역에 조합하는 영역에 대한 포인터  nMode 기술한 영역이 현재 클리핑 영역에 어떻게 조합되는가를 기술한다. RGN_AND 두 영역 중 겹치는 부분을 사용한다.(교집합) RGN_COPY 첫번째 영역의 복사본을 만든다. RGN_DIFF 영역1에는 있지만 영역2에는 없는 부분으로 구성된 영역을 만든다. RGN_OR 두 영역을 합한다.(합집합) RGN_XOR 두 영역을 합하지만 겹치는 부분은 뺀다.

CHAPTER 10  CDC::IntersectClipRect  현재 클리핑 영역에 기술한 사각형을 교차하여 새로운 클리핑 영역을 만든다.  윈도우는 모든 출력을 현재 클리핑 영역으로 클립한다.  virtual int IntersectClipRect( int x1, int y1, int x2, int y2 );  virtual int IntersectClipRect( LPCRECT lpRect );  The new clipping region's type.  COMPLEXREGION 새로운 클리핑 영역은 오버랩 경계를 갖는다.  ERROR 디바이스 컨텍스트는 유효하지 않다.  NULLREGION 새로운 클리핑 영역이 비어 있다.  SIMPLEREGION 새로운 클리핑 영역은 오버랩 경계를 갖지 않는다.  Parameters  x1 현재 클리핑 영역에 교차하는 사각형의 왼쪽 상단의 x좌표(논리 단위)  y1 현재 클리핑 영역에 교차하는 사각형의 왼쪽 상단의 y좌표(논리 단위)  x2 현재 클리핑 영역에 교차하는 사각형의 오른쪽 하단의 x좌표(논리 단위)  y2 현재 클리핑 영역에 교차하는 사각형의 오른쪽 하단의 y좌표(논리 단위)  lpRect 현재 클리핑 영역에 교차하는 사각형을 포함하는 RECT 구조체나 CRect 객체에 대한 포인터

CHAPTER 10  CBitmap::CreateCompatibleBitmap  기술한 디바이스 컨텍스트의 색상 형식과 호환되는 크기의 비트맵을 생성한다.  BOOL CreateCompatibleBitmap( CDC* pDC, int nWidth, int nHeight );  Parameters  pDC 색상 형식이 복사되는 디바이스 컨텍스트에 대한 포인터  nWidth ㅍ 비트맵의 폭 (픽셀 단위)  nHeight 비트맵의 높이 (픽셀 단위)  nWidth, nHeight 파라미터가 0이면, CreateCompatibleBitmap은 1x1 픽셀 모노 비트맵을 생성한다.  CDC::GetClipBox  현재 클리핑 영역의 바운딩 사각형을 얻는다.  바운딩 사각형은 클리핑 영역을 완전히 포함할 수 있는 가장 작은 사각형이다.  virtual int GetClipBox( LPRECT lpRect ) const;  The clipping region's type.  COMPLEXREGION 클리핑 영역은 오버랩 경계를 갖는다.  ERROR 디바이스 컨텍스트는 유효하지 않다.  NULLREGION 클리핑 영역이 비어 있다.  SIMPLEREGION 클리핑 영역은 오버랩 경계를 갖지 않는다.  lpRect 바운딩 사각형의 좌표로 채워지는 RECT 구조체나 CRect 객체에 대한 포인터

CHAPTER 10  CDC::PatBlt  디바이스에 기술한 사각형에 패턴을 칠한다.  패턴은 현재의 브러시와 디바이스에 이미 있는 패턴의 조합이다.  BOOL PatBlt( int x, int y, int nWidth, int nHeight, DWORD dwRop );  Parameters  x 패턴으로 채워지는 사각형의 왼쪽 상단의 x좌표 (논리 단위)  y 패턴으로 채워지는 사각형의 왼쪽 상단의 y좌표 (논리 단위)  nWidth 패턴으로 채워지는 사각형의 폭 (논리 단위)  nHeight 패턴으로 채워지는 사각형의 넓이 (논리 단위)  dwRop 브러시와 패턴이 어떻게 조합되는가를 제어하는 래스터 처리 PATCOPY 대상 비트맵에 패턴을 복사한다. PATINVERT XOR 연산자를 사용하여 대상 비트맵과 패턴을 조합시킨다. DSTINVERT 대상 비트맵을 반대로 한다. BLACKNESS 모든 출력을 검정색으로 한다. WHITENESS 모든 출력을 흰색으로 한다.

CHAPTER 10  CDC::GetDeviceCaps  디바이스의 성능에 관한 여러 가지 정보에 대한 디바이스 컨텍스트에 관련되는 디바이스를 쿼리한다.  int GetDeviceCaps( int nIndex ) const;  Parameters  nIndex 쿼리되는 기능 DRIVERVERSION 디바이스 드라이버 버전 TECHNOLOGY 디바이스 기술(technology) Value Meaning DT_PLOTTER Vector plotter DT_RASDISPLAY Raster display DT_RASPRINTER Raster printer DT_RASCAMERA Raster camera DT_CHARSTREAM Character stream DT_METAFILE Metafile DT_DISPFILE Display file HORZSIZE 물리적인 디스플레이의 폭 (밀리미터) VERTSIZE 물리적인 디스플레이의 높이 (밀리미터) HORZRES 디스플레이의 폭 (픽셀 단위) VERTRES 디스플레이의 높이 (래스터 라인)

CHAPTER 10  Parameters LOGPIXELSX 디스플레이 폭의 논리 인치마다의 픽셀 수  nIndex LOGPIXELSX 디스플레이 폭의 논리 인치마다의 픽셀 수 LOGPIXELSY 디스플레이 높이의 논리 인치마다의 픽셀 수 BITSPIXEL 각 픽셀에 대한 색상 비트의 수 PLANES 색상 판의 수 NUMBRUSHES 디바이스의 특정 브러시의 수 NUMPENS 디바이스 특정 펜의 수 NUMFONTS 디바이스 특정 폰트의 수 NUMCOLORS 디바이스의 색상 표에 있는 엔트리의 수 ASPECTX 라인그리기에 사용되는 디바이스 픽셀의 상대 폭 ASPECTY 라인그리기에 사용되는 디바이스 픽셀의 상대 높이 ASPECTXY 라인그리기에 사용되는 디바이스 픽셀의 대각선의 폭 PDEVICESIZE PDEVICE 내부 데이터 구조체의 크기

CHAPTER 10  CCmdTarget::BeginWaitCursor  커맨드나 처리에 많은 시간 소요가 예상될 때 커서를 모래 시계로 표시하기 위하여 이 함수를 사용한다.  void BeginWaitCursor( );  CCmdTarget::EndWaitCursor  BeginWaitCursor 함수의 반대이고, 모래 시계 커서가 이전의 커서로 리턴하기 위하여 멤버 함수 다음에 호출되어야 한다.  void EndWaitCursor( );  void CMyView::OnSomeCommand() { BeginWaitCursor(); // display the hourglass cursor // do some lengthy processing EndWaitCursor(); // remove the hourglass cursor }

CHAPTER 10  CPoint::Cpoint  CPoint 클래스는 윈도우 POINT 구조체를 감싸는 아주 기본적인 클래스이다.  CPoint 클래스의 생성자  CPoint( );  CPoint( int initX, int initY );  CPoint( POINT initPt );  CPoint( SIZE initSize );  CPoint( DWORD dwPoint );  Parameters  initX 위치의 x 좌표의 초기 값  initY 위치의 y 좌표의 초기 값  initPt POINT 구조체나 위치를 초기화하는 데 사용되는 CPoint 객체 x좌표는 initPoint 구조체나 객체의 cx 멤버에 초기화되고, y좌표는 initPoint 구조체나 객체의 cy 멤버에 초기화된다.  initSize SIZE 구조체나 위치를 초기화하는 데 사용되는 CSize 객체 x좌표는 initSize 구조체나 객체의 cx 멤버에 초기화되고, y좌표는 initSize 구조체나 객체의 cy 멤버에 초기화된다.  dwPoint x 좌표는 이 파라미터의 LOWORD(low-order word of dwPoint)로, y 좌표는 이 파라미터의 HIWORD(high-order word of dwPoint)로 초기화된다.

CHAPTER 10  조건부 컴파일  #ifdef 매크로명 문장1 #endif  #ifndef 매크로명 매크로가 정의되어 있지 않으면 문장1을 컴파일하지 않는다. #ifndef는 매크로가 정의되어 있지않으면 문장1을 컴파일 한다. 매크로가 정의되어 있으면 문장1을 컴파일하지 않는다.

사랑하고 그리고 사랑받는 시간을 따로 떼어 두세요. 생각하는 시간을 따로 떼어 두세요. 그것은 힘의 원천이지요. 노는 시간을 따로 떼어 두세요. 그것은 지혜의 산물이랍니다. 기도하는 시간을 따로 떼어 두세요. 그것은 지상 최대의 힘이지요. 사랑하고 그리고 사랑받는 시간을 따로 떼어 두세요. 그것은 신에게서 주어진 특권이지요. 친절을 베풀 시간을 따로 떼어 두세요. 그것은 행복에의 길이랍니다. 웃는 시간을 따로 떼어 두세요. 그것은 영혼의 음악이랍니다. 주는 시간을 따로 떼어 두세요. 이기적이기에는 하루가 너무 짧지요.

CHAPTER 11 윈도우 메시지 처리와 멀티스레드 프로그래밍

CHAPTER 11  단일 스레드 프로그램에서는 메시지를 어떻게 처리하는가?  MSG message; while (::GetMessage(&message, NULL, 0, 0)) { ::TranslateMessage(&message); ::DispatchMessage(&message); }  윈도우는 프로그램에 속해 있는 메시지를 판단한다.  GetMessage() 함수는 메시지 처리가 필요할 때 리턴한다.  접수된 메시지가 없으면 프로그램은 중지되고, 다른 프로그램들이 실행된다.  메시지가 접수되면 중지된 프로그램이 다시 실행된다.  TranslateMessage() 함수는 WM_KEYDOWN이 발생했을 때 그 키가 ASCII 문자를 포함하는 키일 경우 WM_CHAR 메시지로 변경된다.  DispatchMessage() 함수는 MFC 메시지 펌프에 제어권을 전달한다.

CHAPTER 11  제어권 양보  Win16, Win32는 해당 프로그램의 핸들러 함수가 리턴될때까지 DispatchMessage() 함수가 리턴되지 않는다.  이러한 문제점을 해결하기 위해 핸들러의 메인 루프 내에 다음과 같은 명령들을 삽입해서 핸들러 함수가 제어권을 양보하도록 만든다.  MSG message; if (::PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) { ::TranslateMessage(&message); ::DispatchMessage(&message); }  PeekMessage() 함수는 프로그램에 대한 메시지가 없어도 즉시 리턴한다.  이 경우 핸들러 함수(PeekMessage()을 포함하는 함수)는 계속해서 CPU를 차지하고 있다가 처리할 메시지가 있으면 이 핸들러 (PeekMessage()을 포함하는 함수)는 중지 되고, 처리할 메시지에 대응하는 핸들러가 호출된다.  처리할 메시지에 대응하는 핸들러가 종료된 후에 다시 이 핸들러 (PeekMessage()을 포함하는 함수) 가 시작된다.

CHAPTER 11  GetMessage  호출 스레드의 메시지 큐로부터 메시지를 받는다.  BOOL GetMessage( LPMSG lpMsg, // 메시지 구조체의 주소 HWND hWnd, // 윈도우의 핸들 UINT wMsgFilterMin, // 첫번째 메시지 UINT wMsgFilterMax // 마지막 메시지 );  Parameters  lpMsg 스레드의 메시지 큐로부터 메시지 정보를 받는 MSG 구조체에 대한 포인터  hWnd 메시지를 받는 윈도우를 기술한다. Value Meaning NULL GetMessage retrieves messages for any window that belongs to the calling thread and thread messages posted to the calling thread via PostThreadMessage.  wMsgFilterMin 전달 받은 메시지 값 중 가장 적은 정수 값을 기술한다.  wMsgFilterMax 전달 받은 메시지 값 중 가장 큰 정수 값을 기술한다.

CHAPTER 11  PeekMessage  메시지를 위하여 스레드 메시지 큐를 검사한다.  메시지가 위치한 곳의 구조체를 기술한다.  BOOL PeekMessage( LPMSG lpMsg, // 메시지에 대한 구조체를 가리키는 포인터 HWND hWnd, // 윈도우 핸들 UINT wMsgFilterMin, // 첫 번째 메시지 UINT wMsgFilterMax // 마지막 메시지 UINT wRemoveMsg // 제거 플래그 );  Parameters  lpMsg 윈도우 기반 어플리케이션 큐로부터 메시지 정보를 포함하는 MSG 구조체를 가리킨다.  hWnd 메시지에 대한 윈도우를 기술한다.  wMsgFilterMin 검사된 메시지의 범위 내에서 첫 번째 메시지의 값을 기술한다.  wMsgFilterMax 검사된 메시지의 범위 내에서 마지막 메시지의 값을 기술한다.  wRemoveMsg 메시지를 처리하는 방법을 기술한다. Value Meaning PM_NOREMOVE 메시지가 PeekMessage에 의해 처리된후 큐에서 제거되지 않는다. PM_REMOVE 메시지가 PeekMessage에 의해 처리된후 큐에서 제거된다.

CHAPTER 11  TranslateMessage  가상 키(virtual-key) 메시지들을 문자로 변환한다.  BOOL TranslateMessage( CONST MSG *lpMsg // 메시지 구조체의 주소 );  Parameters  lpMsg GetMessage나 PeekMessage사용에 의해 호출 스레드의 메시지 큐로부터 받은 메시지 정보를 담고 있는 MSG구조체를 가리킨다.  DispatchMessage  메시지를 윈도우 프로시저로 디스패치 한다.  LONG DispatchMessage( CONST MSG *lpmsg // 메시지 구조체에 대한 포인터  lpmsg 메시지를 포함하고 있는 MSG구조체를 가리킨다.

CHAPTER 11  WM_CHAR  The WM_CHAR message is posted to the window with the keyboard focus when a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR contains the character code of the key that was pressed.  WM_CHAR chCharCode = (TCHAR) wParam; // character code lKeyData = lParam; // key data  Parameters  chCharCode Value of wParam. Specifies the character code of the key.  lKeyData Value of lParam. Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag, Value Description 0-15 Specifies the repeat count. The value is the number of times the keystroke is repeated as a result of the user holding down the key. 16-23 Specifies the scan code. The value depends on the original equipment manufacturer (OEM). 24 Specifies whether the key is an extended key, such as the right-hand ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0. 25-28 Reserved; do not use. 29 Specifies the context code. The value is 1 if the ALT key is held down while the key is pressed; otherwise, the value is 0. 30 Specifies the previous key state. The value is 1 if the key is down before the message is sent, or it is 0 if the key is up. 31 Specifies the transition state. The value is 1 if the key is being released, or it is 0 if the key is being pressed.

CHAPTER 11  타이머  타이머는 간격 파라미터를 이용하여 CWnd 멤버 함수 SetTimer()를 호출한 후 발생되는 WM_TIMER에 대한 메시지 핸들러 함수를 ClassWizard를 이용해서 작성하면 된다.  타이머는 정수로 식별된다.  타이머 메시지가 이미 존재하고 있는 경우 윈도우는 타이머 메시지를 메시지 큐에 넣지 않는다.  예제 EX11A  계산 루프 내에서 제어권을 양보함으로써 메시지가 처리되도록 허용하고 타이머 핸들러는 계산 파라미터를 토대로 Progress Control을 갱신한다.  계산 처리 과정에서 제어권을 양보하지 않으면 WM_TIMER 메시지는 처리되지 않는다.

CHAPTER 11  CWnd::SetTimer  콜백 프로시저를 호출하는 타이머를 설정하거나 WM_TIMER 메시지를 지정한 간격으로 윈도우에 보낸다.  UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD) );  Parameters  nIDEvent 타이머 식별자(Timer의 ID)  nElapse 타이머 메시지를 보내는 간격 (1/1000초, 1000millisecond=1초)  lpfnTimer 지정한 시간에 호출되는 타이머 콜백 함수에 대한 포인터. 이 파라미터가 NULL이면, WM_TIMER 메시지는 어플리케이션의 메시지 큐에 위치하게되고, CWnd 객체에 의해 처리된다.  ASSERT  ASSERT( booleanExpression )  booleanExpression Specifies an expression (including pointer values) that evaluates to nonzero or 0.

CHAPTER 11  CWnd::EnableWindow  윈도우를 사용할 수 있게 하거나 사용할 수 없게 한다.  이 윈도우는 리턴 되기 전에 윈도우에 WM_ENABLE 메시지를 보낸다.  BOOL EnableWindow( BOOL bEnable = TRUE );  Parameters  bEnable TRUE, 윈도우가 사용할 수 있게 한다. FALSE, 윈도우가 사용할 수 없게 한다.  volatile  volatile 키워드는 수행중인 프로그램뿐만 아니라 인터럽트에 의해 액세스 될 수 있는 변수의 임시성에 대해 컴파일러에게 알려준다.  volatile declarator  int volatile nVint;  CWnd::OnTimer  WM_TIMER 메시지에 대한 핸들러  afx_msg void OnTimer( UINT nIDEvent );  nIDEvent 타이머의 식별자

CHAPTER 11  CWnd::KillTimer  SetTimer 함수로 생성된 타이머를 파괴한다.  WM_TIMER  The WM_TIMER message is posted to the installing thread’s message queue when a timer expires.  WM_TIMER wTimerID = wParam; // 타이머 식별자 tmprc = (TIMERPROC *) lParam; // 타이머 콜백(callback) 함수의 주소  Parameters  wTimerID Value of wParam.  tmprc Value of lParam.  CWnd::KillTimer  SetTimer 함수로 생성된 타이머를 파괴한다.  BOOL KillTimer( int nIDEvent );  nIDEvent 파괴되는 타이머의 ID. 이 ID는 타이머를 생성한 SetTimer 호출에서 리턴되는 ID.

CHAPTER 11  On-Idle 처리  On-Idle 처리는 어플리케이션의 메시지 큐가 사용중인 상태에서 큐가 비워질 때마다 수행된다.  사용자가 아무것도 하지 않는 상태에서는 어떤 메시지도 발생하지 않으므로 On-Idle 처리가 수행되지 않는다.  OnIdle() 함수를 override 하면 메시지 큐가 비워질 때마다 작성된 코드가 호출은 되지만, 메시지들의 상수 stream이 없으면 코드가 연속적으로 호출되지 않는다.  OnIdle()을 override할 때는 기초 클래스의 OnIdle()을 호출해야 한다.  기초 클래스의 OnIdle()을 호출하지 않으면 툴바 버튼이 갱신되지 않고, 임시 객체도 제거되지 않는다.  사용자가 모달 다이얼로그 박스를 사용하거나 메뉴를 사용하고 있을 때 OnIdle()은 호출되지 않는다.

CHAPTER 11  스레드(Thread)  프로세스 스케줄링의 부담을 줄여 성능을 향상시키기 위한 프로세스의 다른 표현방식  실행 스레드는 Win32가 CPU 시간을 부여하는 기본적인 요소이다.  각각의 스레드는 여러 개의 구조들을 사용해서 다음 프로세서 time slice를 기다리는 동안 자신의 컨텍스트를 저장해 둔다.  스레드의 컨텍스트  스레드의 하드웨어 레지스터  커널 스택  환경 블록  소유자 프로세서의 주소 공간 내의 사용자 스택  Process - 실행중인 프로그램  모든 프로세스는 Thread라는 개별적인 실행 경로를 갖는다.  한 프로세스에 속하는 모든 스레드는 그 프로세스의 코드와 자원, 가상 주소 공간, 전역 변수들을 공유한다.

CHAPTER 11  스레드의 종류  Worker thread  윈도우를 갖지 않으므로 메시지를 처리할 필요가 없다.  배경에서 어떤 작업을 수행하는데 사용한다.  많은 시간을 필요로 하는 계산 처리에 적합하다.  User interface thread  윈도우를 가지고 있어 자신의 고유한 메시지 루프가 있다.  사용자 입력을 처리하는 경우와 사용자에 의해서 발생된 이벤트와 메시지에 대해서 응답하는데 사용한다.  MFC 라이브러리(CWinThread)는 두 종류를 모두 지원한다.  단일 스레드 어플리케이션은 한 개의 스레드(메인 스레드)를 갖는다.  MFC에서는 CWinThread로 부터 CWinApp가 파생된다. (어플리케이션이 바로 스레드이다.)

CHAPTER 11  작업자 스레드 작성과 스레드 시작하기  작업자 스레드를 사용하기 위해서는 먼저 스레드의 메인 프로그램을 위한 전역 함수를 작성해야 한다.  전역 함수는 UINT를 리턴 해야 하며 파라미터로 LPVOID 형 값을 가져야 한다.  스레드가 계산처리를 수행한 후 전역함수가 리턴될 때 스레드는 종료되며 프로세스가 종료될 때도 종료된다.  프로그램에서 스레드 호출 CWinThread* pThread = AfxBeginThread( ComputeThreadProc, GetSafeHwnd(), THREAD_PRIORITY_NORMAL);  스레드의 코드 UINT ComputeThreadProc( LPVOID pParam) { // 스레드 처리작업 return 0; } 전역 함수에게 전달되는 32비트 값 스레드의 우선순위

CHAPTER 11  CWinThread 클래스 데이터 멤버 메소드 설명 m_bAutoDelete m_hThread m_nThreadID m_pMainWnd m_pActiveWnd CWinThread 객체의 하위 스레드가 종료될 때 CWinThread 객체도 함께 종료될 것인지를 지정하는 BOOL Flag 현재 스레드에 대한 핸들 현재 스레드의 ID 응용 프로그램의 중심 창을 가리키는 포인터 OLE 서버가 인플레이스(in-place) 활성화되어 있을 때(자신이 직접 창을 생성했을 때) 컨테이너 응용 프로그램의 중심 창을 가리키는 포인터

CHAPTER 11  CWinThread 클래스 메소드 메소드 설명 GetMainWnd() GetThreadPriority() ResumeThread() SetThreadPriority() SuspendThread() 스레드의 중심 창을 가리키는 포인터를 취한다. 현재 스레드의 우선순위를 취한다. 스레드의 계수(suspend count)를 감소시킨다. 현재 스레드의 우선 순위를 설정한다. 스레드의 계수(suspend count)를 증가시킨다.

CHAPTER 11  가상 CWinThread 클래스 메소드 메소드 설명 ExitInstance() InitInstance() OnIdle() PreTranslateMessage() IsIdleMessage() 스레드가 종료되었을 때 정리하기 위한 재정의 스레드 인스턴스 초기화를 수행하기 위한 재정의 스레드 특정 유휴 시간 처리를 수행하기 위한 재정의 Win32 API 함수인 TranslateMessage() 및 DiapatchMessage() 로 메시지를 전달하기 전에 미리 메시지를 여과한다. 특수 메시지를 점검한다. ProcessWndProcException() ProcessMessageFilter() Run() 스레드의 메시지 및 명령 처리기에 의해서 던져진 모든 처리되지 않는 예외들을 가로챈다. 일부 메시지가 응용 프로그램에 도달하기 전에 그 메시지를 가로챈다. 메시지 펌프를 포함하는 스레드에 대한 제어 함수. 기본 메시지 루프를 사용자 정의하기 위한 재정의

CHAPTER 11  전역 스레드 보조 함수 메소드 설명 AfxBeginThread() AfxGetThread() AfxEndThread() 새로운 스레드를 생성한다. 현재 실행되고 있는 스레드를 포함하는 CWinThread 객체를 가리키는 포인터를 취한다. 포인터를 가리키고자 하는 스레드 내부로부터 이 함수를 호출해야 한다. 스레드의 실행을 종료한다.

CHAPTER 11  AfxBeginThread()  동적으로 CWinThread 객체를 구축하고 스레드를 시작한다.  Worker thread 생성  CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );  User interface thread 생성  CWinThread* AfxBeginThread( CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL,

CHAPTER 11  AfxBeginThread() 매개변수 설명 pfnThreadProc pThreadClass Worker 스레드를 제어하는 함수를 가리키는 포인터. 값이 NULL일 수 없다. 다음과 같이 선언한다. UINT MyControllingFunction( LPVOID pParam ); pThreadClass CWinThread로부터 파생된 객체의 RUNTIME_CLASS pParam Worker 스레드를 제어하는 함수로 전달되는 매개변수 nPriority 새로운 스레드의 우선 순위 수준. 이 값이 ‘0’(NULL)이라면, 새로운 스레드는 자신을 생성한 스레드와 동일한 우선 순위를 가진다. 스레드의 프로세스의 우선 순위 클래스와 함께 이 값은 스레드의 기본 우선 순위 수준을 결정한다. nStackSize 새로운 스레드의 스택 크기(단위:byte)를 지정한다. 이 값이 ‘0’(NULL) 이라면, 새로운 스레드는 자신을 호출한 스레드와 동일한 크기의 스택 크기를 가진다. dwCreateFlags 스레드의 생성을 제어하는 추가적인 플래그를 지정한다. 이 플래그는 다음의 두 가지 값 중에서 한 가지를 값으로 가진다. CREATE_SUSPENDED (이 경우에 스레드는 서스펜드 계수가 1이기 때문에 ResumeThread()가 호출될 때까지 실행되지 않는다.) 또는 ‘0’(NULL, 생성되자마자 스레드를 실행한다.) lpSecurityAttrs 스레드에 대한 보안 속성들을 지정하는 Win32 SECURITY_ATTRIBUTES 구조를 가리키는 포인터. 이 값이 ‘0’(NULL)이라면, 새로운 스레드는 자신을 생성한 스레드와 동일한 보안 속성을 가진다.

CHAPTER 11  SetThreadPriority  스레드의 우선순위를 설정한다.  BOOL SetThreadPriority( int nPriority );  Parameters  nPriority 스레드의 우선순위  CWinThread::ResumeThread  정지된 스레드의 실행을 다시 시작한다.  스레드에 대한 정지 카운트를 하나씩 줄인다.  정지 카운트가 0이면, 스레드는 실행을 다시 시작한다.  DWORD ResumeThread( );  Return Value 성공하면 이전 정지 카운트. 실패하면 0xFFFFFFFF

CHAPTER 11  스레드 우선 순위 수준 우선순위 수준 설명 우선 순위 클래스에 대한 정상 우선 순위를 가리킨다. THREAD_PRIORITY_ABOVE_NORMAL 우선 순위 클래스에 대한 정상 우선 순위보다 1점 높은 것을 가리킨다. THREAD_PRIORITY_BELOW_NORMAL 우선 순위 클래스에 대한 정상 우선 순위보다 1점 낮은 것을 THREAD_PRIORITY_HIGHEST 우선 순위 클래스에 대한 정상 우선 순위보다 2점 높은 것을 THREAD_PRIORITY_IDLE IDLE_PRIORI TY_CLASS, NORMAL_PRIORITY_CLASS, HIGH_PRIORITY_CLASS 프로세스에 대해서는 기본 우선 순위 수준 1을 가리키며, REALTIME_PRIORITY_CLASS 프로세스에 대해서는 기본 우선 순위 수준 16을 가리킨다. THREAD_PRIORITY_LOWEST 우선 순위 클래스에 대한 정상 우선 순위보다 2점 낮은 것을 THREAD_PRIORITY_NORMAL 우선 순위 클래스에 대한 정상 우선 순위를 가리킨다. THREAD_PRIORITY_TIME_CRITICAL 우선 순위 수준 15을 가리키며, REALTIME_PRIORITY_CLASS 프로세스에 대해서는 기본 우선 순위 수준 31을 가리킨다.

CHAPTER 11  메인 스레드(User interface thread)는 작업자 스레드와 어떻게 통신하는가?  전역 변수를 사용한다. (모든 스레드는 전역 변수를 액세스 할 수 있다.)  UINT ComputeThreadProc( LPVOID pParam ) { g_nCount = 0; while( g_nCount < 100 ) { // 계산을 수행한다. ::InterlockedIncrement((long*) &g_nCount); } return 0;  InterlockedIncrement() 함수는 변수가 증가되는 동안 액세스하려는 다른 스레드를 묶으므로 메인 스레드는 작업자 스레드를 안전하게 중지시킬 수 있다.

CHAPTER 11  작업자 스레드는 메인 스레드(User interface thread)와 어떻게 통신하는가?  메인 스레드는 윈도우를 갖는다.  작업자 스레드는 윈도우의 핸들을 갖는다.  작업자 스레드가 윈도우 핸들을 얻는 방법  AfxBeginThread() 호출시 32비트 파라미터에 윈도우 핸들을 전달한다.  메인 스레드에 메시지를 보낼 때 PostMessage()로 메시지를 보낸다.

CHAPTER 11  예제 EX11B  계산이 메인 스레드 대신 작업자 스레드에서 이루어진다.  카운트 값은 전역 변수 g_nCount에 저장되며 다이얼로그 윈도우의 Cancel 버튼 핸들러에서 최대값으로 설정된다.  스레드가 종료될 때 다이얼로그 윈도우로 메시지를 보내면(PostMessage()) DoModal()이 종료되도록 한다.  소스 코드에서 g_nCount가 상수 최대값보다 커지면 함수(스레드)가 종료된다  함수는 종료되기 전에 다이얼로그 윈도우에 사용자 정의 메시지를 보낸다.  예제 EX11C  두 개의 이벤트를 사용하여 메인 스레드와 작업자 스레드간을 동기화 한다.

CHAPTER 11  스레드 스케줄링(Scheduling)  각각 서로 구별될 수 있도록 조치를 취하지 않는 한, 한 프로세스 내에서 실행되고 있는 각 스레드들이 서로를 구별하는 일은 거의 불가능하다.  프로세스 자원을 공유하는 스레드들의 경우 서로 다른 시간에 그 자원에 액세스할 수 있도록 프로세스간 통신의 한 형태를 사용해서 서로 스케줄링 해야 한다.  스레드의 활동을 적절히 스케줄링하는 데 실패할 경우에는 프로세스가 잠기는 dead lock 상황이 초래될 수도 있다.  이러한 상황을 방지하기 위해서 공유 자원에 액세스하는 스레드는 동기화 객체를 사용하는 대기함수(wait function)라고 하는 특별한 Win32 함수를 사용해서 자신의 실행을 다른 스레드의 실행과 동기화할 수 있다.  대기 함수는 스레드가 자신의 실행을 차단할 수 있도록 하며, 함수의 매개변수에 의해서 지정된 어떤 조건이 만족될 때까지는 반환되지 않는다.

CHAPTER 11  스레드 동기화(Synchronization)  동기화란? 둘 또는 그 이상의 프로세스가 동시에 존재할 때, 프로세스에 대한 처리 순서를 결정  스레드는 잠자기(sleeping)를 통해 프로세스 내에서 다른 스레드들과 자신의 행동 사이에서 동기를 맞출 수 있다.  잠자기 전에 자신이 기다릴 특정 이벤트에 관하여 윈도우 시스템에 알린다.  잠자고 있는 스레드를 위해 이벤트를 찾는 것은 윈도우가 해야 할 일이다.  스레드가 요청한 이벤트가 발생할 때까지 스레드는 잠자게 된다.  이벤트가 발생하면, Win32는 스레드에게 일어나라는 신호를 보내게 되고, 스레드는 다시 실행을 계속하게 된다.  이때 스레드와 스레드 사이에 동기화가 이루어졌다고 이야기한다.  스레드 동기화는 특수 동기화 객체에 의해 이루어진다.

◐ 프로세스의 상태전이(State Transition) ◑ CHAPTER 11 실행 상태 준비 상태 봉쇄 상태 ◐ 프로세스의 상태전이(State Transition) ◑ 디스패치 (dispatch) 타이머 종료 (timer runout) 깨움(wakeup) 봉쇄(block) 잠자고 있음 (asleep) 깨어 있음 (awake)

CHAPTER 11  스레드 동기화 객체(Synchronization Object)  한 프로세스 내에서 실행되고 있는 복수의 스레드의 실행을 제어한다.  두 가지 상태 중에서 한 상태를 그 값으로 가진다.  Signaled : 대기 함수가 반환할 수 있도록 한다.  Nonsignaled : 대기 함수가 반환되지 않도록 한다.  하나 이상의 프로세스가 동일한 객체에 대해서 핸들을 가질 수 있으며, 그것 덕분에 프로세스간 동기화가 가능해진다.  동기화 객체에 의해서 제어되는 자원에 액세스하기 위해서 MFC는 “lock” 클래스에서 파생된 두 개의 CObject를 제공한다.  CSingleLock, CMultiLock

CHAPTER 11  스레드 동기화 객체 (Synchronization Object)  상호배제(Mutex, Mutual exclusion)  상호배제는 코드를 실행하기 위해 몇몇 공유 데이터에 대해 순간적으로 배타적인 제어권을 가지는 조그만 코드 조각이다.  한번에 하나의 스레드만 데이터를 액세스 하도록 한다.  임계영역 밖에 있는 프로세스가 임계영역에 들어가려는 다른 프로세스를 막아서는 안된다.  임계영역에 들어가는 것이 무한정 연기되어서는 안된다.  세마포어(Semaphore)  여러 개의 스레드가 자신의 데이터를 동시에 액세스하도록 허용하고 있다.  Win32는 어느 스레드가 세마포어를 소유하고 있는지 알지 못하며, 세마포어 사용자의 자원 카운트만 유지하고 있다.  임계영역(Critical Section)  하나의 프로세스에 속하는 스레드들에 의해서만 사용할 수 있다.  이벤트(Event)  이벤트는 스레드에게 언제 특정 작업을 수행할 것인가를 알려 주며, 다중 스레드가 부드럽게 흘러갈 수 있도록 한다.

CHAPTER 11  이벤트의 종류  스레드 동기화를 위해 이벤트 사용하기  이벤트는 윈도우가 스레드 동기화를 위해 제공해 주는 커널 객체 타입이다.  프로세스 내에서 고유한 32비트 핸들로 정의된다.  프로세스와 스레드도 커널 객체이다.  두 프로세스의 동기화를 위해서는 자동 리셋 이벤트가 적합하다.  메인 스레드가 “Signal”에 의해 작업자 스레드를 시작/정지 시키려면 “start”이벤트와 “kill”이벤트가 필요하다.  이벤트를 전역 객체로 선언하면 다른 스레드에서도 이벤트에 쉽게 액세스 할 수 있다.  메인 스레드에서 작업자 스레드를 시작/종료하고자 할 경우 메인 스레드는 CEvent::SetEvent() 함수를 호출하여 적합한 이벤트를 “signal” 상태로 만들면 된다.  이벤트의 종류  수동(manual) 리셋 이벤트  자동(automatic) 리셋 이벤트  이벤트의 상태  시그널(signaled) 상태 (TRUE)  비시그널(nonsignaled) 상태 (FALSE)

CHAPTER 11  CEvent 클래스 메소드 메소드 설명 SetEvent() 이벤트를 사용 가능한 상태(시그널 상태)로 설정하며, 대기 스레드를 모두 release 한다. PulseEvent() 이벤트를 사용 가능한 상태(시그널 상태)로 설정한 다음에 대기 스레드를 모두 release 하고, 이벤트를 다시 사용 가능하지 않은 상태(비시그널 상태)로 설정한다. ResetEvent() 이벤트를 사용 가능하지 않은 상태(비시그널 상태)로 설정한다.  이벤트의 종류  수동(manual) 이벤트 CEvent 객체는 상대 메소드가 호출될 때까지 SetEvent() 또는 ResetEvent()에 의해서 설정된 현재의 상태에 머무른다.  자동(automatic) 이벤트 CEvent 객체는 적어도 하나의 스레드가 release되면, 자동으로 사용 가능하지 않은 상태(비시그널 상태)로 되돌아간다.

CHAPTER 11  스레드 블록킹  임계구역 (Critical section)  작업자 스레드가 이벤트의 시그널 상태가 될 때까지 단순히 실행을 일시 중지한다.  블록킹 호출은 메인 스레드(user interface thread)에 포함시키지 않도록 해야 한다.  메인 스레드가 블록킹되면 메시지를 처리할 수 없게 되고 프로그램은 느려진다.  임계구역 (Critical section)  두 프로세스 이상이 동시에 공유 데이터를 액세스 할 때 문제가 발생하는 부분  임계구역에 한 프로세스가 들어 있으면 다른 프로세스는 들어가면 안된다.(상호배제)  공유 데이터의 액세스를 통제하는데 적합하다.  MFC에는 윈도우 임계구역 핸들을 랩(wrap)하는 CCriticalSection 클래스가 제공된다  생성자는 InitializeCriticalSection() 함수를 호출  제거자는 DeleteCriticalSection() 함수를 호출  Lock() 멤버 함수와 Unlock() 멤버 함수는 EnterCriticalSection() 과 LeaveCriticalSection() 을 호출한다.

CHAPTER 11  전역 데이터를 보호하기 위한 CCriticalSection 클래스의 사용방법  CCriticalSection g_cs; int g_nCount; void func() { g_cs.Lock(); g_nCount++; g_cs.Unlock(); }

CHAPTER 11  CMutex 객체 사용하기  CMutex( BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL ); 매개변수 설명 bInitiallyOwn CMutex 객체를 생성하는 스레드가 초기에 뮤텍스가 제어할 자원에 대한 액세스 권한을 가지고 있는지의 여부를 지정한다. lpszName CMutex 객체의 이름. 뮤텍스를 복수의 프로세스가 사용해야 한다면, 이름을 반드시 부여해야 한다. lpsaAttribute Win32 SECURITY_ATTRIBUTES 구조에 정의되어 있는 바와 같은 뮤텍스 객체에 대한 보안 속성들  CMutex, CSemaphore 클래스는 별도의 클래스 관련 메소드를 제공하지는 않지만, CSyncObject 클래스로부터 Lock() 과 Unlock()은 그대로 상속해서 사용한다.

CHAPTER 11  CSemaphore 객체 사용하기 LPCTSTR pstrName = NULL,  CSemaphore( LONG lInitialCount = 1, LONG lMaxCount = 1, LPCTSTR pstrName = NULL, LPSECURITY_ATTRIBUTES lpsaAttributes = NULL ); 매개변수 설명 lInitialCount 세마포어에 대한 초기 사용 계수값. 이 값은 ‘0’과 같거나 커야 하며, lMaxCount 보다는 작거나 같아야 한다. lMaxCount 세마포어에 대한 최대 사용 계수값이며, ‘0’보다 커야 한다. pstrName 세마포어의 이름. 세마포어를 복수의 프로세스가 사용해야 한다면, 반드시 이름을 부여해야 한다. lpsaAttribute Win32 SECURITY_ATTRIBUTES 구조에 정의되어 있는 바와 같은 세마포어 객체에 대한 보안 속성들

CHAPTER 11  Win32 대기 함수(Wait Function) 함수 설명 WaitForSingleObject() 지정된 객체가 시그널 상태에 있을 경우나 지정된 시간 제한 기간이 초과되었을 경우에 반환된다. WaitForStringObjectEx() WaitForSingleObject()의 경우와 동일하지만, 시스템이 호출 스레드에 의해서 실행될 I/O 완료 루틴을 대기열에 저장할 때도 반환된다. WaitForMultipleObjects() 하나 또는 모든 지정된 객체가 시그널 상태에 있을 경우 또는 지정된 시간 제한 기간이 초과되었을 경우에 반환된다. WaitForMultipleObjectsEx() WaitForMultipleObjects()의 경우와 동일하지만, 시스템이 MsgWaitForMultipleObjects() 하나 또는 모든 지정된 객체가 시그널 상태에 있을 경우, 스레드의 입력 대기열에 지정된 타입의 입력이 들어온 경우, 또는 지정된 시간 제한 기간이 초과되었을 경우에

CHAPTER 11  CSingleLock 클래스 액세스 제어를 제공한다.  CSingleLock이나 CMultiLock 객체는 CSyncObject 클래스로부터 파생된 동기화 객체를 기다리거나 release하는데 사용해야 한다.  CSingleLock 객체는 한 번에 하나의 객체만 서비스해야 하는 경우에 사용한다.  CSingleLock 클래스 메소드 메소드 설명 IsLocked() 지정된 동기화 객체가 잠겨 있는지의 여부를 결정한다. Lock() 동기화 객체를 기다린다. Unlock() 동기화 객체를 release한다.

CHAPTER 11  CSingleLock 객체를 사용하기 위한 순서 2. 그 자원이 사용 가능한지(시그널 상태인지)의 여부를 결정하기 위해서 Lock() 메소드를 호출한다. 3. 자원이 사용 가능하다면, 메소드의 나머지 부분을 계속해서 실행하지만, 그렇지 않을 경우에는 자원이 release될 때까지 지정된 시간 초과 기간동안 대기하든지 아니면 실패를 반환한다. 4. 스레드가 자원의 사용을 마치면, Unlock() 메소드를 호출하거나 (CSingleLock 객체를 다시 사용해야 한다면) CSingleLock 객체가 소멸되는 것을 허락한다.

CHAPTER 11  CMultiLock 클래스 액세스 제어를 제공한다.  CSingleLock이나 CMultiLock 객체는 CSyncObject 클래스로부터 파생된 동기화 객체를 기다리거나 release하는데 사용해야 한다.  CMultiLock 객체는 복수의 객체를 서비스해야 하는 경우에 사용한다.  CMultiLock 클래스 메소드 메소드 설명 IsLocked() 배열 내의 지정된 동기화 객체가 잠겨 있는지의 여부를 결정한다. Lock() 동기화 객체들로 이루어진 배열을 기다린다. Unlock() 소유된 동기화 객체를 release한다.

CHAPTER 11  CMultiLock 객체를 사용하기 위한 순서 1. 기다릴 동기화 객체들의 배열을 생성한다. 3. 그 자원이 사용 가능한지(시그널 상태인지)의 여부를 결정하기 위해서 Lock() 메소드를 호출한다. 4. 자원이 사용 가능하다면, 메소드의 나머지 부분을 계속해서 실행하지만, 그렇지 않을 경우에는 자원이 release될 때까지 지정된 시간 초과 기간동안 대기하든지 아니면 실패를 반환한다. 5. 스레드가 자원의 사용을 마치면, Unlock() 메소드를 호출하거나 (CMultilock 객체를 다시 사용해야 한다면) CMultilock 객체가 소멸되는 것을 허락한다.

CHAPTER 11  CSyncObject 클래스  CSingleLock 및 CMultiLock 클래스는 모두 그들의 생성자 내에서 CSyncObject 유형의 동기화 객체를 사용한다.  MFC 동기화 클래스 클래스 설명 CCriticalSection Win32 임계영역 객체를 포함한다. CEvent Win32 이벤트 객체를 포함한다. CMutex Win32 뮤텍스 객체를 포함한다. CSemaphore Win32 세마포어 객체를 포함한다.

CHAPTER 11  WaitForSingleObject()  지정된 객체가 시그널 상태에 있을 경우나 지정된 시간 제한 기간이 초과되었을 경우에 반환된다.  DWORD WaitForSingleObject( HANDLE hHandle, // handle of object to wait for DWORD dwMilliseconds // time-out interval in milliseconds );  Parameters  hHandle 객체를 식별한다.  dwMilliseconds 타이머 메시지를 보내는 간격 (1/1000초, 1000millisecond=1초). 이 함수는 객체가 비시그널 상태에 있을 경우라도, 시간이 경과되면 반환된다. 이 함수는 dwMilliseconds가 0이면, 객체의 상태를 검사하고 즉시 반환된다. dwMilliseconds가 INFINITE이면, 이 함수의 time-out 간격이 경과되지 않는다. Value Meaning WAIT_ABANDONED The specified object is a mutex object that was not released by the thread that owned the mutex object before the owning thread terminated. Ownership of the mutex object is granted to the calling thread, and the mutex is set to nonsignaled. WAIT_OBJECT_0 0이면 객체의 상태는 시그널(signaled)이 된다. WAIT_TIMEOUT time-out 간격이 경과되면, 객체의 상태는 비시그널(nonsignaled)이 된다.

CHAPTER 11  CComMultiThreadModel::Increment  static ULONG Increment( LPLONG p );  Return Value If the result of the increment is 0, then Increment returns 0. If the result of the increment is nonzero, the return value is also nonzero but may not equal the result of the increment.  Parameters  p [in] Pointer to the variable to be incremented.

‘존경할만한 도덕적인 성품’이 가장 중요하다. 아담스의 편지 존 퀸시 아담스는 메사추세츠에 살고 있는 자신의 딸에게 이렇게 편지했다. “내 딸아! 너의 남편감으로는 정직한 사람을 구하고, 계속 그가 정직하도록 해주어라. 편하게 살 수 있을 만큼 부유한가 하는 것은 중요한 것이 아니다. 다른 어떤 여건보다도 ‘존경할만한 도덕적인 성품’이 가장 중요하다. 다른 어떤 위대함보다 영혼의 위대함을 생각하고, 다른 어떤 부함보다 마음의 부함을 생각하라.”

CHAPTER 12 메뉴, 키보드 가속기, 리치 에디트 컨트롤, 속성 시트

◐ SDI 메인 프레임 윈도우에 위치하는 차일드 윈도우 ◑ CHAPTER 12  메인 프레임 윈도우와 도큐먼트 클래스  어플리케이션 프레임워크는 프레임에서 뷰로 메시지를 전달함으로써 프레임과 뷰 간의 상호작용을 제어한다. 타이틀바 메뉴바 툴바 상태바 뷰 윈도우 차일드 윈도우 SDI 메인 프레임 윈도우 ◐ SDI 메인 프레임 윈도우에 위치하는 차일드 윈도우 ◑

CHAPTER 12  메인 프레임 윈도우와 도큐먼트 클래스  MainFrm.h, MainFrm.cpp - CFrameWnd 클래스에서 파생된 메인 프레임 윈도우 클래스(CMainFrame)의 코드가 포함되어 있다.  ex12aDoc.h, ex12aDoc.cpp - CDocument클래스에서 파생된 어플리케이션의 도큐먼트 클래스(CEx12aDoc)의 코드가 포함되어 있다.  뷰 객체  반드시 하나의 도큐먼트 객체를 가지고 있다.  CView에서 상속된 GetDocument() 멤버 함수는 뷰와 연결된 도큐먼트 객체의 포인터를 리턴한다.  윈도우 메뉴 ( DevStudio\Vc\mfc\include\afxres.h )  메뉴 아이템이 보조 팝업 메뉴와 결합되면 메뉴 아이템에 오른쪽 방향을 가리키는 화살표가 표시된다.  메뉴 아이템은 속성 다이얼로그에서 모든 특성을 정의하고 정의된 결과는 어플리케이션의 리소스 스크립트(RC) 파일에 저장된다.  메뉴 아이템은 resource.h 파일에 정의된 ID_FILE_OPEN 등과 같은 ID와 결합된다.  프롬프트 - 문자열 리소스의 공통 ID에 의해 메뉴 아이템과 연결된다.

CHAPTER 12  키보드 가속기  키보드 가속기 리소스는 명령 ID와 연결된 조합키 테이블로 구성된다.  Edit메뉴의 Copy메뉴 아이템 (명령 ID로 ID_EDIT_COPY를 가진)은 키보드 가속기 엔트리를 통해 <Ctrl+C>키와 연결된다.  명령 처리  명령 메시지는 메뉴 선택, 키보드 가속기, 툴바와 다이얼로그 버튼 클릭 등에 의해서 발생된다.  CWnd::SendMessage()나 PostMessage() 함수의 호출에 의해서 명령 메시지를 보낼 수 있다.  각 메시지는 리소스 에디터에 의해 부여되는 #define 상수로 정의된다.  프로젝트의 resource.h 파일에는 어플리케이션의 고유한 ID들이 포함되어 있다.  어플리케이션 프레임워크가 메시지 핸들러를 찾는 순서 SDI어플리케이션 MDI어플리케이션 ① 뷰 ② 도큐먼트 ③ SDI 메인 프레임 윈도우 ④ 어플리케이션 ③ MDI 자식 프레임 윈도우 ④ MDI 메인 프레임 윈도우 ⑤ 어플리케이션

CHAPTER 12  명령 처리  명령 핸들러 함수를 만들기 위해서 필요한것  함수 본체와 그 에 대응하는 메시지 맵 엔트리, 그리고 함수 원형 등이 필요하다.  메시지 맵 BEGIN_MESSAGE_MAP( CMyView, CView ) ON_COMMAND( IDM_ZOOM, OnZoom ) END_MESSAGE_MAP()  함수 본체 void CMyView::OnZoom() { // 명령 메시지 처리 코드 }  함수 원형 ( CMyView 클래스 헤더 파일 ) // DECLARE_MESSAGE_MAP 매크로 앞에  afx_msg void OnZoom();  파생 클래스에서 명령 메시지 처리하기  명령 전달 시스템은 명령 메시지 처리가 일차적이고, 클래스 계층구조는 이차적이다.  기초 클래스 메시지 맵 함수 중의 하나를 오버라이드(Override)하려면 파생 클래스에 함수와 메시지 맵 엔트리 모두를 추가해야 한다.

CHAPTER 12  갱신 명령 사용자 인터페이스 핸들러  어플리케이션이 Edit 메뉴에 Clear All 아이템을 가진 경우, 지울 내용이 없을 때는 이 메뉴 아이템을 불가능하게 만들어야 한다.  어플리케이션의 내부적인 상태를 변경하는 모든 코드에 메뉴를 갱신하는 문장이 포함되어야 한다.  MFC 라이브러리는 팝업 메뉴가 출력될 때마다 특수한 갱신 명령 UI 핸들러 함수를 호출하는 색다른 방법을 갖는다.  핸들러 함수의 파라미터는 해당하는 메뉴 아이템 포인터를 포함하는 CCmdUI 객체로, 이를 이용해서 메뉴 아이템의 상태를 변경한다.  갱신 명령 UI 핸들러  팝업 메뉴의 메뉴 아이템에만 적용된다.  탑-레벨(top-level) 메뉴에는 적용되지 않는다.  함수 본체, 메시지 맵 엔트리, 함수 원형 등이 필요하다.  연결되어 있는 ID는 앞의 명령 메시지에 대해 사용한 것과 동일한 상수이다.

CHAPTER 12  갱신 명령 사용자 인터페이스 핸들러  메시지 맵 BEGIN_MESSAGE_MAP( CMyView, CView ) ON_UPDATE_COMMAND_UI( IDM_ZOOM, OnUpdateZoom ) END_MESSAGE_MAP()  함수 본체 void CMyView::OnUpdateZoom( CCmdUI* pCmdUI ) { pCmdUI -> SetCheck( m_bZoomed ); // m_bZoomed - 뷰 클래스의 데이터 멤버 }  함수 원형 ( CMyView 클래스 헤더 파일 )  DECLARE_MESSAGE_MAP 매크로 앞에 추가한다.  afx_msg void OnUpdateZoom( CCmdUI* pCmdUI );

CHAPTER 12  다이얼로그에서 발생하는 명령 ( 버튼이 있는 팝업 다이얼로그의 경우 )  버튼에 의해 명령 메시지가 발생하려면  버튼의 명령 ID값 : 0-8000과 0-DFFF 사이에 존재해야 한다.  리소스 에디터는 메뉴 아이템에 대해서 이와 동일한 ID범위를 적용한다.  뷰가 버튼 명령의 핸들러를 가지고 있다면 이 명령은 뷰에서 처리된다.  ID가 0-8000에서 0-DFFF 사이의 범위에 있게 하려면 ① Developer Studio의 심볼 에디터를 이용하여 ID를 입력한 다음, ② 버튼에 입력한 ID를 부여해야 한다.  어플리케이션 프레임워크의 내장 메뉴 항목  프린트는 선택적이므로 메시지 맵 엔트리가 CView 클래스에 정의되지 않고 CView에서 파생된 뷰 클래스에 만들어진다.  ON_COMMAND ( ID_FILE_PRINT, CView::OnFilePrint )  ON_COMMAND ( ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview )

CHAPTER 12  메뉴 아이템의 가능/불가능 상태  어플리케이션 프레임워크는 현재의 명령 경로상에서 명령 메시지 핸들러를 발견하지 못하면 메뉴 아이템을 불가능 상태로 만든다.  CFrameWnd 클래스의 데이터 멤버 m_bAutoMenuEnable을 False로 설정하면 위의 기능을 없앨 수 있다. (the default)  한 도큐먼트에 두 개의 뷰가 연결되어 있는 상태에서 첫번째 뷰 클래스만이 IDM_ZOOM에 대한 명령 메시지 핸들러를 가지고 있다면 Zoom 메뉴 아이템은 첫번째 뷰가 활성화될 때만 가능한 상태가 된다.  MFC 텍스트 편집 옵션  윈도우는 두 가지 텍스트 편집툴을 제공한다.  에디트 컨트롤  리치 에디트 컨트롤

CHAPTER 12  MFC 텍스트 편집 옵션  CEditView 클래스  텍스트 크기는 64KB로 제한  폰트를 혼합하여 사용할 수 없다.  윈도우 서브 클래싱(subclassing)과 같은 다중 상속은 존재 하지 않는다.  Edit 메뉴의 Cut, Copy, Paste 메뉴 아이템이 활성화 되어 있다.  CRichEditView 클래스  혼합 포맷들과 많은 양의 텍스트들을 입력할 수 있도록 지원해 준다.  CRichEditDoc, CRichEditCntrItem 클래스와 함께 사용되어 완전한 ActiveX 컨테이너 어플리케이션을 구현할 수 있도록 설계되어 있다.

CHAPTER 12  MFC는 CRichEditCtrl 객체가 생성될 때 그 객체에 자동으로 윈도우 서식 있는 편집  CRichEditCtrl(서식 있는 편집 컨트롤) 클래스 (EX12A)  CView에서 파생된 뷰 클래스를 사용하며 뷰의 클라이언트 영역에 뷰의 크기가 변함에 따라 크기가 조정되는 리치 에디트 컨트롤을 출력한다.  CRichEditCtrl 클래스 구조  MFC는 CRichEditCtrl 객체가 생성될 때 그 객체에 자동으로 윈도우 서식 있는 편집 공용 컨트롤을 붙인다.  메소드 프로토타입을 포함한 CRichEditCtrl 객체를 정의하는 모든 클래스 구조 (DevStudio\Vc\mfc\include\Afxcmn.h 812라인에 정의되어 있다.)  CRichEditCtrl의 클래스 메소드  행 관련 메소드  문자 선택 메소드  문자 서식 메소드  편집 메소드  클립보드 메소드  일반적인 목적의 메소드

CHAPTER 12  CRichEditCtrl의 행 관련 메소드 설명 CRichEditCtrl 객체에서 줄의 수를 얻는다. GetLineCount() CRichEditCtrl 객체에서 줄의 수를 얻는다. GetLine() CRichEditCtrl 객체로부터 문자의 줄을 얻는다. GetFirstVisibleLine() CRichEditCtrl 객체에서 최상위의 보이는 줄을 결정한다. LineIndex() CRichEditCtrl 객체에서 특정 줄의 문자 색인을 얻는다. LineFromChar() 어느 줄에 특정 문자가 있는지 결정한다. LineLength() CRichEditCtrl 객체에서 특정 줄의 길이를 얻는다. LineScroll() CRichEditCtrl 객체에서 문자를 스크롤한다.

CHAPTER 12  CRichEditCtrl의 텍스트 선택 메소드 메소드 설명 Clear() 현재 선택된 것을 지운다. GetSel() 현재 선택된 텍스트의 시작 위치와 끝 위치를 얻는다. GetSelectionType() 현재 선택된 텍스트에서 내용의 유형을 얻는다. GetSelText() 현재 선택된 텍스트를 얻는다. HideSelection() 현재 선택된 텍스트를 보이거나 숨긴다. ReplaceSel() 현재 선택된 텍스트를 지정된 텍스트로 대체한다. SetSel() 선택한다.

CHAPTER 12  CRichEditCtrl의 텍스트 서식 메소드 메소드 설명 현재의 기본 문자 형식 특성을 얻는다. GetDefaultCharFormat() 현재의 기본 문자 형식 특성을 얻는다. GetParaFormat() 현재 선택한 문자의 문단 형식 특성을 얻는다. GetSelectionCharFormat() 현재 선택한 문자에서 문자 형식 특성을 얻는다. SetDefaultCharFormat() 현재의 기본 문자 형식 특성을 설정한다. SetParaFormat() 현재 선택한 문자의 문단 형식 특성을 설정한다. SetSelectionCharFormat() 현재 선택한 문자에서 문자 형식 특성을 설정한다. SetWordCharFormat() 현재의 단어에서 문자 형식 특성을 설정한다.

CHAPTER 12  CRichEditCtrl의 편집 메소드 메소드 설명 CanUndo() 편집 작업이 취소될지 안될지를 결정한다. EmptyUndoBuffer() CRichEditCtrl 객체의 취소 플래그를 새로이 설정한다. StreamIn() 입력 스트림으로부터 텍스트를 삽입한다. StreamOut() 출력 스트림에서 CRichEditCtrl 객체의 텍스트를 저장한다. Undo() 마지막으로 편집된 작업을 취소한다.

CHAPTER 12  CRichEditCtrl의 클립보드 메소드 메소드 설명 CanPaste() 클립보드의 내용이 서식 있는 편집 컨트롤로 전달될지 아닐지를 검사한다. Copy() 현재 선택된 텍스트를 클립보드로 복사한다. Cut() 현재 선택된 텍스트를 클립보드로 잘라낸다. Paste() 클립보드의 내용을 서식 있는 편집 컨트롤에 삽입한다. PasteSpecial() 클립보드의 내용을 지정된 데이터 포맷을 사용하여 서식 있는 편집 컨트롤에 삽입한다.

CHAPTER 12  CRichEditCtrl의 일반적인 목적의 메소드 메소드 설명 DisplayBand() FindText() CRichEditCtrl 객체 내의 문자의 위치를 잡는다. FormatRange() 대상 출력 장치를 위해 일정 범위 문자의 형식을 맞춘다. GetCharPos() CRichEditCtrl 객체 내에서 특정 문자의 위치를 얻는다. GetEventMask() CRichEditCtrl 객체에 대한 이벤트 마스크를 얻는다. GetLimitText() 사용자가 CRichEditCtrl 객체에 입력할 수 있는 텍스트의 양에 대한 한계 값을 얻는다. GetModify() 마지막으로 저장한 이후에 CRichEditCtrl 객체의 내용을 수정했는지 여부를 결정한다. GetRect() CRichEditCtrl 객체에 대한 포맷 직사각형을 얻는다. GetTextLength() CRichEditCtrl 객체의 텍스트의 길이를 얻는다.

CHAPTER 12  CRichEditCtrl의 일반적인 목적의 메소드 메소드 설명 LimitText() 제한한다. RequestResize() CRichEditCtrl 객체의 크기를 재조정하기를 요청하는 통보를 그 객체가 부모 창에게 보내도록 만든다. SetBackgroundColor() CRichEditCtrl 객체의 배경색을 설정한다. SetEventMask() CRichEditCtrl 객체의 이벤트 마스크를 설정한다. SetModify() CRichEditCtrl 객체의 수정 플래그를 설정하거나 지운다. SetOptions() CRichEditCtrl 객체의 옵션을 설정한다. SetReadOnly() CRichEditCtrl 객체의 읽기 전용 옵션을 설정한다. SetRect() CRichEditCtrl 객체의 포맷 직사각형을 설정한다. SetTargetDevice() CRichEditCtrl 객체의 대상 출력 장치를 설정한다.

CHAPTER 12  BOOL Create(DWORD dwStyle, const RECT& rect,  CRichEditCtrl 생성하고 초기화하기 1. 클래스 생성자 CRichEditCtrl::CRichEditCtrl() 를 호출하여 객체를 할당한다. 2. CRichEditCtrl::Create() 메소드를 호출하여 CRichEditCtrl 객체를 초기화하고, 그 객체에 윈도우 서식 있는 편집 공용 컨트롤을 붙인다.  CRichEditCtrl::Create()  BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);  Parameter  dwStyle : 컨트롤에서 사용하는 스타일의 조합을 지정한다.  rect : 컨트롤의 크기와 위치를 지정한다.  nParentWnd : 컨트롤의 부모 창을 지정한다.  nID : 컨트롤의 컨트롤 식별자를 지정한다.

CHAPTER 12  CRichEditCtrl 사용하기 1. 문단 형식 및 문자 형식을 정의하기 위해 PARAFORMAT과 CHARFORMAT 구조를 준비한다. 2. 이 구조들을 사용하는 CRichEditCtrl 메소드를 호출하여 원하는 작업을 수행한다. void CMainWnd::SetStyleHeading1(CHARFORMAT& cf) { cf.cbsize = sizeof(CHARFORMAT); cf.dwMask = CFM_COLOR | CFM_FACE | CFM_SIZE | CFM_ITALIC | CFM_BOLD; cf.dwEffects = CFE_BOLD | CFE_ITALIC; cf.yHeight = 500; cf.crTextColor = crRed; cf.bCharSet = ANSI_CHARSET; cf.bPitchAndFamily = FF_ROMAN; }

CHAPTER 12  문자 형식 구조(CHARFORMAT)  GetDefaultCharFormat(), GetSelectionCharFormat(), SetDefaultCharFormat(), SetSelectionCharFormat(), SetWordCharFormat() 모두 CHARFORMAT 유형의 매개 변수를 가진다.  이것은 서식 있는 편집 컨트롤에서 문자 형식에 대한 정보를 담고 있는 Win32 데이터 유형이다.

CHAPTER 12  CHARFORMAT 구조 typedef struct _charformat { UINT cbSize; // 이 구조의 바이트 단위 크기 _WPAD _wPad1; DWORD dwMask; // 설정될 유효한 정보나 속성을 가지는 멤버 DWORD dwEffects; // 문자 효과 LONG yHeight; // 문자 높이 LONG yOffset; // 기준선으로부터의 문자 옵셋. +:위첨자, -:아래첨자 COLORREF crTextColor; // 텍스트 색 BYTE bCharSet; // 문자 집합 값 BYTE bPitchAndFamily; // 글꼴 집합과 크기 TCHAR szFaceName[LF_FACESIZE]; // 글꼴 이름을 가리키는 널로 끝나는 문자 _WPAD _wPad2; } CHARFORMAT;

CHAPTER 12  CHARFORMAT dwMask 값 설명 dwEffects 멤버의 CFE_BOLD 값이 유효하다. CFM_BOLD dwEffects 멤버의 CFE_BOLD 값이 유효하다. CFM_COLOR dwEffects 멤버의 crTextColor 멤버와 CFE_AUTOCOLOR 값이 유효하다. CFM_FACE szFaceName 멤버가 유효하다. CFM_ITALIC dwEffects 멤버의 CFE_ITALIC 값이 유효하다. CFM_OFFSET yOffset 멤버가 유효하다. CFM_PROTECTED dwEffects 멤버의 CFE_PROTECTED 값이 유효하다. CFM_SIZE yHeight 멤버가 유효하다. CFM_STRIKEOUT dwEffects 멤버의 CFE_STRIKEOUT 값이 유효하다. CFM_UNDERLINE dwEffects 멤버의 CFE_UNDERLINE 값이 유효하다.

CHAPTER 12  서식 있는 편집 컨트롤의 가능한 문자/효과 값 값 설명 CFE_AUTOCOLOR 텍스트 색은 GetSysColor(COLOR_WINDOWTEXT)의 반환 값 CFE_BOLD 문자는 굵은 글씨체 CFE_ITALIC 문자는 이탤릭체 CFE_STRIKEOUT 문자는 취소선 CFE_UNDERLINE 문자는 밑줄체 CFE_PROTECTED 문자는 보호된다. 문자를 수정하려고 시도하면, EN_PROTECTED 통보 메시지를 발생시킨다.

CHAPTER 12  속성 시트(Property Sheet)  많은 종류의 정보를 조그만 다이얼로그에 집약할 수 있도록 해준다.  윈도우95는 다이얼로그 내에 삽입할 수 있는 탭 컨트롤을 제공해 준다.  MFC 라이브러리는 속성 시트라고 하는 결과물과 속성 페이지라고 하는 개개의 다이얼로그를 지원한다.  속성 시트 만들기 1. 리소스 에디터를 이용하여 동일한 크기의 다이얼로그 템플릿들을 만든다. 2. ClassWizard를 이용하여 각 템플릿을 위한 클래스를 만든다. 기초 클래스로서 CPropertyPage를 선택한다. 컨트롤을 위한 데이터 멤버들을 추가한다. 3. ClassWizard를 이용하여 CPropertySheet에서 파생된 클래스를 하나 생성한다. 4. 페이지 클래스 각각에 대해 데이터 멤버를 파생된 속성 시트 클래스에 추가한다. 5. 파생된 속성 시트 클래스의 생성자에서 포함된 페이지 객체의 주소를 지정하여 각 페이지에 대해 AddPage() 멤버 함수를 호출한다. 6. 어플리케이션에서는 CPropertySheet에서 파생된 클래스의 객체를 생성한 다음, DoModal()을 호출한다. 생성자 호출시에 캡션을 지정해도 되지만, 나중에 CPropertySheet::SetTitle()를 호출하여 캡션을 변경할 수도 있다. 7. Apply 버튼의 코드를 작성한다.

CHAPTER 12  직접 코드를 작성하지 않으면 아무 일도 하지 않고 버튼도 불가능 상태로 나타난다.  속성 시트 데이터 교환  프레임워크는 사용자가 속성 페이지를 전환할 때마다 해당 속성 페이지의 DDX 코드를 호출한다.  프레임워크는 모든 버튼 클릭에 대해 WM_NOTIFY 메시지를 얻는다.  프레임워크는 OK, Cancel, Apply 버튼이 클릭되면 페이지의 DDX 코드를 호출하고나서 모든 페이지들에 대해 가상 함수 OnApply()를 호출하며, 변경된 플래그를 재설정하여 Apply 버튼을 불가능 상태로 만든다.  사용자가 한 페이지의 내용 변경 후, 다른 페이지로 이동한 다음에 Cancel 버튼을 클릭하면 변경된 내용이 적용되어 데이터 멤버가 갱신된다.  Apply(적용) 버튼  직접 코드를 작성하지 않으면 아무 일도 하지 않고 버튼도 불가능 상태로 나타난다.  버튼을 가능한 상태로 만들려면 가상 함수 CPropertyPage::OnApply()를 Override해서 페이지 클래스에서 Apply 버튼에 대한 핸들러 함수를 작성해야 한다.  버튼이 사용 가능해졌다면 사용자가 페이지 내용을 변경할 때 SetModified(TRUE)를 호출하여 페이지의 변경 플래그를 설정해야 한다.  하나의 페이지 클래스에서만 Override하면 된다.

CHAPTER 12  CMenu 클래스  CMenu 객체는 탑-레벨 항목과 그와 연결된 팝업 메뉴를 포함해서 모든 윈도우 메뉴를 나타낼 수 있다.  CWnd::GetMenu()는 임시적인 CMenu 포인터를 리턴한다.  포인터를 얻은 다음에는 메뉴 객체를 마음대로 액세스하고 갱신할 수 있다.  GetSubMenu() 멤버 함수를 사용하면 메인 CMenu 객체에 포함된 팝업 메뉴의 포인터 (CMenu 포인터)를 얻을 수 있다.  플로팅 팝업(Pop-up)메뉴 만들기  CMenu::TrackPopupMenu() 함수를 이용하면 쉽게 팝업 메뉴를 만들 수 있다. 1. 메뉴 에디터를 이용하여 프로젝트의 리소스 파일에 새로운 메뉴를 삽입한다. 2. 왼쪽의 탑-레벨 항목에 문자들을 입력한 후, 팝업 메뉴에 메뉴 아이템들을 추가한다. 3. ClassWizard를 이용하여 뷰 클래스 또는 마우스 클릭 메시지를 접수할 윈도우 클래스에 WM_CONTEXTMENU 메시지 핸들러를 추가한다.

CHAPTER 12  CPage1 클래스에 팝업(Pop-up)메뉴 만들기 void CPage1::OnContextMenu(CWnd* pWnd, CPoint point) { CMenu menu; menu.LoadMenu(IDR_MAINFRAME); menu.GetSubMenu(1) -> TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON, // 플래그 point.x, point.y, // 위치 this); // 소유자 }

CHAPTER 12  플로팅 팝업(Pop-up)메뉴 만들기 void CMyView::OnContextMenu(CWnd* pWnd, CPoint point) { CMenu menu; menu.LoadMenu(IDR_MYFLOATMENU); menu.GetSubMenu(0) -> TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON, // 플래그 point.x, point.y, // 위치 this); // 소유자 }

CHAPTER 12  네 개의 Win32 API 메뉴 메시지를 두 개의 MFC 메뉴 메시지와 맵핑하기 WM_COMMAND WM_COMMAND 메시지에 맵핑된다. WM_INITMENU WM_INITPOPUPMENU WM_MENUSELECT 없음; MFC는 이 메시지를 무시한다. 없음; CFrameWnd에 의해 자동으로 설정된다. UPDATE_COMMAND_UI 메시지에 맵핑된다. MFC는 어떤 메뉴 핸들러가 메시지를 전달할 것인지를 결정하고, WM_COMMAND 메시지를 받을 수 없는 메뉴 항목은 자동으로 회색으로 만든다.  CMenu 클래스 메소드  생성 메소드  메뉴 연산 메소드  메뉴 항목 연산 메소드  가상 메소드

CHAPTER 12  CMenu 생성 메소드 메소드 목적 Attach() CMenu 객체에 표준 윈도우 메뉴 핸들을 붙인다. CreateMenu() 빈 메뉴를 생성하고, 그것을 CMenu 객체에 붙인다. CreatePopupMenu() 빈 팝업 메뉴를 생성하고, 그것을 CMenu 객체에 붙인다. DeleteTempMap() FromHandle() 멤버함수에 의해 생성된 임시 CMenu 객체를 삭제한다. DestroyMenu() CMenu 객체에 결합된 메뉴를 없애고, 메뉴가 차지한 메모리를 비운다. Detach() CMenu 객체로부터 창의 메뉴 핸들을 제거하고, 핸들을 반환한다. FromHandle() 창의 메뉴 핸들을 받으면, CMenu 객체의 포인터를 반환한다. GetSafeMenu() CMenu 객체에 의해 보호되는 메뉴 핸들 멤버(m_hMenu)를 반환한다. LoadMenu() 실행 파일로부터 메뉴 자원을 적재하고, 그것을 CMenu 객체에 결합한다. LoadMenuIndirect() 메모리의 메뉴 템플릿에서 메뉴를 적재하고, 그것을 CMenu 객체에 결합한다.

CHAPTER 12  메뉴 연산 메소드  DeleteMenu()  메뉴에서 지정된 항목을 삭제한다.  삭제된 메뉴 항목에 관련된 팝업 메뉴가 있다면, 팝업 메뉴의 핸들 역시 삭제되고 메모리는 해제된다.  TrackPopupMenu()  POINT 구조체에서 지정된 장소에 팝업 메뉴를 나타낸다.  가상 메소드  DrawItem()  소유자가 그리는 메뉴의 시각적인 면이 변경되었을 때 MFC가 호출한다.  MeasureItem()  소유자가 그리는 메뉴가 생성될 때 메뉴의 크기를 얻기 위해서 MFC가 호출한다.

CHAPTER 12  메뉴 항목 연산에 이용하는 CMenu 클래스 메소드 메소드 목적 AppendMenu() 특정 메뉴의 끝에 새로운 항목을 추가한다. CheckMenuItem() 팝업 메뉴의 메뉴 항목에 체크 표시를 하거나 삭제한다. CheckMenuRadioItem() 메뉴 항목에 라디오 단추를 넣거나 그룹의 다른 모든 메뉴에서 존재하는 라디오 단추를 삭제한다. EnableMenuItem() 메뉴 항목을 실행 가능하게, 실행 불가능하게, 또는 흐릿하게 만든다. GetMenuContextHelpId() 메뉴와 관련된 도움말 컨텍스트 ID를 가져온다. GetMenuItemCount() 팝업 메뉴나 최상위 메뉴의 항목 개수를 가져온다. GetMenuItemID() 특정 위치에 존재하는 메뉴 항목을 위한 메뉴 항목 ID를 가져온다. GetMenuState() 특정 메뉴 항목의 상태를 가져오거나 팝업 메뉴의 항목 수를 가져온다.

CHAPTER 12  메뉴 항목 연산에 이용하는 CMenu 클래스 메소드 메소드 목적 InsertMenu() 메뉴의 다른 항목을 아래로 옮기고 지정된 위치에 새로운 메뉴 항목을 삽입한다. ModifyMenu() 지정한 위치에 존재하는 메뉴 항목을 변경한다. RemoveMenu() 연관된 팝업 메뉴와 함께 지정된 메뉴의 메뉴 항목을 삭제한다. SetMenuContextHelpId() 메뉴에 연관된 도움말 컨텍스트 ID를 설정한다. SetMenuItemBitmaps() 메뉴 항목에 지정된 체크 표시 비트맵을 적용한다. GetMenuString() 지정한 메뉴 항목의 이름표를 가져온다. GetSubMenu() 팝업 메뉴의 포인터를 가져온다.

CHAPTER 12  CPropertyPage  CPropertyPage();  CPropertyPage( UINT nIDTemplate, UINT nIDCaption = 0);  CPropertyPage(LPCTSTR lpszTemplateName, UINT nIDCaption = 0);  Parameters  nIDTemplate 페이지에 관련되는 다이얼로그 템플릿의 정수 리소스 ID  lpszTemplateName 페이지에 관련되는 다이얼로그 템플릿의 이름을 포함하는 널로 끝나는 문자열 버퍼에 대한 포인터  nIDCaption 페이지에 대한 캡션으로 사용되는 문자열의 문자열 리소스 ID. 0이거나 생략되면, 캡션은 다이얼로그 템플릿 자체에서 얻어진다.  CWnd::OnContextMenu  afx_msg void OnContextMenu( CWnd* pWnd, CPoint pos );  pWnd Handle to the window in which the user right clicked themouse. This can be a child window of the window receiving the message. For more information about processing this message, see the Remarks section.  pos Position of the cursor, in screen coordinates, at the time of the mouse click.

CHAPTER 12  CWnd::SetMenu  윈도우에 대한 메뉴를 특정 메뉴로 변경한다.  CWnd::GetMenu 함수로 이전의 메뉴를 얻고, CMenu::DestroyMenu 함수로 이전의 메뉴를 파괴하여야 한다.  BOOL SetMenu( CMenu* pMenu );  Parameters  pMenu 새로운 메뉴에 대한 포인터. 파라미터가 NULL이면, 현재 메뉴가 윈도우로 부터 제거된다.  CMenu::GetSubMenu  메뉴의 팝업 메뉴에 관련되는 CMenu 객체를 얻는다.  팝업메뉴의 식별자는 이 함수를 사용할 수 없다.  CMenu* GetSubMenu( int nPos ) const;  Return Value 팝업메뉴에 관련되는 CMenu 객체에 대한 포인터  nPos 메뉴에 포함되어 있는 팝업 메뉴의 위치. Position values start at 0 for the first menu item.

CHAPTER 12  CMenu::TrackPopupMenu  BOOL TrackPopupMenu( UINT nFlags, // 플래그 int x, int y, // 위치 CWnd* pWnd, // 소유자 LPCRECT lpRect = NULL ); // 범위  Screen-position flag  TPM_CENTERALIGN  TPM_LEFTALIGN  TPM_RIGHTALIGN  Mouse-button flag  TPM_LEFTBUTTON  TPM_RIGHTBUTTON  x 팝업메뉴의 스크린 좌표상의 수평 위치  y 팝업메뉴의 스크린 좌표상의 수직 위치  pWnd 팝업메뉴 자신의 윈도우를 기술한다.

우리에게 필요되는 것은 무엇이든 해낼 수 있다는 “Can do” 정신이다. 샘물처럼 마르지 않는 왕성한 학습 의욕이 그 생명이며 부정적인 현재보다 긍정적인 미래가 그 지향 목표이다. “컵에 물이 반밖에 차지 않았다.”는 소극적인 자세보다 “컵에 물이 반이나 찼다.”는 적극적인 자세가 매사를 혁신으로 이끈다. ( 실리콘 밸리의 정신 )

CHAPTER 13 툴바와 상태바

CHAPTER 13  툴바와 상태바  AppWizard Step4에서 Docking toolbar와 Initial status bar 옵션을 디폴트로 설정하면 AppWizard는 선택된 요소들에 대해 초기화 기본 코드를 만든다.  컨트롤바와 어플리케이션 프레임워크  툴바 - CToolBar 클래스의 객체  상태바 - CStatusBar 클래스의 객체  CControlBar 클래스 - 메인 프레임 윈도우 내에 위치한 컨트롤바 윈도우들이 부모 프레임 윈도우가 이동하거나 크기 조정에 따라 스스로 그 위치와 크기를 변경시킨다.  어플리케이션 프레임워크 - 컨트롤바 객체의 생성, 소멸 그리고 해당 객체의 윈도우를 만드는 일을 담당  AppWizard - 메인 프레임 윈도우 내에 위치한 컨트롤바 코드를 MainFrm.cpp, MainFrm.h 파일에 생성한다.  SDI 어플리케이션  CToolBar 객체 - CMainFrame 클라이언트 영역의 상단에 위치  CStatusBar 객체 - CMainFrame 클라이언트 영역의 하단에 위치  뷰 - 프레임의 나머지 공간(툴바와 상태바 중간)을 차지한다.

CHAPTER 13  툴바  버튼의 그래픽 이미지들은 어플리케이션의 리소스 파일에 연결된 단일 비트맵으로 저장된다.  메뉴와 가속키처럼 툴바 버튼도 클릭될 때 명령 메시지를 보낸다.  갱신 명령 UI 메시지 핸들러에 의해 버튼의 상태가 갱신되면 어플리케이션 프레임워크는 버튼의 그래픽 이미지를 변경시킨다.  툴바 비트맵  툴바 비트맵은 각 버튼에 대해서 16(폭)x15(높이) 픽셀의 타일(tile)을 가지고 있다.  어플리케이션 프레임워크는 각 버튼의 경계선을 제공하여 현재의 버튼 상태 (눌려진 상태와 눌려지지 않은 상태)에 따라 버튼의 비트맵 색상과 경계선을 변경한다.  툴바 비트맵은 어플리케이션의 \res 서브 디렉토리의 Toolbar.bmp 파일에 저장된다.  비트맵은 리소스 스크립트 파일( .rc)에서 IDC_MAINFRAME으로 식별된다.

CHAPTER 13  버튼의 상태 버튼의 상태 설 명 TBBS_PRESSED TBBS_CHECKED TBBS_DISABLED 설 명 TBBS_PRESSED TBBS_CHECKED TBBS_DISABLED TBBS_INDETERMINATE TBBS_CHECKED | TBBS_DISABLED 눌려져 있지 않은 정상 상태(up) 마우스를 이용해서 현재 선택된(눌려진) 상태 체크된(down) 상태 사용이 불가능한 상태 사용이 가능하지만, up도 down도 아닌 상태 체크된(down) 상태이지만, 사용이 불가능한 상태  표준 어플리케이션의 툴바에서 사용되는 버튼들은 모두 푸시 버튼 형태로 작동된다.  툴바와 명령 메시지  대부분의 경우 툴바 버튼은 메뉴 명령과 일치된다.  어플리케이션의 메뉴 아이템과 대응하는 툴바 버튼의 유무와 상관없이 ClassWizard를 사용하여 명령과 갱신명령 UI 메시지 핸들러를 정의할 수 있다.  툴바는 비트맵 리소스, 버튼과 조합된 메뉴 명령을 정의하는 TOOLBAR 리소스를 갖는다.  비트맵 리소스와 TOOLBAR 리소스는 동일한 ID(ID_MAINFRAME)를 갖는다.

CHAPTER 13  AppWizard가 생성한 툴바 리소스의 텍스트 IDR_MAINFRAME TOOLBAR DISCARDABLE 16, 15 BEGIN BUTTON ID_FILE_NEW BUTTON ID_FILE_OPEN BUTTON ID_FILE_SAVE SEPARATOR BUTTON ID_EDIT_CUT BUTTON ID_EDIT_COPY BUTTON ID_EDIT_PASTE BUTTON ID_FILE_PRINT BUTTON ID_APP_ABOUT END  툴바 비트맵 패인(pane)의 수가 리소스 요소의 수보다 더 많을경우 초과된 버튼들은 출력되지 않는다.  버튼 이미지를 선택한 다음, 왼쪽 패널을 double click하면 버튼의 ID등의 속성을 편집할 수 있는 상태가 된다.

CHAPTER 13  툴바 갱신 명령 UI 메시지 핸들러  갱신 명령 UI 메시지 핸들러가 False 파라미터를 이용하여 CCmdUI::Enable() 멤버함 수를 호출하게 되면 이와 대응하는 버튼이 불가능 상태(회색)로 설정되어 마우스 클릭 에 대해서 반응하지 않게 된다.  CCmdUI::SetCheck()  메뉴 아이템의 경우 - 메뉴 아이템에 체크 표시를 한다.  툴바의 경우 - 체크 박스 버튼을 구현한다.  CCmdUI::SetCheck - 사용자 인터페이스 객체에 체크 표시를 하거나 해제한다.  virtual void SetCheck( int nCheck = 1 );  Parameters  nCheck 체크되지 않은 상태 : 0, 체크 상태 : 1, 중간 상태 : 2  CButton::SetCheck - 버튼의 체크 상태를 설정한다. (라디오 버튼, 체크 박스에서만 유효)  void SetCheck( int nCheck );  nCheck 버튼의 체크 상태 Value Meaning 0 버튼이 체크되지 않게 한다. (라디오 버튼은 선택되지 않는다.) 1 버튼이 체크된다. (라디오 버튼은 선택된다.) 2 버튼이 중간 상태가 된다. 갱신 명령 UI 메시지 핸들러는 어플리케이션의 idle처리중에 호출된다.

CHAPTER 13  툴팁 ( 풍선 도움말 )  툴팁을 만들려면 (p439)  메뉴 프롬프트의 끝 부분에 (\n)문자와 함께 팁 텍스트를 추가하면 된다.  메인 프레임 윈도우 찾기  툴바 객체와 상태바 객체는 어플리케이션의 메인 프레임 윈도우에 부착된다.  SDI와 MDI어플리케이션 모두에 적용되게 하려면 어플리케이션 객체를 통해서 메인 프레임 윈도우를 찾아야 한다.  AfxGetApp()를 이용 - 어플리케이션 객체 포인터를 리턴  CWinApp 클래스의 데이터 멤버인 m_pMainWnd를 이용 - 어플리케이션 객체 포인터  CMainFrame* pFrame = ( CMainFrame*)AfxGetApp()->m_pMainWnd; CToolBar* pToolBar = &pFrame->m_wndToolBar;  m_wndToolBar는 유도 클래스의 멤버이므로 CFrameWnd* 에서 CMainFrame*로 m_pMainWnd를 형변환시켜야 한다.  SDI 어플리케이션의 경우 - m_pMainWnd의 값은 뷰의 OnCreate() 함수에서 메인 프레임 윈도우를 액세스 해야 할 경우 GetParentFrame() 함수를 이용해야 한다.

CHAPTER 13  CToolBar 클래스 메소드 메소드 설명 CommandToIndex() Create() GetItemID() GetItemRect() GetPaneInfo() GetPaneStyle() GetPaneText() GetStatusBarCtrl() SetIndicators() SetPaneInfo() SetPaneStyle() SetPaneText() 특정 지시자 ID의 인덱스를 얻는다. 상태 표시줄을 생성하고, 그것을 CStatusBar 객체에 붙인다. 특정 인덱스에 대한 지시자 ID를 얻는다. 특정 인덱스에 대한 출력 직사각형을 얻는다. 특정 인덱스에 대한 지시자 ID, 스타일, 너비를 얻는다. 특정 인덱스에 대한 지시자 스타일을 얻는다. 특정 인덱스에 대한 지시자 문자를 얻는다. CStatusBarCtrl 객체 참조로 상태 표시줄 공용 컨트롤에 대한 직접적인 액세스를 허락한다. 지시자 ID를 설정한다. 특정 인덱스에 대한 지시자 ID, 스타일, 너비를 설정한다. 특정 인덱스에 대한 지시자 스타일을 설정한다. 특정 인덱스에 대한 지시자 텍스트를 설정한다.

CHAPTER 13  예제 EX13A - 툴바  사용자가 원을 그린 경우 Circle 메뉴 아이템과 툴바 버튼이 불가능하게 되고, 사각형을 그린 경우 Square 메뉴 아이템과 툴바 버튼이 불가능하게 된다.  어플리케이션의 Draw 메뉴에서 대각선 패턴이 활성화될 때 Pattern 메뉴 아이템은 체크 표시가 되며, 이에 대응하는 툴바 버튼은 대각선 패턴이 활성화 되면 다운(down)으로 표시되고 활성화되지 않았을 경우 업(up)으로 표시된다. 메뉴 아이템 기능 Circle Square Pattern 뷰 윈도우에 원을 그린다. 뷰 윈도우에 사각형을 그린다. 새로운 사각형과 원 내부를 대각선 패턴으로 채운다.

CHAPTER 13  상태바  프로그램의 제어로 패인(pane)에 텍스트를 출력하는 역할만 한다.  상태바는 메시지 라인 패인과 상태 표시자 패인 두 가지 형태의 텍스트 패인을 지원한다.  상태바 정의 static UINT BASED_CODE indicators[] = { ID_SEPARATOR, // status line indicator ID_INDICATOR_CAPS, ID_INDICATOR_NUM, ID_INDICATOR_SCRL, ID_INDICATOR_PAGE, };  CStatusBar::SetIndicators - 상태바에 대한 창 지시자를 설정한다.  BOOL SetIndicators( const UINT* lpIDArray, int nIDCount );  Return Value  성공하면 TRUE, 실패하면 FALSE  Parameters  lpIDArray 상태바 창에 대한 커맨드 ID를 나타내는 UINT 배열에 대한 포인터  nIDCount 창의 수. lpIDArray 배열에 있는 요소의 수와 동일하다. 정적 배열 indicators[]은 어플리케이션의 상태바 패인(pane)을 정의

CHAPTER 13  메시지 라인 패인 (pane)  프로그램이 동적으로 제공하는 문자열을 출력한다.  인덱스 파라미터를 사용 - 0번 패인 : 맨 왼쪽 패인, 1번 패인 : 다음 패인(CAP)  CMainFrame* pFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; CStatusBar* pStatus = &pFrame->m_wndStatusBar; pStatus->SetPaneText( 0, “message line for first pane” );  일반적으로 메시지 라인 패인의 길이는 전체 상태바 폭의 1/4이다.  메시지 라인이 첫번째 패인(인덱스 0)인 경우 경계선이 없는 확장된 패인이 되어 최소 길이는 전체 표시 폭의 1/4이 된다.  CStatusBar::SetPaneText - 특정 상태바 창에 대해 텍스트를 설정한다.  BOOL SetPaneText( int nIndex, LPCTSTR lpszNewText, BOOL bUpdate = TRUE );  Return Value  성공하면 TRUE, 실패하면 FALSE  Parameters  nIndex 특정 상태바 창을 나타내는 0에서 시작하는 인덱스  lpszNewText 새로운 창 텍스트에 대한 포인터  bUpdate 상태바가 갱신되어야 하면 TRUE, 그렇지 않으면 FALSE

CHAPTER 13  상태 표시자(Status Indicator) 패인  단일 리소스에 의해 제공되는 문자열과 연결된다.  문자열은 갱신 명령 UI 메시지 핸들러 함수에 의해 표시되거나 사라진다.  각 표시자는 문자열 리소스 ID에 의해서 식별된다.  CapsLock 표시자는 프레임 클래스의 메시지 맵 엔트리와 핸들러 함수에서 처리된다.  ON_UPDATE_COMMAND_UI ( ID_INDICATOR_CAPS, OnUpdateKeyCapsLock ) void CMainFrame::OnUpdateKeyCapsLock ( CCmdUI* pCmdUI ) { pCmdUI->Enable(::GetKeyState(VK_CAPITAL) & 1)); }  상태바의 갱신 명령 UI 메시지 함수는 idle 처리중에 호출되므로 어플리케이션이 메시지를 접수할 때마다 상태바가 갱신된다. 인덱스 파라미터

CHAPTER 13  상태바의 제어 얻기  상태바를 제어하기 위해서는 디폴트 ID(AFX_IDW_STATUS_BAR)대신 다른 차일드 윈도우 ID를 사용해야 하고 다른 표시자 ID 상수를 사용해야 한다.  CFrameWnd::OnUpdateKeyIndicator(CCmdUI* pCmdUI) 에서 상태바의 상태 표시자가 갱신된다.(..\vc\mfc\src\Winfrm.cpp - 1733라인)  상태바의 차일드 윈도우 ID를 변경하는 이유는 프레임워크가 0번 패인에 메뉴 프롬프트를 표시하지 못하도록 하기 위함이다.  고유한 윈도우 ID를 부여하려면 m_wndStatusBar.Create(this); 를 다음과 같이 변경한다. m_wndStatusBar.Create(this, WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, ID_MY_STATUS_BAR);  표준 어플리케이션의 View 메뉴에는 사용자가 상태바를 show/hide 할 수 있도록 해준다.

CHAPTER 13  CStatusBar::Create - 상태바를 생성한다.  상태바는 AFX_IDW_STATUS_BAR 자식 윈도우 ID로 주어진다. 이것은 MFC 프레임워크가 프레임 윈도우의 어느 자식 윈도우가 상태바인가를 알 수 있는 방법  BOOL Create( CWnd* pParentWnd, DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, UINT nID = AFX_IDW_STATUS_BAR );  Return Value  성공 : TRUE, 실패 : FALSE  Parameters  pParentWnd 부모 윈도우에 대한 포인터  dwStyle 상태바와 표준 윈도우 스타일 CBRS_TOP Control bar is at top of frame window. CBRS_BOTTOM Control bar is at bottom of frame window. CBRS_NOALIGN Control bar is not repositioned when the parent is resized.  nID 툴바의 자식 윈도우 ID.

CHAPTER 13  RecalcLayout  이 멤버는 프레임 윈도우의 크기가 변경되거나 컨트롤바가 표시되거나 숨겨질 때 호출된다. 프레임 윈도우의 레이아웃 행위를 Customize하기 위하여 중복될 수 있다.  virtual void RecalcLayout( BOOL bNotify = TRUE );  Parameters  bNotify TRUE이면, 프레임에 대한 활성화 인플레이스 항목이 레이아웃 변경에 대해 통보 받는다.

CHAPTER 13  예제 EX13B - 상태바 패인 인덱스 문자열 ID Type 설명 1 2 3 1 2 3 ID_SEPARATOR(0) ID_INDICATOR_LEFT ID_INDICATOR_RIGHT Type 메시지 라인 상태 표시자 설명 x 커서 좌표 y 커서 좌표 왼쪽 마우스 버튼 상태 오른쪽 마우스 버튼 상태  CStatusBar::SetPaneInfo - 특정 상태바 창에 대한 창 정보를 설정한다.  void SetPaneInfo( int nIndex, UINT nID, UINT nStyle, int cxWidth );  Parameters  nIndex 특정 상태바 창을 나타내는 0에서 시작하는 인덱스  nID 창에 대한 커맨드 ID  nStyle 창의 스타일 SBPS_NOBORDERS 경계가 없다. SBPS_POPOUT Popout 경계 SBPS_DISABLED 텍스트를 그리지 않는다. SBPS_STRETCH 창을 남아 있는 영역까지 확장한다. SBPS_NORMAL 기본 창.  cxWidth 창의 폭

CHAPTER 14 재사용 가능한 프레임 윈도우 기초 클래스

CHAPTER 14  프레임 윈도우  프레임 윈도우는 MFC가 제공하는 가장 편리한 클래스 중의 하나이다.  관련 윈도우 API 함수에 대한 단순한 캡슐화를 제공하는 것뿐만 아니라, 윈도우 어플리케이션에 표준화된 확장 기능을 지원한다. 클래스 이름 설명 CFrameWnd CMDIFrameWnd CMDIChildWnd CMiniFrameWnd 모든 프레임 윈도우에 대한 기초 클래스 다중 도큐먼트 어플리케이션에 사용되는 프레임 클래스 다중 도큐먼트 자식 윈도우 보통 툴바에 사용되는 프레임 윈도우  클래스 요약

CHAPTER 14  CPersistentFrame 클래스  CPersistentFrame 클래스는 영구적인 SDI프레임 윈도우를 지원한다.  윈도우 크기  윈도우 위치  최대화된 상태  최소화된 상태 ( Iconized status )  툴바와 상태바의 가능화와 위치  CFrameWnd 클래스와 ActivateFrame() 멤버 함수  MFC SDI 어플리케이션에서 메인 프레임 윈도우는 항상 뷰 윈도우의 부모 윈도우가 된다.  어플리케이션 프레임워크는 사용자가 메인 프레임 윈도우의 크기를 변경함에 따라 차일드 윈도우들도 적절하게 축소, 확대시킨다.  메인 프레임 윈도우의 크기를 제어하는 함수  CFrameWnd::ActivateFrame()

CHAPTER 14  CFrameWnd::ActivateFrame  이 함수는 프레임 윈도우를 보이게(현재 아이콘화되었으면 복원)하고 최상위 Z순위 윈도우 위치에 오게 한다.  또한 사용자 상호작용의 결과로 윈도우를 표시하는 데 사용되거나 기본 윈도우 활성화 행위를 Customize하기 위하여 중복시킬 수 있다.  virtual void ActivateFrame( int nCmdShow = -1 );  Parameters  nCmdShow 프레임 윈도우의 결과 보기 상태. 이 값이 -1이면, 윈도우는 아이콘화가 되어 있는 경우 복원되고(SW_RESTORE), 그렇지 않으면 SW_SHOWNORMAL이 사용된다. 값이 -1이 아니면, nCmdShow의 명시적인 값이 사용된다. CWnd::ShowWindow를 참조

CHAPTER 14  CFrameWnd 클래스와 ActivateFrame() 멤버 함수  어플리케이션 프레임워크는 SDI 메인 프레임 윈도우 생성 과정에서 가상함수 ActivateFrame()을 호출한다.  프레임워크  nCmdShow 파라미터를 사용하여 CWnd::ShowWindow() 함수를 호출  ShowWindow()  프레임 윈도우를 화면에 보이도록 한다.  nCmdShow 파라미터  윈도우를 최대화할 것인지 최소화할 것인지, 아니면 두 경우 모두에 대응할 것인지의 여부를 결정한다.  파생클래스에서 ActivateFrame() 을 Override하면 nCmdShow 파라미터가 CFrameWnd::ActivateFrame() 함수에 전달되기 전에 파라미터 값을 변경 할 수 있다.  CWnd::SetWindowPlacement()  메인 프레임 윈도우의 크기와 위치, 컨트롤 바의 표시상태 설정

최대화면이면, 윈도우는 원래 크기와 위치로 복원된다. CHAPTER 14  CWnd::ShowWindow - 윈도우의 보이기와 상태를 제어한다.  BOOL ShowWindow( int nCmdShow );  Return Value Nonzero if the window was previously visible; 0 if the CWnd was previously hidden.  Parameters  nCmdShow SW_HIDE 이 윈도우를 숨기고 다른 윈도우로 활성화를 전달한다. SW_MINIMIZE 윈도우를 아이콘화하고 윈도우 시스템의 리스트에 최상위 윈도우를 활성화한다. SW_RESTORE 윈도우를 활성화하고 표시한다. 윈도우가 아이콘화나 최대화면이면, 윈도우는 원래 크기와 위치로 복원된다. SW_SHOW 윈도우를 활성화하고 현재 크기와 위치에 표시한다. SW_SHOWMAXIMIZED 윈도우를 활성화하고 최대 화면으로 표시한다. SW_SHOWMINIMIZED 윈도우를 활성화하고 아이콘으로 표시한다. SW_SHOWMINNOACTIVE 윈도우를 아이콘으로 표시한다. 현재 활성화된 윈도우가 활성화된다. SW_SHOWNA 윈도우를 현재 상태로 표시한다. SW_SHOWNOACTIVATE 윈도우를 가장 최근의 크기와 위치로 표시한다. SW_SHOWNORMAL 윈도우를 활성화하고 표시한다. 윈도우가 아이콘화나

CHAPTER 14  CWnd::SetWindowPlacement  윈도우의 표시 상태와 위치를 설정한다.  이 함수는 보통과 아이콘화된 상태의 위치를 설정하는 데 사용된다.  BOOL SetWindowPlacement( const WINDOWPLACEMENT*lpwndpl );  Parameters  lpwndpl 윈도우의 표시 상태와 위치를 기술하는 WINDOWPLACEMENT 구조체에 대한 포인터  CWnd::GetWindowPlacement  윈도우의 표시 상태와 위치 정보로 WINDOWPLACEMENT 구조체를 채운다.  BOOL GetWindowPlacement( WINDOWPLACEMENT* lpwndpl ) const;  lpwndpl 윈도우의 표시 상태(보이기, 숨기기, 최대 화면, 아이콘 화면)와 위치 정보로 채워지는 WINDOWPLACEMENT 구조체에 대한 포인터. 플래그 멤버는 항상 0으로 설정된다.

CHAPTER 14  WINDOWPLACEMENT Structure  The WINDOWPLACEMENT structure contains information about the placement of a window on the screen  typedef struct tagWINDOWPLACEMENT { /* wndpl */ UINT length; UINT flags; UINT showCmd; POINT ptMinPosition; POINT ptMaxPosition; RECT rcNormalPosition; } WINDOWPLACEMENT;

CHAPTER 14  WINDOWPLACEMENT Structure  Members  length Specifies the length, in bytes, of the structure.  flags Specifies flags that control the position of the minimized window and the method by which the window is restored. This member can be one or both of the following flags: WPF_SETMINPOSITION Specifies that the x- and y-positions of the minimized window can be specified. This flag must be specified if the coordinates are set in the ptMinPosition member. WPF_RESTORETOMAXIMIZED Specifies that the restored window will be maximized, regardless of whether it was maximized before it was minimized. This setting is valid only the next time the window is restored. It does not change the default restoration behavior. This flag is valid only when the SW_SHOWMINIMIZED value is specified for the showCmd member.  showCmd Specifies the current show state of the window.

CHAPTER 14  PreCreateWindow() 멤버 함수  윈도우가 화면에 출력되기 전에 윈도우의 특성을 변경시키기 위해 override 한다.  프레임워크는 ActivateFrame()을 호출하기 전에 PreCreateWindow() 함수 를 호출한다.  CREATESTRUCT 구조체를 파라미터로 갖는다.  style 윈도우에 경계선, 스크롤바, 최소화 박스 등을 갖게 할 것인지를 결정  dwExStyle 상태바를 항상 상단에 있게 설정  lpszClass 윈도우의 배경 브러시, 커서, 아이콘을 변경  CWnd::PreCreateWindow  virtual BOOL PreCreateWindow( CREATESTRUCT& cs );  Parameters  cs 생성되는 윈도우를 기술하는 CREATESTRUCT 구조체에 대한 포인터.

CHAPTER 14  윈도우 레지스트리  Registry는 윈도우에 의해서 운영되는 시스템 파일들의 집합체 계층적 데이터베이스로 구성되어 있다.  사용자와 관련된 정보 - USER.DAT  하드웨어와 컴퓨터와 관련된 셋팅 - SYSTEM.DAT  모든 레지스트리 함수들은 파라미터로 헤딩명(heading name)과 엔트리명(entry name)을 갖는다.  TEXTPROC // 프로그램명, Root Key Text formatting // Heading name, Font = Times Roman // Entry name, Value Points = 10 // Entry name, Value  MFC 는 INI 파일에 사용했던 4개의 CWinApp 멤버 함수로 레지스트리에 접근한다.  SetRegistryKey(_T(“Local AppWizard-Generated Applications”)); 이 라인을 제거하면 어플리케이션은 더 이상 레지스트리를 사용하지 않고, 윈도우 디렉토리(c:\Windows)에 INI 파일을 생성하여 사용한다.

CHAPTER 14  윈도우 레지스트리  헤딩명과 엔트리명을 정의하는 레지스트리 함수  GetProfileInt  GetProfileString  WriteProfileInt  WriteProfileString  레지스트리 함수를 사용하려면 어플리케이션 객체 포인터가 필요하므로 글로벌 함수 AfxGetApp()를 이용한다.  AfxGetApp()->WriteProfileString(“Text formatting”, “Font”, “Times Roman”);  AfxGetApp()->WriteProfileString(“Text formatting”, “Point”, 10);

CHAPTER 14  CWinApp::SetRegistryKey  레지스트리 키를 설정하고 프로파일 액세스 멤버(WriteProfileInt, GetProfileString)가 호출될 때, 레지스트리를 사용하기 위하여 MFC에 알려준다.  레지스트리 키는 보통 회사 이름이다.  이 함수는 다른 레지스트리 멤버가 호출되기 전에 호출되어야 한다.  void SetRegistryKey( LPCTSTR lpszRegistryKey );  void SetRegistryKey( UINT nIDRegistryKey );  Parameters  lpszRegistryKey 레지스트리 키  nIDRegistryKey 레지스트리 키를 지정하는 문자열 리소스 ID.

CHAPTER 14  CWinApp::GetProfileInt  레지스트리나 어플리케이션 이름의 .INI 파일에서 정수 값을 얻는다.  GetProfileInt는 프로그래머가 먼저 SetRegistryKey()를 호출하는 경우에만 그 레지스트리를 사용할 수 있다. UINT GetProfileInt( LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault ); Parameters  lpszSection 섹션이름  lpszEntry 엔트리 이름  nDefault 엔트리가 없을 때 리턴되는 값 unsigned value : 0 - 65,535, signed value : -32,768 - 32,767  CWinApp::GetProfileString  레지스트리나 어플리케이션 이름의 .INI 파일에서 문자열 값을 얻는다.  GetProfileString은 프로그래머가 먼저 SetRegistryKey()를 호출하는 경우에만  CString GetProfileString( LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszDefault = NULL);  Parameters  lpszSection 섹션 이름  lpszDefault 엔트리가 없을 때 리턴되는 값. NULL은 빈 문자열이 리턴되었다는 것을 나타낸다.

CHAPTER 14  CWinApp::WriteProfileInt  레지스트리나 어플리케이션 이름의 .INI 파일에 정수 값을 쓴다.  WriteProfileInt는 프로그래머가 먼저 SetRegistryKey()를 호출한 다음에만 레지스트리를 사용할 수 있다.  BOOL WriteProfileInt( LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue );  Parameters  lpszSection 섹션 이름  lpszEntry 엔트리 이름  nValue 쓰기할 정수 값  CWinApp::WriteProfileString  레지스트리나 어플리케이션 이름의 .INI 파일에 문자열 값을 쓴다.  WriteProfileString은 프로그래머가 먼저 SetRegistryKey()를 호출한 다음에만  BOOL WriteProfileString( LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue );  lpszEntry 엔트리 이름  lpszValue 쓰기할 문자열 값. NULL이면 엔트리는 제거된다.

CHAPTER 14  Example CString strSection = "My Section"; CString strStringItem = "My String Item"; CString strIntItem = "My Int Item"; CWinApp* pApp = AfxGetApp(); pApp->WriteProfileString(strSection, strStringItem, "test"); CString strValue; strValue = pApp->GetProfileString(strSection, strStringItem); ASSERT(strValue == "test"); pApp->WriteProfileInt(strSection, strIntItem, 1234); int nValue; nValue = pApp->GetProfileInt(strSection, strIntItem, 0); ASSERT(nValue == 1234);

CHAPTER 14  CString 클래스 사용하기  CString 클래스의 가장 중요한 특징  동적 메모리 할당  CString 객체의 사용 방법 CString strFirstName(“Elvis”); CString strLastName(“Presley”); CString strTruth = strFirstName + “ “ + strLastName; // 연결 strTruth += “ is alive”; ASSERT( strTruth == “Elvis Presley is alive” ); ASSERT( strTruth.Left(5) == strFirstName ); ASSERT( strTruth[2] == ‘v’ ); // 서브 스크립트 연산자  ASSERT  하나의 불 값 매개변수를 계산하여 결과가 FALSE이면, 진단 메시지를 출력하고(MFC의 디버그 버전에서), 프로그램을 중단시키게 된다. char *buf; buf = (char *) calloc( 20, sizeof(char) ); ASSERT( buf != NULL ); strcpy( buf, "Hello, World" ); free( buf );

CHAPTER 14  CString 클래스 사용하기  프로그램은 그 함수들의 문자열 표현 방식에 맞춰 일치시켜야 한다.  CString 클래스가 CString 객체를 문자 포인터로 전환하는 const char* 연산자를 제공한다.  LPCTSTR은 CString 객체 포인터가 아니라 const char*를 표현한 것  AfxMessageBox  CWinApp에서 파생한 클래스의 DoMessageBox 함수를 호출하는 Helper 함수  int AfxMessageBox( LPCTSTR lpszText, UINT nType = MB_OK, UINT nIDHelp = 0 );  int AFXAPI AfxMessageBox( UINT nIDPrompt, UINT nType = MB_OK, UINT nIDHelp = (UINT) -1 );  Parameters  lpszText 메시지의 텍스트  nType 메시지 상자의 모양과 옵션을 기술하는 SDK에 정의되어 있는 하나 또는 그 이상의 메시지의 조합  nIDHelp nIDHelp 도움말 텍스트의 인덱스. 사용되지 않으면 0, 문자열 리소스의 ID의 값이 사용되면 -1.  nIDPrompt 메시지의 텍스트에 대한 문자열 리소스 ID

CHAPTER 14  CWnd::MessageBox  int MessageBox( LPCTSTR lpszText, LPCTSTR lpszCaption = NULL, UINT nType = MB_OK );  Parameters  lpszText 메시지박스에 표시하려는 텍스트를 포함하는 널로 끝나는 문자열에 대한 포인터  lpszCaption 메시지박스의 캡션으로 표시하려는 텍스트를 포함하는 널로 끝나는  nType 플래그의 조합  Message_Box Types  MB_ABORTRETRYIGNORE Abort, Retry, and Ignore.  MB_OK OK.  MB_OKCANCEL OK and Cancel.  MB_RETRYCANCEL Retry and Cancel.  MB_YESNO Yes and No.  MB_YESNOCANCEL Yes, No, and Cancel.  아이콘 플래그  MB_ICONSTOP  MB_ICONQUESTION  MB_ICONEXCLAMATION  MB_ICONINFORMATION

CHAPTER 14  CString 클래스 사용하기  const char* 연산자는 CString 객체를 상수 문자 포인터로 변환해 주는 역할을 한다.  상수 문자 포인터를 CString 객체로 변환하려면?  상수 문자 포인터를 CString 객체로 변환해 주는 생성자는 CDC::TextOut() 등과 같이 CString 참조 파라미터를 갖는 함수와 함께 실행된다.  pDC->TextOut( 0, 0, “Hello, World!”, 13 );  문자열 파라미터를 갖는 함수를 만들 경우 선택할 사항  함수가 문자열의 내용을 변경하지 않고, 이 함수 내의 strcpy() 와 같은 C 런타임 함수를 사용할 경우 const char* 파라미터를 사용하도록 한다.  함수가 문자열의 내용을 변경하지 않고, 이 함수 내에서 CString 멤버 함수를 사용할 경우 const CString& 파라미터를 사용하도록 한다.  함수가 문자열의 내용을 변경하는 경우 CString& 파라미터를 사용하도록 한다.

CHAPTER 14  최대화된 윈도우의 위치  윈도우 우측 상단 코너에 있는 버튼(최대화 버튼)  최대화된 윈도우가 자신의 원래 크기와 위치를 기억하고 있다는 것을 의미.  GetWindowRect - 윈도우의 스크린 좌표를 구한다.  GetWindowPlacement - 현재 윈도우가 최대화/최소화 되어 있는 상태인지, 아니면 두 경우 모두 해당되는 상태인지를 나타내는 플래그와 함께 윈도우가 최대화되지 않은 상태의 좌표를 구해준다.  SetWindowPlacement - 윈도우의 최대화/최소화된 상태, 윈도우의 위치/크기를 설정한다.  CWnd::GetWindowRect - 윈도우 사각형의 좌표를 얻는다.  void GetWindowRect( LPRECT lpRect ) const;  Parameters  lpRect 윈도우 좌표로 채워지는 RECT 구조체나 CRect 객체에 대한 포인터

CHAPTER 14  컨트롤바의 상태와 레지스트리  SaveBarState(), LoadBarStatw()를 제공  정적 데이터 멤버  CPersistentFrame 클래스는 레지스트리 키 이름을 static const char 배열 데이터 멤버에 저장한다.  전역변수를 이용하는 경우는 Encapsulation에 역행하므로 사용하지 않는다.  정적 데이터멤버를 선택하도록 한다.  정적 데이터 멤버는 상수로서 프로그램의 읽기전용 데이터 섹션에 분리하여 넣을 수 있고 동일한 프로그램의 여러 인스턴스에 맵핑될 수 있다.  디폴트 윈도우 사각형  CRect rect( CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 );  CPersistentFrame 클래스는 고정된 크기와 위치를 갖는 디폴트 윈도우 사각 형을 나타내는 rectDefault 를 정적 데이터 멤버로 선언하여 기초 클래스 멤버를 은닉한다.

CHAPTER 14  RECT Structure  The RECT data structure has the following form:  typedef struct tagRECT { LONG left; LONG top; LONG right; LONG bottom; } RECT; The RECT structure defines the coordinates of the upper-left and lower-right corners of a rectangle.  Members  left Specifies the x-coordinate of the upper-left corner of a rectangle.  Top Specifies the y-coordinate of the upper-left corner of a rectangle.  Right Specifies the x-coordinate of the lower-right corner of a rectangle.  Bottom Specifies the y-coordinate of the lower-right corner of a rectangle.

FISHING TIPS Go where the “fish” are. Use the right “bait”. Be patient!

CHAPTER 15 뷰로부터 도큐먼트 분리

CHAPTER 15  도큐먼트 / 뷰 상호작용 함수  도큐먼트 객체 - 데이터를 저장  뷰 객체  도큐먼트 객체의 데이터를 출력하거나 편집할 수 있도록 해준다.  자신과 연결된 하나의 도큐먼트 객체만을 가지고 있다.  SDI 어플리케이션  CDocument 에서 파생된 하나 이상의 뷰 클래스를 갖는다.  CView::GetDocument() 함수  도큐먼트 클래스의 멤버 함수 또는 public 데이터 멤버를 접근할 수 있도록 도큐먼트 포인터를 제공하여 뷰에서 도큐먼트를 조정할 수 있도록 해준다.  사용자가 에디트 컨트롤에 새로운 데이터를 입력할 때 뷰 객체가 메시지를 받는다면 새로운 데이터가 입력됨에 따라 뷰는 도큐먼트 객체에게 기존 데이터를 갱신하도록 알려야 한다.

CHAPTER 15  CView::GetDocument() 함수  CView 에서 파생된 클래스를 생성할 때 CDocument 포인터가 아닌 파생된 클래스의 객체 포인터를 리턴한다.  CMyDoc* GetDocument() { return (CMyDoc*) m_pDocument; }  컴파일러는 뷰 클래스 코드에서 GetDocument() 함수를 호출할 때 CDocument의 객체 포인터가 아닌 파생된 클래스의 객체 포인터를 리턴하는 함수를 사용하므로 리턴된 값을 형변환시킬 필요가 없다.  CView::GetDocument  CDocument* GetDocument( ) const;

CHAPTER 15  CDocument::UpdateAllViews() 함수  도큐먼트 데이터가 변경되면 모든 뷰는 변경된 사실을 통보받아 각각의 뷰가 표시하고 있는 데이터를 갱신할 수 있어야 한다.  UpdateAllViews() 함수가 호출되면 뷰에서는 OnUpdate()가 호출된다.  CDocument::UpdateAllViews  도큐먼트와 관련된 모든 뷰들을 갱신하는데 사용된다.  주어진 파라미터로 각각의 CView::OnUpdate 멤버를 호출한다.  void UpdateAllViews( CView* pSender, LPARAM lHint = 0L, CObject* pHint = NULL );  Parameters  pSender 갱신을 시작하는 CView 객체 NULL이면 모든 뷰가 갱신(update)된다.  lHint 변경한 데이터 내용에 대한 정보를 제공할 수 있는 프로그래머의 지시 내용  pHint lHint에 의해 기술되는 지시 내용에 좀더 세부적인 내용을 포함하고 있는 CObject에서 파생한 클래스

CHAPTER 15  CView::OnUpdate() 함수 데이터를 얻은 다음 변경된 내용을 뷰의데이터 멤버나 컨트롤에 반영하여 갱신한다  뷰의 일부를 무효화하여 OnDraw() 함수에 의해 도큐먼트 데이터를 윈도우에 다시 그리도록 한다.  디폴트 OnUpdate()는 윈도우 사각형 전체를 무효화하여 윈도우 영역 전체를 다시 그린다.  CView::OnUpdate  도큐먼트에 있는 정보가 변경될 때 호출되고, 뷰는 이 새로운 정보를 반영하기 위하여 갱신된다.  전체 뷰 윈도우가 갱신되게 무효화한다.  virtual void OnUpdate( CView* pSender, LPARAM lHint, CObject* pHint );  Parameters  pSender 갱신을 시작하는 뷰. NULL이면 모든 뷰가 갱신(update)된다.  lHint 어떤 도큐먼트 정보가 변경되었는가를 나타내는 프로그래머가 제공하는 코드  pHint 특정 지시 내용(Hint)을 포함하는 프로그래머가 제공하는 객체

CHAPTER 15  CView::OnInitialUpdate() 함수  어플리케이션이 시작될 때, 사용자가 메뉴를 선택했을 때 호출되는 함수  OnInitialUpdate() 함수는 OnUpdate()함수만을 호출한다.  파생된 뷰 클래스에서 OnInitialUpdate() 함수를 override할 경우 기초 클래 스의 OnInitialUpdate() 함수나 파생된 뷰 클래스의 OnUpdate() 함수를 호출해야 한다.  어플리케이션이 실행되는 동안 OnCreate() 함수는 한 번 호출되지만 OnInitialUpdate()는 여러 번 호출될 수 있다.  CView::OnInitialUpdate  virtual void OnInitialUpdate( );

CHAPTER 15  CDocument::OnNewDocument() 함수  도큐먼트가 처음 생성될 때, 사용자가 메뉴를 선택했을 때 프레임워크는 OnNewDocument() 를 호출한다.  Override된 OnNewDocument() 함수에는 CDocument::OnNewDocument() 함수 호출이 포함된다.  CDocument::OnNewDocument  virtual BOOL OnNewDocument( );  간단한 도큐먼트 - 뷰 어플리케이션  도큐먼트가 여러 개의 뷰를 필요로 하지 않고 어플리케이션 프레임워크의 파일 지원을 이용하고자 할 경우 UpdateAllViews() 함수와 OnUpdate() 함수에 대해서는 신경쓰지 않아도 된다.  어플리케이션을 만드는 방법 1. 파생된 도큐먼트 클래스 헤더 파일에 도큐먼트의 데이터 멤버들을 선언한다. 2. 파생된 뷰 클래스에서 가상 함수 OnInitialUpdate()를 override한다. 3. 파생된 뷰 클래스의 윈도우 메시지 핸들러, 명령 메시지 핸들러, OnDraw() 함수는 도큐먼트 객체를 접근하기 위해 GetDocument() 함수를 이용하여 도큐먼트 데이터 멤버를 직접 읽거나 갱신한다.

CHAPTER 15  간단한 도큐먼트-뷰의 상호작용에 대한 이벤트 순서 어플리케이션 시작 CMyDocument 객체가 생성된다. CMyView 객체가 생성된다. 뷰 윈도우가 만들어진다. CMyView::OnCreate() 함수가 호출된다. CMyDocument::OnNewDocument() 함수가 호출된다. CMyView::OnInitialUpdate() 함수가 호출된다. 뷰 객체가 초기화 된다. 뷰 윈도우가 무효화된다. CMyView::OnDraw() 함수가 호출된다. 사용자 데이터 편집 CMyView 클래스 함수들은 CMyDocument 데이터 멤버를 갱신한다. 어플리케이션 종료 CMyView 객체가 소멸된다. CMyDocument 객체가 소멸된다.

CFormView : public CScrollView CHAPTER 15 CFormView : public CScrollView  CFormView 클래스  다이얼로그 박스처럼 여러 가지 컨트롤들을 포함시킬 수 있는 뷰  다른 뷰들과 마찬가지로 동시에 여러 개의 폼 뷰를 생성할 수 없다.  DDX, DDV 함수들을 지원한다.  AppWizard Step6에서 뷰의 기초 클래스로 CFormView를 선택한다.  CFormView 객체  통보 메시지 - 폼 뷰 내의 컨트롤로 부터 받는다.  명령 메시지 - 어플리케이션 프레임워크로 부터 받는다.  통보 메시지나 명령 메시지에 대응하여 필요에 따라 직접 UpdateData() 함수를 호출해야 한다.  CScrollView에서 파생되므로 CDialog 클래스의 멤버 함수들은 지원하지 않는다.  GotoDlgCtrl() 또는 NextDlgCtrl() 과 같은 CDialog 멤버 함수를 사용할 수 있다.  ( (CDialog*) this ) -> GotoDlgCtrl(GetDlgItem(IDC_NAME));  CFormView 포인터를 CDialog 포인터로 형변환하여 사용한다.

CHAPTER 15  TRACE 매크로  Debug 모드로 설정될 때, 전역변수 afxTraceEnabled가 True로 설정될 때 활성화된다.  일반적인 TRACE 문의 형태 int nCount = 9; CString strDesc(“total”); TRACE(“Count = %d, Description = %s\n”, nCount, strDesc);  TRACE 매크로를 사용하여 디버거의 Output 윈도우에 결과를 출력하기 위해서는 MFC Trace Options 다이얼로그의 Enable tracing 이 체크되어야 한다.  afxTraceEnabled  BOOL afxTraceEnabled;  By default, output from the TRACE macro is disabled.

CHAPTER 15  afxDump  CDumpContext afxDump;  전역 객체 afxDump  afxDump는 cout과 유사한 문법을 갖는다.  Overload된 연산자들이 출력 포맷을 제어한다.  TRACE 문과 동일하게 디버거의 Output 윈도우에 출력된다.  afxDump 문의 형태 int nCount = 9; CString strDesc(“total”); #ifdef _DEBUG afxDump << “Count = “ << nCount << “ , Description = “ << strDesc << “\n”; #endif // _DEBUG  #ifdef 매크로명 문장1 #endif  #ifndef 매크로명 #ifdef는 매크로가 정의되어 있으면 문장1을 컴파일 한다. 매크로가 정의되어 있지 않으면 문장1을 컴파일하지 않는다. #ifndef는 매크로가 정의되어 있지않으면 문장1을 컴파일 한다. 매크로가 정의되어 있으면 문장1을 컴파일하지 않는다.

CHAPTER 15  삭제되지 않는 객체의 자동 덤프  Debug 모드인 경우 어플리케이션 프레임워크는 프로그램 종료시에 삭제되지 않는 모든 객체를 덤프한다.  메모리 블록에 디버깅 정보 추가  메모리 블록에 디버깅 정보 추가하는 코드는 CRT(C 런타임) 라이브러리의 Debug 버전에 있다.  CPP파일의 상단부에 다음 라인을 추가하면 #define new DEBUG_NEW CRT 라이브러리는 메모리 할당이 이루어진 위치의 파일명과 라인 번호를 리스트 한다.  AppWizard는 모든 CPP 파일의 상단부에 #define new DEBUG_NEW를 생성한다.

CHAPTER 15  보다 향상된 도큐먼트 - 뷰 상호작용  개발 과정 1. 파생된 도큐먼트 클래스 헤더 파일에 도큐먼트의 데이터 멤버들을 선언한다. 2. ClassWizard를 이용하여 파생된 뷰 클래스에 가상함수 OnUpdate()를 Override 한다. 도큐먼트 데이터가 변경될 때마다 어플리케이션 프레임워크는 OnUpdate() 함수를 호출한다. 3. 모든 명령 메시지들에 대해서 어느 클래스에 맵핑할 것인지를 판단한다. 각 명령 메시지가 도큐먼트 특성적인지, 뷰 특성적인지를 결정한다.  도큐먼트 - Edit메뉴의 Cleaar All 4. 파생된 뷰 클래스의 명령 메시지 핸들러에서 도큐먼트 데이터를 변경할 수 있도록 만든다 이 메시지 핸들러는 리턴하기 전에 CDocument::UpdateAllViews() 함수를 호출해야 한다 5. 파생된 도큐먼트 클래스의 명령 메시지 핸들러에서 도큐먼트 데이터를 변경할 수 있도록 만든다.

CHAPTER 15  향상된 도큐먼트-뷰 상호작용에 대한 이벤트 순서 어플리케이션 시작 CMyDocument 객체가 생성된다. CMyView 객체가 생성된다. 다른 뷰 객체들이 생성된다. 뷰 윈도우가 만들어진다. CMyView::OnCreate() 함수가 호출된다. CMyDocument::OnNewDocument() 함수가 호출된다. CMyView::OnInitialUpdate() 함수가 호출된다. CMyView::OnUpdate() 함수를 호출된다. 뷰를 초기화 한다. 사용자가 뷰 명령을 실행 CMyView 함수가 CMyDocument 데이터 멤버를 갱신한다. CDocument::UpdateAllViews() 함수를 호출한다. 다른 뷰들의 OnUpdate() 함수가 호출된다. 사용자 도큐먼트 명령을 실행 CMyDocument 함수가 데이터 멤버를 갱신한다. CDocument::UpdateAllViews() 함수를 호출한다. CMyView::OnUpdate() 함수가 호출된다. 다른 뷰들의 OnUpdate() 함수가 호출된다. 어플리케이션 종료 뷰 객체가 소멸된다. CMyDocument 객체가 소멸된다.

CHAPTER 15  CObList 콜렉션 클래스  CObList 클래스  CObject에서 파생된 클래스의 객체 포인터에 대한 리스트를 관리한다.  혼합된 포인터들을 포함할 수 있다.  CObject 클래스  진단 덤핑과 직렬화에 대한 이점을 제공해 준다.  CPtrList 클래스  CObject 포인터 대신에 void 포인터를 관리한다.  진단 덤핑과 직렬화에 대한 이점을 제공받지 못한다.  First-In, First-Out(FIFO) 리스트의 CObList 사용하기  CObList를 사용하는 방법  리스트의 맨 끝(tail)에 새로운 요소를 추가하고, 리스트의 맨 앞(head)의 요소를 제거한다.

CHAPTER 15  CObList 순환 - POSITION 변수 GetNext() 멤버 함수를 제공한다.  GetNext() 는 32비트 POSITION 타입의 파라미터를 가지고 있다.  GetNext() 의 파라미터는 POSITION&로 선언된다.  POSITION 변수는 리스트에서 검색된 요소의 위치를 내부적으로 표현한 것  GetNext() 1. POSITION 파라미터에 들어오는 값에 의해 식별되는 리스트 내의 “현재” 객체에 대한 포인터를 리턴해 준다. 2. POSITION 파라미터의 값을 다음 번 리스트 요소를 증가시킨다.  CObList::GetNext  기술한 위치에 근거한 리스트에 있는 다음 노드를 얻는다.  컴파일러는 사용하는 문맥에 따라 GetNext의 2개의 형식 중에서 어느 것을 사용하는가를 판단한다.  CObject*& GetNext( POSITION& rPosition );  CObject* GetNext( POSITION& rPosition ) const;  Parameters  rPosition 현재 노드의 위치

CHAPTER 15  Example  CAction* pAction; POSITION pos = actionList.GetHeadPosition(); while( pos != NULL){ pAction = (CAction*) actionList.GetNext(pos); pAction -> PrintTime(); }  GetNext() 는 항상 POSITION 변수를 증가시키므로 GetNext() 를 이용하여 엔트리를 검색할 수가 없다.  CObList::GetHeadPosition  리스트에 있는 첫번째(Head) 노드의 위치를 리턴한다.  POSITION GetHeadPosition( ) const;  CDocument::DeleteContents  도큐먼트가 갖게 되는 데이터를 제거하기 위하여 호출된다.  도큐먼트가 제거되기 전이나 도큐먼트 객체가 재사용되기 전에 호출된다.  virtual void DeleteContents( );

CHAPTER 15  다음 번 리스트 요소를 얻는 명령 메시지 핸들러 함수  m_actionList - CObList 객체로 CMyView 클래스에 포함된다.  m_position - 현재의 리스트 위치를 저장하는 POSITION 변수  void CMyView::OnCommandNext() { POSITION pos; CAction* pAction; if((pos = m_position) != NULL) { m_actionList.GetNext(pos); // 리스트의 위치를 증가시킨다. if(pos != NULL) { // 리스트의 끝에서 pos는 NULL이 된다. pAction = (CAction*) m_actionList.GetAt(pos); // 엔트리를 검색한다. pAction -> PrintTime(); m_position = pos; } else { AfxMessageBox(“End of list reached”);

CHAPTER 15  CObList::GetAt  기술한 위치에 근거한 노드의 데이터를 리턴한다. 사용하는가를 판단한다.  CObject*& GetAt( POSITION position );  CObject* GetAt( POSITION position ) const;  Parameters  position 원하는 노드의 위치  CTypedPtrList 템플릿 콜렉션 클래스  혼합된 포인터를 콜렉션에 포함되도록 할 경우  CObList 클래스를 이용한다.  한 가지 타입의 객체 포인터만을 포함하는 type-safe 콜렉션이 필요한 경우  MFC 라이브러리 템플릿 콜렉션의 CTypedPtrList 클래스를 이용한다.  CTypedPtrList - 지정된 클래스의 객체 포인터를 리스트로 관리한다.

CHAPTER 15  CTypedPtrList 템플릿 콜렉션 클래스  CAction 포인터를 위한 객체 선언  CTypedPtrList<CObList, CAction*> m_actionList;  기초 클래스로는 CPtrList, CObList 두 가지 만이 사용될 수 있다. ( 두 클래스만이 MFC 라이브러리 포인터 리스트 콜렉션 클래스이다.)  CObject 에서 파생된 클래스의 객체를 저장하려면 CObList나 , CPtrList를 사용해야 한다.  pAction = m_actionList.GetAt(pos); // 형 변환이 필요없다.  typedef CTypedPtrList<CObList, CAction*> CActionList; // 간결한 선언  CActionList m_actionList; 콜렉션의 기초클래스 파라미터 타입, 리턴값의 타입

CHAPTER 15  덤프 컨텍스트(Dump Context)와 콜렉션 클래스  콜렉션의 요소가 되는 객체가 DECLARE_DYNAMIC 과 IMPLEMENT_DYNAMIC 매크로를 사용할 경우 Dump() 함수는 각 객체의 클래스 이름을 출력해준다.  콜렉션 Dump() 함수는 요소가 되는 객체의 클래스 이름과 객체 주소만을 디폴트로 출력한다.  #ifdef _DEBUG afxDump.SetDepth(1); // Specifies deep dump #endif afxDump << actionList;  결과 a CObList at $411832 a CAction at $412632 a CAction at $4126EA with 4 elements time = 1 time = 3 a CAction at $412CD6 a CAction at $41268E time = 0 time = 2  CDumpContext::SetDepth  void SetDepth( int nNewDepth );  Parameters  nNewDepth The new depth value.

CHAPTER 15 ◐ 단순한 문서/보기 응용 프로그램 구조를 위한 클래스 관계 ◑ CWinApp 응용 프로그램 개체 CDocTemplate 문서 템플릿 CDocument 문서 CFrameWnd CView 보기 창 응용 프로그램 프레임 창

CHAPTER 16 도큐먼트 읽기/쓰기 - SDI 어플리케이션

CHAPTER 16  직렬화(Serialization)란?  객체들을 영구화시킴으로써 프로그램이 종료할 때 디스크에 저장(save)하고 프로그램이 재 실행될 때 디스크로부터 복원(restore)하는 일련의 처리과정을 직렬화(serialization)라 한다.  Serialize() 함수는 사용자가 File 메뉴의 Open 아이템이나 Save 아이템을 선택할 때 어플리케이션 프레임워크에 의해 호출된다.  도큐먼트와 결합된 모든 객체는 디스크 파일에 순차적으로 저장되고 읽혀지기 때문에 디스크 파일의 임의적인 주소에서 개별적인 객체를 접근할 수 없다.  직렬화는 데이터베이스 관리 시스템으로 대체될 수가 없다.  순차적 파일과 데이터베이스 사이에 적용할 수 있는 저장 방식  OLE 구조화 저장(Structured Storage)

CHAPTER 16  디스크 파일과 보관소  디스크 파일 - CFile 클래스 객체로 표현  CFile 객체  Win32 함수 CreateFile() 을 통해 얻을 수 있는 이진 파일 핸들을 포함한다.  어플리케이션 프레임워크는 ReadFile(), WriteFile(), SetFilePointer() 등의 Win32 함수 호출시에 파일 핸들을 포함한다.  CArchive 객체  CFile 객체의 데이터를 위한 중간 보관소 역할을 한다.  디스크에 저장되는지, 아니면 디스크로부터 읽혀지는지의 여부를 나타내는 내부 플래그를 가지고 있다.  활성화된 하나의 Archive만이 파일과 연결된다.  Serialize() 함수  CArchive 객체에 데이터를 저장하거나 CArchive 객체로부터 데이터를 읽어들인다.

CHAPTER 16  디스크 파일과 보관소  어플리케이션 프레임워크  CFile 객체와 CArchive 객체를 생성 영구적인 도큐먼트 오브젝트 Serialization CArchive 객체 CFile 객체  Archive - 원본에서 만들어지며, 원본 재현에 충분한 데이터가 포함되어 있는 파일 (이진 포맷으로 저장)

CHAPTER 16  CObject에서 클래스를 파생하기  CObject에서 클래스를 파생하는 것은 CObject 런타임 정보, 동적인 생성과 Serialize 서비스가 요구될 때 클래스의 선언(DECLARE_매크로)과 구현(IMPLEMENT_매크로)에 매크로를 삽입하는 것을 제외하고는 다른 클래스의 파생과 같다.  CObject에서 파생한 클래스에 대한 매크로 매크로 용도 위치 DECLARE_DYNAMIC IMPLEMENT_DYNAMIC DECLARE_DYNCREATE IMPLEMENT_DYNCREATE DECLARE_SERIAL IMPLEMENT_SERIAL 런타임 정보 런타임 정보와 동적인 생성 런타임 정보, 동적인 생성과 Serialize 클래스 선언 클래스 구현  직렬화 클래스 만들기  클래스 선언 - DECLARE_SERIAL 매크로 호출을 포함해야 한다.  클래스 구현 파일 - IMPLEMENT_SERIAL 매크로 호출을 포함해야 한다.

CHAPTER 16  DECLARE_DYNAMIC  런타임 정보를 사용하는 CObject에서 파생한 클래스의 선언의 부분  확장될 때, 이 매크로는 적당한 CRuntimeClass 데이터 정보를 클래스에 추가한다.  이 구조체는 이 정보를 제공하는 데 필요한 부하를 소화하기 위하여 클래스의 static 멤버이다.  매크로는 static CRuntimeClass 구조체를 얻는데 사용되는 GetRuntimeClass() 멤버 함수를 포함한다.  DECLARE_DYNAMIC( class_name )  Parameters  class_name 클래스 이름 (어떤 인용문도 필요 없다).  IMPLEMENT_DYNAMIC  런타임 정보를 사용하는 CObject에서 파생한 클래스의 구현의 부분  확장될 때, 이 매크로는 그 클래스에 대한 static CRuntimeClass 구조체를 초기화한다.  GetRuntimeClass() 멤버 함수를 구현한다.  IMPLEMENT_DYNAMIC( class_name, base_class_name )  class_name 클래스 이름 (어떤 인용문도 필요 없다).  base_class_name 기초 클래스 이름 (어떤 인용문도 필요 없다).

CHAPTER 16  DECLARE_DYNCREATE  동적인 생성을 사용하는 CObject에서 파생한 클래스의 선언의 부분  이 매크로는 DECLARE_DYNAMIC 매크로로 확장되고, 이 클래스의 객체가 동적인 생성을 위해서 MFC에 의해 내부적으로 사용되는 static CreateObject() 멤버 함수를 추가한다.  DECLARE_DYNCREATE( class_name )  Parameters  class_name 클래스 이름 (인용부호는 필요 없다).  IMPLEMENT_DYNCREATE  동적인 생성을 사용하는 CObject에서 파생한 클래스의 구현의 부분  이 매크로는 IMPLEMENT_DYNAMIC 매크로로 확장되고, 이 클래스의 객체가 멤버 함수를 구현한다.  IMPLEMENT_DYNCREATE( class_name, base_class_name )  class_name 클래스 이름 (인용부호는 필요 없다).  base_class_name 기초 클래스 이름 (인용부호는 필요 없다).

CHAPTER 16  DECLARE_SERIAL  시리얼라이즈를 사용하는 CObject에서 파생하는 클래스의 선언의 부분  이 매크로는 DECLARE_DYNAMIC 매크로로 확장되고, 시리얼라이즈를 위하여 MFC에 의해 내부적으로 사용되는 연산자 >> 멤버를 추가한다.  DECLARE_SERIAL( class_name )  Parameters  class_name 클래스 이름 (인용부호는 필요 없다).  IMPLEMENT_SERIAL  시리얼라이즈를 사용하는 CObject에서 파생하는 클래스의 구현의 부분  이 매크로는 IMPLEMENT_DYNAMIC 매크로로 확장되고, 시리얼라이즈를 위하여 MFC에 의해 내부적으로 사용되는 연산자 >> 멤버를 구현한다.  스키마(schema) 파라미터는 동일한 객체의 다른 버전 사이에서 구분하는 데 사용된다.  어플리케이션이 객체의 다른 버전을 지원할 필요가 있으면, 객체에 대한 스키마의 변경이 그 클래스의 Serialize() 멤버에 반영되어야 한다.  IMPLEMENT_SERIAL( class_name, base_class_name, wSchema )  class_name 클래스 이름 (인용부호는 필요 없다).  base_class_name 기초 클래스 이름 (인용부호는 필요 없다).  wSchema 클래스의 "version number" , UINT

CHAPTER 16  DECLARE_DYNAMIC, IMPLEMENT_DYNAMIC  클래스 이름, MFC계층 내에서의 위치와 같은 실행 시간 클래스 정보에 액세스할 수 있게 한다.  DECLARE_SERIAL, IMPLEMENT_SERIAL  기본 수준 매크로의 기능을 모두 포함하고 있다.  객체들이 자신의 데이터를 Archive로 부터 읽거나 쓸 수 있도록 지원한다. - 직렬화(serialization) 레벨2 매크로 DECLARE_SERIAL IMPLEMENT_SERIAL 레벨1 매크로 DECLARE_DYNAMIC IMPLEMENT_DYNAMIC

CHAPTER 16  Serialize() 함수 작성 어플리케이션의 CArchive 객체를 식별하는 CArchive형 참조자  Serialize() 함수 작성  void CStudent::Serialize(CArchive& ar) { TRACE (“Entering CStudent::Serialize\n”); if( ar.IsStoring()) { ar << m_strName << m_nGrade; } else { ar >> m_strName >> m_nGrade;  Serialize() 함수는 CObject 클래스의 가상 함수이므로 리턴값과 파라미터 타입을 CObject 함수 원형과 일치시켜야 한다. 현재 요청된 작업이 저장하기 위한 작업인지, 로드하기 위한 작업인지를 알려준다.

CHAPTER 16  Serialize() 함수 작성  삽입(<<), 추출(>>) 연산자  삽입(<<) 연산자 - 객체 ar 에 순차적으로 데이터를 저장  추출(>>) 연산자 - 객체 ar로부터 순차적으로 데이터를 읽어들인다.  데이터 멤버로 나열형 m_nType이 있을 경우  ar << (int) m_nType;  ar >> (int&) m_nType;  아키이브로 부터 읽기 - 포함된 객체와 포인터  void CStudent::Serialize(CArchive& ar) { if(ar.IsStoring()) { ar << m_strName << m_nGrade; } else { ar >> m_strName >> m_nGrade; m_transcript.Serialize(ar); // CTranscript 클래스는 CObject 로부터 파생되어 } 자신만의 Serialize() 멤버 함수를 가진 클래스 public: CTranscript m_transcript;

CHAPTER 16  아키이브로 부터 읽기 - 포함된 객체와 포인터  void CStudent::Serialize(CArchive& ar) { if(ar.IsStoring()) { ar << m_strName << m_nGrade; } else { m_Transcript = new CTranscript; ar >> m_strName >> m_nGrade; m_Transcript.Serialize(ar); // CTranscript 객체 포인터를 } 데이터 멤버로 포함할 경우 public: CTranscript* m_Transcript;

CHAPTER 16  아키이브로 부터 읽기 - 포함된 객체와 포인터  void CStudent::Serialize(CArchive& ar) { if(ar.IsStoring()) ar << m_strName << m_nGrade << m_pTranscript; else ar >> m_strName >> m_nGrade >> m_pTranscript; }  CTranscript 객체 생성  CTranscript 클래스에 DECLARE_SERIAL, IMPLEMENT_SERIAL 매크로를 사용.  CTranscript 객체가 CArchive 에 저장될 때 매크로에 의해 해당 클래스 이름과 데이터가 함께 저장된다.  읽어들일 때는 클래스 이름으로 읽혀진다.  CStudent 객체가 생성되고 CArchive로부터 데이터가 로드되지 않았다면 포인터는 NULL이다. CArchive 삽입(<<), 추출(>>) 연산자는 CObject를 지원 &m_Transcript;로 할 수는 없다.

CHAPTER 16  직렬화 콜렉션  모든 콜렉션 클래스는 CObject에서 파생되고, DECLARE_SERIAL 매크로로 호출이 포함되기 때문에 콜렉션 클래스를 이용하면 편리하게 직렬화 작업을 할 수 있다.  콜렉션 클래스의 로딩(Loading)  만약 콜렉션이 혼합된 클래스의 객체 포인터를 포함하는 경우  개개의 클래스 이름이 CArchive에 저장되므로 해당 클래스 생성자가 호출되어 객체들이 생성된다.  만약 도큐먼트 등과 같은 컨테이너 객체가 포함된 객체로 콜렉션을 가지고 있으면  로드된 데이터는 기존 콜렉션에 추가된다.  로딩하기 전에 콜렉션을 비워야 할 경우  도큐먼트의 가상함수 DeleteContents()에서 수행된다.  CObject 포인터의 콜렉션이 CArchive로부터 로드될 때  객체의 클래스가 정의된다.  객체를 위해 힙 메모리 영역이 할당된다.  객체의 데이터가 할당된 메모리 영역으로 로드된다.  새로운 객체의 포인터가 콜렉션에 저장된다.

CHAPTER 16  Serialize() 함수와 어플리케이션 프레임워크  도큐먼트 객체가 CArchive 추출 연산자와 함께 사용되지 않고, 콜렉션에 포함되지 않았다면 DECLARE_SERIAL, IMPLEMENT_SERIAL 매크로가 필요 없다.(어플리케이션 프레임워크가 도큐먼트의 Serialize() 함수를 직접 호출한다.)  SDI 어플리케이션  어플리케이션 객체  CMyApp theApp; // 전역 객체  548쪽 참조

CHAPTER 16  빈 도큐먼트(Empty Document) 생성하기 - CWinApp::OnFileNew()  어플리케이션 클래스의 InitInstance() 함수  AddDocTemplate() 멤버 함수를 호출 OnFileNew()를 호출  OnFileNew() - 내부적으로 연결된 클래스의 이름들을 정렬한다.  다음의 과정을 수행 1. 도큐먼트 객체를 구성 2. CMainFrame 클래스의 객체를 구성, 메인 프레임 윈도우를 생성 3. 뷰 객체를 구성, 뷰 윈도우를 생성 4. 도큐먼트, 메인 프레임, 뷰 객체 간을 연결 5. 도큐먼트 오브젝트에 대해 CDocument::OnNewDocument 호출 DeleteContents() 호출 6. CView::OnInitialUpdate() 멤버 함수 호출 7. 메인 프레임의 가상 함수 CFrameWnd::ActivateFrame()을 호출  OnFileNew()는 항상 도큐먼트 내용을 지우기 위해 DeleteContents()를 호출

CHAPTER 16  도큐먼트 클래스의 OnNewDocument() 함수  사용자가 File 메뉴의 New, Open 메뉴 아이템을 선택할 때마다 도큐먼트를 초기화하기 위해 OnNewDocument()함수를 Override 해야 한다.  실제로 SDI 어플리케이션은 기존 도큐먼트 객체를 재사용한다.  OnNewDocument()이 제대로 수행되지 않으면 False 를 리턴한다.  CDocument::GetFile  CFile 객체에 대한 포인터를 얻는데 사용된다.  리턴된 CFile 객체는 반드시 도큐먼트와 관련되지 않는다. 단순한 Helper 함수이다.  virtual CFile* GetFile( LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError );  Parameters  lpszFileName 파일 이름  nOpenFlags 파일 열기 플래그  pError 열기 파일 처리의 상태를 얻는 CFileException에 대한 포인터

CHAPTER 16  도큐먼트 클래스의 DeleteContents() 함수  SDI 어플리케이션의 경우 DeleteContents() 함수는 현재까지 편집중인 도큐먼트 내용을 삭제할 때 사용한다.  File Save 와 File Save As를 직렬화 코드에 연결하기  File 메뉴의 New, Open  CWinApp::OnFileNew(), CWinApp::OnFileOpen() 에 맵핑  File 메뉴의 Save, Save As  CDocument::OnFileSave(), CDocument::OnFileSaveAs() 에 맵핑

CObject 클래스  직렬화(Serialization)  BOOL IsSerializable() const; 용도 설명 멤버 함수 선언된 헤더 DevStudio\Vc\mfc\include\<afx.h> 객체의 계열화(Serialization), 런타임 클래스 정보, 디버깅 진단 등. CObject 클래스는 MFC의 뿌리에 해당하는 기본적인 클래스 (거의 모든 MFC 클래스들이 CObject에서 파생된다.) IsSerializable(), Serialize(), GetRuntimeClass(), AssertValid(), Dump()  직렬화(Serialization)  BOOL IsSerializable() const; : 객체를 직렬화할 수 있는지 여부를 조사한다. TRUE, FALSE를 리턴.  CAge a(21); ASSERT(a.IsSerializable());

CObject 클래스  직렬화(Serialization)  virtual void Serialize(CArchive& ar); : CArchive(기록 저장 클래스) 안에 있는 객체의 내용을 읽거나 쓸 수 있다.  void CAge::Serialize(CArchive& ar) { CObject::Serialize(Ar); if(ar.IsStoring()) // CArchive에 저장을 원하면 ar << m_years; // m_years를 ar에 저장한다. else // 읽어들이려면 ar >> m_years; // m_years를 ar에서 읽어들인다. }

CObject 클래스  런 타임 클래스 정보(Run-time class information)  virtual CRuntimeClass* GetRuntimeClass() const; 현재 클래스에 대한 정보(CRuntimeClass 구조체)를 얻어낸다. 예) CAge a(21); CRuntimeClass* prt = a.GetRuntimeClass(); ASSERT (strcmp (prt->m_lpszClassName, “CAge”)==0);  BOOL IsKindOf(const CRuntimeClass* pClass) const; 객체가 파생한 인스턴스인가, CObject에서 파생한 클래스인가를 판단한다.  Parameter pClass 기술한 클래스에 대한 CRuntimeClass에 대한 포인터 ASSERT (a.IsKindOf(RUNTIME_CLASS(CAge))); ASSERT (a.IsKindOf(RUNTIME_CLASS(CObject)));

CObject 클래스  출력 진단(Object Diagnostic output) : 이 두 가지 함수들은 주로 디버깅 할 때 많이 쓰인다. 현재의 작업이 제대로 수행되는지 의심스러울 때 이러한 함수들을 사용한다.  virtual void AssertValid() const; : 현재 객체가 제대로 동작하는지 확인 작업을 수행. 디버깅할 때 많이 사용되고, const형이기 때문에 테스트 도중에 객체의 상태를 변화시킬 수 없다.  void CAge::AssertValid() const  void CAge:Dump(CDumpContext &dc) const { { CObject::AssertValid(); CObject::Dump(dc); ASSERT(m_years > 0); dc << “Age = “ << m_years; ASSERT(m_years > 105); } }  virtual void Dump(CDumpContext &dc) const;  CWinApp 객체에 대한 진단 함수  지정된 객체의 내용을 CDumpContext 객체에 덤프한다.

CHAPTER 17 도큐먼트 읽기/쓰기 - MDI 어플리케이션

CHAPTER 17  MDI 어플리케이션  Developer Studio는 소스 코드 파일을 출력하는 윈도우에 대해  전형적인 MDI 어플리케이션, MFC 스타일  어플리케이션은 한 개의 메뉴와 한 개의 툴바를 가지고 있고 차일드 윈도우로 모든 명령이 전달된다.  메인 윈도우의 타이틀 바는 활성화된 차일드 윈도우의 도큐먼트 파일 이름을 반영한다.  차일드 윈도우가 없는 상태에서 어플리케이션을 시작되게 하려면 어플리케이션 클래스 파일에 있는 ProcessShellCommand() 의 파라미터를 변경하면 된다.

CHAPTER 17  MDI 어플리케이션 객체  MDI 나 SDI 어플리케이션은 동일하게 CWinAPP에서 파생된 어플리케이션 객체에 override된 InitInstance() 멤버 함수를 가지고 있다.  InitInstance() 함수의 AddDocTemplate() 를 호출하는 부분이 MDI와 SDI가 서로 다르다.  MDI 도큐먼트 템플릿 클래스  InitInstance() 안의 MDI 템플릿 구성 CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_EX17ATYPE, // nIDResource RUNTIME_CLASS(CStudentDoc), // Doc Class RUNTIME_CLASS(CChildFrame), // MDI 차일드 프레임 RUNTIME_CLASS(CStudentView)); // View class AddDocTemplate(pDocTemplate);

CHAPTER 17  RUNTIME_CLASS  RUNTIME_CLASS( class_name )  Parameters  Example // example for RUNTIME_CLASS CRuntimeClass* prt = RUNTIME_CLASS( CAge ); ASSERT( lstrcmp( prt->m_lpszClassName, "CAge" ) == 0 );  CObject::GetRuntimeClass  호출한 객체의 클래스에 해당되는 CRuntimeClass 구조를 반환한다.  virtual CRuntimeClass* GetRuntimeClass( ) const; // example for CObject::GetRuntimeClass CAge a(21); CRuntimeClass* prt = a.GetRuntimeClass(); ASSERT( strcmp( prt->m_lpszClassName, "CAge" ) == 0 );

CHAPTER 17  MDI 도큐먼트 템플릿 클래스  MDI 어플리케이션  다중 도큐먼트 타입을 사용할 수 있고 도큐먼트 객체가 하나 이상 존재할 수 있다.  AddDocTemplate() 함수  각 도큐먼트 객체와 뷰 객체가 연결된 다중 차일드 윈도우를 MDI 어플리케이션에 지원한다.  도큐먼트 템플릿 객체  어플리케이션이 실행중에 생성된 도큐먼트 객체의 리스트를 관리한다.  도큐먼트 객체 리스트를 검색하기 위해서 CMultiDocTemplate::GetFirstDocPosition() 과 GetNextDoc()를 사용한다.  도큐먼트 클래스에서 해당 템플릿을 얻기 위해서 CDocument::GetDocTemplate() 를 사용한다.

CHAPTER 17  CDocTemplate::GetFirstDocPosition  템플릿에 관련된 모든 도큐먼트를 반복하기 위하여 GetNextDoc와 같이 사용된다.  virtual POSITION GetFirstDocPosition( ) const = 0;  CDocTemplate::GetNextDoc  템플릿에 관련된 다음 도큐먼트를 얻기 위하여 사용된다.  GetFirstDocPosition을 처음 호출한 다음에만 사용되어야 한다.  virtual CDocument* GetNextDoc( POSITION& rPos ) const = 0;  Parameters  rPos 현재 참조 도큐먼트 위치

CHAPTER 17  MDI 프레임 윈도우와 MDI 차일드 윈도우  SDI 어플리케이션  하나의 프레임 윈도우 클래스와 하나의 프레임 윈도우 객체만을 가지고 있다.  MDI 어플리케이션  두 개의 프레임 윈도우 클래스와 다수의 프레임 윈도우 객체를 가진다. 메뉴와 컨트롤 바 AppWizard에 의해 생성된 클래스 객체 수 기초 클래스 뷰 포함 여부 CMDIFrameWnd CMDIChildWnd CMainFrame CChildFrame 1개 차일드 윈도우당 Yes No 객체 생성 어플리케이션 클래스에서 InitInstance 함수 프레임워크에 의해 새로운 차일드 윈도우가 열렸을 때

CHAPTER 17  프레임 윈도우 클래스들  SDI 프레임 윈도우  클래스 CFrameWnd로부터 파생된 것이다.  Document/View 응용 프로그램에서 프레임 윈도우는 현재의 Document에 대한 View를 갖게 된다.  MDI 프레임 윈도우  클래스 CMDIFrameWnd로부터 파생된 것이다.  CMDIFrameWnd 객체는 CMDIChildWnd 프레임 윈도우 객체들에 대한 포인터들을 유지하고 있다.  실제로 Document의 View를 담고 있는 것은 차일드 프레임 윈도우이다.

CHAPTER 17  MDI 프레임 윈도우와 뷰 윈도우의 관계 Title bar Menu bar Toolbar Window main frame window MDI child frame window View windows Status window

CHAPTER 17  MDI 어플리케이션  CMainFrame* pMainFrame = new CMainFrame; if( !pMainFrame -> LoadFrame(IDR_MAINFRAME)) return FALSE; // 차일드 프레임을 생성하기 위해 ProcessShellCommand()를 호출한다. m_pMainWnd = pMainFrame; pMainFrame -> ShowWindow(m_nCmdShow); pMainFrame -> UpdateWindow();  MDI InitInstance() 함수는 메인 프레임 윈도우의 객체 포인터를 CWinApp 클래스의 데이터 멤버 m_pMainWnd에 설정한다.  메인 프레임 윈도우의 객체 포인터를 얻어야 할 경우 전역 함수 AfxGetApp()를 통해 m_pMainWnd에 접근하면 된다.

CHAPTER 17  메인프레임과 도큐먼트 템플릿 리소스  MDI 어플리케이션은 IDR_MAINFRAME과 IDR_EX17ATYPE으로 정의된 문자열 리소스와 메뉴 리소스를 가지고 있다. IDR_MAINFRAME “ex17a” // 어플리케이션 윈도우 캡션 IDR_MYDOCTYPE “\n” // (사용되지 않는다). “Ex17a\n” // 디폴트 도큐먼트 이름의 루트 부분 “Ex17a\n” // 도큐먼트 타입 이름 “Ex17a File (*.17a)\n” // 도큐먼트 타입 설명과 필터 (파일 열기 다이얼로그의 파일 필터) “.17a\n” // 도큐먼트 타입에 대한 확장자 (파일 열기 다이얼로그의 파일 확장자) “Ex17a.Document\n” // 레지스트리 파일 타입 ID “Ex17a Document” // 레지스트리 파일 타입 설명

CHAPTER 17  OnFileNew (p590)  ID_FILE_NEW 커맨드에 대한 기본 핸들러  ID_FILE_NEW는 File New 메뉴 커맨드에 대한 AppWizard가 발생한 커맨드이다.  OnFileNew()는 자신의 도큐먼트 템플릿의 OpenDocumentFile 멤버에 NULL을 전달하여 빈 문서를 생성한다.  단 하나의 도큐먼트 템플릿이 등록되었으면, 등록된 타입의 새로운 도큐먼트가 생성된다.  하나 이상이 도큐먼트 템플릿이 등록되었으면, 등록된 도큐먼트 타입들을 표시하는 다이얼로그박스가 표시된다.  사용자가 도큐먼트 타입을 선택하면, 선택한 타입의 새로운 도큐먼트가 생성된다.  ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)  이 함수는 호출되는 어플리케이션의 메시지맵에 있어야 한다.  public afx_msg void OnFileNew();

CHAPTER 17  OnFileOpen (p590)  ID_FILE_OPEN 커맨드에 대한 기본 핸들러  ID_FILE_OPEN은 File Open 메뉴 커맨드에 대한 AppWizard가 발생한 커맨드이다.  OnFileOpen()은 DoPromptFileName()을 호출하여 사용자에게 열 파일을 지정하도록 한 다음에, OpenDocumentFile()을 호출하여 파일을 연다.  ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)  이 함수는 호출되는 어플리케이션의 메시지맵에 있어야 한다.  public afx_msg void OnFileOpen();

CHAPTER 17  DragAcceptFile  윈도우가 파일관리자에게 드래그되는 파일을 받는가를 나타내기 위하여 호출한다.  받는 것이 가능하면, 윈도우는 WM_DROPFILE 메시지를 받는다.  void DragAcceptFiles ( BOOL bAccept = TRUE);  Parameter bAccept 윈도우가 드래그 파일을 받으면 TRUE, 그렇지 않으면 FALSE  EnableShellOpen  RegisterShellFileTypes와 관련되어 어플리케이션이 관련 파일을 열거나 인쇄하기 위하여 윈도우 파일 관리자에 의해 동작되게 한다.  EnableShellOpen은 프로그램을 동작시킬 때 파일 관리자에게 DDE링크에 사용된 어플리케이션에 대한 단 하나뿐인 식별자를 만든다.  protected void EnableShellOpen();

CHAPTER 17  RegisterShellFileTypes  모든 어플리케이션의 문서에 대해 OS에 파일 타입을 등록한다.  CWinApp에서 파생한 InitInstance 멤버에서 호출된다.  모든 도큐먼트 템플릿이 어플리케이션에 추가된 다음에 호출되어야 한다.  protected void RegisterShellFileTypes (BOOL bWin95 = FALSE);  Parameter bWin95 윈도우 95에서 동작하면 TRUE, 그렇지 않으면 FALSE  ProcessShellCommand  커맨드라인을 통해 전달된 Shell Command(파일열기/인쇄)를 처리한다.  public BOOL ProcessShellCommand (CCommandLineInfo& rCmdInfo); rCmdInfo 커맨드에 기술한 CCommandLineInfo 객체에 대한 참조

CHAPTER 17  CCommandLineInfo::CCommandLineInfo  CCommandLineInfo( );  Remarks This constructor creates a CCommandLineInfo object with default values. The default is to show the splash screen (m_bShowSplash = TRUE) and to execute the New command on the File menu (m_nShellCommand = NewFile). The application framework calls ParseParam to fill data members of this object.

CHAPTER 18 프린트와 프린트 미리보기

CHAPTER 18  대화형 Print Page 선택  프로그램은 사용자의 페이지 선택에 따라 인쇄할 정보를 계산하고 나서 선택된 페이지를 프린트한다.  1000명의 학생 이름을 포함한 리스트에서 학생 리포트 5페이지를 인쇄하려면?  한 페이지가 50라인이라면 5페이지에는 201에서 250까지의 레코드가 포함된다.  MFC 리스트 콜렉션 클래스를 이용하면 201번째 학생 레코드에 직접 접근 하지 못해 프린트를 시작하기 전에 처음 레코드부터 200번째 레코드 요소 까지 검색하게 된다.  CObArray 클래스를 이용하면 학생 레코드의 201번째로 직접 접근할 수 있다.  학생 데이터가 여러 라인의 텍스트 바이오 그래픽 필드를 포함한다면  전체 파일을 검색하여 페이지 브레이크(page break)를 결정해야 한다.

CHAPTER 18  화면 페이지와 인쇄 페이지 비교  full-size 용지에 인쇄되는 출력물을 프로그램에서 읽으려면 화면보다 큰 출력 윈도우가 필요하다.  이 경우에는 CScrollView 클래스와 같은 스크롤링 뷰가 이상적이다.  프린트 미리보기  프린트 미리보기는 윈도우의 기능이 아닌 MFC 라이브러리 기능이다.  프린트 미리보기 프로그램은 각각의 문자를 검사하여 프린트 디바이스 컨텍스트를 토대로 문자 위치를 결정하고 적당한 폰트를 선택한 후 프린트 미리보기 윈도우의 적당한 위치에 문자를 출력한다.  프린터를 위한 프로그램  프린트와 프린트 미리보기의 대부분 작업은 어플리케이션 프레임워크가 한다.  함수 호출 순서, 오버라이드되는 함수를 숙지해야 한다.

CHAPTER 18  프린터 디바이스 컨텍스트와 CView::OnDraw() 함수  프로그램은 데이터를 인쇄할 때 CDC 클래스의 디바이스 컨텍스트 객체를 사용한다.  어플리케이션 프레임워크  디바이스 컨텍스트 객체를 생성하여 뷰의 OnDraw() 함수에 파라미터로 전달한다  화면에 출력중이면 OnPaint() 함수는 디스플레이 디바이스 컨텍스트 (화면 DC)를 OnDraw() 함수에 파라미터로 전달한다.  인쇄중이면 CView 가상 함수 OnPaint()는 프린터 디바이스 컨텍스트 (프린터 DC)를  OnPaint() 함수는 한 페이지를 프린트할 때마다 한번 호출한다.  프린터 미리보기 모드에서 OnDraw() 함수의 파라미터는 CPreviewDC 객체의 포인터가 되며 프린트 작업이나 미리보기 작업에 상관없이 OnDraw()와 OnPrint() 함수는 동일한 일을 수행한다.

CHAPTER 18  CView::OnPrint() 함수  Base class의 OnPrint() 함수는 OnDraw() 를 호출  맵핑 모드는 OnPrint()가 호출되기 전에 설정해야 한다.  타이틀 페이지, 머리글, 바닥글 등을 인쇄하기 위해 OnPrint() 를 Override 한다.  OnPrint() 함수의 파리미터  프린터 디바이스 컨텍스트 포인터  페이지 디멘션, 현재 페이지 번호, 최대 페이지 수 등을 포함하는 프린트 정보 객체(CPrintInfo)포인터  어플리케이션 프레임워크는 CPrintInfo 구조체에 있는 현재 페이지 수를 사용하여 인쇄될 각 페이지에 대해 단 한 번만 OnPrint() 함수를 호출한다.

CHAPTER 18  CView::OnPrepareDC() 함수  뷰 클래스가 CView에서 직접 파생되었다면 OnPrepareDC()를 Override 해야 한다.  뷰가 CScrollView에서 파생된 경우에는 이미 Override된 상태가 된다.  맵핑 모드는 뷰에 그려지기 전이나 프린터로 인쇄되기 전에 설정된다.  두 번째 파라미터는 CPrintInfo 구조체 포인터이다.  이 포인터는 인쇄되기 전에 OnPrepareDC() 함수가 호출되었을 때만 유효하다.  CDC 멤버 함수 IsPrinting()을 호출하여 유효성 여부를 검사한다.  CView::OnPrepareDC  프린트 컨텍스트를 초기화하기 위하여 OnDraw와 OnPrint 앞에 호출된다.  프린트하는 페이지는 pInfo 변수의 m_nCurPage 멤버에 의해 주어진다.  OnPrint가 호출될 때, 디바이스 컨텍스트는 이미 OnPrepareDC를 호출하여 초기화되었다.  virtual void OnPrepareDC( CDC* pDC, CPrintInfo* pInfo = NULL );  Parameters  pDC 프린트 컨텍스트  pInfo 프린트 작업에 대한 정보를 포함한다.

CHAPTER 18  CView::OnDraw  뷰의 이미지가 그려질 필요가 있을 때, 어플리케이션 프레임워크에 의해 호출  virtual void OnDraw( CDC* pDC ) = 0;  Parameters  pDC 디바이스 컨텍스트에 대한 포인터  CView::OnPrint  한 페이지의 정보를 프린트하기 위하여 인쇄나 미리 보기 중에 호출된다.  프린트하는 페이지는 pInfo 변수의 m_nCurPage 멤버에 의해 주어진다.  OnPrint()가 호출될 때, 디바이스 컨텍스트는 이미 OnPrepareDC를 호출하여 초기화되었다.  virtual void OnPrint( CDC* pDC, CPrintInfo* pInfo );  pDC 프린터 디바이스 컨텍스트에 대한 포인터  pInfo 현재 프린트 작업에 대한 정보를 포함하는 CPrintInfo 구조체에 대한 포인터

CHAPTER 18  프린트 작업의 시작과 끝  프린트 작업이 시작되면 어플리케이션 프레임워크는 CView의 함수 OnPreparePrinting()과 OnBeginPrinting()을 호출한다.  OnPreparePrinting()  인쇄 다이얼로그가 출력되기 전에 호출된다.  OnBeginPrinting()  인쇄 다이얼로그가 출력된 후 호출된다.  OnEndPrinting()  마지막 페이지가 프린트된 후 프린트 작업을 종료할 때 호출된다. 함 수 작 업 OnPreparePrinting OnBeginPrinting OnPrepareDC(각 페이지마다) OnPrint (각 페이지마다) OnEndPrinting 최소/최대 페이지 수 설정 GDI 객체 생성 맵핑 모드 설정/더 출력할 페이지가 있는지 검사 프린트 지정 결과를 수행하고 나서 OnDraw() 호출 GDI 객체 제거

CHAPTER 18  CArray  template <class TYPE, class ARG_TYPE> class CArray : public CObject  Parameters  TYPE 배열에 저장된 객체의 타입을 기술하는 템플릿 파라미터 ( CArray에 의해 리턴되는 파라미터이다. )  ARG_TYPE 배열에 저장된 접근 객체로 사용되는 전달인자 타입을 기술하는 템플릿 파라미터 ( CArray로 전달되는 파라미터 )  #include <afxtempl.h>  CArray::RemoveAll  배열의 모든 요소를 제거한다.  배열에 할당된 메모리는 FreeExtra()를 호출하거나 그 객체가 파괴될 때까지 해제되지 않는다.  void RemoveAll( );

CHAPTER 18  CArray::GetUpperBound  CObArray::GetUpperBound  GetSize에 의해 리턴되는 요소의 전체 수보다 1이 작은 마지막 요소의 인덱스 배열의 상한 인덱스를 리턴한다.  int GetUpperBound( ) const;  Return value 배열의 상한 인덱스(m_bSize - 1)  The following table shows other member functions that are similar to CObArray::GetUpperBound. Class Member Function CByteArray int GetUpperBound( ) const; CDWordArray int GetUpperBound( ) const; CPtrArray int GetUpperBound( ) const; CStringArray int GetUpperBound( ) const; CUIntArray int GetUpperBound( ) const; CWordArray int GetUpperBound( ) const;

CHAPTER 18  CArray::GetSize  CObArray::GetSize  배열의 크기를 리턴한다.  배열의 크기는 가장 큰 인덱스보다 1이 더 크다.  int GetSize( ) const;  CArray::SetSize  CObArray::SetSize  필요하면 메모리를 할당하거나, 배열의 요소의 수를 설정한다.  nGrowBy 파라미터는 배열이 증가될 필요가 있으면 생성되는 최소 요소의 수를 기술한다.  void SetSize( int nNewSize, int nGrowBy = -1 ); throw( CMemoryException );  Parameters  nNewSize 새로운 배열 크기(number of elements).  nGrowBy 생성하는 보조 요소의 수 (minimum number of element)

CHAPTER 18  Example  See CObList::CObList for a listing of the CAge class used in all collection examples. // example for CObArray::GetUpperBound CObArray array; array.Add( new CAge( 21 ) ); // Element 0 array.Add( new CAge( 40 ) ); // Element 1 ASSERT( array.GetUpperBound() == 1 ); // Largest index

CHAPTER 18  CPrintInfo::SetMaxPage  void SetMaxPage( UINT nMaxPage );  Parameters  nMaxPage Number of the last page of the document.  CPrintInfo::SetMinPage  void SetMinPage( UINT nMinPage );  nMinPage Number of the first page of the document.  CPrintInfo::GetMaxPage  UINT GetMaxPage( ) const;  Return Value  The number of the last page of the document.  CPrintInfo::GetMinPage  UINT GetMinPage( ) const;  The number of the first page of the document.

CHAPTER 18  템플릿 콜렉션 클래스 - CArray 클래스  템플릿 클래스는 콜렉션 안의 모든 요소를 직렬화하기 위해 전역 함수 SerializeElements()를 사용한다.  디폴트 SerializeElements() 함수는 CArchive 객체에서 각 요소의 bitwise 복사를 수행한다.  배열의 요소가 되는 클래스가 포인터 또는 다른 복합체를 포함하면 SerializeElements() 함수를 직접 작성할 필요가 있다.  컴파일러는 템플릿 내부에서 SerializeElements() 함수를 대체하여 사용한다.  이 작업은 컴파일러가 템플릿 클래스 선언을 인식하기 전에 SerializeElements() 함수 원형을 인식해야 작동한다.  이 함수를 사각형 배열로 작성하면 다음과 같다. void AFXAPI SerializeElements( CArchive& ar, CRect* pNewRects, int nCount) { for(int i=0; i < nCount; i++, pNewRects++){ if(ar.IsStoring()){ ar << *pNewRects; } else{ ar >> *pNewRects;

CHAPTER 18  RAND_MAX  #include <stdlib.h>  Remarks  The constant RAND_MAX is the maximum value that can be returned by the rand function. RAND_MAX is defined as the value 0x7fff.  rand  Generates a pseudorandom number.  int rand( void ); Routine Required Header Compatibility rand <stdlib.h> ANSI, Win 95, Win NT  Return Value  rand returns a pseudorandom number, as described above. There is no error return.  The rand function returns a pseudorandom integer in the range 0 to RAND_MAX. Use the srand function to seed the pseudorandom-number generator before calling rand.

CHAPTER 18  srand  Set a random starting point.  void srand( unsigned int seed ); Routine Required Header Compatibility srand <stdlib.h> ANSI, Win 95, Win NT  Return Value  None  Parameters  seed Seed for random-number generation.  Remarks  The srand function sets the starting point for generating a series of pseudorandom integers. To reinitialize the generator, use 1 as the seed argument. Any other value for seed sets the generator to a random starting point. rand retrieves the pseudorandom numbers that are generated. Calling rand before any call to srand generates the same sequence as calling srand with seed passed as 1.

CHAPTER 18  Example /* RAND.C: This program seeds the random-number generator * with the time, then displays 10 random integers. */ #include <stdlib.h> #include <stdio.h> #include <time.h> void main( void ) { int i; /* Seed the random-number generator with current time so that * the numbers will be different every time we run. */ srand( (unsigned)time( NULL ) ); /* Display 10 numbers. */ for( i = 0; i < 10;i++ ) printf( " %6d\n", rand() ); } Output 6929 8026 21987 30734 20587 6699 22034 25051 7988 10104

CHAPTER 18  CDC::GetTextExtent  현재 폰트를 사용하여 기술한 문자열의 높이와 폭(논리 단위)을 계산한다.  CSize GetTextExtent( LPCTSTR lpszString, int nCount ) const;  CSize GetTextExtent( const CString& str ) const;  Return Value 문자열의 크기(논리단위)를 포함하는 CSize object.  Parameters  lpszString 계산되는 크기에 대한 텍스트 문자열에 대한 포인터  nCount lpszString 파라미터에 의해 가리키는 문자열의 길이(바이트)  str 계산되는 크기에 대한 텍스트 문자열을 포함하는 CString 객체에 대한 참조

CHAPTER 19 분할 윈도우와 다중 뷰

CHAPTER 19  분할 윈도우와 다중 뷰(Splitter Windows and Multiple Views)  윈도우용 워드프로세서를 사용해 보면 하나의 문서 내용이 여러 부분으로 동시에 오픈 되는 것을 보게 되는데, 이 두 개의 윈도우는 모두 일반 뷰를 가질 수도 있고 하나는 페이지 레이아웃 뷰, 다른 하나는 아웃라인 뷰를 가질 수도 있다.  어플리케이션 프레임워크는 다중 뷰를 출력하기 위해 분할 윈도우(splitter window)나 다중 MDI 차일드 윈도우를 사용한다.  분할 윈도우  분할 윈도우는 패인(pane)에 여러 뷰를 갖는 프레임 윈도우의 특별한 형태이다.  분할 윈도우는 CSplitterWnd 클래스의 객체로 표현된다.  CSplitterWnd 객체는 프레임 윈도우(CFrameWnd 나 CMDIChildWnd)의 클라이언트 영역을 차지하는 윈도우가 된다.  뷰 윈도우는 분할 윈도우의 패인 영역을 차지한다.  분할 윈도우는 명령 전달 체계에 관여하지 않으며, 활성화된 뷰 윈도우는 뷰의 프레임 윈도우에 직접 연결된다.

CHAPTER 19  뷰 옵션들  분할 윈도우를 갖는 SDI 어플리케이션, 하나의 뷰 클래스  각 분할 윈도우 패인은 다른 도큐먼트 부분을 스크롤 되게 할 수 있다.  EX19A  분할 윈도우를 갖는 SDI 어플리케이션, 다수의 뷰 클래스  프로그래머는 패인의 개수와 뷰의 순서를 결정하고 사용자는 프로그램 실행시에 패인 크기를 변경할 수 있다.  EX19B  분할 윈도우를 갖지 않는 SDI 어플리케이션, 다수의 뷰 클래스  사용자는 메뉴의 선택에 따라 뷰 클래스를 전환한다.  EX19C  분할 윈도우를 갖지 않는 MDI 어플리케이션, 하나의 뷰 클래스  사용자가 윈도우 메뉴의 New Window 메뉴 아이템을 선택하면 이미 오픈된 도큐먼트에 대한 새로운 차일드 윈도우를 오픈하게 한다.  분할 윈도우를 갖지 않는 MDI 어플리케이션, 다수의 뷰 클래스  표준 MDI 어플리케이션을 약간 변경하면 다수의 뷰를 사용할 수 있다.  EX19D  분할 차일드 윈도우를 갖는 MDI 어플리케이션  온라인 설명서에 상세히 설명된다.

CHAPTER 19  동적 분할 윈도우와 정적 분할 윈도우  동적 분할 윈도우(Dynamic Splitter Windows)  사용자가 메뉴 아이템을 선택하거나 스크롤바에 있는 분할 박스를 드래그 하여 윈도우를 분할할 수 있다.  패인 - 일반적으로 동일한 뷰 클래스를 사용하며, 스크롤바는 뷰 사이에 공유된다.  하나의 뷰 객체로 시작된다.  사용자가 프레임을 분할하면 다른 뷰 객체가 생성되고 분할을 해제하면 뷰 객체가 소멸된다.  정적 분할 윈도우(Static Splitter Windows)  패인 - 윈도우가 처음 생성될 때 정의되어 이후에 변경되지 않는다.  스크롤바를 공유하지 않는다.  모든 뷰 객체는 프레임 생성시 생성되고 프레임이 소멸될 때 모두 소멸된다.

CHAPTER 19  예제 EX19A - 단일 뷰 클래스 SDI 동적 분할  4개로 분리된 뷰 객체는 모두 하나의 뷰 클래스에 의해 관리된다.  AppWizard Step4에서 Advanced… 버튼을 누른 후, Windows Styles 탭에서 Use split window를 체크한다.  기존에 있는 어플리케이션의 CMainFrame 클래스에 분할 기능 코드를 직접 추가할 수 있다.  분할을 위한 리소스  Use split window가 체크되면 AppWizard는 View 메뉴에 Split 메뉴 아이템을 추가한다.  ID_WINDOW_SPLIT는 CView::OnSplitCmd()에 맵핑되어 있다.

CHAPTER 19  예제 EX19A - 단일 뷰 클래스 SDI 동적 분할  CMainFrame 클래스  MainFrm.h protected: CSplitterWnd m_wndSplitter; //Overrides public: virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);  어플리케이션 프레임워크는 메인 프레임 객체가 생성될 때 CFrameWnd::OnCreateClient()를 호출한다.  MainFrm.cpp BOOL CMainFrame::OnCreateClient( LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext) { return m_wndSplitter.Create( this, 2, 2, // 행과 열의 개수 조정 CSize(10, 10), // 패인의 최소 크기 조정 pContext); }

CHAPTER 19  CFrameWnd::OnCreateClient  적당한 메뉴를 갖는 기본 사용자 윈도우를 생성하는 데 사용된다.  MDI 사용자 윈도우의 생성을 Customize하기 위하여 중복시킬 수 있다.  virtual BOOL OnCreateClient( LPCREATESTRUCT lpcs, CCreateContext* pContext );  Return Value 성공하면 TRUE, 실패하면 FALSE  Parameters lpcs CREATESTRUCT 구조체에 대한 포인터 pContext CCreateContext 구조체에 대한 포인터

CHAPTER 19  예제 EX19B - 이중 뷰 클래스 SDI 정적 분할  두 개의 뷰가 출력되는 정적 분할 윈도우를 만든다.  이 분할 윈도우는 두 개의 패인으로 초기화된다.  정적 분할 어플리케이션을 만드는 방법  CSplitterWnd::CreateStatic() 을 사용한다.  프로그램 수정  ex19bDoc.cpp, ex19bDoc.h, ex19bView.cpp, ex19bView.h삭제  아래의 파일을 추가한다.(Project메뉴 - Add To Project - Files) PoemDoc.cpp, PoemDoc.h, StringView.cpp, StringView.h LogScrollView.cpp, LogScrollView.h, HexView.cpp, HexView.h  ex19b.cpp 수정 #include “ex19bDoc.h”, #include “ex19bView.h” 제거 #include “PoemDoc.h”, #include “StringView.h” 추가 RUNTIME_CLASS(CEx19bDoc), RUNTIME_CLASS(CEx19bView)의 내용을 RUNTIME_CLASS(CPoemDoc), RUNTIME_CLASS(CStringView)로 바꾼다.

CHAPTER 19  CSplitterWnd::CreateView  virtual BOOL CreateView( int row, int col, CRuntimeClass* pViewClass, SIZE sizeInit, CCreateContext* pContext );  Parameters  row 분할 윈도우의 행의 수  col 분할 윈도우의 열의 수  pViewClass 새로운 뷰의 CRuntimeClass  sizeInit 새로운 뷰의 초기 크기  pContext 뷰를 생성할 때 사용되는 컨텍스트 생성에 대한 포인터 (usually the pContext passed into the parent frame's overridden CFrameWnd::OnCreateClient member function in which the splitter window is being created).

CHAPTER 19  CSplitterWnd::CreateStatic  BOOL CreateStatic( CWnd* pParentWnd, int nRows, int nCols, DWORD dwStyle = WS_CHILD | WS_VISIBLE, UINT nID = AFX_IDW_PANE_FIRST );  Parameters  pParentWnd 분할 윈도우의 부모 프레임 윈도우  nRows 행의 수. 이 값은 16을 초과할 수 없다.  nCols 열의 수. 이 값은 16을 초과할 수 없다.  dwStyle 윈도우의 스타일  nID 윈도우의 자식 윈도우 ID The ID can be AFX_IDW_PANE_FIRST unless the splitter window is nested inside another splitter window.

CHAPTER 19  예제 EX19C - 윈도우를 분할하지 않고 뷰 클래스 전환하기  분할 윈도우를 생성하지 않고 CStringView 클래스와 CHexView 클래스 사이를 전환하는 SDI 어플리케이션이다.  리소스 요구사항  View 메뉴의 Split 삭제, 다음 두 개의 아이템을 View 메뉴에 추가한다. 제목 명령 ID CMainFrame 클래스의 메시지 함수 String View Hex View ID_VIEW_STRINGVIEW ID_VIEW_HEXVIEW COMMAND : OnViewStringView() UPDATE_COMMAND_UI : OnUpdateViewStringView() COMMAND : OnViewHexView() OnUpdateViewHexView()

CHAPTER 19  예제 EX19C - 윈도우를 분할하지 않고 뷰 클래스 전환하기  HexView.h StringView.h 수정  HexView.h StringView.h public: public: CHexView(); CStringView(); DECLARE_DYNCREATE(CHexView) DECLARE_DYNCREATE(CStringView)  CFrameWnd::GetActiveView  현재 활성화된 뷰를 리턴한다. (있을 경우)  CView* GetActiveView( ) const;  Return Value  현재 활성화된 뷰에 대한 포인터. 없으면 NULL

CHAPTER 19  CWnd::GetDlgItem  지정한 자식 윈도우 포인터나 핸들을 리턴한다.  보통 다이얼로그에 있는 컨트롤을 얻는 데 사용된다.  CWnd* GetDlgItem( int nID ) const;  void CWnd::GetDlgItem( int nID, HWND* phWnd ) const;  Parameters  nID 얻을 자식 윈도우 ID 또는 컨트롤의 ID  phWnd 지정 자식 윈도우 핸들로 채워지는 HWND에 대한 포인터  Return value 첫번 째 함수는 지정 자식 윈도우에 대한 포인터를 리턴하거나 자식 윈도우가 존재하지 않으면 NULL  CView::GetDocument  뷰에 대한 관련되는 도큐먼트를 리턴한다.  CDocument* GetDocument( ) const;  Return Value 관련 도큐먼트에 대한 CDocument 포인터. 관련 도큐먼트를 갖지 않으면 NULL

CHAPTER 19  CWnd::SetDlgCtrlID  자식 윈도우 ID를 특정 ID로 변경한다.  int SetDlgCtrlID( int nID );  Parameters  nID 새로운 자식 윈도우 ID  RecalcLayout  프레임 윈도우의 크기가 변경되거나 컨트롤바가 표시되거나 숨겨질 때 호출된다.  프레임 윈도우의 레이아웃 행위를 customize하기 위하여 중복될 수 있다.  virtual void RecalcLayout( BOOL bNotify = TRUE );  Parameter  bNotify TRUE - 프레임에 대한 활성화 인플레이스 항목이 레이아웃 변경에 대해 통보받는다.

CHAPTER 19  CObject::IsKindOf  BOOL IsKindOf( const CRuntimeClass* pClass ) const;  Parameters  pClass 기술한 클래스에 대한 CRuntimeClass에 대한 포인터  CView::OnInitialUpdate  뷰가 도큐먼트에 추가된 다음에 뷰가 표시되기 전에 처음 호출되는 함수  virtual void OnInitialUpdate( );

CHAPTER 19  예제 EX19D - 다중 뷰 클래스 MDI 어플리케이션 어플리케이션을 생성한다.  AppWizard에서 MDI 옵션을 설정, AppWizard Step4에서 Context-Sensitive Help 옵션을 설정  프로그램 수정  ex19dDoc.cpp, ex19dDoc.h, ex19dView.cpp, ex19dView.h삭제  아래의 파일을 추가한다.(Project메뉴 - Add To Project - Files) PoemDoc.cpp, PoemDoc.h, StringView.cpp, StringView.h LogScrollView.cpp, LogScrollView.h, HexView.cpp, HexView.h  ex19d.cpp 수정 #include “ex19dDoc.h”, #include “ex19dView.h” 제거 #include “PoemDoc.h”, #include “StringView.h”, #include “HexView.h” 추가 RUNTIME_CLASS(CEx19dDoc), RUNTIME_CLASS(CEx19dView)의 내용을 RUNTIME_CLASS(CPoemDoc), RUNTIME_CLASS(CStringView)로 바꾼다.  HexView.cpp, PoemDoc.cpp, StringView.cpp 수정  #include “ex18a.h” 를 #include “ex19d.h”로 바꾼다.

CHAPTER 19  CWinApp::ExitInstance  윈도우 인스턴스에 대한 청소 작업을 수행한다.  인스턴스가 종료하려고 할 때, MFC에 의해 호출된다.  virtual int ExitInstance( );  Return Value  The application's exit code; 0 indicates no errors, and values greater than 0 indicate an error. This value is used as the return value from WinMain.  CMDIFrameWnd::MDIGetActive  현재 활성화 MDI 자식 윈도우를 얻는다.  CMDIChildWnd* MDIGetActive( BOOL* pbMaximized = NULL ) const;  활성화 MDI 자식 윈도우에 대한 포인터. 아무 것도 존재하지 않으면 NULL  Parameters  pbMaximized BOOL 리턴값에 대한 포인터 윈도우가 최대화 되었으면 TRUE, 그렇지 않으면 FALSE.

CHAPTER 19  OnFilePrintPreview  뷰를 사용하여 미리 보기 세션을 시작하기 위하여 호출된다.  세션에 대해 새로운 CPrintPreviewState 객체를 생성하고 DoPrintPreview를 호출한 다음에 세션이 완료된 다음에 청소 작업을 한다.  void CView::OnFilePrintPreview() { // In derived classes, implement special window handling here // Be sure to Unhook Frame Window close if hooked. // must not create this on the frame. Must outlive this function CPrintPreviewState* pState = new CPrintPreviewState; if (!DoPrintPreview(AFX_IDD_PREVIEW_TOOLBAR, this, RUNTIME_CLASS(CPreviewView), pState)) // In derived classes, reverse special window handling // here for Preview failure case TRACE0("Error: DoPrintPreview failed"); AfxMessageBox(AFX_IDP_COMMAND_FAILURE); delete pState; // preview failed to initialize, delete State now }

CHAPTER 19  AfxGetApp  CWinApp에서 파생한 어플리케이션 객체에 대한 포인터를 얻는다.  CWinApp* AfxGetApp( );  Return Value  CWinApp에서 파생한 객체에 대한 포인터  AssertValid(), ASSERT_VALID  객체를 확인한다.  각 CObject에서 파생한 클래스는 특정 확인을 수행하기 위하여 이 함수를 중복시켜야 한다.  보통 이 함수는 디버그 모드에 있을 때 파생 클래스에 대해서만 구현된다.  ASSERT_VALID 매크로는 객체 자체에 대한 포인터 값을 검사한다.  Debug모드 : ASSERT_VALID는 먼저 CObject에서 파생한 포인터에 의해 가리키는 메모리를 검사한 다음 AssertValid()를 호출한다.  Release모드 : ASSERT_VALID는 아무 것도 하지 않는다.  virtual void AssertValid() const;  ASSERT_VALID( pObject )  Parameters  pObject CObject에서 파생한 클래스의 객체

CHAPTER 19  CDocTemplate::CreateNewFrame  보관된 프레임 런타임 클래스로부터 새로운 도큐먼트를 생성하고 템플릿에 추가한다.  성공하면, 프레임의 리소스가 메로리에 로드된다.  프레임은 도큐먼트와 관련된 뷰를 포함하는 데 사용된다.  virtual CFrameWnd* CreateNewFrame( CDocument* pDoc, CFrameWnd* pOther );  Return Value 성공하면 새로운 CFrameWnd에 대한 포인터. 그렇지 않으면 NULL.  Parameters  pDoc 새로운 프레임과 관련되는 도큐먼트에 대한 포인터. 그렇지 않으면 NULL.  pOther 새로운 프레임이 근거되는 프레임에 대한 포인터. 템플릿에 관련되는 프레임을 사용하려면 NULL.

CHAPTER 19  CDocTemplate::InitialUpdateFrame  도큐먼트의 모든 뷰가 OnInitialUpdate 통보 메시지를 받을 수 있게 호출된다.  CFrameWnd::InitialUpdateFrame 함수에 제어를 전달한다.  virtual void InitialUpdateFrame( CFrameWnd* pFrame, CDocument* pDoc, BOOL bMakeVisible = TRUE );  Parameters  pFrame 통보 메시지를 받을 도큐먼트를 포함하는 프레임 윈도우  pDoc 통보 메시지를 받는 도큐먼트. 이 값은 NULL일 수 있다.  bMakeVisible TRUE - 윈도우를 보이게 한다. FALSE - 보이지 않게 한다.  VERIFY  ASSERT와 거의 유사  Debug와 Release 모두에서 작동한다.  VERIFY( booleanExpression )  booleanExpression Specifies an expression (including pointer values) that evaluates to nonzero or 0.

CHAPTER 19  CFrameWnd::GetActiveDocument  virtual CDocument* GetActiveDocument( );  Return Value 현재 활성화된 도큐먼트에 대한 포인터. 활성화 도큐먼트가 없으면 NULL.

CHAPTER 20 문맥감지형 도움말

CHAPTER 20  문맥감지형 도움말(Context-Sensitive Help)  MFC 4.21 어플리케이션 프레임 워크로 생성된 프로그램은 윈도우에 포함되어 있는 WinHelp의 help 엔진을 이용하여 문맥 감지형 도움말 기능을 제공한다.  윈도우 WinHelp 프로그램  RTF(Rich Text Format)  윈도우 SDK 문서에는 도움말 파일 형식으로 rich text format이라고 하는 ASCII 파일 포맷을 제시한다.  RTF는 마이크로소프트사에서 표준화한 파일형식. 서로 다른 프로그램, 운영체제에서 형식화된 텍스트를 전송하기 쉽게 하기 위해 만들어진 것이다.  도움말 작성  도움말 프로젝트 파일 *.Hpj를 만들기 위해서는 도움말의 문서 형식, 즉 서식 있는 문자열 *.Rtf 파일이 필요하다.  서식 있는 문자열(*.Rtf) 파일을 만들기 위해서는 RTF를 지원하는 워드프로세서가 필요하다.

CHAPTER 20  사용자 정의 각주에 따른 기능 사용자 정의 각주 기능 # K + @ $ ! * 문서간 점프 지정 사용자 정의 각주 기능 # K + @ $ ! * 문서간 점프 지정 검색 기능을 위한 색인(Keyword) 지정 Browse sequence 지정 저자 정의 설명 현재의 제목에 이름 지정 현재의 제목 시작시 실행되는 매크로 지정 특수한 구조 태그

CHAPTER 20  도움말 프로젝트 파일 [OPTIONS] CONTENTS=HID_CONTENTS TITLES=SIMPLE Application Help // 도움말 파일의 제목 COMPRESS=true // 압축 설정 여부, true - 압축 설정 WARNING=2 // 컴파일시 모든 경고 메시지 표시 [FILES] simple.rtf // 도움말 문서지정 - 도움말의 텍스트를 담은 rtf 파일이 simple.rtf 임을 지정

CHAPTER 20  도움말 파일 만들기  Microsoft Help Workshop(HCRTF) 유틸리티를 실행 (DevStudio\Vc\bin\Hcrtf.exe)  4.02 이전 버전의 HCRTF 유틸리티의 경우 MS-WORD97에 의해 생성된 RTF를 지원하지 않으므로 HwDll.dll을 DevStudio\Vc\bin 디렉토리에 복사해야 한다.  도움말 파일 구성  도움말 토픽 파일(.rtf)  도움말 프로젝트 파일(.hpj) - Help 컴파일 후 (.hlp) 파일 생성  도움말 목차 파일(.cnt)  도움말 그래픽/멀티미디어 파일

CHAPTER 20  어플리케이션 프레임워크와 WinHelp 제공한다.(F1, Shift-F1) 1. AppWizard의 Step4에서 Context-Sensitive Help 옵션을 선택한다. 2. AppWizard는 어플리케이션의 Help 메뉴에 Help Topics 메뉴 아이템을 생성하고 도움말 프로젝트 파일 (.hlp), 도움말 컴파일러를 실행할 배치 파일과 하나 이상의 도움말 토픽 파일 (.rtf)을 생성한다. 3. AppWizard는 가속기 F1을 삽입하고 F1키와 Help Topics 메뉴 아이템을 메인 프레임 윈도우 객체의 멤버 함수에서 맵핑 한다. ON_COMMAND(ID_HELP, CFrameWnd::OnHelp) 4. 사용자가 F1키를 누르거나 Help Topics 메뉴 아이템을 선택하면 Help context ID가 WinHelp로 전달되어 해당 도움말 토픽이 출력된다.

CHAPTER 20  WinHelp 호출하기  CWinApp 클래스의 멤버 함수 WinHelp()는 어플리케이션 내부로 부터 WinHelp를 활성화 한다.  WinHelp()의 두 번째 파라미터에 Help context ID를 설정하고 프로그램이 다음과 같은 문장을 포함한다면, Simple Help 파일을 사용할 수 있다. AfxGetApp()->WinHelp(HID_TOPIC1);  WinHelp에서 어떤 도움말 파일이 사용되는지 어떻게 알 수 있는가?  어플리케이션의 이름과 도움말 파일의 이름이 동일하기 때문이다. 실행 프로그램 : Simple.exe, 도움말 파일 : Simple.hlp  프로그램에서 사용되는 상수 HID_TOPIC1(WinHelp()의 첫번째 파라미터) 과 도움말 토픽 파일의 Help context ID를 어떻게 연결시키는가?  도움말 프로젝트 파일(.hpj)에 MAP 섹션이 포함되어야 한다.

CHAPTER 20  WinHelp 호출하기  어플리케이션의 resource.h 파일에 HID_TOPIC1이 101로 정의되었다면 도움말 프로젝트 파일(Simple.hpj)에 다음과 같은 MAP 섹션이 추가되어야 한다.  [MAP] HID_TOPIC1 101  프로그램의 resource.h 파일에 #define HID_TOPIC1 101로 정의된 매크로 상수명(HID_TOPIC1)과 프로젝트 파일의 MAP 섹션에 추가한 Help context ID(HID_TOPIC1) 이름이 반드시 일치할 필요는 없다.  지정된 숫자 101(컨텍스트 번호)은 반드시 동일해야 한다.

CHAPTER 20  검색 문자열 사용하기  Help context ID보다는 키워드를 기준으로 도움말이 필요한 어플리케이션의 경우 WinHelp()의 두 번째 파라미터에 HELP_KEY 또는 HELP_PARTIALKEY를 사용한다.  CString string(“find this string”); AfxGetApp()->WinHelp((DWORD)(LPCSTR)string, HELP_KEY);  어플리케이션 메뉴로부터 WinHelp 호출하기  AfxGetApp() -> WinHelp(0L, HELP_FINDER);  색인 탭 다이얼로그가 출력된다.  AfxGetApp() -> WinHelp(0L, HELP_INDEX);  목차 테이블 화면이 출력된다.

CHAPTER 20  Help context ID Aliases  도움말 프로젝트 파일(.hpj)의 Alias 섹션은 Help context ID와 동일하게 사용할 수 있는 다른 이름을 설정할 때 사용한다.  [ALIAS] HID_TOPIC1 = HID_GETTING_STARTED [MAP] HID_TOPIC1 101  도움말 토픽 파일(.rtf)에서 HID_TOPIC1과 HID_GETTING_STARTED 모두 사용이 가능하며 숫자 101(컨텍스트 번호)에 연결된다.

CHAPTER 20  Help context 결정하기  어플리케이션 프레임워크는 활성화된 프로그램 요소의 ID에 기초하여  프로그램 요소에는 메뉴 아이템, 프레임 윈도우, 다이얼로그, 메시지 박스, 컨트롤바를 포함한다.  프로그램 요소의 ID값이 중복될 경우, 어플리케이션 프레임 워크는 ID값 중복 문제를 해결하기 위해 프로그램 요소의 ID에서 유도된 #define 상수를 새롭게 정의한다.  HID_EDIT_CLEAR_ALL(0x1E121)은 ID_EDIT_CLEAR_ALL(0xE121)에 대응되고, IDR_MAINFRAME(0x20080)은 IDR_MAINFRAME(0x80)에 대응된다.

CHAPTER 20 비 클라이언트 영역  Help context 결정하기 프로그램 요소 프로그램 요소 ID 기준(16진수) 메뉴 아이템 프레임, 다이얼로그 에러 메시지 박스 컨트롤 바 디스패치 에러 메시지 ID_ IDR_, IDD_ IDP_ DW_ HID_ HIDR_, HIDD_ HIDP_ H... HIDW_ 10000 20000 30000 40000 50000 60000  Help 명령 처리 (예제 - EX20B)  F1 키 처리 - OnCommandHelp()  Shift+F1 키 처리 - OnHelpHitTest()  모달 다이얼로그와 메시지 박스에서는 작동하지 않는다.

CHAPTER 20  ON_MESSAGE  ON_MESSAGE( message, memberFxn )  Parameters  message 메시지 ID.  memberFxn 메시지를 맵핑하기 위한 메시지 핸들러 함수의 이름  CWinApp::WinHelp  WinHelp 어플리케이션을 실행하고, 기술한 대로 도움말 토픽을 동작시킨다.  virtual void WinHelp( DWORD dwData, UINT nCmd = HELP_CONTEXT );  dwData 부가적인 데이터를 기술한다. 도움말 파일에서 어디로 점프하는지를 판단한다. 이 값은 nCmd 파라미터의 값에 따른다.  nCmd 표시하고 어떻게 기술한 도움말 토픽을 찾는가의 도움말 타입을 기술한다.

CHAPTER 20  OnCommandHelp (F1 키 처리)  프레임 윈도우에 대한 도움말 커맨드 호출을 처리한다.  afx_msg LRESULT OnCommandHelp( WPARAM wParam, LPARAM lParam );  Parameters  wParam 사용되지 않는다.  lParam 도움말 컨텍스트 ID  OnHelpHitTest (Shift + F1 키 처리)  사용자가 다이얼로그의 특정 위치를 클릭할 때 윈도우 도움말 엔진에 전달되는 도움말 컨텍스트 ID를 판단하는 데 사용된다.  기본 구현은 항상 HID_BASE_RESOURCE 상수의 값에 다이얼로그의 도움말 ID를 더하여 리턴한다.  afx_msg LRESULT OnHelpHitTest( WPARAM wParam, LPARAM lParam );  Return value 도움말 인덱스 ID를 리턴한다.  wParam 마우스 위치의 x축 디바이스 좌표  lParam 마우스 위치의 y축 디바이스 좌표

CHAPTER 20  Help Files  Help Context Ranges  The Microsoft Foundation classes assume a single Help file. That Help file must have the same name and path as the application (.EXE -> .HLP).  This is a public CWinApp member variable named m_pszHelpFilePath that the user can change if desired.  Help Context Ranges  0x00000000 - 0x0000FFFF : user defined  0x00010000 - 0x0001FFFF : commands (menus/command buttons)  0x00010000 + ID_ (note: 0x18000-> 0x1FFFF is practical range since command IDs are >=0x8000)  0x00020000 - 0x0002FFFF : windows and dialogs  0x00020000 + IDR_ (note: 0x20000-> 0x27FFF is practical range since IDRs are <= 0x7FFF)  0x00030000 - 0x0003FFFF : error messages (based on error string ID)  0x00030000 + IDP_  0x00040000 - 0x0004FFFF : special purpose (non-client areas)  0x00040000 + HitTest area  0x00050000 - 0x0005FFFF : controls (those that are not commands)  0x00040000 + IDW_  These rules are hard-coded into the default implementation of the Microsoft Foundation classes. They can be overridden by providing different implementations of the various Help-related member functions.

청어가 살아있는 비결 북쪽 바다에서 청어잡이를 하는 어부들의 가장 큰 관심사는, 어떻게 하면 북해로부터 먼 거리에 있는 런던까지 청어를 싱싱하게 살려서 가지고 가는가 하는 것이었다. 모든 어부들이 아무리 잘 해도 배가 런던에 도착해 보면 청어들은 거의 죽어 있는데, 꼭 한 어부만은 싱싱하게 청어를 산채로 런던에 가지고 와서 큰 수입을 얻는 것이었다. 동료 어부들이 이상해서 물었으나 그는 비밀이라며 가르쳐 주지 않다가 압력에 못 이겨 다음과 같이 말했다. “나는 청어를 잡아서 넣은 통에다 메기를 한 마리씩 넣습니다.” 그러자 모든 어부들이 눈이 둥그래지면서 “그러면 메기가 청어를 잡아 먹지 않소?”라고 묻는 것이었다. 그는 다음과 같이 말했다. “네, 메기가 청어를 잡아 먹습니다. 그러나 메기는 청어를 두 세 마리 밖에 못 잡아 먹지요. 그러나 그 통에 있는 수백 마리의 청어들은 잡혀 먹히지 않으려고 계속 도망쳐 다니지요. 런던에 올 때까지 모든 청어들은 마치 올챙이들처럼 헤엄치고 도망 다니고 있습니다. 그래서 청어는 여전히 살아서 싱싱합니다. 다 살아 있거든요” 오해하지 마십시오. 편안하고 풍요로운 것만이 행복은 아니라는 것을!

CHAPTER 21 DLL(동적 링크 라이브러리)

CHAPTER 21  DLLs(Dynamic Link Libraries)  DLL 의 기초 이론  클래스 - build_time 모듈러  DLL - run_time 모듈러  내용이 변경될 때마다 다시 만들고 테스트해야 하는 거대한 EXE 프로그램 대신, 작은 DLL 모듈들을 만들면 개별적인 수정과 테스트가 가능하다.  DLL 의 기초 이론  DLL은 디스크상의 파일(.dll)로서 글로벌 데이터, 컴파일된 함수들, 프로세스의 일부분이 되는 리소스로 구성되어 있다.  DLL은 컴파일되어 기본 주소에 로드되고 다른 DLL과 충돌이 없다면 프로세스에서 동일한 가상 주소에 맵핑된다.  DLL은 다양한 익스포트된 함수들을 가지고 있고 클라이언트 프로그램은 익스포트된 함수들을 임포트한다.  Win32에서 각 프로세스는 자신만의 DLL의 읽기/쓰기 글로벌 변수의 복사본을 갖는다.  프로세스간에 메모리 공유를 원하면 메모리 맵 파일을 사용하거나 데이터 섹션 분리(shared data section)를 선언해야 한다.

CHAPTER 21  임포트(Imports)와 익스포트(Exports) 연결 방법  익스포트되는 함수들을 symbolic name과 ordinal number라고 하는 정수로 외부에 노출된다.  클라이언트 프로그램은 DLL을 로드할 때 symbolic name과 ordinal number 를 인식하고, 이때 동적 링크 프로세스가 클라이언트가 호출한 함수를 DLL 에 있는 함수 테이블의 함수 주소와 연결시킨다.  DLL코드 - 익스포트된 함수 선언  __declspec(dllexport) int MyFunction( int n );  클라이언트 프로그램 - 임포트를 선언  __declspec(dllimport) int MyFunction( int n );  C++에서 MyFunction()이라는 C 함수를 사용하려면 extern “C” __declspec(dllexport) int MyFunction( int n ); extern “C” __declspec(dllimport) int MyFunction( int n );

CHAPTER 21  암시적 연결과 명시적 연결(Implicit Linkage vs. Explicit Linkage)  암시적 연결(Implicit linking)  DLL 을 만들 때 링커는 DLL의 익스포트된 함수에 대한 정보(symbolic name, ordinal number)를 포함하는 임포트 라이브러리 파일(.lib)을 생성한다.  클라이언트 프로그램을 만들 때 링커에 생성된 임포트 라이브러리 파일(.lib)을 지정 하면(정적 링크) 임포트된 symbolic name, ordinal number는 임포트 라이브러리 파일의 익스포트된 symbolic name, ordinal number에 매칭된다.  클라이언트 프로그램이 로드될 때 DLL이 로드된다.  symbolic name, ordinal number에 동적으로 링크된다.  명시적 연결(Explicit linking)  명시적 연결은 임포트 라이브러리 파일(.lib)을 사용하지 않는다.  LoadLibrary() 함수 파라미터로 DLL의 경로를 지정하여 호출한다.

CHAPTER 21  암시적 연결과 명시적 연결(Implicit Linkage vs. Explicit Linkage)  클라이언트 프로그램의 명시적 연결 예  extern “C” __declspec(dllexport) double SquareRoot( double d ); typedef double (SQRTPROC) (double); HINSTANCE hInstance; SQRTPROC* pFunction; VERIFY(hInstance = ::LoadLibrary(“c:\\windows\\system\\mydll.dll”)); VERIFY(pFunction = (SQRTPROC*)::GetProcAddress(hInstance, “SquareRoot”)); double d = (*pFunction)(81.0); // DLL의 SquareRoot()을 호출

CHAPTER 21  symbolic name과 ordinal number  MFC 라이브러리의 DLL은 ordinal number 연결을 사용한다.  ordinal number 연결은 임포트의 긴 symbolic name을 포함할 필요가 없기 때문에 프로그램의 EXE 파일을 작게 할 수 있다.  ordinal number 연결로 자신만의 DLL을 만들려면 프로젝트의 모듈 정의 파일(.def)에 ordinal number를 지정한다.  익스포트된 함수가 C++ 함수라면 모듈 정의 파일(.def)에 decorated이름을 사용해야 한다. (또는 extern “C”로 함수를 선언한다.)  MFC 라이브러리의 DEF(DevStudio\VC\mfc\src\intel\MFC42.DEF) ?ReadList@CRecentFileList@@UAEXXZ @ 5458 NONAME ?ReadNameDictFromStream@CPropertySection@@QAEHPAUIStream@@@Z @ 5459 NONAME ?ReadObject@CArchive@@QAEPAVCObject@@PBUCRuntimeClass@@@Z @ 5460 NONAME ?ReadString@CArchive@@QAEHAAVCString@@@Z @ 5461 NONAME ?ReadString@CArchive@@QAEPADPADI@Z @ 5462 NONAME ?ReadString@CInternetFile@@UAEHAAVCString@@@Z @ 5463 NONAME ?ReadString@CInternetFile@@UAEPADPADI@Z @ 5464 NONAME symbol ordinal number

CHAPTER 21  모듈정의 파일 *.def  모듈 정의 파일은 프로그래머가 작성한 프로그램(또는 소스)을 컴파일하여 생기는 오브젝트(.OBJ) 파일을 링크(Link) 시키는데 필요한 정보를 포함한다.  과거에는 모든 윈도 프로그램이 링커가 사용할 모듈정의 파일을 가져야 했다.  32비트 윈도우 프로그램의 경우에는 더 이상 모듈정의 파일을 필요로 하지 않는다. NAME DESCRIPTION EXETYPE STUB CODE DATA HEAPSIZE STACKSIZE SAMPLE ‘The Windows Program SAMPLE.C’ WINDOWS ‘WINSTUB.EXE’ PRELOAD MOVEABLE DISCARDABLE PRELOAD MOVEABLE MULTIPLE 1024 5120 ◐ 모듈 정의 파일 템플릿(.DEF) ◑

CHAPTER 21  모듈정의 파일 CODE PRELOAD MOVEABLE DISCARDABLE DATA PRELOAD MOVEABLE MULTIPLE HEAPSIZE 1024 STACKSIZE 5120  모듈정의 파일 코드 세그먼트를 어떤 방식으로 메모리에 로드할 것인가를 결정하기 위해 설정. 응용 프로그램의 코드 세그먼트에 대한 해당 메모리 옵션을 명시한다. 응용 프로그램에서 사용될 힙(Local Heap)의 크기를 바이트 단위로 할당. 256BYTE ~ 65536BYTE 응용 프로그램에서 사용될 스택(Stack)의 크기를 바이트 단위로 할당. 5BYTE ~ 65536BYTE

CHAPTER 21  모듈정의 파일 옵션 의미 PRELOAD LOADONCALL FIXED MOVEABLE MULTIPLE SINGLE DISCARDABLE 프로그램이 처음 시작될 때 윈도우가 코드 세그먼트를 즉시 로드하게 한다. 프로그램이 코드 세그먼트나 데이터 세그먼트를 요청하는 순간에 코드 세그먼트나 데이터 세그먼트가 기억장소로 로드되면 고정되어 이동할 수 없게 한다. 사용되는 코드 세그먼트나 데이터 세그먼트를 이동 가능한 형식으로 설정한다. 인스턴스들이 각기 자체적인 데이터 세그먼트를 사용하게 한다. 모든 인스턴스들이 하나의 같은 데이터 세그먼트를 나누어 사용하게 한다. 필요한 경우에는 프로그램이 메모리에서 제거되었다가 다시 로드될 수 있다는 것을 의미한다.

CHAPTER 21  DLL Entry Point-DllMain  윈도우는 DLL을 로드하면 __DllMainCRTStartup 스타트 코드를 호출한다.  __DllMainCRTStartup 스타트 코드는 전역 객체를 생성하고, 전역 함수 DllMain()을 호출한다.  DllMain()은 DLL이 프로세스에 결합하거나 분리될 때, 스레드가 시작되거나 닫힐 때 dwReason 파라미터에 따라 호출된다.  DLL에서 DllMain() 함수가 없으면 런타임 라이브러리를 사용할 수 없다.  EXE의 스타트 코드 - _WinMainCRTStartup

CHAPTER 21  DLL Entry Point-DllMain  DllMain() 함수의 키포인트 HINSTANCE g_hInstance; extern “C” int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { if(dwReason == DLL_PROCESS_ATTACH) TRACE0(“EX21A.DLL Initializing!\n”); // 여기에 초기화 설정 } else if(dwReason == DLL_PROCESS_DETACH) TRACE0(“EX21A.DLL Terminating!\n”); // 여기에 해제 작업 설정 return 1;

CHAPTER 21  인스턴스 핸들 - 리소스 읽기  모든 인스턴스 핸들은 특정 프로세스에서만 유효하며, DLL이나 EXE가 시작되는 가상 주소를 나타낸다.  프로세스(EXE) 인스턴스 핸들의 주소 - 0x400000  로드된 DLL 인스턴스 핸들의 디폴트 주소 - 0x10000000  FindResource() - 리소스 핸들을 얻는다.  DLL의 리소스가 필요하면 HINSTANCE 파라미터에 DLL의 인스턴스 핸들을 지정한다.  EXE의 리소스가 필요하면 EXE의 인스턴스 핸들을 지정하여 해당 리소스 핸들을 얻을 수 있다.  GetModuleHandle() - 인스턴스 핸들을 얻는다.  EXE의 인스턴스 핸들이 필요하면 NULL 파라미터를 사용한다.  DLL의 인스턴스 핸들이 필요하면 DLL 이름을 파라미터로 GetModuleHandle() 함수를 호출한다.

CHAPTER 21  클라이언트 프로그램이 DLL을 찾는 방법  경로를 지정하지 않는 암시적 연결의 경우 / 명시적 연결의 경우 1. EXE 파일을 포함하는 디렉토리 / LoadLibrary() 에 지정된 디렉토리 2. 프로세스의 현재 디렉토리 3. 윈도우의 시스템 디렉토리 4. 윈도우 디렉토리 5. Path 환경 변수에 지정된 디렉토리  DLL 파일을 \windows\system 디렉토리에 복사한 후 프로그램을 실행한다.  MFC DLLs - 확장 DLL과 일반 DLL  확장 DLL  C++ 인터페이스를 지원하므로 클래스 자체를 익스포트 할 수 있다.  MFC 라이브러리와 동적으로 링크되기 때문에 MFC 어플리케이션에서만 사용할 수 있다.  일반 DLL  C 스타일 함수로만 익스포트 할 수 있다.  MFC 라이브러리를 정적 연결이나 동적 연결로 선택하여 사용할 수 있다.  정적 연결을 선택하면 필요로 하는 MFC 라이브러리 코드가 DLL안에 복사되므로 DLL크기가 커진다.  동적 연결을 사용하면 크기는 줄어들지만, 인스톨하려는 컴퓨터에 필요한 MFC DLL이 있어야 한다.

CHAPTER 21  MFC DLLs - 확장 DLL과 일반 DLL  공유 MFC DLL과 윈도우 DLL 각주 공유 MFC 라이브러리 동적 연결 MFC 라이브러리 정적 연결 일반 DLL 확장 DLL 클라이언트 EXE _AFXDLL, _USRDLL _AFXEXT, _AFXDLL _AFXDLL _USRDLL 지원되지 않음 #define 상수 없음  공유 MFC DLL과 윈도우 DLL  Debug 모드에서 프로그램을 만들었다면 그 프로그램은 MFC DLL중 하나 또는 그 이상에 동적으로 연결된다.  mfc42d.dll 핵심 MFC 클래스 mfco42d.dll ActiveX(OLE) 클래스 mfcd42d.dll 데이터베이스 클래스(ODBC와 DAO) mfcn42d.dll Winsock, WinInet 클래스  Release 모드로 만들 경우 프로그램은 mfc42.dll에 동적으로 연결된다.

CHAPTER 21  MFC 확장 DLL - 클래스 익스포트  DLL에 클래스를 추가하고 해당 클래스 선언에 AFX_EXT_CLASS 매크로를 추가  class AFX_EXT_CLASS CStudent::public Cobject //p694  MFC 확장 DLL 리소스 검색 순서  확장 DLL, MFC DLL, EXE 순으로 리소스를 검색한다.  리소스 검색 순서 변경 HINSTANCE hInstResourceClient = AfxGetResourceHandle(); //사용하는 DLL의 인스턴스 핸들 설정(리소스 검색 순서를 DLL의 리소스를 먼저 찾도록 설정한다.) AfxSetResourceHandle(::GetModuleHandle(“mydllname.dll”)); CString strRes; strRes.LoadString(IDS_MYSTRING); // 클라이언트 프로그램의 인스턴스 핸들로 복원 (리소스 검색 순서를 원래대로 복원한다.) AfxSetResourceHandle(hInstResourceClient);  확장 DLL에서 AfxGetInstanceHandle()은 DLL의 핸들이 아닌 EXE의 핸들을 리턴하므로 사용할 수 없다.

CHAPTER 21 유형 MFC DLL 설명 일반 DLL 확장 DLL 정적 공유  C 스타일의 함수만 익스포트 한다.

CHAPTER 21  The TRACE Macro  This topic explains how to use the TRACE macro during development to print or display debugging messages from a program. TRACE prints a string argument to your debugger.  Note With 32-bit MFC, the only way to get debug output is via the debugger.  The TRACE macro can handle a variable number of arguments, similar to the way printf operates. Following are examples of different ways to use TRACEmacros:  int x = 1; int y = 16; float z = 32.0; TRACE( "This is a TRACE statement\n" ); TRACE( "The value of x is %d\n", x ); TRACE( "x = %d and y = %d\n", x, y ); TRACE( "x = %d and y = %x and z = %f\n", x, y, z );  The TRACE macro is active only in the debug version of the class library. After a program has been debugged, you can build a release version to deactivate all TRACE calls in the program.  Tip When debugging Unicode, the TRACE0, TRACE1, TRACE2, and TRACE3 macros are easier to use because the _T macro is not needed.

CHAPTER 21  TRACE  TRACE( exp )  Parameters  exp Specifies a variable number of arguments that are used in exactly the same way that a variable number of arguments are used in the run-time function printf.  TRACE is limited to sending a total of 512 characters at a time. If you call TRACE with formatting commands, the total string length after the formatting commands have been expanded cannot be more than 512 characters, including the terminating NULL. Exceeding this limit causes an ASSERT.  Example // example for TRACE int i = 1; char sz[] = "one"; TRACE( "Integer = %d, String = %s\n", i, sz ); // Output: 'Integer = 1, String = one'

CHAPTER 21  TRACE0  TRACE0( exp )  Parameters  exp A format string as used in the run-time function printf.  Remarks TRACE0 is similar to TRACE, and is one variant of a group of trace macros that you can use for debug output. The group includes:  TRACE0 - Takes a format string (Only) and can be used for simple text messages which are dumped to afxDump  TRACE1 - Takes a format string plus one argument (one variable which is dumped to afxDump)  TRACE2 - Takes a format string plus two arguments (two variables which are dumped to afxDump)  TRACE3 - Takes a format string plus three arguments (three variables which are dumped to afxDump)  TRACE0 does nothing if you have compiled a release version of your application. As with TRACE, it only dumps data to afxDump if you have compiled a debug version of your application.  Note This macro is available only in the debug version of MFC.  Example // example for TRACE0 TRACE0( "Start Dump of MyClass members:" );

CHAPTER 21  TRACE1  TRACE1( exp, param1 )  Parameters  exp A format string as used in the run-time function printf.  param1 The name of the variable whose value should be dumped.  Example int i = 1; TRACE1( "Integer = %d\n", i ); // Output: 'Integer = 1'  TRACE2  TRACE2( exp, param1, param2 )  param2 The name of the variable whose value should be dumped. char sz[] = "one"; TRACE2( "Integer = %d, String = %s\n", i, sz ); // Output: 'Integer = 1, String = one'

CHAPTER 21  TRACE3  TRACE3( exp, param1, param2, param3 )  Parameters  exp A format string as used in the run-time function printf.  param1 The name of the variable whose value should be dumped.  param2 The name of the variable whose value should be dumped.  param3 The name of the variable whose value should be dumped.  AfxGetResourceHandle  리소스를 찾을 때 윈도우에 의해 사용되는 기본 리소스 인스턴스 핸들을 얻는다.  HINSTANCE AfxGetResourceHandle( );  Return Value  리소스 인스턴스 핸들  AfxSetResourceHandle  리소스를 찾을 때 윈도우에 의해 사용되는 기본 리소스 인스턴스 핸들을 설정한다.  void AfxSetResourceHandle( HINSTANCE hInstResource );  hInstResource 리소스 인스턴스 핸들

CHAPTER 21  AfxGetInstanceHandle  어플리케이션의 인스턴스 핸들을 얻는다.  이것은 항상 항상 MFC의 USRDLL 버전을 사용하는 DLL에서 호출되지 않으면 실행 파일에 대한 것이다.  HINSTANCE AfxGetInstanceHandle( );  Return Value  어플리케이션의 인스턴스 핸들

CHAPTER 21  MFC 일반 DLL - CWinApp 파생 클래스  AppWizard가 일반 DLL을 생성할 때 DllMain() 함수는 프레임워크 내부에 있게 된다.  EXE 프로그램과 같이 CWinApp에서 파생된 클래스로 끝난다.  일반적으로 C 함수를 작성하여 _declspec(dllexport) 키워드 또는 프로젝트 모듈 정의 파일(.def)에 엔트리 지정)로 익스포트 한다.  확장 DLL의 경우 AppWizard가 생성한 코드 안에 DllMain() 함수가 있게 된다.  AFX_MANAGE_STATE 매크로 사용하기  mfc42.dll은 프로세스의 일부로 로드될 때 전역 변수에 데이터를 저장한다.  일반 DLL에서 mfc42.dll이 호출되는 경우 전역 변수는 동기화 되지 않는다.  문제 해결 - 일반 DLL의 익스포트된 함수 안에 다음 라인을 삽입한다.  AFX_MANAGE_STATE(AfxGetStaticModuleState()); // p700  DLL이 정적으로 MFC 라이브러리에 연결되는 일반 DLL의 경우 이 매크로를 사용할 필요가 없다.

CHAPTER 21  AFX_MANAGE_STATE  AFX_MANAGE_STATE( AFX_MODULE_STATE* pModuleState )  Parameters  pModuleState AFX_MODULE_STATE 구조체에 대한 포인터  AfxGetStaticModuleState  AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState( );  Return Value  AFX_MODULE_STATE 구조체에 대한 포인터  MFC 일반 DLL 리소스 검색 순서  일반 DLL에 연결된 클라이언트 프로그램 내부에서 리소스 로딩 함수를 호출하면 EXE 자신의 리소스만을 로드하고, 일반 DLL 내부에서 리소스 로딩 함수를 호출하면 DLL 자신의 리소스를 로드한다.  클라이언트 프로그램에서 DLL의 리소스를 로드하고자 할 경우 AfxSetResourceHandle() 함수를 사용하여 일시적으로 리소스 검색 순서를 변경하면 된다. // PowerPoint 333쪽

CHAPTER 21  커스텀 컨트롤 DLL (A Custom Control DLL)  원래 커스텀 컨트롤은 순수한 C로 작성된 독립된 DLL이었다.  일반(regular) DLL은 C++ 인터페이스를 필요로 하지 않고 custom control을 받아 사용하는 개발 시스템에 사용할 수 있기 때문에 최선의 선택이다.  커스텀 컨트롤이란 무엇인가?  커스텀 컨트롤은 에디트 컨트롤과 같은 표준 컨트롤처럼 작동한다.  WM_COMMAND 통보 메시지를 부모 윈도우에 보내고 사용자 정의 메시지를 받는다.  사용자 정의 메시지인 경우에는 ClassWizard를 사용할 수 없으므로 수작업으로 맵핑해야 한다.  커스텀 컨트롤의 윈도우 클래스  다이얼로그 리소스 템플릿은 기호식 윈도우 클래스 이름에 의해 커스텀 컨트롤을 지정한다.  윈도우 클래스  클래스 이름  클래스 윈도우에 보내진 메시지를 받는 WndProc 함수의 포인터  배경 브러시 같은 여러 가지 속성  클라이언트 프로그램은 컨트롤 윈도우 클래스 이름을 사용하여 차일드 윈도우를 만든다.

CHAPTER 21  커스텀 컨트롤의 윈도우 클래스(WNDCLASS)  창 클래스 데이터 구조는 모니터에 나타난 모든 창을 정의할 때 사용한다.  창 클래스는 실제로 객체지향 클래스가 아니다. 단지 창의 유형만을 의미한다.  창 클래스는 진정한 OOP 기술인 상속이나 다형성은 지원하지 않고 있다. typedef struct _WNDCLASS { UINT style; // 윈도우 클래스 스타일 WNDPROC lpfnWndProc; // 메시지를 받아 처리할 윈도우 프로시저의 포인터 int cbClsExtra; // 여분의 클래스 바이트 int cbWndExtra; // 여분의 윈도우 바이트 HANDLE hInstance;// 윈도우 클래스를 정의하는 어플리케이션의 인스턴스 핸들 HICON hIcon; // 아이콘 핸들 HCURSOR hCursor; // 커서 핸들 HBRUSH hbrBackground; // 배경 색상(브러시) LPCTSTR lpszMenuName; // 리소스 파일에 정의한 메뉴 이름 LPCTSTR lpszClassName; // 윈도우 클래스 이름 } WNDCLASS;

CHAPTER 21  윈도우 WNDCLASS 구조의 멤버들 목적 style lpfnWndProc cbClsExtra cbWndExtra hInstance hIcon hCursor hbrBackground lpszMenuName lpszClassName 창의 클래스 스타일 또는 스타일을 지정한다. 창 프로시저를 가리키는 포인터. 창 클래스 구조의 마지막 부분에 할당할 별도의 바이트를 지정한다. 이 바이트는 윈도우가 ‘0’으로 자동으로 초기화한다. 창 인스턴스의 뒤를 이을 별도의 바이트를 지정한다. 응용 프로그램의 창 프로시저에서 창 클래스의 응용 프로그램 인스턴스를 식별한다. 창 클래스에 대한 아이콘으로 사용할 아이콘 자원의 핸들을 식별한다. 창 클래스에 대한 커서로 사용할 커서 자원의 핸들을 식별한다. 클래스 창의 배경을 그리는데 사용할 물리적 붓 또는 색 값 배경 붓을 가리키는 핸들을 식별한다. 클래스에 대해서 사용할 메뉴 자원의 이름을 지정하는 NULL 종료 문자열을 가리키는 포인터. 창 클래스의 이름을 지정하는 NULL 종료 문자열을 가리키는 포인터.  DevStudio\Vc\include\winuser.h(1067라인, 배경색상 정의 - 5914라인)

CHAPTER 21  윈도우 WNDCLASS 구조의 멤버들  색 값 붓을 창 클래스의 hbrBackground 멤버로 지정한다면, 그 색 값을 붓 핸들(HBRUSH)로 형 변환 해야 한다. wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);  색 값이 ‘0’이 되는 것을 방지하기 위해 색 값에 1을 더한다.  창 클래스 스타일 ( Window style )  창 클래스 스타일은 해당 클래스에 속해 있는 모든 창들에 대해서 공통적인 행동 양식을 정의한다.

CHAPTER 21  MFC 라이브러리와 WinProc 함수 호출한다.  컨트롤에 대한 C++ 클래스는 ClassWizard를 사용하여 CWnd에서 파생되는 새로운 클래스(CRygWnd)를 작성한다.  컨트롤 WinProc() 함수 LONG MyControlWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { if(this is the first message for this window){ CWnd* pWnd = new CMyControlWindowClass(); attach pWnd to hWnd } return AfxCallWndProc(pWnd, hWnd, message, wParam, lParam);  MFC 전역 함수 AfxCallWndProc()는 프레임워크에서 전달받은 메시지를 CMyControlWindowClass에 맵핑된 멤버 함수에 전달한다.

CHAPTER 21  커스텀 컨트롤 통보 메시지(Custom Control Notification Messages)  컨트롤은 특정 WM_COMMAND 통보 메시지로 부모 윈도우와 통신하며, 부가적인 정보를 갖는 파라미터가 전달된다.  통보 코드는 임의적이고 컨트롤 의존적이며, 통보 코드를 받는 부모 윈도우는 해당 컨트롤에서 보낸 코드를 사용하여 세부 처리를 한다.  예, 코드 77이 컨트롤에 위치해 있는 동안 사용자가 문자를 입력한 것으로 지정하면 컨트롤은 다음과 같이 통보 메시지를 보낸다. GetParent()->SendMessage(WM_COMMAND, GetDlgCtrlID() | ID_NOTIFYCODE << 16, (LONG) GetSafeHWnd());  클라이언트 프로그램 - MFC ON_CONTROL로 메시지를 맵한다. ON_CONTROL(ID_NOTIFYCODE, IDC_MYCONTROL, OnClickedControl)  핸들러 함수를 선언한다. afx_msg void OnClickedMyControl(); 파라미터 사용 (HIWORD)wParam (LOWORD)wParam lParam 통보 코드 차일드 윈도우 ID 차일드 윈도우 핸들

CHAPTER 21  컨트롤에 보내진 사용자 정의 메시지  예제 EX21D - 커스텀 컨트롤(Custom Control)  사용자 정의 메시지는 클라이언트 프로그램이 컨트롤과 통신하는 수단이다.  메시지가 32비트 값을 반환하므로 PostMessage() 함수보다 SendMessage() 함수를 사용하면 클라이언트 프로그램은 컨트롤로부터 부가 정보를 얻을 수 있다.  예제 EX21D - 커스텀 컨트롤(Custom Control)  off, red, yellow, green 상태를 나타내는 신호등 컨트롤을 구현한 MFC 일반 DLL  좌측 마우스 버튼을 클릭하면 DLL은 클릭된 통보 메시지를 부모 윈도우에 보내고, 부모 윈도우에서 보내는 사용자 정의 메시지 RYG_SETSTATE, RYG_GETSTATE에 대응하는 메시지 핸들러가 있고, 색깔을 나타내는 정수 m_nState 데이터 멤버가 있다.  ON_CONTROL  ON_CONTROL( wNotifyCode, id, memberFxn )  Parameters  wNotifyCode 컨트롤의 통지 코드  id command ID.  memberFxn 커맨드를 맵핑하는 메시지 핸들러 함수의 이름

Seven Deadly Sins (일곱 가지 치명적인 죄악들) 1) Pleasure without conscience (양심 없는 쾌락) 2) Politics without principle (원칙 없는 정치) 3) Commerce without ethics (윤리 없는 상거래) 4) Knowledge without character (성품 없는 지식) 5) Science without humanity (인간성 없는 과학) 6) Wealth without work (노동 없는 부) 7) Worship without sacrifice (희생 없는 종교적 숭배) - 간디 -

CHAPTER 23 Component Object Model

CHAPTER 23  컴포넌트 객체 모델 ( Component Object Model )  Component Object Model(COM)은 새로운 ActiveX 기술의 토대이며, 현재는 윈도우의 핵심 부분으로 통합되었다.  ActiveX 기술의 배경  OLE - Object Linking and Embedding을 의미하며, drag and drop을 포함한 ActiveX 기술의 일부분이다.  IIS - Microsoft Internet Information Server  “server” - 데이터베이스 서버, 인터넷 서버  “Component” - OLE 서버의 새로운 이름  COM이 풀어야 할 문제  윈도우 프로그램 모듈을 위한 표준 방법이 없어 서로간에 통신이 이루어지지 않는다.  COM의 본질  윈도우 API - 350개 이상의 분리된 함수로 존재하여 프로그래밍 “표면 영역”이 너무 크다.  VBX - 32비트에서는 작동하지 않는다.  DDE - 어플리케이션, 토픽, 아이템에 관한 시스템이 복잡하다.

CHAPTER 23  COM의 본질  윈도우에 단일화되고 확장 가능한 객체지향 통신 프로토콜을 제공한다.  Win32 클라이언트 EXE가 Win32 DLL을 로드하고 호출하는데 있어 언어 독립적인 표준 방법을 제공한다.  동일한 컴퓨터 내에서 EXE가 다른 EXE를 컨트롤하는 일반적인 목적을 가진 방식을 제공한다. (DDE 대체)  VBX 컨트롤을 대체할 ActiveX Control을 제공한다.  어플리케이션 프로그램이 운영체제와 상호 작용하는 새롭고 강력한 방법을 제공한다.  마이크로소프트의 OLE DB 데이터베이스 인터페이스와 같은 새로운 프로토콜을 수용할 수 있는 확장성을 제공한다.  새롭게 배포된 분산 COM(DCOM)은 EXE가 다른 컴퓨터(컴퓨터가 서로 다른 microprocessor-chip을 사용해도)에 있는 EXE와 통신할 수 있는 방법을 제공한다.  COM - COM은 하나의 소프트웨어 모듈을 다른 것과 연결하고 나서 픽쳐(데이터의 형식을 지정하는)를 드롭하는 프로토콜이다.  연결이 설정된 후 두 모듈은 인터페이스라고 불리는 메커니즘을 통해 통신할 수 있다.  인터페이스는 정적 또는 동적으로 링크된 엔트리 포인터나 통신 프로세스가 시작되는 일반 목적용 COM함수와 다른 하드-코드된 주소를 필요로 하지 않는다.

CHAPTER 28 마이크로소프트 ODBC를 통한 데이터베이스 관리

CHAPTER 28  ODBC(Open DataBase Connectivity)  ODBC는 SQL(Structured Query Language)의 표준화된 버전에 기초를 둔다.  ODBC와 SQL을 사용하면, 다른 데이터베이스 제품과는 상관없는(독립적인) 데이터베이스 액세스 코드를 작성할 수 있다.  데이터베이스 관리의 이점  표준 파일 포맷 사용 - MDB포맷을 사용하면, 데이터베이스의 모든 테이블과 인덱스를 하나의 디스크 파일에 포함시킬 수 있다.  인덱스 파일 액세스 - 키를 사용하여 레코드를 빠르게 액세스하려면, 인덱스 파일 액세스가 필요하다.  데이터 무결성 보호 - 전문적인 DBMS 제품은 데이터를 보호하는 프로시저를 가지고 있다.(예, 트랜잭션 처리)  트랜잭션에는 일련의 연관성 있는 변화들이 포함되는데, 이 때 트랜잭션 전체가 처리되지 못하면 트랜잭션은 rollback되고, 따라서 데이터베이스는 트랜잭션 이전의 원래 상태로 돌아가게 되므로 서로 관련되는 데이터들의 무결성이 보장된다.  다중 사용자 액세스 컨트롤  DBMS는 대부분 레코드 로킹을 제공하여 동시 사용자들 사이에서의 엉킴을 막아준다.

CHAPTER 28  SQL(구조적 질의어)  자체의 문법을 가진 표준 데이터베이스 액세스 언어이다.  데이터베이스는 행(row:레코드)과 열(column:필드)로 이루어진 테이블의 콜렉션이다.  ODBC 표준  SQL 문법 규칙과, SQL 데이터베이스에 대한 C언어 프로그래밍 인터페이스를 정의.  Visual C++과 ODBC SDK에는, DBF 파일, 액세스 MDB 데이터베이스, 액셀 XLS파일, 폭스프로 파일, ASCII 텍스트 파일, SQL서버 데이터베이스를 위한 32비트 드라이버가 포함되어 있다.  C++ 프로그램을 사용하여 SQL 서버 데이터베이스를 갱신한 다음, 규격품인 ODBC 호환 리포트 라이터를 사용하여 포맷을 만들고 데이터를 프린트할 수 있다.  ODBC는 실제 데이터베이스 관리 및 처리로부터 사용자 인터페이스를 분리한다.  ODBC를 이용하면 프로그래머들은 데이터베이스 제품에 상관없이 하나의 API만을 배우면 된다.

CHAPTER 28  ODBC 아키텍처  DLL에 기초한 ODBC 고유의 아키텍처는 시스템 전체를 모듈러로 만드는 것.  ODBC32.DLL은 API를 정의한다.  ODBC32.DLL은 프로그램이 실행되는 동안 특정 데이터베이스가 지정한 DLL(드라이버)을 로드한다.  ODBC32.DLL은 윈도우 레지스트리의 도움을 받아, 데이터베이스에 지정된 DLL이 이용가능한지 추적하여 단일 프로그램이 다수의 DBMS 데이터를 동시에 접근하도록 한다.  ODBC SDK 프로그래밍  ODBC 요소 3가지 - 환경(environment), 커넥션(connection), 문장(statement)  ODBC32.DLL에는 레지스트리에서 정의된 커넥션을 나열한 내장 윈도우 다이얼로그를 가지고 있다.  일단 커넥션이 있으면, 실행할 SQL문장이 필요하다. SELECT FNAME, LNAME, CITY FROM AUTHORS WHERE STATE = ‘UT’ ORDER BY LNAME 특정 드라이버와 데이터 소스 조합을 참조한다.

CHAPTER 28  ODBC SDK 프로그래밍  다이너셋(Dynaset) - 동적 행집합  데이터베이스가 변경될 때마다 행집합을 갱신한다.  스냅샷(Snapshots) - 정적 행집합  레코드를 가리키는 포인터의 리스트를 메모리 내에 구축하게 된다.  이들 레코드들은 일단 스크롤하면 변경되지 않으므로, 다중 사용자 상황에서는 정기적으로 데이터베이스를 다시 질의하여 스냅샷을 재구축해야 한다.  MFC ODBC 클래스 - CRecordset(행집합)과 CDatabase  CRecordset의 객체들은 스크롤되는 행집합을 표현한다.  CDatabase의 객체들은 데이터 소스와의 ODBC연결을 표현한다.  일반적으로 CRecordset에서 클래스를 파생하여 데이터베이스 테이블의 열(column)들을 매칭시킨다.  CRecordset::Open() - 파라미터 값과 데이터 멤버들을 사용하여 CDatabase 객체를 생성하고 오픈한다.  CRecordset 클래스는 기본 ODBC 행집합 코드와 더불어 데이터베이스 Dynaset과 Snapshots을 관리한다.

CHAPTER 28  CRecordset 멤버 함수 함수 설명 Open() AddNew() Update() Delete() Edit() IsBOF() IsEOF() MoveNext() MoveFirst() MoveLast() MovePrev() 레코드 셋을 연다. 새로운 레코드를 테이블에 추가할 준비를 한다. 데이터 소스에 새로운 데이터나 편집된 데이터를 저장함으로써 AddNew()와 Edit()를 완료한다. 레코드 셋 에서 현재 레코드를 삭제한다. 현재 레코드를 편집할 준비를 한다. 현재 레코드가 첫번째 레코드 앞에 위치하고 있는지를 알아낸다. 현재 레코드가 마지막 레코드 뒤에 위치하고 있는지를 알아낸다. 현재 레코드를 다음 레코드에 설정한다. 현재 레코드를 처음 레코드에 설정한다. 현재 레코드를 마지막 레코드에 설정한다. 현재 레코드를 이전 레코드에 설정한다.

CHAPTER 28  CRecordset 멤버 함수 함수 설명 GetDefaultConnect() GetDefaultSQL() DoFieldExchange() GetStatus() GetRecordCount() GetODBCFieldCount() GetODBCFieldInfo() 레코드 셋의 기초가 되는 데이터 소스의 디폴트 연결 문자열을 얻는다. 디폴트 SQL을 얻는다. 레코드 셋 데이터 필드와 데이터 소스간에 대응되는 레코드끼리 데이터를 교환한다. 레코드 셋의 현재 레코드 인덱스와 최종 개수 상태를 얻는다. 레코드 셋 안에 있는 레코드의 개수를 얻는다. 레코드 셋 객체 내의 필드 수를 얻는다. 레코드 셋 객체 내의 필드에 대한 정보를 얻는다.

CHAPTER 28  레코드 셋 내의 행(row) 개수 count  레코드 셋에 포함된 레코드 수를 알고 싶은 경우 MoveNext()를 호출하여 전체 테이블을 루핑해야만 한다.  프로그램에서 레코드를 추가/삭제하거나, 또는 다른 사용자가 레코드를 추가/삭제하더라도 레코드 개수는 조정되지 않는다.  high-water mark 현재까지 추출되어진 레코드의 총 개수

CHAPTER 28  ODBC 예외 처리하기  MFC ODBC 호출들은 대부분 에러 코드를 리턴하지 않고, 대신 에러를 설명하는 문자열을 포함한 ODBCException 객체를 제시한다.  CRecordset::Delete() 를 호출했을 때, MFC 기초 클래스에서 제시된 ODBC 에러 메시지 박스가 출력된다. 예) 서로 릴레이션이 설정되어 있는 A와 B 두 개의 테이블이 있을 때 : A테이블에서 레코드를 삭제하려 하면, 액세스는 참조 무결성에 의해 B테이블의 행이 의존하고 있는 행을 삭제하지 못하도록 막는다.  프로그램은 에러를 삭제하여 현재 레코드에 의존하는 CRecordset::MoveNext()와 같은 함수들을 호출하지 않도록 해야 한다.  참조 무결성(Referential Integrity)  레코드의 추가, 변경, 삭제 작업시 해당 테이블과 릴레이션이 맺어 있는 테이블을 검증하여 모순이 없을 때만 작업을 허락함으로써 데이터 베이스의 신뢰성을 높이는 수단.  일단 상관되는 테이블간에 릴레이션을 설정할 때 참조 무결성을 강화해 놓으면 이러한 모순이 발생치 않도록 데이터베이스 엔진이 알아서 관리해 준다.

CHAPTER 28  ODBC 예외 처리하기  try { m_pSet->Delete(); } catch(CDBException* e) { AfxMessageBox(e->m_strError); e->Delete(); m_pSet->MoveFirst(); UpdateData(FALSE); return; m_pSet->MoveNext();

MessageBeep  MessageBeep()  BOOL MessageBeep( UINT uType );  Parameters  uType Specifies the sound type, as identified by an entry in the [sounds] section of the registry.  MessageBeep() 함수에서 이용할 수 있는 매개 변수 목록 매개변수 설명 0xFFFFFFFF MB_ICONASTERISK MB_ICONEXCLAMATION MB_ICONHAND MB_ICONQUESTION MB_OK PC 스피커를 이용하는 표준 경고음 SystemAsterisk SystemExclamation SystemHand SystemQuestion SystemDefault  MessageBeep()는 사용자의 제어판에 있는 소리 애플릿에서 WindowsAsterisk 소리와 결합된 웨이브 파일을 재생한다.  웨이브 파일 소리는 MB_ICONASTERISK 매개 변수에 의해 결정된다.  사용자의 PC에서 소리를 이용할 수 없다면, MessageBeep()는 PC 스피커에서만 나타난다. MessageBeep

일반 진단 매크로  MFC가 제공하는 범용 진단 매크로 매크로 사용 방법 ASSERT DEBUG_NEW TRACE ASSERT_KINDOF ASSERT_VALID DEBUG_NEW TRACE TRACE0 TRACE1 TRACE2 TRACE3 VERIFY 하나의 불 값 매개변수를 계산하여 결과가 FALSE이면, 진단 메시지를 출력하고(MFC의 디버그 버전에서), 프로그램을 중단시키게 된다. 가리키는 객체가 특정 클래스의 객체(또는 특정 클래스로 부터 파생된 객체) 이어야 함을 나타내는 역할을 한다. 자신의 AssertValid() 메소드를 호출하여 CObject 객체(또는 이로부터파생된 객체)의 내부 상태의 유효성을 조사한다. 메모리가 깨지는 현상을 디버깅하는 것을 도와 준다. 힙 영역을 할당하기 위해 new 연산자를 사용할 수 있는 곳이면, 어느 곳에서나 사용할 수 있다. 모든 객체 를 할당할 때 파일 이름과 줄 번호를 제공하는 역할을 한다.(디버그 모드일때) MFC의 디버그 버전에서 C 실행 시간 라이브러리 printf() 함수와 같이 포맷된 디버깅 출력을 제공하는 역할을 한다. 매개변수가 없는 포맷 문자열만 받아들인다. 매개변수가 하나만 있는 포맷 문자열만 받아들인다. 두 개의 매개변수만 갖는 포맷 문자열만 받아들인다. 세 개의 매개변수만 갖는 포맷 문자열만 받아들인다. ASSERT와 유사하지만 MFC의 디버그 버전은 물론 발표 버전에서도 동작한다.  MFC42.DLL : Release 버전, MFC42D.DLL : Debug 버전

일반 진단 변수와 함수  MFC의 일반 진단 변수와 함수 함수 설명 AfxCheckMemory() afxDump AfxEnableMemoryTracking() 현재 할당된 모든 메모리 무결성을 조사한다. 디버거로부터 호출되었을 때 기본 객체 덤프 기능을 제공하고 있다. CDumpContext 객체를 통해서 디버거 출력창(또는 디버그 터미널) 에 디버깅 데이터를 보낸다. 메모리 블록이 올바로 할당되는지를 확인하기 위해 메모리 추적 기능을 활성화하거나 비활성 상태로 만드는 역할을 한다. AfxIsMemoryBlock() new 연산자의 디버그 버전을 사용할 때 메모리 블록이 올바로 할당되었는지의 여부를 검증한다. AfxIsValidAddress() 메모리 주소가 응용 프로그램의 메모리 공간 내에 존재하는지 조사한다. AfxIsValidString() 문자열에 대한 포인터가 조사한다. afxMemDF 디버깅 메모리 할당자의 행동을 제어하여 할당 상태의 진단을 사용자가 조정할 수 있게 한다. AfxSetAllocHook() 메모리를 할당하기 전에 특정 함수를 호출할 수 있게 하는 후크를 설정한다. afxTraceEnabled TRACE 매크로가 활성화되어 있는지의 여부를 결정한다. afxTraceFlags MFC의 내장된 보고 기능을 활성화하는 역할을 한다.

일반 진단 변수와 함수  MFC 객체 진단 함수  AfxDoForAllClasses() 매크로 DECLARE_DYNAMIC, DECLARE_DYNCREATE, DECLARE_SERIAL로 실행 시간 유형 조사를 지원하는 모든 CObject로 부터 파생된 클래스들에 대해 특정 반복 함수를 호출한다.  AfxDoForAllObjects() new 연산자를 사용하여 할당된 모든 CObject로 부터 파생된 객체들에 대해 특정 함수를 호출한다.

문자열  CString 객체를 문자 배열로 취급할 때 사용하는 String 메소드와 연산자 메소드 또는 연산자 설명 Empty() 문자 배열의 길이가 0이 되도록 CString 을 비운다. GetAt() 배열에서 특정 위치에 존재하는 문자를 얻는다. GetLength() CString 문자열 내의 문자들의 수를 구한다. IsEmpty() CString 객체가 아무 문자라도 갖고 있는지 조사한다. SetAt() 문자열 내에서 특정 위치에 있는 문자를 바꾼다. (바꿀 문자는 \0이 될 수 없다.) 연산자 [ ] 배열 내의 특정 위치에 있는 문자를 얻는다. GetAt() 메소드 대신에 사용한다. 연산자 LPCTSTR CString 객체에 저장되어 있는 문자들에 대한 포인터를 반환한다.

문자열  CString 할당, 접합, 비교, 추출 연산자 설명 연산자 = 새 값을 CString 객체에 할당한다. 연산자 + 두 개의 문자열을 더하여 새 문자열을 반환한다. 연산자 += 새 문자열을 기존의 문자열의 끝에 붙인다.  CString str1 = “This is an easy way to perform”; CString str2 = “string concatenation”; CString str3 = str1 + “ ” + str2; AfxMessageBox(str3, MB_OK | MB_ICONINFORMATION);

문자열  CString 비교 메소드와 연산자 메소드 또는 연산자 설명 Compare() 두 문자열을 비교한다. (대소문자 구별) CompareNoCase() 두 문자열을 비교한다. (대소문자 구별하지 않음) 연산자 == 두 문자열이 같은지 조사한다. (대소문자 구별) 연산자 != 두 문자열이 서로 다른지 조사한다. (대소문자 구별) 연산자 < 한 문자열이 다른 문자열보다 작은지 조사한다. (대소문자 구별) 연산자 > 한 문자열이 다른 문자열보다 큰지 조사한다. (대소문자 구별) 연산자 <= 한 문자열이 다른 문자열보다 작거나 같은지 조사한다. (대소문자 구별) 연산자 >= 한 문자열이 다른 문자열보다 크거나 같은지 조사한다. (대소문자 구별)  A string < a string A string > A String A string = A string

문자열  CString 추출 메소드 메소드 설명  하위 문자열을 추출하고 연결 Left() 문자열의 문자 배열 왼쪽 부분에서 지정한 수의 문자들을 추출한다. Mid() 문자열의 문자 배열 중간 부분에서 지정한 수의 문자들을 추출한다. Right() 문자열의 문자 배열 오른쪽 부분에서 지정한 수의 문자들을 추출한다. SpanExcluding() 지정한 문자 배열에 없는 문자들로만 이루어진 하위 문자열을 추출한다. SpanIncluding() 지정한 문자 배열에 있는 문자들로만 이루어진 하위 문자열을 추출한다.  하위 문자열을 추출하고 연결 CString str1 = “This is the way to perform string extraction!”; CString str2 = str1.Left(8) + str1.Right(18); AfxMessageBox(str2, MB_OK | MB_ICONINFORMATION);

문자열  CString 서식 지정과 변환 메소드 메소드 설명  CString 검색 메소드 Format() C 실행시간 라이브러리 함수 sprintf()가 하는 것과 같은 방법으로 문자열의 서식을 지정한다. FormatMessage() 메시지 문자열의 서식을 지정한다.(Format()과 유사) MakeLower() 문자열 내의 모든 문자를 소문자로 변환한다. MakeReverse() 문자열 내의 문자들을 뒤집는다. MakeUpper() 문자열 내의 모든 문자를 대문자로 변환한다. TrimLeft() 문자열의 왼쪽에서 여백 문자들을 제거한다. TrimRight() 문자열의 오른쪽에서 여백 문자들을 제거한다. Find() 지정한 하위 문자열과 일치하는 문자열 내의 첫번째 문자의 0을 기반으로 한 인덱스를 반환한다. ReverseFind() 지정한 하위 문자열과 일치하는 문자열 내의 마지막 문자의 0을 FindOneOf() 지정한 하위 문자열 내에 포함된 임의의 글자와 일치하는 문자열 내의 첫번째 문자의 0을 기반으로 한 인덱스를 반환한다.  CString 검색 메소드

문자열  CString 버퍼 액세스 메소드 메소드 설명 FreeExtra() GetBuffer() GetBufferSetLength() 그러나 문자열을 지정된 길이만큼 자른다. ReleaseBuffer() GetBuffer() 메소드가 반환한 버퍼에 있는 문자열을 반환한다. LockBuffer() 문자열의 복사본을 만들고, 이를 버퍼 내에 잠금으로써 CString 참조 계수기를 비활성 상태로 만들고, 버퍼 내의 문자열을 보호한다. UnlockBuffer() LockBuffer() 메소드를 호출하여 얻은 버퍼의 잠금을 풀고 참조 계수기를 활성화한다.

문자열  문자열 비교  int strcmp( const char *string1, const char *string2 );  헤더파일 string.h  int wcscmp( const wchar_t *string1, const wchar_t *string2 );  wide-character, 헤더파일 string.h, wchar.h  int _mbscmp(const unsigned char *string1, const unsigned char *string2 );  multibyte-character, 헤더파일 mbstring.h  int strncmp( const char *string1, const char *string2, size_t count );  int wcsncmp( const wchar_t *string1, const wchar_t *string2, size_t count );  int _mbsncmp( const unsigned char *string1, const unsigned char *string2, size_t count );  int _strnicmp( const char *string1, const char *string2, size_t count );  int _wcsnicmp( const wchar_t *string1, const wchar_t *string2, size_t count );  int _mbsnicmp( const unsigned char *string1,  Parameters  string1, string2 Strings to compare  count Number of characters to compare

문자열  헤더파일 string.h  wide-character, 헤더파일 string.h, wchar.h  문자열 복사  char *strcpy( char *strDest, const char *strSource );  헤더파일 string.h  wchar_t *wcscpy( wchar_t *strDest, const wchar_t *strSource );  wide-character, 헤더파일 string.h, wchar.h  unsigned char *_mbscpy( unsigned char *strDest, const unsigned char *strSource );  multibyte-character, 헤더파일 mbstring.h  char *strncpy( char *strDest, const char *strSource, size_t count );  wchar_t *wcsncpy( wchar_t *strDest, const wchar_t *strSource, size_t count );  unsigned char *_mbsncpy( unsigned char *strDest, const unsigned char *strSource, size_t count );  Parameters  strDest Destination string  strSource Source string  count Number of characters to be copied

문자열  문자열 연결  char *strcat( char *strDest, const char *strSource );  헤더파일 string.h  wchar_t *wcscat( wchar_t *strDest, const wchar_t *strSource );  wide-character, 헤더파일 string.h, wchar.h  unsigned char *_mbscat( unsigned char *strDest, const unsigned char *strSource );  multibyte-character, 헤더파일 mbstring.h  char *strncat( char *strDest, const char *strSource, size_t count );  wchar_t *wcsncat( wchar_t *strDest, const wchar_t *strSource, size_t count );  unsigned char *_mbsncat( unsigned char *strDest, const unsigned char *strSource, size_t count);  Parameters  strDest Null-terminated destination string  strSource Null-terminated source string  count Number of characters to append

문자열  문자열 길이  size_t strlen( const char *string );  헤더파일 string.h  size_t wcslen( const wchar_t *string );  wide-character, 헤더파일 string.h, wchar.h  size_t _mbslen( const unsigned char *string );  multibyte-character, 헤더파일 mbstring.h  size_t _mbstrlen( const char *string );  헤더파일 stdlib.h  Parameter  string Null-terminated string

콜렉션 클래스  템플릿 기반의 콜렉션 클래스  비템플릿 기반의 콜렉션 클래스  콜렉션 모양  배열  이들 클래스는 동적으로 크기를 변경할 수 있고, 인덱스가 붙은 객체 배열을 제공한다.  목록  이들 클래스는 이중 링크 목록으로 구현된 요소들의 목록을 제공한다.  목록 내에 요소들을 넣고 빼는 작업을 매우 빠르고 효율적으로 수행할 수 있다.  맵  이들 클래스는 키 객체를 값 객체와 연관시키는 콜렉션을 제공한다.

콜렉션 클래스 배열 클래스 설명  비템플릿 기반의 콜렉션 클래스  AFXCOLL.H 를 포함시켜야 한다. CByteArray() 동적으로 크기를 변경할 수 있는 바이트의 배열을 지원한다.(BYTE형) CDWordArray() 동적으로 크기를 변경할 수 있는 32바이트의 배열을 지원한다.(DWORD형) CObArray() 동적으로 크기를 변경할 수 있는 CObject 포인터의 배열을 지원한다. CPtrArray() 동적으로 크기를 변경할 수 있는 void 포인터의 배열을 지원한다.(void *형) CStringArray() 동적으로 크기를 변경할 수 있는 CString 객체의 배열을 지원한다.  비템플릿 기반의 콜렉션 클래스  AFXCOLL.H 를 포함시켜야 한다.  비템플릿 기반의 배열 클래스  이들 클래스는 보통 이미 사용하고 있는 이전의 MFC 프로그램과의 호환성을 위해 사용한다. CUIntArray() 동적으로 크기를 변경할 수 있는 부호없는 정수의 배열을 지원한다. CWordArray() 동적으로 크기를 변경할 수 있는 16비트의 배열을 지원한다.(WORD형)

콜렉션 클래스 목록 클래스 설명  비템플릿 기반의 목록 클래스 CObList() CPtrList() CStringList() 유일하지 않은 CObject 포인터들의 순서가 있는 이중 링크 목록을 지원한다. CPtrList() 유일하지 않은 void 포인터들의 순서가 있는 이중 링크 목록을 지원한다. CStringList() 유일하지 않은 CString 포인터들의 순서가 있는 이중 링크 목록을 지원한다.  비템플릿 기반의 목록 클래스

콜렉션 클래스 맵 클래스 설명  비템플릿 기반의 맵 클래스 CMapPtrToPtr() void 포인터를 키로 갖고 있는 void 포인터의 맵을 지원 CMapPtrToWord() void 포인터를 키로 갖고 있는 16비트 워드의 맵을 지원 CMapStringToOb() 고유의 CString 객체나 문자열을 키로 갖고 있는 CObject 포인터의 맵을 지원  비템플릿 기반의 맵 클래스 콜렉션 클래스 CMapStringToPtr() 고유의 CString 객체를 키로 갖고 있는 void 포인터(void *)의 맵을 지원 CMapStringToString() CString 객체를 키로 갖고 있는 CString 객체의 맵을 지원 CMapWordToOb() 16비트 단어를 키로 갖고 있는 CObject 포인터의 맵을 지원 CMapWordToPtr() 16비트 단어를 키로 갖고 있는 void 포인터(void *)의 맵을 지원

콜렉션 클래스 템플릿 클래스 설명  템플릿 기반의 클래스 CArray 임의 유형의 객체로 된 배열을 생성하는데 사용한다. CList 임의 유형의 객체로 된 목록을 생성하는데 사용한다. CMap 임의 유형의 객체로 된 맵을 생성하는데 사용한다.  템플릿 기반의 클래스  이들 클래스는 개발자가 재사용할 수 있는 소프트웨어 클래스를 만들 수 있도록 해준다.  이들 클래스를 이용하면, 임의 유형의 객체로 된 배열과 목록, 맵을 만들 수 있다. CTypedPtrArray CObArray 와 CPtrArray 객체로 된 유형 안전 배열을 만드는데 사용한다. CTypedPtrList CObList 와 CPtrList 객체로 된 유형 안전 목록을 만드는 데 사용한다. CTypedPtrMap CObMap과 CPtrMap객체로 된 유형 안전 맵을 만드는데 사용한다.

날짜와 시간 클래스  CTime 클래스 메소드 메소드 설명 Format() FormatGmt() GetDay() GMT(Greenwich Mean Time)로 알려진 UTC(Universal Time Coordinates) 를 바탕으로 서식이 지정된 문자열로 CTime 객체를 변환한다. GetDay() GetDayOfWeek() CTime 객체에 나타난 그 달의 오늘 날짜(1-31)를 구한다. CTime 객체에 나타난 요일(1-7)을 구한다. GetGmtTm() CTime 객체를 UTC를 기반으로 각 요소별로 분석한다. (Time.h 에 있는 tm 구조에 정의된 대로) GetHour() CTime 객체에 나타난 시간(0-23)을 구한다. GetLocalTm() CTime 객체를 지역 시간대를 기반으로 각 요소별로 분석한다. GetMinute() CTime 객체에 나타난 분(0-59)을 구한다. GetMonth() GetSecond() CTime 객체에 나타난 월(1-12)을 구한다. CTime 객체에 나타난 초(0-59)를 구한다. GetTime() CTime 객체의 의미에 맞게 time_t 구조를 채운다. GetYear() CTime 객체에 나타난 연도를 구한다.

날짜와 시간 클래스  CTime 클래스 연산자 연산자 설명 연산자 = 시간 값을 할당한다. 연산자 + CTimeSpan과 CTime 객체를 더한다. 연산자 - CTimeSpan과 CTime 객체를 뺀다. 연산자 += CTimeSpan객체를 CTime 객체에 더한다. 연산자 -= CTimeSpan객체를 CTime 객체로부터 뺀다. 연산자 == 두 개의 절대 시간이 같은지 비교한다. 연산자 != 두 개의 절대 시간이 같지 않은지 비교한다. 연산자 < 두 개의 절대 시간 중 하나가 다른 것보다 작은지 비교한다. 연산자 > 두 개의 절대 시간 중 하나가 다른 것보다 큰지 비교한다. 연산자 <= 두 개의 절대 시간 중 하나가 다른 것보다 작거나 같은지 비교한다. 연산자 >= 두 개의 절대 시간 중 하나가 다른 것보다 크거나 같은지 비교한다.

날짜와 시간 클래스  CTimeSpan 클래스 메소드 메소드 설명 Format() GetDays() CTimeSpan에 있는 완전한 날의 수를 구한다. GetHours() 오늘 날짜의 수(-23 ~ 23)를 구한다. GetMinutes() 현재의 시간에 있는 분의 수(-59 ~ 59)를 구한다. GetSeconds() 현재의 분에 있는 초의 수(-59 ~ 59)를 구한다. GetTotalHours() CTimeSpan에 있는 완전한 시간의 전체 수를 구한다. GetTotalMinutes() CTimeSpan에 있는 완전한 분의 전체 수를 구한다. GetTotalSeconds() CTimeSpan에 있는 완전한 초의 전체 수를 구한다.

날짜와 시간 클래스  CTimeSpan 클래스 연산자 연산자 설명 연산자 = 새 시간 값을 할당한다. 연산자 + 연산자 - CTimeSpan 객체를 뺀다. 연산자 += CTimeSpan객체를 CTimeSpan 객체에 더한다. 연산자 -= CTimeSpan객체를 CTimeSpan 객체로부터 뺀다. 연산자 == 두 개의 절대 시간이 같은지 비교한다. 연산자 != 두 개의 절대 시간이 같지 않은지 비교한다. 연산자 < 두 개의 절대 시간 중 하나가 다른 것보다 작은지 비교한다. 연산자 > 두 개의 절대 시간 중 하나가 다른 것보다 큰지 비교한다. 연산자 <= 두 개의 절대 시간 중 하나가 다른 것보다 작거나 같은지 비교한다. 연산자 >= 두 개의 절대 시간 중 하나가 다른 것보다 크거나 같은지 비교한다.

CDialog  CDialog 클래스 메소드 메소드 설명 DoModal() EndDialog() 규격 대화 상자를 호출하고, 대화 상자가 닫히기 전에는 반환하지 않는다. EndDialog() 규격 대화 상자를 닫거나 비규격 대화 상자를 숨긴다. GetDefID() 대화 상자의 기본 누름 단추 컨트롤의 ID를 받는다. GotoDlgCtrl() 대화 상자 내의 특정 컨트롤에 입력 포커스를 맞춘다. MapDialogRect() 직사각형의 대화 상자 단위를 나타내기 위한 단위에 맵핑한다. NextDlgCtrl() 대화 상자의 입력 포커스를 다음 컨트롤로 옮긴다. PrevDlgCtrl() 대화 상자의 입력 포커스를 이전 컨트롤로 옮긴다. SetDefID() 대화 상자에 기본 누름 단추 컨트롤을 설정한다. SetHelpID() 대화 상자에 문맥을 감지하여 동작하는 도움말 ID를 설정한다.

DDV(Dialog Data Validation)  이 함수들은 전형적으로 유효성 검사시 일어난 문제점을 알리는 메시지 상자를 나타내고, 문제가 일어난 컨트롤에 포커스를 맞춘다.  사용자가 입력한 데이터가 유효하지 않거나 받아들일 수 있는 범위를 벗어났을 때 예외를 발생시킨다.  컨트롤의 DDV 함수의 호출은 DDX 함수를 호출한 후에 일어나야 한다. 메소드 설명 DDV_MaxChars() 특정 값의 매개 변수와 연결된 컨트롤에서 문자의 개수가 지정된 값을 초과하지 않았는지를 확인한다. DDV_MinMaxByte() 컨트롤의 BYTE 값이 지정된 최소, 최대값 사이에 있는지 확인한다. DDV_MinMaxDouble() 컨트롤의 DOUBLE 값이 지정된 최소, 최대값 사이에 있는지 확인한다. DDV_MinMaxDWord() 컨트롤의 DWORD 값이 지정된 최소, 최대값 사이에 있는지 확인한다. DDV_MinMaxFloat() 컨트롤의 FLOAT 값이 지정된 최소, 최대값 사이에 있는지 확인한다. DDV_MinMaxInt() 컨트롤의 INT 값이 지정된 최소, 최대값 사이에 있는지 확인한다. DDV_MinMaxLong() 컨트롤의 LONG 값이 지정된 최소, 최대값 사이에 있는지 확인한다. DDV_MinMaxUnsigned() 컨트롤의 UINT 값이 지정된 최소, 최대값 사이에 있는지 확인한다.