Visual C++ Programming Controls and CList Department of Digital Contents Sang Il Park
Review: Control 표준화된 형태와 특성을 가진 윈도우 사용자에게 입력을 받거나 정보를 보여줌
Review: Message-based system 컨트롤과 부모 윈도우 통지 메시지 (Notification Message) 컨트롤의 상태가 변화되었음을 알림 메모리 부족 등으로 인한 오류를 알림 컨트롤 메시지 (Control Message) 컨트롤의 상태를 알아내거나 변경 컨트롤 (자식 윈도우) 부모 윈도우 ① 통지 메시지 ② 컨트롤 메시지
Review: Various controls MFC 컨트롤 클래스 컨트롤 MFC 클래스 컨트롤 버튼 버튼 컨트롤 CButton 정적 컨트롤 CStatic 편집 컨트롤 CEdit 리스트 박스 컨트롤 CListBox 콤보 박스 컨트롤 CComboBox 스크롤 바 컨트롤 CScrollBar
Review: Button Control Radio Button 그룹
Review: 버튼 컨트롤 컨트롤 생성 방법 ① 일반 윈도우에서 직접 만들기 ② 대화상자를 통해 만들기
Review: 버튼 붙이기 1. 버튼 객체를 맴버 변수로 추가 Ex) CChildView의 header file에 CButton 객체 추가 2. CButton의 Create(..) 맴버 함수를 호출하여 생성 Ex) CChildView::OnCreate() 내부에 추가 ChildView.h의 CChildView의 내부에… CButton m_button; // C++ 객체 추가 m_button.Create( "누르세요", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, CRect(100, 100, 200, 130), this, 101); // 푸시 버튼 생성
Review: 버튼 컨트롤 생성 방법 CButton::Create() 함수 Caption - 캡션 문자열 Style - 일반 윈도우 스타일 + 버튼 컨트롤 스타일 rect - 컨트롤 크기와 위치 pParentWnd - 부모 윈도우 UINT nID - 컨트롤 ID (ex, 101, 102…) BOOL CButton::Create (Caption, Style, rect, pParentWindow, ID) ;
Review: 버튼 컨트롤의 Style 버튼 컨트롤 스타일 의미 BS_PUSHBUTTON 푸시 버튼 BS_CHECKBOX 체크 박스 BS_AUTOCHECKBOX 자동 체크 박스:클릭하면 자동으로 체크 표시가 On/Off BS_3STATE 3상태 체크 박스 BS_AUTO3STATE 자동 3상태 체크 박스: 클릭하면 자동으로 체크 표시가 On/Grayed/Of BS_RADIOBUTTON 라디오 버튼 BS_AUTORADIOBUTTON 자동 라디오 버튼: 클릭하면 자동으로 선택과 선택 해제가 이뤄짐과 선택 해제가 이루어짐 BS_GROUPBOX 그룹 박스
Review: 버튼 컨트롤의 동작 버튼이 눌렸다면? 버튼이 눌렸다는 메시지 발생 통지 메시지 처리하기 메시지 핸들러 작성 메시지 맵에 메시지 추가 메시지 핸들러 함수구현 컨트롤 (자식 윈도우) 부모 윈도우 통지 메시지
Review: 버튼 컨트롤의 동작 1. Message Map에 추가 2. 핸들러 함수 추가 ON_BN_CLICKED( ID, 함수 이름) Ex) ON_BN_CLICKED( 101, OnButtonClicked) // 메시지맵 void CChildView::OnButtonClicked( ) // 메시지 핸들러 { MessageBox("버튼을 눌렀습니다."); }
Review: 버튼 컨트롤의 정보 변경 버튼의 상태를 변경하고 (알고) 싶다면? 컨트롤 메시지활용 버튼의 상태를 변경하고 (알고) 싶다면? 컨트롤 메시지활용 컨트롤(버튼)의 현재 상태를 변화 시킴 컨트롤(버튼)에게 현재의 상태를 물어봄 컨트롤 (자식 윈도우) 부모 윈도우 컨트롤 메시지
Review: 버튼 컨트롤의 정보 변경 컨트롤 메시지 보내기 멤버 함수 호출 버튼의 체크상태 변환 버튼의 체크상태 확인 m_button.SetCheck(BST_CHECKED); m_button.SetCheck(BST_UNCHECKED); if ( m_button.GetCheck() == BST_CHECKED ) AfxMessageBox(“버튼이 체크되었습니다”);
코딩연습 다음과 같은 다양한 버튼을 만들어 본다.
버튼 컨트롤 생성 방법 컨트롤 생성 - 두 번째 방법 대화상자 템플릿에 컨트롤 추가 컨트롤 변수 생성 대화상자가 생성될 때 컨트롤도 자동으로 생성 컨트롤 변수 생성 컨트롤 자체를 나타내는 변수(=컨트롤 변수)를 생성하고 이를 이용하여 컨트롤을 조작
코딩 연습 대화상자기반을 선택하여 프로젝트 생성 (또는 FormView) 대화상자편집기를 사용하여 창을 디자인
버튼 컨트롤 메시지 핸들러 추가 방법1 대화창의 속성창을 통해 이벤트 핸들러 추가
버튼 컨트롤 메시지 핸들러 추가 방법2 해당 콘트롤에 마우스 오른 버튼 이벤트핸들러추가선택
버튼 컨트롤 변수 추가 해당 콘트롤에 마우스 오른 버튼 변수추가선택
버튼 컨트롤 (8/8) 컨트롤 변수 생성 (cont'd) // 헤더 파일 // 구현 파일 class CTestDlg::public CDiglog { ... CButton m_button; } // 구현 파일 void CTestDlg::DoDataExchange(CDataExchange* pDX) CFormView::DoDataExchange(pDX); //{{AFX_DATA_MAP(CExButtonView) DDX_Control(pDX, IDC_BUTTON1, m_button); //}}AFX_DATA_MAP
코딩연습 다음과 같이 대화상자에 다양한 버튼을 만들어 본다. Pust Button을 누르면 가 버튼의 선택사항을 보여줌
Control (Button) 편하게 쓰기.. (라디오) 버튼이 많다면? 일일이 핸들러를 추가하기 귀찮다 한꺼번에 핸들러를 추가한다. ON_COMMAND_RANGE 사용 ON_COMMAND_RANGE (IDC_RADIO1, IDC_RADIO6, OnRadioClick) 시작ID 번호 끝ID 번호 호출함수 홈페이지에 있는 예제 프로그램 참고: http://dasan.sejong.ac.kr/~sipark/class2008/vc/RadioButtonTest.zip
잠깐 번외편: Linked List 와 MFC Template Library CList
많은 데이터를 저장하는 방법 1. Array 이용 A[4] 2 Linked List 이용 a NULL 10 20 30 40 value: 10 Node * p value: 20 Node * p value: 30 Node * p value: 40 Node * p a NULL
구조체와 포인터를 이용한 Linked List 구조체 내에 포인터를 맴버로 가질 수 있다 struct IHavePointer { int a; int * p; };
구조체와 포인터를 이용한 Linked List 구조체를 가리키는 포인터를 맴버로 가질 수 있다 struct test { int a; test * p; };
구조체를 가리키는 맴버 포인터 struct test { int a; test * p; }; test ts; ts.a=20; ts.p=&ts; cout<<“ts.a:”<<ts.a<<“\n”; cout<<“ts.p->a:”<<ts.p->a<<“\n”; cout<<“ts.p->p->a:”<<ts.p->p->a<<“\n”;
구조체를 가리키는 맴버 포인터 struct Dizzy { int id; Dizzy * p; }; Dizzy a,b,c; a.id = 1; a.p=&b; b.id = 2; b.p=&c; c.id = 3; c.p=&a; cout<<“a.id:”<<a.id<<“\n”; cout<<“b.id:”<<a.p->id<<“\n”; cout<<“c.id:”<<a.p->p->id<<“\n”;
구조체를 가리키는 맴버 포인터
코딩연습 (linked list) 다음과 같은 구조체를 만들고 Node 변수 a,b,c,d 4개를 만든다. 각 변수를 그림과 같이 연결한다. a부터 시작해 반복문(while) 을 통해 모든 변수의 value값을 출력 해 보자 struct Node { int value; Node * p; }; value: 10 Node * p value: 20 Node * p value: 30 Node * p value: 40 Node * p a b c d NULL
템플릿과 STL
템플릿 (Template) ? tem·plate n. 1 본뜨는 공구(工具), 형판(型板) 2【건축】 보받이, 도리받이 3 조선대(造船臺)의 쐐기;(반)투명의 피복지(彼覆紙) 4【생화학】 (핵산의) 주형(鑄型) 5【컴퓨터】 보기판, 템플릿 《키보드 위에 놓고 각 키에 할당된 명령의 내용을 보이는 시트》
일반성이 필요한 예제: 두 정수 중 큰 수를 알려주는 max 함수 int max(int a, int b) { if(a>b) return a; else return b; } 두 실수 간의 비교가 필요하다면??? 오버로딩! OVERLOADING!
일반성이 필요한 예제: 두 실수 중 큰 수를 알려주는 max 함수 두 double 간의 비교가 필요하다면??? float max(float a, float b) { if(a>b) return a; else return b; } 오버로딩! OVERLOADING! 두 char 간의 비교가 필요하다면??? 오버로딩! OVERLOADING! 두 complex 간의 비교가 필요하다면??? 오버로딩! OVERLOADING!
한 번에 해결할 수 없을까? 템플릿 (Template)!
다시 붕어빵… 템플릿 (Template)!
템플릿의 활용방법 템플릿 클래스 템플릿 함수
일반적인 스마트 포인터 class AutoArray { public: AutoArray(int * ptr) { _ptr = ptr; } ~AutoArray() { delete [] _ptr; } int& operator[] (int index) { return _ptr[index]; } private: int * _ptr; };
스마트 포인터 활용 AutoArray는 정수형에 대해서만 동작! int main() { AutoArray arr( new int[100] ); arr[20] = 30; return 0; } AutoArray는 정수형에 대해서만 동작!
정수형 스마트 포인터 class AutoArray { public: AutoArray(int * ptr) { _ptr = ptr; } ~AutoArray() { delete [] _ptr; } int& operator[] (int index) { return _ptr[index]; } private: int * _ptr; };
템플릿 클래스의 사용(1) 모든 타입의 배열을 위한 스마트 포인터 클래스 template <typename T> class AutoArray { public: AutoArray(T* ptr) { _ptr = ptr; } ~AutoArray() { delete[] _ptr;} T& operator[] (int index) { return _ptr[index]; } private: T* _ptr; };
템플릿 클래스의 사용(2) 모든 타입의 배열을 위한 스마트 포인터 클래스 int main() { AutoArray<float> arr( new float [100] ); arr[0] = 99.99f; return 0; }
템플릿 클래스의 사용(3) 템플릿 매개 변수의 사용 [29-1]
템플릿 클래스의 이해 템플릿 클래스 객체를 생성하는 순간 컴파일러 내부적으로 알맞은 클래스 생성 개발자가 만든 코드 template< typename A, typename B, int MAX > class TwoArray { // 중간 생략 A arr1[ MAX ]; B arr2[ MAX ]; }; TwoArray< char, double, 20 > arr;
템플릿 클래스의 이해 템플릿 클래스 객체를 생성하는 순간 컴파일러 내부적으로 알맞은 클래스 생성 컴파일러가 새로 만든 클래스 class TwoArray_char_double_20 // 이 이름은 임의로 만든 것 { // 중간 생략 char arr1[ 20 ]; 컴파일러에 의해 생성된 클래스 double arr2[ 20 ]; };
Standard Template Library C++ = 언어 클래스, 멤버함수, 상속, 템플릿, 오버로딩 등의 기술 STL = 템플릿 기반의 편한 사용 툴: 클래스, 함수 등의 집합체 array 나 pointer를 대체하는 데이터 관리에 용이
Standard Template Library 구성: Container 같은 타입의 원소를 관리하는 데이터 구조 지원 클레스 list, vector, deque, … Algorithm Container에 대해 복사, 전환, 병합, 정렬 random_shuffle, replace, fill, remove, sort, … Iterator 원소의 관리 방법 ( = 포인터) 함수 개체 함수 연산자 ( ) 를 오버로딩
STL 컨테이너 자주 사용하는 STL의 컨테이너 클래스 [표 29-1]
Linked List 장점: 데이터의 추가 및 삭제가 용의한 데이터 구조 단점: 데이터의 접근이 순차적으로만 가능
CList MFC에서 제공하는 Linked List Template Class 정의 방법: CList < datatype > a; 데이터 추가: CList::AddTail(..) CList::AddHead(..) 데이터 삭제: CList::RemoveTail(); CList::RemoveHeat(); CList::RemoveAt(..) 사용예: CList < int > a; 데이터 추가: CList::AddTail(3) CList::AddHead(4) 데이터 삭제: CList::RemoveTail(); CList::RemoveHeat(); CList::RemoveAt(..) iterator: POSITION
Iterator Container에서 Pointer와 같은 역할을 하는 것 MFC의 iterator 변수형 : POSITION CList <int> a; a.AddTail(10); a.AddTail(20); a.AddTail(30); POSITION pos = a.GetHeadPosition(); // 첫 데이터 위치 반환 while(pos != NULL) { int value = a.GetNext(pos); // pos위치의 데이터반환 // pos는 다음 위치 가르킴 }
Iterator a pos value 10 20 30 NULL CList <int> a; a.AddTail(10); POSITION pos = a.GetHeadPosition(); while(pos != NULL) { int value = a.GetNext(pos); }
Iterator a pos value 10 20 30 NULL CList <int> a; a.AddTail(10); POSITION pos = a.GetHeadPosition(); while(pos != NULL) { int value = a.GetNext(pos); }
Iterator a pos value 10 10 20 30 1회호출 NULL CList <int> a; a.AddTail(10); a.AddTail(20); a.AddTail(30); POSITION pos = a.GetHeadPosition(); while(pos != NULL) { int value = a.GetNext(pos); } 1회호출
Iterator a pos value 10 20 20 30 2회호출 NULL CList <int> a; a.AddTail(10); a.AddTail(20); a.AddTail(30); POSITION pos = a.GetHeadPosition(); while(pos != NULL) { int value = a.GetNext(pos); } 2회호출
Iterator a pos value 10 30 20 30 3회호출 NULL CList <int> a; a.AddTail(10); a.AddTail(20); a.AddTail(30); POSITION pos = a.GetHeadPosition(); while(pos != NULL) { int value = a.GetNext(pos); } 3회호출
Iterator a pos value 10 30 20 30 NULL 종료 CList <int> a; a.AddTail(10); a.AddTail(20); a.AddTail(30); POSITION pos = a.GetHeadPosition(); while(pos != NULL) { int value = a.GetNext(pos); } 종료
Insertion // 맨 앞에 추가 CList::AddHead( value ) // 맨 뒤에 추가 CList::AddTail( value ) // 임의의 위치에 추가 CList::InsertAfter (POSITION, value)
Retrieval/Modification // 값 얻어오기 value = CList::GetAt( POSITION ) // 값의 reference 얻어오기 value & = CList::GetAt( POSITION ) CList <int> a; a.AddHead(10); a.AddHead(20); a.AddHead(30); POSITION pos; pos = a.GetHeadPosition(); int b = a.GetAt(pos); // value int &c = a.GetAt(pos); // reference
Removal // 맨 앞 삭제 CList::RemoveHead( ) // 맨 뒤 삭제 CList::RemoveTail( ) // 임의의 위치 삭제 CList::RemoveAt(POSITION) // 모두 삭제 CList::RemoveAll( )
기타 여러가지 MFC Container Class CList CVector CMap
코딩연습 마우스 왼쪽 버튼 드래깅을 하면 그 위치에 점을 그리되 점들의 위치를 Clist를 이용하여 저장하라. 마우스 오른쪽 버튼 드래깅으로 사각형 안에 든 점들을 삭제 하라. 마우스 왼쪽 드래깅으로 점찍기 마우스 오른쪽 드래깅으로 사각형 지정 포함된 점들 지우기