4 장 메시지처리유형 김성영교수 금오공과대학교 컴퓨터공학부
메시지처리유형 윈도우에서발생하는이벤트에대응하는윈도우메시지를처리 2 장및 3 장의실습예제 자식윈도우에서발생한이벤트를부모윈도우에서처리 WM_COMMAND 메시지처리 실습 4.2 자식윈도우에서발생한사건유형을구분하여처리 Notification code 처리 실습 4.7 Notification code 의한계를극복하여처리 실습 4.9 SendMessage() 혹은 PostMessage() 를통한메시지처리 실습 4.11 2
실습 4.1 버튼윈도우를포함한프로그램을작성하자. Windows 운영체제가미리만들어둔윈도우클래스를사용하자!! LRESULT CALLBACK WndProc(... ) { static HWND hbtn1; switch( msg ) { case WM_CREATE: hbtn1 = CreateWindow( "BUTTON", "click", WS_VISIBLE WS_CHILD BS_PUSHBUTTON, 0, 0, 100, 100, hwnd, NULL, _hinstance, NULL ); break;... } 3
메시지처리유형 : 두번째 컨트롤윈도우에서발생한이벤트를부모윈도우에서처리 WM_COMMAND 메시지처리 컨트롤윈도우 Windows 운영체제가정의해놓은윈도우 4
실습 4.2 유형 II 버튼을클릭하면메시지박스를출력하자. WM_COMMAND 메시지를사용하자!! WM_COMMAND 부모윈도우 컨트롤윈도우 메시지처리후출력 5
실습 4.3 두개의버튼을추가하자. 각버튼에대해서로다른메시지박스를출력하자!! 6
두개이상의컨트롤윈도우구분 (1) WM_COMMAND 메시지의부가정보를통해구분 WM_COMMAND 메시지가발생하는경우 메뉴에서메뉴항목을선택했을때 단축키가눌렸을때 컨트롤윈도우에서부모윈도우에게 notification 코드를보낼때 http://msdn.microsoft.com/ko-kr/library/ms647591(en-us,vs.85).aspx 7
두개이상의컨트롤윈도우구분 (2) WM_COMMAND 부가정보 int wnotifycode = HIWORD( wparam ); int wid = LWORD( wparam ); HWND hwndctl = (HWND)lParam; Message Source wparam (high word) wparam (low word) lparam 메뉴 0 단축키 1 컨트롤 Control-defined notification code Menu identifier (IDM_*) Accelerator identifier (IDM_*) Control identifier 0 0 Handle to the control window http://msdn.microsoft.com/ko-kr/library/ms647591(en-us,vs.85).aspx 8
두개이상의컨트롤윈도우구분 (2) 자식윈도우의식별자 (identifier) 설정 HWND CreateWindow(, HMENU hmenu, ) 9번째인자 (hmenu) WS_POPUP 또는 WS_OVERLAPPED 스타일윈도우 : 메뉴핸들 정수값부여 : 자식윈도우의식별자 hbtn1 = CreateWindow( "BUTTON", "click", WS_VISIBLE WS_CHILD BS_PUSHBUTTON, 0, 0, 100, 100, hwnd, (HMENU)888, _hinstance, NULL ); 9
컨트롤윈도우의종류 스타일 의미 BUTTON COMBOBOX 버튼윈도우 콤보박스윈도우 EDIT 에디트윈도우 ( 키보드입력을통해문자열편집이가능 ) LISTBOX 리스트박스윈도우 ( 문자열목록을가지며선택된문자열표시 ) RichEdit 리치에디트윈도우 ( 에디트윈도우보다풍부한편집기능보유 ) SCROLLBAR 스크롤바윈도우 STATIC 스태틱윈도우 ( 간단한문자열이나사각형출력용도 ) http://msdn.microsoft.com/en-us/library/bb773169(v=vs.85).aspx 10
실습 4.4 버튼과에디트윈도우를추가하자. 참고 에디트윈도우는 WS_BORDER 스타일사용 11
에디트윈도우 문자열편집에필요한다양한키 ( 문자, 방향키등 ) 를사용가능 스타일 ES_AUTOHSCROLL ES_AUTOVSCROLL ES_MULTILINE ES_NUMBER ES_PASSWORD ES_READONLY 의미 라인끝에문자를입력했을때 10문자씩자동으로오른쪽스크롤마지막라인에서엔터키를눌렀을때자동으로아래로스크롤여러라인을가질수있도록설정숫자만입력되도록함입력문자열을모두 * 로표시, 비밀번호입력에사용입력이불가능하고읽기만가능하게설정 에디트윈도우스타일적용 hedt1 = CreateWindow(..., WS_VISIBLE WS_CHILD WS_BORDER ES_AUTOHSCROLL ES_AUTOVSCROLL ES_MULTILINE,... ); 12
실습 4.5 버튼을누르면에디트윈도우의내용을메인윈도우에출력하자. 참고 이전슬라이드의에디트윈도우스타일적용 GetWindowText( ) 함수사용 13
실습 4.6 에디트윈도우에여러줄을입력한경우동일하게출력되 록하자. 힌트 : 기지를발휘하자. 14
NOTIFICATION 코드 컨트롤윈도우는사건의유형을부모윈도우에게통보 노티피케이션 (Notification) 코드사용 WM_COMMAND 메시지의 wparam 으로부터추출 버튼윈도우코드 : BN_* 에디트윈도우코드 : EN_* int wnotifycode; 노티피케이션코드 wnotifycode = HIWORD( wparam ); http://msdn.microsoft.com/en-us/library/bb773169(v=vs.85).aspx 15
실습 4.7 유형 III 첫번째에디트윈도우에문자를입력하면곧바로두번째에디트윈도우에그내용을출력하자. 참고 에디트윈도우의 EN_CHANGE 식별코드사용 16
노티피케이션코드이벤트처리의한계 컨트롤윈도우메시지처리에서필요하다고판단되는것들만일부구현함 예 : BN_CLICKED = WM_LBUTTONDOWN + WM_LBUTTONUP 프로그래머가요구하는모든이벤트유형을다루기에는부족함 17
실습 4.8 마우스가움직일때마우스커서의좌표를메인윈도우에 출력하자. 18
문제점 증상 버튼윈도우내부에서는이벤트처리가안됨 문제점 버튼윈도우의메시지처리함수를확인할수없음 버튼윈도우의 MOUSEMOVE 이벤트처리에대한노티피케이션코드는존재하지않음 19
실습 4.9 유형 IV 버튼윈도우상에서마우스를움직이면부모윈도우영역 에좌표를출력하자. 20
처리단계 1. 기존버튼윈도우메시지처리함수의주소찾기 LONG GetWindowLong( HWND hwnd, int nindex ); 2. 버튼윈도우에대한새로운메시지처리함수작성 3. 새로운함수에서 WM_MOUSEMOVE 메시지처리 4. 기존버튼윈도우메시지처리함수의호출 LRESULT CallWindowProc( WNDPROC lpprevwndfunc, HWND hwnd, UINT Msg, WPARAM wparam, LPARAM lparam ); 5. 기존함수를새로작성한메시지처리함수로대체 LONG SetWindowLong( HWND hwnd, int nindex, LONG dwnewlong ); 21
GetWindowLong / SetWindowLong / CallWindowProc GetWindowLong 본함수는지정된윈도우에대한정보를검색해준다. nindex 는다음과같이정의되어있다. 검색된정보는모두 LONG 으로형 - 변환되어반환되므로필요한형으로형 - 변환한다. 예들들어 nindex 가 GWL_WNDPROC 인경우 WNDPROC 로형 - 변환하여사용한다. SetWindowLong 본함수는 GetWindowLong 의반대로, 값을설정하는데사용된다. 세번째인자에설정값을주는데, 요구하는타입이 LONG 임에주의한다. SetWindowLong 본함수는첫번째인자로호출하고자하는메시지처리함수의주소인자가포함되어있는것만제외하고는기존의 WndProc() 함수와동일하다. 22
실습 4.10 두개의윈도우를생성하고자식윈도우에서마우스를움 직일때현재위치에 X 표시를출력하자. 자식윈도우프로시저에서 WM_MOUSEMOVE 메시지처리 23
실습 4.11 유형 V 부모윈도우에서마우스를움직이면자식윈도우의해당 좌표에 X 표시를출력하자. 24
방법 1. WM_MOUSEMOVE 메시지처리시출력윈도우만자식윈도 우로설정함 25
방법 2. 접근방법 부모윈도우에서이벤트처리및자식윈도우의코드수행 처리방법 부모가자식윈도우프로시저를호출함으로써구현가능 직접호출이불가능하므로부모에서자식윈도우프로시저에메시지를보냄 SendMessage( ) 함수사용 SendMessage( ) LRESULT SendMessage( HWND hwnd, UINT Msg, WPARAM wparam, LPARAM lparam ); 26
실습 4.12 부모윈도우에서의마우스움직임방향과직각으로자식 윈도우에 X 표시를출력하자. 27
메시지전달 SendMessage( ) 특정윈도우프로시저직접호출 PostMessage( ) 메시지를애플리케이션메시지큐에전달 ( 간접호출 ) PostMessage() BOOL PostMessage( HWND hwnd, UINT Msg, WPARAM wparam, LPARAM lparam ); 28
윈도우프로그래밍정리 (HW) 버튼 1, 2, 3 을클릭하면각명령에대한답변을 edit 1 에출력한다. 버튼 4 에서마우스를움직이면파란점을 static 윈도우의비례위치에출력한다. 버튼 4 를클릭하면 static 윈도우에그려진내용을지운다. Edit 2 에문자를입력하면바로 edit 1 의화면에같은내용을출력한다. 부모윈도우를움직이면자식윈도우가따라서움직인다. 부모윈도우의크기를변경하면자식윈도우의가로크기를동일한크기로변경한다. 29