7 장컨트롤 VS 2015 007. 윈도우프로그래밍 Updated 2010. 10. 11 Updated 2012. 09. 18 Updated 2015. 09. 15 http://idb.korea.ac.kr DB & Data Mining LAB. Korea University 이종욱 eastwest9@korea.ac.kr 1
7-1 컨트롤의정의 1 컨트롤 (control) : 인터페이스를통해사용자로부터명령과입력을받아들이고출력결과를보여준다. 이때컨트롤은바로입출력도구를의미한다 프로그램은실행중에끊임없이사용자와통신을하는데컨트롤을통해명령과정보를받아들이고또한컨트롤을통해실행결과를사용자에게보고 컨트롤의 3 요소 1 컨트롤스타일, 2 통지메시지, 3 부모윈도우가보내는메시지 2
7-1 컨트롤의정의 2 표준컨트롤 : 버튼, 에디트, 리스트박스, 콤보박스, 스크롤바, 스태틱 컨트롤도일종의윈도우 화면상의일정한영역을차지하며자신의고유메시지를처리 보통대화상자의차일드윈도우로존재 윈도우를만들때는 1WNDCLASS형의구조체를정의 2RegisterClass 함수로등록 3CreateWindow함수로호출컨트롤은윈도우가운영체제차원에서제공하기때문에윈도우클래스등록이필요없이미리등록되어있는윈도우클래스사용 윈도우클래스 button static scrollbar edit listbox combobox 컨트롤버튼, 체크, 라디오텍스트스크롤바에디트리스트박스콤보박스 3
7-1 Button(1/2): 윈도우클래스를 MyBotton 으로한다. why? MyButton 프로젝트생성 // 컨트롤의윈도우클래스이름이 Button 이다!!! // 따라서, 현재생성하는윈도우의이름을 Button 으로사용하면안됨 // 지금생성하는버튼윈도우클래스이름이 button 4
7-1 Button(2/2): 윈도우클래스를 MyBotton 으로한다. why? 5
7-1 버튼만들기 1 컨트롤은윈도우이지만, 홀로사용될수없으며반드시부모윈도우의차일드로 존재 CreateWindow(1 _T("button"_, 2 _T("Click Me"), 3WS_CHILD WS_VISIBLE BS_PUSHBUTTON, 4~720,20,100,25, 8 hwnd, 9(HMENU)0, 10g_hInst, 11NULL); 1 _T("button") : 어떤차일드컨트롤을만들것인가 - 윈도우의윈도우클래스 - 컨트롤의윈도우클래스명을적어둔다 현재는버튼을만들기위한윈도우 : 디폴트 인 button 사용 주의 ) 현재프로젝트의클래스이름을절대 button 으로하면안됨! 2 _T("Click ME") : 타이틀바에사용되는문자열 - 해당윈도우에따라타이틀바에사용되기도하고, 메뉴자체에사용되기도한다 - 현재 Button에서는버튼위에표현된다 - List Box 나 Scroll Bar처럼캡션이필요없을때에는 NULL 로지정한다 6
7-1 버튼만들기 2 3 스타일 : WS_CHILD WS_VISIBLE BS_PUSHBUTTON : 윈도우의속성값 - 차일드윈도우이므로반드시 WS_CHILD 사용하고, WS_VISIBLE 을사용해야지만 ShowWindow 함수를호출하지않아도컨트롤이화면에출력 - 그외컨트롤에따른스타일지정 ( 버튼에도여러종류가존재 ) 4~7 위치 : 20, 20, 100, 25 - (20, 20) 위치, 폭 100, 높이 25 픽셀 스타일 BS_PUSHBUTTON BS_DEFPUSHBUTTON BS_CHECKBOX BS_3STATE BS_AUTOCEHCKBOX BS_AUTO3STATE BS_RADIOBUTTON BS_GROUPBOX 속성푸시버튼디폴트푸시버튼체크박스 3가지상태를가지는체크박스자동체크박스 3가지상태를가지는자동체크박스라디오버튼그룹박스 8 부모윈도우 : hwnd 이컨트롤의부모가누구인지알아야한다 - 메인윈도우의핸들인 hwnd 를적어줌으로써부모윈도우를지정 - 부모윈도우를생성할때는 NULL. 7
7-1 버튼만들기 3 9 해당컨트롤 ID : (HMENU)0 - 윈도우에서사용할메뉴의핸들 - 차일드컨트롤은메뉴를가지지않으므로이인수를컨트롤의 ID 지정용도로사용 - (HMENU) 로사용자가캐스팅해준다. - 컨트롤이많아진다면미리매크로상수 (#define) 를정의해사용하는것이좋다. 10 g_hinst : 이윈도우를만드는인스턴스의핸들 - WinMain 의첫번째인수로전달받은 hinstance 를전역변수에저장한 g_hinst 를사용하면 된다. 11 NULL : 사용자정의데이터 - MDI 에서사용하는구조체인데현재우리는단일윈도우이므로 NULL 사용 - 차일드컨트롤을만들때는이인수를사용하지않는다 8
7-1 부모와의통신 1 해당컨트롤에어떤사건이발생했을때부모윈도우에게통지메시지 (Notification Message) 를보내어떤내용인지알린다. 버튼을클릭할경우 WM_COMMAND 메시지를부모윈도우에게보내며전달되는정보는다음과같다. 인수 HIWORD(wParam) LOWORD(wParam) lparam 설명통지코드컨트롤의 ID 메시지를보낸차일드윈도우의윈도우핸들 컨트롤 ID 는 CreateWindow 의아홉번째인수에서지정한정수값 어떤컨트롤이통지메시지를보냈는지알려준다. 통지코드는차일드컨트롤이왜메시지를보냈는가를나타내는값 버튼의경우사용자가버튼을클릭했다는의미 BN_CLICKED 9
7-1 부모와의통신 2 부모윈도우는 WM_COMMAND 에서 LOWORD(wParam) 값을조사하여어떤컨트롤 이눌러졌는지에따라적절한처리를한다. // wparam 의하위워드 (LOWORD) 에컨트롤 ID 가전달된다 1) 선택 팝업 // 현재는버튼이단순하게 BN_CLICKED 메시지만발생시키므로굳이통지코드 HIWORD(wParam) 에어떤메시지가왔는지! 확인하지않음 10
7-1 부모와의통신 3 1 차로컨트롤 ID 에의해분기하고, 2 차로통지코드에따라분기한다 case WM_COMMAND: switch(loword(wparam)) { // ID에따른분기 case 메뉴1: 처리1; break; case 컨트롤1: switch(hiword(wparam)) { // 통지코드에따른분기 case 통지코드1: 처리1; break; case 통지코드2: 처리2; break;... } return 0; break; } // 메시지가 ( 통지코드 ) 단하나만있는경우에는 // 통지코드에따른분기를수행하지않는다. 11
7-2 체크박스 : 체크박스의종류 체크박스는참, 거짓의진위적인선택을입력받을때주로사용 클릭하면 V 표시가보이거나사라진다 선택가능한옵션개수에따른구분 두가지상태를가지는체크박스 (BS_CHECKBOX) 3 가지상태체크박스 (BS_3STATE) 동작방법에따른구분 자동체크박스 : 박스체크상태를자동으로확인 수동체크박스 : 박스체크상태를확인하기위해부모윈도우에서메시지보냄 12
7-2 Check(1/4) Check 프로젝트생성 // WinMain( ) 윈도우클래스멤버설정에서!! // COLOR_BTNFACE 버튼표면색상, 버튼을그릴때시스템이사용하는색상 // 흰색배경대신버튼표면과같은색상으로일치시킴 13
7-2 Check(2/4) // AUTO 가있는 c2, c4 와없는 c1, c3 의차이는무엇인가? // 하나의컨트롤에핸들 C1 과아이디 (HMENU)0 가존재하는이유는? 14
// 아래의 SendMessage 의역할들은무엇인가?! // case 를보면 0 과 2 만있고, 1 과 3 은없다! 왜??? 7-2 Check(3/4) 15
7-2 Check(4/4) 16
7-2 컨트롤의메시지 1 통지메시지 컨트롤이변화가있을때마다부모윈도우에게보내는메시지를보냄 체크박스가클릭되면보내는메시지 BN_CLICKED 메시지 부모가차일드에게어떤지시를내리기위해보내는명령 메시지 설명 BM_GETCHECK 체크박스가현재체크되어있는상태인지를조사하며추가정보는없다. BM_SETCHECK 체크박스의체크상태를변경하며 wparam 에변경할체크상태를보 내주면된다. BM_SETCHECK 에의해설정되는체크박스 3 가지상태 상수 값 의미 BST_CHECKED 1 현재체크되어있다. BST_UNCHECKED 0 현재체크되어있지않다. BST_INDETERMINATE 2 체크도아니고안체크도아닌상태 17
7-2 컨트롤의메시지 2 BN_CLICKED : 클릭되었음 부모윈도우 BM_GETCHECKED : 체크상태질문 BM_SETCHECKED : 체크상태변경 체크박스 case WM_COMMAND: switch(loword(wparam)) { case 0: if (SendMessage(c1, BM_GETCHECK, 0, 0)==BST_UNCHECKED) { SendMessage(c1, BM_SETCHECK, BST_CHECKED, 0); ELLIPSE = TRUE; } else { SendMessage(c1, BM_SETCHECK, BST_UNCHECKED, 0); ELLIPSE = FALSE; } InvalidateRect(hWnd, NULL, TRUE); break; 18
Radio 프로젝트생성 7-2 라디오버튼 (1/5): 그룹중하나선택 버튼중스타일이 BS_GROUPBOX 19
7-2 라디오버튼 (2/5): 그룹중하나선택 20
7-2 라디오버튼 (3/5): 그룹중하나선택 21
7-2 라디오버튼 (4/5): 그룹중하나선택 22
7-2 라디오버튼 (5/5) 레디오버튼의열거형은다음과같은의미이다 #define ID_R1 101 #define ID_R2 102 #define ID_R3 103 #define ID_R4 104 #define ID_R5 105 #define ID_R6 106 두개의전역변수 Graph 와 Color가선언되어변수들의현재선택된옵션값을기억. WM_PAINT에서참조하여선택된도형, 색상으로그림 r1, r4 라디오버튼에 WS_GROUP 스타일이설정되어있다 BOOL CheckRadioButton( HWND hdlg, int nidfirstbutton, int nidlastbutton, int nidcheckbutton ); 23
7-3 에디트 (1/4) 문자열을직접입력받을때사용 문자열또는정수와같은수치데이터입력 콘솔환경의 gets, scanf 와같은함수역할 edit 윈도우클래스로생성 CreateWindow 함수의세번째인수로지정. 스타일 설명 ES_AUTOHSCROLL 수평스크롤을지원한다. ES_AUTOVSCROLL 여러줄편집시수직스크롤을지원한다. ES_LEFT 왼쪽정렬한다. ES_CENTER 중앙정렬한다. ES_RIGHT 오른쪽정렬한다. ES_LOWERCASE 소문자로변환하여표시한다. ES_UPPERCASE 대문자로변환하여표시한다. ES_MULTILINE 여러줄을편집할수있도록한다. ES_NOHIDESEL 포커스를잃더라도선택된영역을표시한다. ES_READONLY 읽기전용으로만들어편집을금지한다. 24
7-3 에디트 (2/4) EN_UPDATE 문자열이변경된후화면에출력하기직전에보내는메시지 이메시지를받아사용자는문자열길이에따라에디트의폭을늘리거나다른것들을할수있다. EN_CHANGE 문자열이화면으로출력되고난후보내는메시지 문자열이변경된후 EN_UPDATE 메시지를보내고화면에그린후다시 EN_CHANGE 메시지를보낸다. 보통 EN_CHANGE 메시지사용 메시지 설명 EN_CHANGE 문자열이변경되었다. EN_ERRSPACE 메모리가부족하다. EN_HSCROLL 사용자가수평스크롤바를클릭하였다. EN_VSCROLL 사용자가수직스크롤바를클릭하였다. EN_KILLFOCUS 포커스를잃었다. EN_SETFOCUS 포커스를얻었다. EN_MAXTEXT 지정한문자열길이를초과하였다. EN_UPDATE 문자열이변경되기직전이다. 25
7-3 에디트 (3/4): Edit 프로젝트 Edit Test 프로젝트생성 // 주어진사각형크기이상입력가능 // 에디트컨트롤과통신하기위해, 에디트윈도우핸들값저장 26
7-3 에디트 (4/4) // 컨트롤의 ID 에의해분기 // 해당컨트롤의 통지코드 에의해분기 인수 HIWORD(wParam) LOWORD(wParam) lparam 설명통지코드컨트롤의 ID 메시지를보낸차일드윈도우의윈도우핸들 27
7-3 컨트롤도윈도우다 (1/4) 타이틀바가없는윈도우이다. 윈도우의차일드이다. 타이틀바가없기때문에직접이동시킬수없다. 스타일을가지며, 만들때지정한스타일에따라모양이나기능이달라짐 스스로메시지를처리할수있는능력 WM_PAINT 메시지처리가능하므로자신을 REPAINT( 복구 ) 할수있다 체크박스는 BM_SETCHECK 메시지를받으면 wparam값에따라자신의체크상태를스스로변경 버튼이나에디트를만들때사용한함수 CreateWindow 28
EditWnd 프로젝트생성 7-3 컨트롤도윈도우다 (2/4): EditWnd 프로젝트 29
7-3 컨트롤도윈도우다 (3/4): EditWnd 프로젝트 30
7-3 컨트롤도윈도우다 (4/4): EditWnd 프로젝트 31
7-4 리스트박스 (1/4) 선택가능한여러개의항목들을나열해놓고그중하나 ( 또는여러개 ) 를선택하는컨트롤 리스트박스도차일드윈도우이며 listbox 라는윈도우클래스로생성 차일드윈도우이므로 WS_CHILD, WS_VISIBLE 스타일은기본으로지정 스타일 LBS_MULTIPLESE L LBS_NOTIFY 설명 여러개의항목을선택할수있도록한다. 이스타일을적용하지않으면디폴트로하나만선택할수있다. 사용자가목록중하나를선택했을때부모윈도우로통지메시지를 보내도록한다. LBS_SORT 추가된항목들을자동정렬하도록한다. LBS_OWNERDRAW 문자열이아닌비트맵이나그림을넣을수있도록한다. LBS_STANDARD LBS_NOTIFY LBS_SORT WS_BORDER 32
7-4 리스트박스 (2/4) 메시지설명 ( 리스트박스메시지 ) LB_ADDSTRING 리스트박스에항목을추가한다. lparam 으로추가하고자하는문자열의번지를넘겨주면 된다. LB_DELETESTRING 항목을삭제한다. wparam 으로항목의번호를넘겨주며남은문자열수를리턴한다. LB_GETCURSEL 현재선택된항목의번호 (Index) 를조사해준다. LB_GETTEXT 지정한항목의문자열을읽는다. wparam 에항목번호, lparam 에문자열버퍼의번지를넘 겨주면버퍼에문자열을채워준다. LB_GETCOUNT 항목의개수를조사한다. LB_SETCURSEL wparam 이지정한항목을선택하도록한다. 메시지 설명 ( 리스트박스통지메시지 ) LBN_DBLCLK 리스트박스를더블클릭하였다. LBN_ERRSPACE 메모리가부족하다. LBN_KILLFOCUS 키보드포커스를잃었다. LBN_SELCANCEL 사용자가선택을취소하였다. LBN_SELCHANGE 사용자에의해선택이변경되었다. LBN_SETFOCUS 키보드포커스를얻었다. 33
7-4 리스트박스 (3/4): MyListBox 프로젝트 MyListBox 프로젝트생성 // 리스트박스아이디매크로상수 34
7-4 리스트박스 (4/4) // 리스트박스의순서에맞게출력될문자열정보를전달! // 어떤리스트가선택되었는지 Get한결과를 i에저장 // 텍스트정보를얻어와 str에저장 // str의내용을윈도우타이틀바에출력! 35
7-4 콤보박스 (1/4) 에디트컨트롤과리스트박스를결합해놓은컨트롤이다. 목록에있는항목을선택 OR 직접입력가능 장점 : 필요한경우만목록을열어서선택 ( 공간적게차지 ) 단점 : 선택에시간걸리고, 어떤목록이있는지바로확인안됨 스타일 설명 CBS_SIMPLE 에디트만가진다. CBS_DROPDOWN 에디트와리스트박스를가진다. CBS_DROPDOWNLIST 리스트박스만가지며에디트에항목을입력할수는없다. 36
7-4 콤보박스 (2/4): MyComboBox 프로젝트 MyComboBox 프로젝트생성 37
7-4 콤보박스 (3/4): MyComboBox 프로젝트 // 클래스스타일은 콤보박스, // 드럽다운이가능한콤보박스스타일지정 38
7-4 콤보박스 (4/4): MyComboBox 프로젝트 39
7-5 스크롤바 1 : scrollbar 윈도우클래스이름 수평스크롤바 SBS_HORZ, 수직 SBS_VERT BOOL SetScrollRange( HWND hwnd, int nbar, int nminpos, int nmaxpos, BOOL bredraw ); // 범위 //int SetScrollPos( HWND hwnd, int nbar, int npos, BOOL bredraw ); // 3 번째인수스크롤바의현재위치 인수 설명 LOWORD(wParam) 스크롤바내의어디를눌렀는가? HIWORD(wParam) lparam 현재위치 스크롤바의윈도우핸들 값 LOWORD(wParam) 로전달되는값 설명 SB_LINELEFT 또는 SB_LINEUP 사용자가왼쪽화살표버튼을눌렀다는뜻이며이때는왼쪽으로한단위스크롤시킨다. SB_LINERIGHT 또는 SB_LINEDOWN 사용자가오른쪽화살표버튼을눌렀다는뜻이며이때는오른쪽으로한단위스크롤시킨다. SB_PAGELEFT 또는 SB_PAGEUP 사용자가왼쪽몸통부분을눌렀다는뜻이며이때는한페이지왼쪽으로스크롤시킨다. SB_PAGERIGHT 또는 SB_PAGEDOWN 사용자가오른쪽몸통부분을눌렀다는뜻이며이때는한페이지오른쪽으로스크롤시킨다. SB_THUMBPOSITION 스크롤박스를드래그한후마우스버튼을놓았다. SB_THUMBTRACK 스크롤박스를드래그하고있는중이다. 이메시지는마우스버튼을놓을때까지계속전달된다. 40
7-5 스크롤바 2 수평의왼쪽, 수직의위쪽은값을감소시킴 썸 (Thumb) 몸통 (Shaft) 화살표 (Arrow) 값 LOWORD(wParam) 로전달되는값 설명 SB_LINELEFT 또는 SB_LINEUP 사용자가왼쪽화살표버튼을눌렀다는뜻이며이때는왼쪽으로한단위스크롤시킨다. SB_LINERIGHT 또는 SB_LINEDOWN 사용자가오른쪽화살표버튼을눌렀다는뜻이며이때는오른쪽으로한단위스크롤시킨다. SB_PAGELEFT 또는 SB_PAGEUP 사용자가왼쪽몸통부분을눌렀다는뜻이며이때는한페이지왼쪽으로스크롤시킨다. SB_PAGERIGHT 또는 SB_PAGEDOWN 사용자가오른쪽몸통부분을눌렀다는뜻이며이때는한페이지오른쪽으로스크롤시킨다. SB_THUMBPOSITION 스크롤박스를드래그한후마우스버튼을놓았다. SB_THUMBTRACK 스크롤박스를드래그하고있는중이다. 이메시지는마우스버튼을놓을때까지계속전달된다. 41
7-5 스크롤바 3 (1/4) MyScrollBar 프로젝트생성 42
7-5 스크롤바 3 (2/4) // Red, Greed, Blue 용 스크롤바 윈도우생성 // 수평스크롤바 // 스크롤의최대, 최소값지정 // 스크롤의현재위치 43
7-5 스크롤바 3 (3/4) 44
7-5 스크롤바 3 (4/4) 45
7-5 스태틱 : MyStatic 프로젝트 MyStatic 프로젝트생성 입력하는기능은없고, 문자열을보여주기만하는것 46