2012년 3월 17일 토요일

[C++][WINAPI] GetKeyState()와 GetAsyncKeyState()의 차이점


예전에 인터넷에서 두 함수의 차이점을 검색해보았을때 잘못된 정보로 인해 혼란을 겪은 적이 있기 때문에 직접 정리해보기로 하였다.

일단 두 함수의 설명을 MSDN에서 찾아서 직접 번역해보았다.
이해하기 쉽도록 약간 의역 + 수정하였음을 밝혀둔다.


1.

SHORT GetKeyState( 
   int nVirtKey 
); 


이 함수는 특정 가상키의 상태를 찾아온다(retrieves). 키의 상태란 UP / DOWN / 토글 ON / OFF 상태를 말한다.

리턴값은,
키가 DOWN(눌린) 상태일때 최상위비트(high-order bit, 0x8000)가 1이고, UP이면 0이다.
토글 ON 이면 최하위비트(high-order bit, 0x0001)가 1이고, OFF이면 0이다.
(※ 참고로 GetKeyState는 Num Lock, Caps Lock 같은 토글키 이외에도 모든 키에 대하여 누를때마다 리턴값이 1과 0으로 토글된다.)

이 함수가 리턴하는 키의 상태는 특정 스레드가 그 메시지 큐로부터 키 메시지를 읽으면 변한다. 즉, 하드웨어 인터럽트 레벨에서의 키 상태를 반영하지는 못한다. 더 즉각적인 정보를 위해서는 GetAsyncKeyState 함수를 이용하는 것이 좋다.

응용프로그램은 키보드 입력 메시지에 대하여 GetKeyState를 호출한다. 이 함수는 입력 메시지가 생성되었을 때의 키의 상태를 반영한다.



2.

SHORT GetAsyncKeyState( 
  int vKey 
); 

이 함수는 함수 호출 시점에 특정키가 눌렸는지를 확인하며(determine) 바로 전의 호출과 이번 호출 사이에 키가 눌린 적이 있는지도 확인해준다.

키가 눌린 상태이면 최상위비트(most significant bit, 0x8000)가 셋(1)되고, 바로 전 호출 이후에 키가 눌린적이 있으면 최하위비트(least significant bit, 0x0001)가 셋된다.
GetAsyncKeyState()는 다른 스레드나 프로세스의 윈도우가 키보드 포커스를 가지고 있어도 값을 리턴해준다.




ps. 스타일러스 스크린이 눌렸을때 VK_LBUTTON 가상키로 감지할 수 있다.
ps2. GetAsyncKeyState가 검출하는 VK_LBUTTON 가상키 상태는 물리적인 마우스의 왼쪽 버튼 상태를 반영한다. 즉, 왼손잡이용으로 좌우 설정을 바꿔놨어도 상관없이 마우스 기계의 왼쪽 버튼 상태를 리턴한다. 참고로 GetSystemMetrics(SM_SWAPBUTTON) 연산을 사용하면 마우스 버튼이 스왑되어 있을 경우 참을 리턴한다.




GetKeyState()와 GetAsyncKeyState()는 아래 가상키를 처리할 수 있다.

VK_CONTROL   /// 좌우 상관없이 처리됨
VK_RCONTROL
VK_LCONTROL
VK_SHIFT
VK_LSHIFT
VK_RSHIFT
VK_MENU
VK_RMENU
VK_LMENU





3. 정리

GetKeyState()는 메시지 큐를 읽어서 리턴하고, GetAsyncKeyState()는 메시지 큐와 비동기적(asynchronized)으로, 즉 메시지 큐와 상관없이 기계입력에 즉각적으로 반응한다.
따라서 게임과 같은 즉각적인 키보드 반응이 필요한 경우 GetAsyncKeyState()가 더 좋다고 할 수 있다. GetKeyState()를 사용하면 만약에 메시지 큐에 메시지가 많이 밀렸을 경우 렉 현상이 생길 수 있기 때문이다.

사실 요즘은 하드웨어 성능이 워낙 빨라서 GetKeyState()를 써도 왠만해선 큰 차이가 느껴지지는 않는다. 그리고 토글키의 상태를 얻어오려면 어차피 반드시 GetKeyState()를 사용해야 한다.



ps. 다른 블로그에서 GetKeyState()는 윈도우 프로시저의 메시지큐 처리 루틴에서만 사용해야 한다는 글이 있었는데 이는 잘못된 정보이다. 영문 해석 과정에서의 실수로 보인다.

댓글 없음:

댓글 쓰기