• 검색 결과가 없습니다.

004. 입력

N/A
N/A
Protected

Academic year: 2022

Share "004. 입력"

Copied!
37
0
0

로드 중.... (전체 텍스트 보기)

전체 글

(1)

1

DB & Data Mining LAB.

Korea University

004. 입력

이 종 욱

eastwest9@korea.ac.kr

윈도우 프로그래밍 및 실습

Updated 2011. 9. 7 Updated: 2012. 08. 31 Updated: 2012. 09. 06 Updated: 2014. 09. 22 Last updated: 2015. 08. 26

(2)

Purpose of this chapter

• How to input some information in your program

이번 강의 자료부터, Apistart.txt 에 있는 코드를 기본적으로 이용한다!

(3)

3

4장 입력

 멀티 태스킹 환경

 하나의 프로그램이 입력을 받기 위해 대기한다고 해서, 시스템을 블록해서는 안 된다.

 입력(마우스, 키보드등)이 이뤄지면 포커스(입력 초점)를 가진 프로그램 에 키보드 메시지(WM_CHAR, WM_KEYDOWN)를 보내며 프로그램은 이런 메시지를 받아 키보드 입력을 처리한다.

 포커스를 가진 컨트롤만 키보드 입력을 받을 수 있으며 관련 메시지도 포

커스를 가진 컨트롤에게만 전달된다.

(4)

4-1. WM_CHAR 메시지 (1/3): 키보드 입력

 입력된 메시지 저장 : static TCHAR str[256];

 키보드 입력 시점(WM_CHAR)과 출력(WM_PAINT) 시점이 분리

 WM_CHAR 메시지는 입력된 문자의 코드를 wParam로 전달, wParam의 값 을 읽어 어떤 문자키를 눌렀는지 알아낸다

S를 누르면 0x53문자 코드값이

wParam

에 전달

lParam

에는 비트별로 다음 정보가 전달 LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)

 WM_CHAR가 발생하기 이전에 WM_KEYDOWN이 발생된다.

 TranslateMessage(&Message) 에서 WM_CHAR로 변형되는 것

(5)

5

4-1. WM_CHAR 메시지 (2/3)

// 키보드로 입력된 문자열 저장 방법 len = _tcslen(str);

str[len] = wParam;

str[len+1] = 0;

Key 프로젝트 생성

typing

InvalidateRect( ) 의 역할은?

(6)

4-1. WM_CHAR 메시지 (3/3)

 InvalidateRect(hWnd, NULL, FALSE)

사용이유!

 키보드 메시지가 발생하면 WM_CHAR에 있는 문자열에 저장만 된다.

 화면에 변화가 있음을 인지하지 못하므로,

강제적

으로

화면에 변화가 있음

WM_PAINT에서 인지하도록 해야 한다

 주의) 키보드 메시지가 반드시 화면에 출력되는 것이 아니다.

 이 프로그램의 문제점, 키보드를 통해 입력되는 문장이, 윈도우화면을 벗어나면 자동으로 다음 줄로 넘어가지 않는다. 어떻게 해야 하는가?! (고민해보고 과제로

풀어서 제출)

(7)

7

4-1. TranslateMessage

 키보드에서 A가 눌러졌을 때 발생하는 ‘3가지 순차적 메시지’

 1) WM_KEYDOWN, 2) WM_CHAR

(인위적 발생)

, 3) WM_KEYUP

 메시지 큐에 있는 메시지를 GetMessage에 의해 꺼내져 TranslateMessage로

 TranslateMessage는 WM_KEYDOWN 확인 후 조건이 맞으면 WM_CHAR 추가발생

 TranslateMessage( )는 문자키 WM_CHAR를 만들기 위해 존재함

 따라서 WM_CHAR 필요 없을 때에는 생략 가능.

 여러 변수(SHIFT, Caps Lock 등) 확인

 DispatchMessage에 의해 WndProc로 보내짐 while(GetMessage(&Message,0,0,0)) {

TranslateMessage(&Message);

DispatchMessage(&Message);

}

(8)

4-1. 무효영역 (1/3)

 무효 영역 (Invalid Region)

 화면에 보여지는 외부적인 요인에는 바로 반응 WM_PAINT 메시지 발생

 내부적인 문자입력은 화면에 보여지는 것인지? or 내부적인 계산, 전송에 관련된 것인지 운영 체제가 판단할 수 없다.

 BOOL InvalidateRect(HWND hWnd, CONST RECT *lpRect, BOOL bErase);

 윈도우 작업영역을 무효화하여 운영체제로 하여금 WM_PAINT 메시지를 해당 윈도우에 보내 도록 함

1) 무효화 시킬 윈도우.

2) 무효화할 영역 지정. NULL이면 전체 영역 무효화

3) TRUE: 지우고 다시 그림/ FALSE: 지우지 않음  덮어쓴다.

InvalidateRect(hWnd, NULL, FALSE)

(9)

9

4-1. 무효영역 (2/3)

 WM_CHAR 메시지에서 wParam에 ‘스페이스 키(32)’가 입력되면 문자열을 지우도 록 한 예제

: (

강의 자료 p.5(Key 프로젝트)의 WM_CHAR 부분을 다음과 같이 변경

)

Invalidate( )의 3번째 인자가 FALSE가 아닌 TRUE 라면 어떻게 되는가?!

typing

Space 누른 후 dd 입력!

// space 입력여부 확인!

// 문자열에 입력된 내용을 지움

(10)

4-1. 무효영역 (3/3)

typing

Space

dd 입력 FALSE Vs. TRUE 이해?

(11)

11

WM_KEYDOWN

 문자만을 입력받는 WM_CHAR로 처리가 불가능한 Ins, Del, function키 등을 처리하는데 쓰임

 가상키 코드(Virtual Key Code) : 키보드에 상관 없이 키를 입력 받기 위해 만들 어진 범용적인 코드값

가상키 코드

VK_BACK 08 Backspace

VK_TAB 09 Tab

VK_RETURN 0D Enter VK_SHIFT 10 Shift VK_CONTROL 11 Ctrl

VK_MENU 12 Alt

VK_PAUSE 13 Pause

VK_CAPITAL 14 Caps Lock VK_ESCAPE 1B Esc

VK_SPACE 20 스페이스

VK_PRIOR 21 PgUp

VK_NEXT 22 PgDn

VK_END 23 End

VK_HOME 24 Home

VK_LEFT 25 좌측 커서 이동키

VK_UP 26 위쪽 커서 이동키

이하생략 이하생략

(12)

KeyDown 예제

 A를 상하좌우로 이동시키면서 화면에 출력

// InvalidateRect(hWnd, NULL, TRUE)

KeyDown 프로젝트 생성

(13)

13

4-2. Mouse

 마우스 관련 메시지

 마우스 메시지가 발생할 위치 좌표

 (LOWORD(lParam), HIWORD(lParam))

 wParam에는 마우스 버튼의 상태와 키보드 조합 키(Shift, Ctrl)의 상태가 전달된다. 조합 키 상태는 다음 값들과 비트 연산을 해보면 알 수 있다.

버튼 누름 놓음 더블클릭

좌측 WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK 우측 WM_RBUTTONDOWN WM_RBUTTONUP WM_RBUTTONDBLCLK 중앙 WM_MBUTTONDOWN WM_MBUTTONUP WM_MBUTTONDBLCLK

설명

MK_CONTROL Ctrl 키가 눌러져 있다.

MK_LBUTTON 마우스 왼쪽 버튼이 눌러져 있다.

MK_RBUTTON 마우스 오른쪽 버튼이 눌러져 있다.

MK_MBUTTON 마우스 중간 버튼이 눌러져 있다.

MK_SHIFT Shift 키가 눌러져 있다.

16비트 시절 wParam : WORD 16bit, lParam : LONG 32bit

(14)

4-2. Mouse : 자유 곡선 그리기 (1/2)

Mouse 프로젝트 생성

(15)

15

4-2. Mouse : 자유 곡선 그리기 (2/2)

더블 클릭 케이스에 설정한 내용의 의미는?

Free Line을 그린 후!

 더블 클릭을 해보자!  변화가 있는가?

(16)

4-2. 더블클릭: 화면지우기

 화면지우기

 InvalidateRect( )를 호출하여 작업영역 전체를 무효화 한다.

 왼쪽 마우슨 버튼 클릭시 화면을 지우기 위하여, 다음 부분을 WndProc 함수의 메시지 처리 부분에 추가

 아무리 빨리 누른다 해도, WM_LBUTTONDONW과 WM_LBUTTONUP이 연속해서 발생한 다. 따라서, 윈도우 클래스 스타일에서

더블클릭을 인식하도록

해야 한다.

case WM_LBUTTONDBLCLK:

InvalidateRect(hWnd, NULL, TRUE);

return 0;

 더블 클릭에 대한 case 코드를 추가해도 실행되지 않음!

WndClass.lpszMenuName=NULL;

WndClass.style=CS_HREDRAW | CS_VREDRAW |

CS_DBLCLKS;

RegisterClass(&WndClass);

※ 더블클릭을 지원하도록 플래그 추가

// main 문의 WndClass 속성에서

(17)

17

4-3. 타이머 (1/5): 시계! 사용자의 동작과 상관없이 발생하는 메시지

 시간을 구함

 SYSTEMTIME 구조체와 GetLocalTime( ) 사용

 WndProc에 시간값을 조사할 SYSTEMTIME 구조체 st 객체

 시간값을 보여주기 위해 문자열로 변경하여 저장할 sTime 문자열 static 선언

 WndProc 에서 첫번째로 처리하는 메시지 WM_CREATE

 윈도우가 처음 생성될 때 발생

 프로그램 시작 시 꼭 한 번만 초기화해야 하는 것 처리

 실행에 필요한 메모리 할당, 전역변수 초기값 등의 초기화 처리가 이뤄짐

 SetTimer 함수를 WM_CREATE에 두고, 타이머를 생성 & 초기 설정함

SetTimer(hWnd, 1, 1000, NULL)

UINT SetTimer(HWND hWnd, UINT nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc)

생성되는 타이머에 ID 부여(프로그래머가) 타이머 메시지가 발생할 때마다 호출될 함수 지정 사용하지 않으면 NULL

NULL 이면 WndProc( ) 함수에서 처리.

이 값이 1000 이면 1초에 한번 hWnd로 타이머메시지 전달 타이머 주기 설정 단위 1/1000초

(18)

4-3. 타이머 (2/5): 화면에 현재 시간 출력

 WM_TIMER

 wParam

으로 타이머 ID를 전달받으며,

lParam

에게 타이머 메시지 발생시 호출될 함 수의 번지 전달 : 현 예제는 ID 1이고, 타이머 메시지를 전담하여 처리할 함수가 없으므로 NULL

 WM_TIMER 메시지 발생하면 GetLocalTime( ) 로 시간을 조사한 후 출력을 위해 sTime 문 자열로 변환

 시간이 바뀔 때마다 화면을 갱신하기 위해 InvaildateRect( ) 사용

 시간을 조사하는 부분과 출력하는 부분이 분리(윈도우 프로그램의 특징)

 WM_DESTROY

 일반적으로, 설치된 타이머를 제거하는 함수를 추가함 killTimer( )

 단, KillTimer( )는 프로그래머의 의도에 따라, 다른 곳에 위치할 수 있음 // SetTimer(hWnd, 1, 1000, NULL) 에 의해 WM_TIMER 발생

(19)

19

4-3. 타이머 (3/5): 화면에 현재 시간 출력

MyTimer 프로젝트 생성

(20)

4-3. 타이머 (4/5): 화면에 현재 시간 출력

 2가지 문제점!

 시간이 바로 출력되지 않고, 1초 후에 출력!

 화면 깜빡거림(시스템이 느리다면!)

MyTimer 프로젝트 생성

(21)

21

4-3. 타이머 (5/5): SendMeaage

 문제점 1: WM_CREATE의 타이머주기가 1초. 따라서, WM_TIMER 메시지가 1초 후 발생

 프로그램 시작 직후에 WM_TIMER 에게 강제로 메시지를 발생시켜 시간을 확인

 SendMessage( ) 함수를 사용한다

 문제점 2: 화면 깜빡거림  전체 화면을 지운 후 그리기 때문

 InvalidateRect(hWnd, NULL, TRUE);

 두 번째 인수가 NULL이라 화면 전체가 무효화되고, TRUE이므로 화면을 지운 후 다시 그림.

 FALSE 는 덧칠하는 것. 따라서, 잔상이 남는다.  해결:시계 부분만 무효화할 영역으로 지정 case WM_CREATE:

SetTimer(hWnd,1,1000,NULL); // 3번째 인자 1000은  1초를 의미

SendMessage(hWnd, WM_TIMER, 1, 0);

// 추가 return 0;

static RECT rt={100,100,400,120};

// switch 문 전에 다시 그려질 부분 사각형 크기 설정

InvalidateRect(hWnd, &rt, TRUE);

// WM_TIMER에 있는 InvalidateRect( ) 함수 설정 변

(22)

4-3. 두 개의 타이머 (1/2): ① 시간 출력, ②5초마다 경고음

 2개 이상의 타이머는 WM_TIMER의 타이머 ID로 구분: (프로그래머가 지정한다!)

// Timer 2개

TwoTimer 프로젝트 생성

(23)

23

4-3. 두 개의 타이머 (2/2): 시간 출력, 5초마다 경고음

wParam에 전달된 타이머 ID를 구별하여, 해당하는 명령을 실행한다 wParam에 의해 구별되는 switch 문 추가함

// 1번 타이머

// 화면에 현재 시간 출력

// 2번 타이머

// 5초마다 경고음을 발생시킴!!!

// Timer 2개 메모리 정리

(24)

4-3-라. 백그라운드 작업 (1/4)

 한 프로그램이 제어권을 독점하고 있으면 안됨: 무한루프 프로그램 작성 금지

반드시 메시지가 전달되었을 때에 한해 필요한 작업을 해야 한다.

• 어떤 작업이 이뤄지더라도, 다른 작업 메시지가 들어오면 해당 메시지 처리

 Timer message를 이용하여, 특정 작업이 자원을 독점하는 것을 막는다.

 초당 20번 주기의 타이머에서 주기마다 1000개의 점을 난수로 얻은 임의좌표에 임의색상을 출력:

• ‘1초에 2만개의 점이 생성’됨 & ‘왼쪽 마우스 버튼 클릭하면 원 발생’하는 윈도우 프로그램 작성.

(25)

25

4-3-라. 백그라운드 작업 (2/4)

RandGrp 프로젝트 생성

// Timer 가 발생하면 화면 랜덤 위치에 // 랜덤한 색상을 갖는 점을 출력

(26)

4-3-라. 백그라운드 작업 (3/4)

// 마우슨 왼쪽 버튼 누르면, // 랜덤 위치에 원 출력

(27)

27

4-3-라. 백그라운드 작업 (4/4)

 이전에는 초당 20번의 메시지가 발생하고 그 메시지가 발생할 때마다 for문에서 1000번을 반복하며 점을 출력했다.

 왼쪽 마우스를 클릭하면 출력하던 것이 멈췄을 때, WM_LBUTTONDOWN 메시지 처 리를 하는 곳으로 메시지 제어권을 보내주므로 원이 화면에 출력되었다.

(28)

4-3. 콜백함수 (1/3)

 Callback Function

 일반적인 API함수들은 운영체제가 제공하며 프로그램에서는 이 함수들을 호출해서 운영체 제의 서비스를 받는다.

 반대로, 응용 프로그램이 제공하며 운영체제가 필요할 때 호출하는 함수

 운영체제에 의해 호출되는 프로그램 내부의 함수

 콜백함수 예 : 대표적인 것이 바로 메시지 처리 함수 WndProc

 메시지가 발생할 때마다 윈도우가 호출하며 응용 프로그램 내부에 있지만 응용 프로그램에 서 직접 함수를 호출하지는 않는다. 오직 운영체제만이 이 함수를 호출

# 콜백 함수 코드 작성 실습  Timer를 위한 전용 함수 만들기 (RandGrp 프로젝트를 일부 변경한 Callback프로젝트 생성! )

(29)

29

4-3. 콜백함수 (2/3)

// WinProc( )에 있는 SetTimer( ) 3번째 옵션에 처리 함수 등록 // Timer에 의해 메시지 발생하면 TimerProc( ) 에서 처리하게 된다.

SetTimer(hWnd, 1, 1000, TimerProc);

WM_TIMER

윈도우 번호 Timer ID  1 윈도우 실행 후 진행 시간

# WndProc( ) 함수 위에, 타이머 메시지 처리 전용 TimerProc( ) 콜백함수 코드 추가한다.

 WndProc( ) 함수 정의 부분 앞에 있기 때문에, TimerProc( )정의만 작성(함수 선언하지 않아도 됨) Callback 프로젝트 생성

(30)

4-3. 콜백함수 (3/3)

// TimerProc ( ) 함수를 SetTimer( ) 에 등록

(31)

31

4-3. 일회용 타이머 (1/2):

OnceTimer

 프로그램 상태를 잠시 정지 시키고, 도움말을 표시하고 싶다

case WM_LBUTTONDOWN:

문자열 출력 Sleep(3000);

문자열 삭제 return 0;

문제점?!

3초 동안 시스템 정지됨

해결 방안:

메시지가 보인 뒤에, 3초 뒤에 메시지를 삭제 하게 할 수 있도록 타이머 설치

OnceTimer 프로젝트 생성

(32)

4-3. 일회용 타이머 (2/2):

OnceTimer

 마우스 왼쪽 버튼 클릭

 3초 뒤 사라짐.

(33)

33

4-4. 윈도우 관리 메시지: 생성 및 파괴

 메모리를 동적으로 생성하고 할당된 메모리 지움.

// C 스타일의 동적 메모리 할당 and 해제 // C++ 스타일 new, delete

(34)

4-4. 작업영역

 작업영역 : Client Area

 비작업 영역 : Non Client Area

 윈도우가 차지하고 있는 작업영역 크기를 알아내는 함수

 작업영역 크기 조사를 위하여 GetClientRect( ) 함수를 특정 메시지에 위 치시킨다. 이 때, 메시지 위치에 따라서 다른 점이 무엇인지 확인: 3가지 위 치는 다음과 같다!!

• WM_CREATE

• WM_SIZE

• WM_PAINT

작업 영역

BOOL GetClientRect(HWND hWnd, LPRECT lpRect);

(35)

35

4-4. 작업영역 크기 정보 얻기 1: WM_CREATE

 WM_CREATE에서 작업영역 크기 조사

1) 클라이언트 크기 알아냄, WM_CREATE 는 프로그램 처음 실행 시, 단 한번만 발생한다!

2) 클라이언트의 중앙 위치에 글자 출력!!!

# 주의: 창의 크기가 변동될 때, 글자는 처음 출력된 위치에서 변화 없음!

Client 프로젝트 생성

(36)

4-4. 작업영역 크기 정보 얻기 2: WM_SIZE

 WM_SIZE에서 작업영역 크기 조사

 프로그램 창 크기가 변화하는 순간에 발생하는 메시지.

// GetClientRect( ) 이 아닌, 메시지의 lParam // 매개변수를 통해 오른쪽 하단 정보 추출 가능

(37)

37

 WM_PAINT에서 작업영역 크기 조사

 화면 변화가 발생한 그 순간, 다시 작업영역의 내용을 그리기 위해 발생.

4-4. 작업영역 크기 정보 얻기 3: WM_PAINT

참조

관련 문서

◈ _messageEntries: 각 메시지 종류에 따라서 메시지 식별 번호, Function Pointer 등을 가 지는 엔트리의 Array. ◈ messageMap: 기반 클래스의 messageMap에 대한

광고 언어는 국어학의 관점에서 보는 외형적인 특성과 함께 메시지 전달 역할의 측 면이 있다.광고 언어의 연구가 보다 심도 있게 전개되기 위해서는 광고 언어를

여러분이 열심히 참여하 다보면 스마트폰이 단순히 문자 메시지 전송, 전화, 카카오톡, 카카오스토리, 페이스북, 트위터 뿐만 아니라 다양한 기능이 있음을 알게

afx_msg void OnCreate()(LPCREATESTRUCT); // 메시지 핸들러 prototype afx_msg void OnLButtonDown(UINT, CPoint); // 메시지 핸들러 prototype DECLARE_MESSAGE_MAP()

l 수신한 메시지 인증코드를 영심이의 공개키 로 복호화하여 메시지 다이제스트 유도 l 두 메시지 다이제스트가 일치하면

(서버용 프로그램과 클라이언트용 프로그램은 각각 작성함!).. • 다음과 같은 화면이 나오는지 확인. • 클라이언트가 서버에게 보낸 메시지 “안녕하세요

l ISAKMP 메시지: 헤더, 보안연계 페이로드, 제안 페이로드(ISAKMP), 트랜스폼 페이로드(오클리 l ISAKMP 메시지: 헤더, 보안연계 페이로드,

 사용할 차트의 형태를 알려주는 것은 데이터나 측정단위가 아니라 메시지 , 즉 보여주고자 하는 요점이다.  차트는 시각적 자료이지 의도를 전달하기 위한 글이나