. 키보드와 문자

문자를 입력하는 기본적인 장치는 키보드이다. OCR이나 음성, 펜같은 대안이 전혀 없는 것은 아니지만 아직도 문자입력용으로 키보드만한 장치가 없으며, 한 동안은 아마도 키보드가 계속 사용될 것이다. GUI 운영체제인 윈도우즈의 기본 입력장치도 아직까지는 마우스가 아니라 키보드이다. 그래서 우리는 문자입력을 프로그래밍하기 위해 키보드와 문자의 관계를 먼저 알아 볼 필요가 있다. 키보드에 의해 문자가 어떤 식으로 입력되는지를 연구해보자.

키보드는 키보드 드라이버가 관리하는데 사용자가 키를 누르거나 뗄 때 드라이버는 키의 눌림과 떨어짐을 운영체제에 보고(인터럽트)한다. 운영체제는 키보드 드라이버로부터 이 보고를 받았을 때 포커스를 가진 윈도우에게 메시지를 전달하여 키보드로부터 입력이 있었음을 알려준다. 이때 전달되는 메시지는 <Alt>키의 눌림 여부와 키의 상태에 따라 WM_(SYS)KEYDOWN(UP) 중 하나가 된다. 물론 wParam, lParam으로는 어떤 키가 눌러졌는지, 다른 키의 상태는 어떤지에 대한 정보가 전달될 것이다.

키보드는 키의 눌림과 떨어짐을 보고할 뿐이지 문자의 입력에는 전혀 관여하지 않는다. 응용 프로그램이 키보드 메시지로부터 입력된 문자를 계산해 내야 한다. 예를 들어 <r>키가 눌러졌으면 r 문자를 입력받고, <\>키가 눌러졌으면 \ 문자를 입력받으면 된다. 그런데 눌러진 키로부터 대응되는 문자를 알아내는 작업이 생각처럼 그렇게 간단하지가 않다. <r>키를 눌렀을 때 입력되어야 할 문자는 r, R, , ㄲ 넷 중 하나가 되는데 한글키, <Shift>, <Caps Lock> 등 주변 상황에 많은 영향을 받게 된다.

뿐만 아니라 현재 키보드가 2벌식인지 3벌식인지, 또 일본어 모드인지 러시아어 모드인지에 따라서도 실제 입력받을 문자가 달라진다. 응용 프로그램이 WM_KEYDOWN을 받아 이 메시지로부터 정확한 문자 해석을 직접 하는 것은 무척 어렵고 번거로운 일이다. 그래서 운영체제에게 지금 받은 키보드 메시지를 어떤 문자로 해석해야 할 지를 물어 볼 수 있는데 이 때 사용하는 함수가 바로 TranslateMessage 함수이다. 이 함수는 통상 메시지 루프에 포함되어 있으며 GetMessage가 큐에서 메시지를 꺼내는 즉시 호출된다.

 

while(GetMessage(&Message,0,0,0)) {

     TranslateMessage(&Message);

     DispatchMessage(&Message);

}

 

받은 메시지가 WM_KEYDOWN일 경우 TranslateMessage 함수는 현재 키보드의 레이아웃, Shift, Caps Lock, 기타 입력모드 등의 여러 가지 상태를 종합적으로 판단하여 최종적으로 입력되어야 할 문자를 계산해 내며 그 결과를 WM_CHAR 메시지로 보내준다. 만약 키보드 메시지가 아니거나 문자와 상관없는 키일 경우, 예를 들어 펑션키나 커서이동키인 경우는 아무 일도 하지 않으며 DispatchMessage로 이 메시지를 전달하여 WndProc으로 메시지를 보낸다.

그래서 응용 프로그램이 문자를 입력받으려면 다른 것은 신경쓸 필요없이 WM_CHAR 메시지를 받고 wParam으로 어떤 문자코드가 왔는지만 보면 되는 것이다. 요약하자면 문자입력을 받을 때는 WM_CHAR 메시지를 프로그래밍해야 하며 이 메시지를 사용하면 최종적으로 입력된 문자만 받을 수 있다.