Tutorial 6: Keyboard Input
이 번장에서는, Windows가 어떻게 키보드의 입력을 인식하는지를 설명한다.
소스 | 실행 결과 |
|
보통, PC에는 키보드가 한개 뿐이므로(두개를 연결하더라도 활성된 키보드는 한개다), 모든 프로그램은, 키보드 자원을 공유해서 사용한다. 그래서, Windows는 현재 활성화된 윈도우에게만 , 키보드의 입력 정보를 보내게 되어 있다.
즉, 화면에 여러개의 윈도우가 있어도, 활성 윈도우에게만 키보드 입력 정보가 보내져서 활성윈도우가 키스트로크(keystroke)를 받게된다. 키스트로크(keystroke)를 받는 윈도우인가 아닌가는, 타이틀바를 보면 알 수있다. 키스트로크(keystroke)를 받는 윈도우의 타이틀바는 하이라이트 되어 있다.
키보드 메세지에는 2개의 메세지 타입이 있다. 먼저, 키보드를 키의 집합으로 생각하는 방식이 있다. 이 경우, 키를 누르면, Windows는 포커스 된 윈도우에 WM_KEYDOWN 메세지를 보내주고, 그 윈도우에 키가 입력되었다고 인식시킨다. 그리고, 키를 놓으면,Windows로부터 WM_KEYUP 메세지가 보내진다. 따라서, 키를 버튼과 같이 다루게 된다(UP/DOWN).다른방식으로는, 키보드를 문자입력장치로 생각하는는 방식이다. 이 경우는"a" 키를 누르면, Windows는 WM_CHAR 메세지를 윈도우에 전하게 되고, "a" 라고 하는 문자도 같이 전달하게 된다(wParam에 키가 전달).
실제로, Windows는 WM_KEYDOWN와 WM_KEYUP의 2개의 메세지를 전송하고, 키보드 메세지를 TarnslateMessage 함수를 사용해서 WM_CHAR 메세지로서 변환한 후 해당 윈도우에 보낸다. 윈도우 프로시저에서 이 메세지들을 모두 처리할 수도 있고, 한가지만 처리 할 수도 있다. 대부분, WM_KEYDOWN 와 WM_KEYUP 메세지는 무시하는 방식을 취한다. 본 예제에서는 WM_CHAR 메세지에 대해서만 다루기로 한다.
|
|
|
char WPARAM 20h ; the character the program receives from keyboard이 변수는, 키보드로부터 전달받은 문자 코드를 저장할 변수이다. 그 문자는 윈도우 프로시저의 WPARAM 매개변수로 전달되므로, WPARAM형의 변수를 정의하고 있다. 초기값을 20h 즉 공백문자로 하는 이유는, 윈도우를 처음 표시했을 경우, 키보드로부터 아무것도 입력되지 않기 때문에,공백문자를 넣어준것이다.
.ELSEIF uMsg==WM_CHAR push wParam pop char invoke InvalidateRect, hWnd, NULL, TRUE윈도우 프로시저에서 WM_CHAR 메세지를 처리하고 있다. 예제에서는, char 라는 변수에 입력된 문자를 저장하고, InvalidateRect 함수를 호출하고 있다. InvalidateRect 함수는 해당 윈도우의 작업영역을 강제로 무효영역으로 만들어서, 윈도우 프로시저에 WM_PAINT 메세지를 강제로 발생시키는 함수다.(화면갱신 / 복구)
이 함수의 프로토타입은 다음과 같이 되어있다.
InvalidateRect proto hWnd :HWND,\ lpRect :DWORD,\ bErase :DWORDlpRect 는작업영역의 무효영역을 지정하는 구조체의 포인터로서 , 그영역이 무효영역이 된다. 이 변수가 NULL이면, 작업영역 전체가 무효영역이 된다.
bErase 는 Windows에 배경을 어떻게 처리할 지를 지정하는 플래그다. TRUE 면 BeginPaint 함수가 호출될때에, 무효영역의 배경을 Windows가 제거하게 된다.
결과적으로, 작업영역의 출력에 관한 모든 필요한 정보를 설정해서, 작업영역에 WM_PAINT 메세지를 발생시키게 된다. 물론, 윈도우 프로시저의 WM_PAINT 섹션에서, 메세지를 어떻게 처리할지를 미리 생각해 두어야한다. 이것은 아주 번거롭게 보이지만 윈도우 프로그래밍의 룰이다.
GetDC 함수와 ReleaseDC 함수의 사이에서 WM_CHAR 메세지를 처리함으로서, 작업영역에 출력 하는 것이 가능하다. 거기에는 아무런 문제도 없다. 다만, 작업영역의 화면복구 요구가 발생 했을때, 문제가 발생하게 된다. 문자를 출력하는 부분은 WM_CHAR 섹션이므로, 윈도우 프로시저에서는 작업영역의 화면복구 처리를 할 수가 없는것이다. 그렇기 때문에, (WM_CHAR 섹션의) 가장 마지막에(invoke InvalidateRect, hWnd, NULL, TRUE), WM_PAINT 메세지로 출력 하기 위해서 필요한 데이터와 코드를 써 두는 것이다. 이런 방법을 사용하면, 어떠한 부분에서도 WM_PAINT 메세지를 발생시켜, 언제라도 작업영역의 화면복구를 처리 할 수가 있다.
invoke TextOut, hdc, 0,0, ADDR char, 1InvalidateRect 함수가 호출되면, 윈도우 프로시저에 WM_PAINT 메세지 발생된다. 그렇기 때문에, WM_PAINT 메세지를 처리하는 부분을 WM_PAINT 섹션이라고 하는 것이다. BeginPaint 함수를 호출해서,DC핸들을 구해서, TextOut 함수로 작업영역의 좌표 x=0 y=0 부분에 문자열을 출력한다. 프로그램을 실행하고, 아무 키나 누르면, 작업영역의 최상단에 입력한 키가 표시된다. 그리고, 윈도우를 일단 최소화하고 나서 최대화하면, 문자는 여전히 출력된 채로 있다. 이것은, WM_PAINT 메세지가 화면을 복구해주고 있는 것이다.