posted by nsakura 2010. 7. 18. 12:28

WM_CHAR 메세지를 이용하면 입력을 받을 수 있다는것을 알게 되었는데

한가지 문제가 있었다. 문자 이외에는 입력을 받지 않는다는 것이다.

그래서 ins,del키 기능키 는 문자키가 아니기 때문에 이런  키는 아무리 눌러봤자 WM_CHAR메세지에 전달이 안된다.

이럴 때는 WM_KEYDOWN을 사용한다. 단(ALT,한영키, 등 몇가지는 제외가 된다)

wParam에 전달되는 것은 문자 코드가 아니라 가상의 키코드가 간다 이 키도는 다음과 같이 정의 되어있다.

 가상 키코드  값  키 
 VK_LBUTTON  01  
 VK_RBUTTON  02  
 VK_CANCEL  03  ctrl-break
 VK_MBUTTON  04  
 VK_BACK  08  backspace
 VK_TAB  09  tab
 VK_CLEAR  0C  numlook이 꺼져 있을때 5
 VK_RETRUN  0D  entwer
 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  space
 VK_PRIOR  21  pgup
 VK_NEXT  22  pgdn
 VK_END  23  end
 VK_HOME  24  home

 VK_LEFT  25  좌 화살표
 VK_UP  26  상 화살표
 VK_RIGHT  27  우 화살표
 VK_DOWN  28  하 화살표
 VK_SELECT  29  
 VK_PRINT  2A  
 VK_EXECUTE  2B  
 VK_SNAPSHOT  2C  print screen
 VK_INSERT  2D  insert
 VK_DELETE  2E  delete
 VK_HLEP  2F
 30~39
 41~5A
 
 숫자키 0~9
 영문자 A~Z
 VK_LWIN  5B  왼쪽 윈도우 키
 VK_RWIN  5C  오른쪽 윈도우키
 VK_APP  5D  Application 키
 VK_NUMPAD0~9  60~69  숫자패드 0~9
 VK_MULTIPLY  6A  숫자패드의 *
 VK_ADD  6B  숫자패드의 +
 VK_SEPARATOR  6C  
 VK_SUBTRACT  6D  숫자패드의 -
 VK_DECLMAL  6E  숫자패드의 .

 VK_DIVIDE  6F  숫자패드의 /
 VK_F1~F24  70~87  F1~F24키
 VK_NUMLOOK  90  NUMLOOK키
 VK_SCROOL  91  SCROLL LOCK


설마 이 표를 다 외울 생각을 하는 사람이 있는가? .. 있다면 할 필요 없다.

단순히 이런게 있다고만 기억하면 된다.

가상키는 현재는 물론 향후 나올지도 모르는 키에 대해서도 미리 정해두었다.

 WM_KEYDOWN 메세지 처리 루틴에서 wParam의 값과 가상 키코드값을 비교해 봄으로서 어떤 키가 눌렀는지 알아낼 수 있다.

그럼 예제를 한번보도록 하자.

#include <windows.h>

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

HINSTANCE nsakura;

LPCTSTR windName=TEXT("GFP KeyDown");

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd){
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 nsakura=hInstance;

 WndClass.cbClsExtra=0;
 WndClass.cbWndExtra=0;
 WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
 WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
 WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
 WndClass.hInstance=hInstance;
 WndClass.lpfnWndProc=WndProc;
 WndClass.lpszClassName=windName;
 WndClass.lpszMenuName=NULL;
 WndClass.style=CS_HREDRAW|CS_VREDRAW;
 RegisterClass(&WndClass);

 hWnd=CreateWindow(windName,windName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,(HMENU)NULL,hInstance,NULL);

 ShowWindow(hWnd,nShowCmd);

 while(GetMessage(&Message,NULL,0,0)){
  TranslateMessage(&Message);
  DispatchMessage(&Message);
 }

 return (int)Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam){
 HDC hdc;
 PAINTSTRUCT ps;
 static xpos=400;
 static ypos=400;

 switch(iMessage){

 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;

 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  TextOut(hdc,xpos,ypos,TEXT("GFP"),3);
  EndPaint(hWnd,&ps);
  return 0;

 case WM_KEYDOWN:
  switch(wParam){

  case VK_UP:
   ypos-=8;
   break;

  case VK_DOWN:
   ypos+=8;
   break;

  case VK_RIGHT:
   xpos+=8;
   break;

  case VK_LEFT:
   xpos-=8;
   break;

  }
 
  InvalidateRect(hWnd,NULL,true);
 }
 
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}


키보드의 방향키를 누르면 gfp 글씨가 움직일 것이다.

InvalidateRect(hWnd,NULL,true); 이것을 false로 바꿔서 해보자


이런식으로 이동시키게 되면 잔상이 남게 될것이다. 뭐 이건 어제 설명했으니 자세한 설명은 패스하도록 하겠습니다.

  자 위의 코드를 보고  스페이스바가 누르면 GFP글씨가 껌뻑이게 만들어보자.

방법은 자유.

본인이 사용한 방법은


TranslateMessage
 
그것을 아는가 키보드로부터 입력을 받으면 WM_KEYDOWN ->WM_CHAR->WM_KEYUP 순으로 메세지가 발생한다.

WM_KEYDOWN이 발생되면 내부적으로 그게 문자이면 WM_CHAR를 발생시키고 문자가 아닌경우 아무 일도 안하고

GetMeesage는 메세지큐에서 메세지를 꺼내고 TranslateMessage함수는 오로지 키보드로부터 문자키 입력 메세지인 WM_CHAR를

만들어내기 위한 것이다.

이 외에도 키보드 메세지들은

WM_SYSKEYDOWN,WM_SYSKEYUP, WM_SYSCHAR이 있는데

SYS(system)가 붙은건.  ALT가키와 함께 눌러지는 키보드 메세지들이다.

단 리턴을 할때는 DefWindowProc으로 보내줘야한다. 그렇지 않으면 alt esc,alt tap등의 화면전환 키까지 불능이 되버리기 때문이다.


'Computer > Win API' 카테고리의 다른 글

WinApi 타이머  (0) 2010.07.18
WinApi 마우스 입력.  (0) 2010.07.18
WinApi input WM_CHAR  (0) 2010.07.17
WinApi MessageBox  (0) 2010.07.17
WinApi 여러가지 출력  (0) 2010.07.16