Hacking Arts
키보드 입력 본문
- 키보드 입력 이벤트는 간단하게 WM_KEYDOWN,WM_KEYUP, WM_CHAR 이렇게다.
- WM_KEYDOWN : 키보드의 어느 키가 눌러지든 발생한다.
- WM_KEYUP : 키보드의 어느 키가 눌렸다가 떼는 과정에서 발생한다.
이 두개는 한쌍으로 발생한다.
- 가상 키코드 wParam으로 가상 키코드가 들어오게 되는데
카상키코드표 여기에 들어가면 볼 수 있다. 표에는 숫자와 영문자가 정의되어 있지 않은데 문자 키의 식별은 아스키 코드를 비교하여 식별 하면 되고, 그 외의 키는 정의된 가상 키 코드를 가지고 식별하면 된다.
[ 그림 1 key 이벤트 발생 ]
-아래 와 같은 소스를 통해 위 그림 1의 이벤트 발생 시킬 수 있다
case WM_KEYDOWN: switch (wParam) { case VK_HOME: MessageBox(hWnd, L"HOME 키를 누름", L"HOME", MB_OK); return 0; case VK_END: MessageBox(hWnd, L"END 키를 누름", L"END", MB_OK); return 0; } return 0;
- 그렇다면 WM_CHAR는 어떻게 발생하는가? WM_CHAR의 경우 wParam으로 아스키코드표에 맞는 문자가 오게 된다.
아래소스 코드를 실행하게되면 그림 처럼 z 키와 home키를 구분해서 받는 것을 확인 할 수 있다.
[ 그림 2 key 이벤트 발생 ]
static TCHAR strChar[MAX_PATH]; int nlen = 0; HDC hdc; PAINTSTRUCT ps; switch (iMessage) { case WM_KEYDOWN: switch (wParam) { case VK_HOME: MessageBox(hWnd, L"HOME 키를 누름", L"HOME", MB_OK); return 0; case VK_END: MessageBox(hWnd, L"END 키를 누름", L"END", MB_OK); return 0; } return 0; case WM_CHAR: nlen = strlen((char *)strChar); strChar[nlen] = (char)wParam; strChar[nlen + 1] = 0; InvalidateRect(hWnd, NULL, FALSE); return 0; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); TextOut(hdc, 100, 100, strChar, strlen((char*)strChar)); EndPaint(hWnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; }
- 키보드 입력시 부가 정보
- wParam을 통해서 키 값은 모두 전달된다. 영문자 및 숫자와 같은 문자 키일 경우에는 아스키코드 값이 문자 키가 아닌 경우에는 가상 키코드 값이 들어온다
- lParam의 경우는 이렇게 쓰이는데 중요하지는 않다. 보는 정도로 넘어가자
비트 번호 |
설명 |
0 - 15 |
키의 반복되는 카운트 |
16 - 23 |
스캔 코드 |
24 |
확장키가 눌러졌을 때 1이 된다. |
25 - 28 |
사용 안함 |
29 |
Alt 키가 눌려졌을 때 1 |
30 |
메시지를 보내기 전에 키가 눌려져 있으면 1 |
31 |
키가 눌려지면 1, 키가 떼어지면 0 |
- TranslateMessage 함수
이전에 WM_KEYDOWN은 무조건 발생하기 때문에 Translate함수가 중요하다. 문자와 문자가 아닌 키의 구별을 위한 함수이다. 아래 그림과 같은 처리과정을 거치게 된다. 왼쪽이 문자 오른쪽이 문자가 아닌 키이다.
[ 그림 3 키보드 이벤트 처리 과정 ]
- 캐럿 : 커서라고도 부르는 깜빡이면서 대기하는 것이다.
[ 그림 4 캐럿 처리 단계]
- 포커스 : 여러 윈도우중 현재 사용하고 있는 윈도우에 포커를 맞추게 된다. 내가 지금 이 글을 쓰는 동안에는 브라우져가 포커스를 가지게 된다.
-WM_SETFOCUS : 이 메시지는 윈도우가 키보드 포커스를 받은 후에 전달 된다. 즉 키보드 포커스의 이동 완료 후에 바로 이메시지가 발생한다. 결국 이 메시지가 발생 시 캐럿을 생성하고 보여주고, 위치를 설정해 준다.
- WM_KILLFOCUS : 캐럿은 시스템 전역적으로 사용하는 유일한 자원이므로 윈도우가 포커스를 잃으면사용 중인 캐럿을 파괴해야된다. 이 메시지를 이용해 파괴 하면 된다.
[ 그림 5 캐럿]
- 아래 그림처럼 캐럿 생성과 포커스의 설명을 볼 수 있다.
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) { static TCHAR strChar[MAX_PATH]; int nlen = 0; static int pos = 0; SIZE size; HDC hdc; PAINTSTRUCT ps; switch (iMessage) { case WM_CREATE: strcpy((char *)strChar, ""); return 0; case WM_CHAR: nlen = strlen((char *)strChar); strChar[nlen] = (char)wParam; strChar[nlen + 1] = 0; pos++; hdc = GetDC(hWnd); GetTextExtentPoint(hdc, strChar, pos, &size); ReleaseDC(hWnd, hdc); SetCaretPos(size.cx + 100, 100); InvalidateRect(hWnd, NULL, FALSE); return 0; case WM_SETFOCUS: hdc = GetDC(hWnd); CreateCaret(hWnd, NULL, 2, 14); ShowCaret(hWnd); SetCaretPos(100, 100); return 0; case WM_KILLFOCUS: HideCaret(hWnd); DestroyCaret(); return 0; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); TextOut(hdc, 100, 100, strChar, strlen((char*)strChar)); EndPaint(hWnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return(DefWindowProc(hWnd, iMessage, wParam, lParam)); }
'Programing > API Programing' 카테고리의 다른 글
resource (icon/cursor) (0) | 2014.11.04 |
---|---|
타이머 (0) | 2014.10.11 |
마우스 입력 (0) | 2014.10.10 |
문자열 / 점 / 선 / 사각형 / 원 / 다각형 / 메시지 박스 (0) | 2014.10.10 |
출력 / GDI / DC (0) | 2014.10.10 |