Windows 환경에서는 프로그램이 자기 화면(창)에다 뭔가를 그리고 표시하는 걸 보통은 WM_PAINT 메시지가 왔을 때 한다.
하지만 반드시 그때만 그림을 그릴 수 있는 건 아니다. 키보드나 마우스 입력(특히 뭔가 드래그)이 들어와서 특정 지점에 대한 시각 피드백만 즉각 주고 싶을 때, 혹은 타이머를 걸어서 일정 시간 주기로 반드시 뭔가를 그리고 싶을 때는 InvalidateRect라든가 WM_PAINT에 의존하지 않고, 프로그램이 직통으로 DC를 얻어 와서 그림을 그려도 된다.

화면 그리기뿐만 아니라 키보드 입력 인식도 마찬가지이다.
반드시 WM_KEYDOWN/UP 메시지를 통해서만 키보드 입력을 인식할 수 있는 건 아니다. 마우스 메시지를 처리 중일 때도 shift나 ctrl 같은 modifier key가 같이 눌렸는지, 혹은 caps/num/scroll lock 램프가 현재 켜져 있는지를 함수 호출 하나로 간편하게 알 수 있다.
그런 modifier 글쇠조차 매번 WM_KEYDOWN/UP때만 감지할 수 있다면.. 응용 프로그램이 지역 변수의 범위를 넘어서는 지저분한 key state 관리자를 둬야 할 것이고, 코딩이 굉장히 번거롭고 불편해질 것이다.

옛날에 도스 시절에 키 입력을 감지하는 건 꽤 번거로웠던 걸로 본인은 기억한다.
문자가 아닌 화살표, home/end, page up/down 같은 글쇠에 대해서는 0번(null) 문자가 prefix 명목으로 오고, 동일 함수를 한번 더 호출해서 실제 값(아마 스캔 코드)을 얻는 형태였다. 그러고 보니 저건 나름 dead key라는 개념이 구현된 셈이다.

그것 말고 ctrl이나 shift, 각종 lamp 글쇠는 저런 방식으로도 잡히지 않았기 때문에 또 다른 도스 API를 동원해야 했다. 요것들은 키보드 버퍼를 차지하지 않고, 컴퓨터가 바쁠 때 아무리 누르고 있어도 삑삑 소리를 발생시키지 않는 조용한 특수글쇠이기 때문이다.;;

글쇠를 누르는 것 말고 떼는 것을 감지하는 것도 본인은 도스 시절에 개인적으로 경험한 적이 없다.
글쇠를 누르고 있는 동안 해당 문자를 일정 간격으로 반복해서 접수해 주는 것은 컴퓨터 하드웨어 차원에서 행해지는 일인데.. 그런 키보드 속도에 구애받지 않고 누른 것과 뗀 것 자체만을 감지하는 건 특히 게임 만들 때의 필수 테크닉이다.
그랬는데 Windows에서는 모든 글쇠들이 한 치의 차별 없이 WM_KEYDOWN과 WM_KEYUP 메시지 앞에서 평등해지고 가상 키코드값을 부여받게 됐다니~! 정말 혁명 그 자체였다. 프로그래밍 패러다임이 싹 바뀌었다.

가상 키코드는 기반이 전적으로 소프트웨어에 있는 계층이기 때문에 같은 하드웨어에서도 차이가 날 수 있다. 가령, 같은 글쇠에다 가상 키코드를 부여하는 방식은 Windows와 mac이 서로 다를 수 있으며, Windows는 사용하는 키보드 드라이버에 따라서도 차이가 날 수 있다.

Windows의 가상 키코드는 caps lock 내지 shift의 영향을 받지는 않기 때문에 a건 A건 코드값이 같다. 하지만 num lock의 영향은 받기 때문에 키패드 0~9 숫자와 키패드 화살표의 코드값이 서로 다르다. 키패드 numlock 숫자는 진짜 숫자키의 숫자와도 가상 키코드가 다르다.
가상 키코드와 달리 스캔 코드는 각각의 물리적인 글쇠들에 고정불변으로 부여되어 있다. 좌우로 두 개 있는 shift처럼 가상 키코드가 동일한 글쇠는 스캔 코드로 방향을 구분할 수 있다.

요컨대 스캔 코드는 저수준이고 가상 키코드는 고수준이다. 여기에다가 문자 글쇠는 message loop에서 TranslateMessage 함수를 거침으로써 caps lock(대소문자)까지 고려한 실제 입력 문자가 담긴 WM_CHAR로 바뀐다.
WM_CHAR가 생성되는 과정(가상 키코드와 스캔 코드로부터 문자를 얻기)이 별도의 함수로 제공되기도 한다. 바로 ToUnicode 내지 ToAscii이다.

배경 설명이 좀 길어졌는데..
현재 어떤 글쇠가 눌러졌는지 여부를 알려주는 대표적인 함수는 GetKeyState이다. 인자로는 가상 키코드를 주면 되고, 리턴값으로는 2비트의 유의미한 정보가 담긴 BYTE값이 돌아온다.
최상위 비트 0x80은 이 key가 지금 눌렸는지의 여부이고, 최하위 비트 1은 눌렸다 뗐다 toggle 여부이다. 3대 lock들의 램프 점등 여부는 &1을 해 보면 알 수 있다.

심지어 GetKeyboardState 함수는 모든 가상 키코드값에 대한 키보드 상태를 배열 형태로 한꺼번에 되돌려 준다.
컴퓨터 키보드의 글쇠는 많아야 100여 개이지만 가상 키코드의 범위는 0~255라는 바이트 규모이므로 가상 키코드를 할당할 공간은 아주 넉넉한 셈이다.

그런데 Windows에는 GetAsyncKeyState라는 함수도 있다. 무엇이 비동기적이라는 얘기이며 GetKeyState와는 어떤 차이가 있는 걸까..?
GetKeyState는 현재 스레드의 메시지/input 큐 기준으로 WM_KEYDOWN/UP 메시지가 마지막으로 처리되었던 그 순간의 키보드 상태를 일관되게 쭉 되돌린다. 한 메시지가 처리되던 도중에 사용자가 어떤 글쇠를 누르거나 떼더라도 값이 변함없다.
한 컴퓨터에 키보드야 하나만 존재하겠지만, 각 응용 프로그램의 UI 스레드별 키보드 상태는 이론적으로 서로 제각각으로 다를 수 있다.

그 반면, GetAsyncKeyState는 그런 것과 상관없이 시스템 전체의 현재 키보드 상태를 실시간으로 반영해서 알려준다. 그리고 이유는 알 수 없지만 GetKey*는 최상위 bit 크기가 BYTE인 반면, GetAsyncKey*는 최상위 bit 크기가 WORD이다.
둘 다 함수의 리턴 타입은 short로 잡혀 있다. 하지만 전자는 눌려 있는 글쇠를 0x80으로 표현하는 반면, 후자는 0x8000으로 표현한다.

그러면 마우스 휠을 Ctrl을 누른 채로 굴렸는지 감지하고 싶을 때 GetKey*와 GetAsyncKey* 중 무엇을 쓰는 게 좋을까?
프로그램이 사용자의 키보드· 마우스 입력에 0.1초 안으로 정상적으로 반응하고 있는 상태라면 두 함수는 유의미한 차이를 보이지 않는다.

GetAsyncKey*는 내 프로그램이 작업을 하느라 수 초 동안 응답이 멎은 중에 사용자가 ESC를 누른 것 정도나 잡아내는 용도로 쓰면 된다. 아니면 애초에 자기 GUI 창이 없는 콘솔 프로그램에서 키 입력을 감지하는 것 말이다. 얘는 심지어 포커스가 다른 프로그램에 가 있을 때에도 특정 글쇠가 눌린 것을 감지할 수 있다.

이와 달리 GetKey*는 메시지 처리 단위로 실행 결과가 '동기화'돼 있으며, 정확하게 자기 스레드의 UI에 포커스가 가 있을 때 글쇠가 눌린 것만 감지해 준다. 그러니 일반적인 상황에서 우리에게 필요한 것은 대체로 GetAsyncKey*가 아니라 그냥 GetKey*이다.

Async가 붙은 놈이건 안 붙은 넘이건, 이들 함수는 글쇠가 눌린 것을 감지만 하지, 그걸 처리한 것으로 퉁쳐 주지는 않는다. 내 작업 루틴에서 ESC가 눌린 것을 감지해서 하던 작업을 중단했다 하더라도 UI에서 WM_KEYDOWN + VK_ESCAPE 메시지가 가는 것은 변함없다.
이럴 거면 GetAsyncKey*를 호출할 게 아니라 Peek/Get/DispatchMessage로 메시지를 정식으로 처리하는 게 더 낫다. GetAsyncKey*는 쓸 일이 더욱 줄어드는 셈이다.

Posted by 사무엘

2021/03/20 08:35 2021/03/20 08:35
, , ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1867

옛날 물건들 추억

1. 특수한 그리기 도구(?)

오래 전에 아이패드를 보고는 문득 이런 물건 생각이 났다.
저렇게 태블릿과 비슷하게 생긴 판때기 모양의 장난감이었는데, 전기를 쓰지는 않고 안에 가루 같은 게 꽉 차 있었다. 그리고 그 표면에다 펜으로 뭘 그리면 그림이 그려졌다. 흔들거나 다른 특수한 방법으로 내용을 다 지우고 화면을 초기화할 수도 있었다.
이런 식으로 내부의 가루 상태를 이용해서 단색 그림을 그리는 패드가 있었는데 이 이상 더 자세한 정보가 남아 있질 않고 인터넷으로 더 검색도 할 수 없다. 이런 거 기억하시는 분의 제보를 기다린다.

2. 카세트 테이프의 주행

지금이야 음악 감상은 컴퓨터의 디지털 기술 기반으로 완전히 바뀌었지만 옛날에는 카세트 테이프라는 게 시대를 풍미하는 음성 매체였다.
카세트 테이프에는 주행용 구멍이랄까 회전축이랄까 그게 두 개가 있다. 재생을 하면 두 구멍 중 오른쪽에 있는 것 하나만 돌아간다. 되감기를 하면 왼쪽 것이 돌아가고. 즉, 한쪽의 동력이 다른 한쪽으로도 전해지는 형태이다.

사용자 삽입 이미지

그런데 난 테이프를 재생하는 중에 두 구멍의 회전 속도가 왜 서로 차이가 나는지가 어릴 때부터 굉장히 궁금했다.
갓 재생을 시작해서 테이프들이 아직 왼쪽에 몰려 있을 때는 왼쪽 구멍의 회전이 느리고 오른쪽 구멍의 회전이 빨랐다.
그러나 한 편을 다 들어서 테이프가 오른쪽에 몰려서 오른쪽이 거대해지고 나면, 반대로 왼쪽은 빨리 돌아가고 오른쪽은 느려졌다.

지금 그 모양을 다시 생각해 보니 카세트 테이프는 직경이 다른 두 톱니바퀴의 회전으로 인한 변속이라는 개념을 설명해 주는 좋은 예였다. (테이프가 한쪽에서 다른 쪽으로 감기면서 양 구멍의 직경이 서로 달라지므로..)
아니, 더 나아가 테이프는 톱니라기보다는 벨트에 더 가까운 형태이니, CVT 무단변속기를 떠올릴 수 있을지도 모르겠다.
지금 카세트 테이프 재생기가 있으면 주행 과정에서 양 구멍/바퀴의 변속비가 얼마까지 달라지는지를 더 눈여겨보고 싶다.

3. 노래방 기계 글꼴

요즘 노래방을 가 보면 옛날에 비해 가사의 글꼴이 더 새끈한 걸로 바뀐 것만 봐도 시대가 바뀌었다는 걸 개인적으로 딱 바로 알 수 있었다.
오랫동안 노래방 가사 자막용으로 쓰인 서체는 아래 그림에서 보듯이 아래아한글 40*40 비트맵 명조를 떠올리게 하는 구닥다리 비트맵 명조체였기 때문이다. 1990년대 초반에 아래아한글 1.x로 조판된 듯한 옛 영진 출판사 책들을 보는 느낌이다.

사용자 삽입 이미지

그러다가 이 명조체를 대체한 것은 큐닉스 서체인 가을체와 으뜸체 정도. 노래방 기계에서는 요 둘이 굉장히 많이 쓰인 것 같다.

사용자 삽입 이미지사용자 삽입 이미지

나중에는 노래방에서도 서울남산이나 나눔(바른)고딕을 볼 수 있지 않을까 싶다.

4. 옛날 키보드

한동안 완전히 잊고 있었는데.. 그러게, 한 30년 전쯤의 구닥다리 컴퓨터들은 키보드의 구성이 지금과는 살짝 달랐다. 미국 원판은 84키이고 한국에서는 한영/한자가 추가돼서 86키였다.

사용자 삽입 이미지

난 초딩 시절에 컴퓨터 학원에서 이 구식 키보드를 본 기억이 있다. 지금 키보드와 다른 점은 다음과 같다.

  • 일단 F1~F10 기능키는 왼쪽에 2열 종대로 늘어서 있고 F11과 F12는 존재하지 않는다.
  • 문자 키와 키패드 사이에 여분의 화살표 내지 키패드 기능 키들(pg dn/up, home, end, insert, del)이 따로 존재하지 않는다. 따라서 Num lock이 켜져 있는 동안은 키패드 기능 키들을 사용할 수 없다.
  • Ctrl은 지금 Caps lock이 있는 곳에 있다. 그 대신 Caps lock은 우측 하단에 있다. (그래 그랬다, 완전 추억 쩐다!)
  • ESC가 지금의 Num lock 자리에 있다.
  • 키패드에는 +가 지금의 엔터 자리에 있다. 그리고 / 는 키패드에 존재하지 않는다.

그러다가 지금 키보드의 전신인 101키 키보드가 나오고, 국내에서는 역시 한영/한자가 추가돼서 103키가 되었다. Windows 95부터는 Win키가 그것도 좌우에 하나씩 2개나 추가되고, 또 컨텍스트 메뉴키가 더해져서 10키가 되었고, 이것이 현재까지 전해 내려오고 있다.
그나저나 키보드의 연결 단자 자체도 DIN 내지 AT 단자부터 시작했다가 PS/2 단자를 거쳐 지금은 USB가 대세가 됐으니 이것도 격세지감이다.

저런 '정식 키보드'는 규격이 전부 통일되어 있는 반면, 기계마다 살짝 차이가 있어서 혼동을 주는 건 노트북 컴퓨터 키보드에서 키패드의 기능키들이 배당된 방식들이다. 특히 pg up/dn이나 home/end 같은 것.
그리고 노트북은 부족한 키의 기능을 보충하려다 보니 자체적인 fn 키도 있는데.. 일반 노트북의 경우 좌측 하단에 Ctrl fn win alt의 순으로 키가 있었던 반면, 맥북은 fn ctrl alt win으로 순서가 미묘하게 바뀌어 있어서 이것도 적응이 몹시 힘들었다.

Posted by 사무엘

2015/10/09 08:34 2015/10/09 08:34
, , , ,
Response
No Trackback , 2 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1147

윈도우 운영체제용 한국어 키보드 드라이버에는 type 3이라는 방식이 있다. 이게 왜 있는지 내력을 좀 설명하자면 이렇다.

한국에서 쓰이는 PC 키보드에는 한글/영문 입력 모드 전환을 위해 한영 키가 있고, 한자 변환을 위해 별도의 한자 키가 있다. 하지만 도스 시절에 이 키를 하드웨어적으로 인식하기란 쉽지 않았고, 당시 많은 자체한글 프로그램들이 실제로는 Shift+Space로 한영 전환을 하곤 했다. 그리고 한자 변환은 아래아한글의 관행인 F9가 대세였다.

한영 전환 글쇠에 대한 호불호는 사람마다 편차가 큰 것 같다. 한영 키가 직관적으로 그렇게 누르기 편한 위치에 있지도 않은 건 사실이다. 그 때문에, 이걸 굉장히 싫어하고 오로지 Shift+Space만 쓰는 사람도 있다. 오로지 한영 전환 글쇠 때문에 MS IME를 버리고 새나루나 <날개셋> 한글 입력기를 쓸 정도이니까.

그러나 반대로 Shift를 이용한 뒤에 진짜로 공백을 누르고 싶은데 실수로 글쇠 전환이 되어 버려서 그게 불편하다고 느끼는 사람도 있다. 본인은 후자에 가까운 타입이어서 그냥 한영 키를 쓰는 것을 선호한다.

마이크로소프트는 자사의 제품에서 원래 ‘정석대로’ 한영/한자 키만을 지원하였다. 그러나 도스 시절의 저 관행에 익숙한 사람들을 위해 Shift+Space를 한영 키로, Ctrl+Space를 한자 키로 드라이버 차원에서 인식하는 키보드 드라이버도 별도로 제공했는데, 이것이 바로 type 3이다.

이 드라이버는 반대로 기존 한영/한자 키는 Ctrl/Alt로 인식한다. 그래서 드라이버를 쓰면 Shift뿐만 아니라 Ctrl/Alt도 좌우를 구분할 수 있다. 그러나 Shift+Space와 Ctrl+Space를 원래 자체적인 용도로 쓰는 엑셀 같은 프로그램(행 또는 열 전체 선택)에서는 해당 글쇠를 사용할 수 없어지는 문제도 존재한다.

type 3 키보드를 사용하려면 제어판에 들어가서 키보드 드라이버를 업데이트해야 하는데, 수 단계에 걸친 마법사 질문들을 전부 일관적으로, 운영체제가 권장하지 않는(non-typical) 예외 옵션만 골라야 사용할 수 있다.

이런 키보드 드라이버가 있기 때문에 본인은 <날개셋> 한글 입력기를 도대체 어느 장단에 맞춰 춤을 추도록 만들어야 할지 모르는 고민에 빠지게 됐다. 일단 이 프로그램은 한영 전환과 한자 전환 글쇠를 마음대로 사용자 지정 가능하기 때문에, 드라이버 차원에서 글쇠를 변조해 주는 type 3 같은 드라이버는 사용하지 않길 권한다. 기존 type 1에서도 얼마든지 Shift+Space로 한영 전환이 가능하고 그게 기본값이다.

일단, 이 프로그램은 type 3에 대한 보정을 한다. 사용자가 Shift+Space를 누른 것을 드라이버가 한영이라고 fake로 알려 주더라도, 키의 스캔코드는 여전히 space이기 때문에 한영이 아닌 Shift+Space에 해당하는 단축글쇠를 참고한다. type 3은 Ctrl과 Alt의 좌우 구분은 가능하지만 한영과 한자 키를 전혀 인식하지 못하는 모드가 되는 것이다.

한자 키는 지금까지는 보정을 했는데 다음 버전부터는 보정하지 않을 것이다. 보정을 하기 때문에 Ctrl+Space는 말 그대로 한자가 아닌 Ctrl+Space로 type 3에서도 그대로 인식되며, 이 때문에 <날개셋> 한글 입력기의 설치 직후 기본 설정으로는 type 3 키보드로 한자 변환을 할 수 없었다. 보정을 하지 않게 되면 이 키는 Ctrl+한자 키로 인식된다.

그리고 다음 버전부터는 ‘한자’ 키뿐만이 아니라 ‘Ctrl+한자’도 한자 후보 변환으로 인식하는 값을 단축글쇠 테이블의 기본값으로 추가할 것이다. 이로써 동일한 기본 설정만으로 type 1과 type 3 모두 각각의 한자 키로 한자 변환이 가능해지는 것이다. 요컨대 한영 전환인 Shift+Space는 보정을 하지만, 한자 변환인 Ctrl+Space는 보정하지 않는다는 뜻이다.

한영 전환 글쇠와는 달리 한자 변환 글쇠는 매우 드물게 쓰이고 사용자별 편차도 거의 없으니, 그냥 이렇게 하는 게 더 나은 선택이겠다. 어차피 MS IME는 그냥 한자를 누르든 Shift+한자를 누르든, Ctrl+한자를 누르든 똑같이 동작하더라.

다만, <날개셋> 한글 입력기의 다음 버전에서는 후보 변환 기능이 세분화되어 Shift+한자는 제2 후보 변환으로 기본 설정이 바뀔 예정이다. 이것을 type 3 키보드는 제대로 인식을 못 할 것이다. 그렇기 때문에 <날개셋> 한글 입력기를 사용할 때는 글쇠를 임의로 변조하는 type 3 대신 글쇠를 있는 그대로 돌려 주는 기본 type 1을 쓸 것을 권한다.

여담이다만, 윈도우 운영체제의 한글 키보드는 한영 전환과 한자 변환 말고 전/반자 모드 전환이라는 또 다른 명령이 존재한다. 이건 완전히 듣보잡화한 상태이기 때문에 아는 사람이 거의 없을 것이다. -_-;; 키보드에 독립된 글쇠가 있지도 않고, 그 글쇠가 Alt+=로 정의되어 있다.

Posted by 사무엘

2012/03/09 08:58 2012/03/09 08:58
, ,
Response
No Trackback , 8 Comments
RSS :
http://moogi.new21.org/tc/rss/response/652


블로그 이미지

철도를 명절 때에나 떠오르는 4대 교통수단 중 하나로만 아는 것은, 예수님을 사대성인· 성인군자 중 하나로만 아는 것과 같다.

- 사무엘

Archives

Authors

  1. 사무엘

Calendar

«   2021/04   »
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30  

Site Stats

Total hits:
1580717
Today:
329
Yesterday:
517