일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- C++
- 표준 라이브러리 함수
- 캡슐화
- 유튜브 동영상 강의
- 소켓 통신
- 실습으로 다지는 c#
- 졸업 작품 소재
- 추천
- 언제나휴일
- 파이썬
- 알고리즘
- 졸업 작품
- c언어
- 산책하기 좋은 곳
- 네트워크 프로그래밍
- 소스 코드
- 동영상 강의
- 실습
- 클래스 다이어그램
- 무료 동영상 강의
- Windows Forms
- 강의
- 안드로이드 앱 개발
- 충남 천안
- 프로젝트
- 표준 입출력
- 원격 제어 프로그램
- 언제나 휴일
- c#
- 동영상
- Today
- Total
프로그래밍 언어 및 기술 [언제나휴일]
5. 키보드 입력 [Windows API] 본문
안녕하세요. 언제나휴일입니다.
이전 강의에서 마우스 입력을 알아보았어요.
이번에는 키보드 입력을 알아볼게요.
Windows API 키보드 입력에 관한 주요 메시지는 WM_KEYDOWN, WM_KEYUP, WM_CHAR 입니다.
윈도우즈 운영체제에서 키보드 포커스를 소유한 윈도우는 전체 시스템에서 유일합니다.
그리고 이러한 메시지(WM_KEYDOWN, WM_KEYUP, WM_CHAR)는 포커스를 소유한 윈도우에게만 발생합니다.
메시지 이름을 보면 알 수 있듯이 WM_KEYDOWN은 키 누름, WM_KEYUP은 키 뗌입니다.
WM_CHAR는 문자 키를 입력하였을 때 발생할 수 있는 메시지인데 디폴트로 발생하지는 않습니다.
메시지 루프에서 TranslateMessage를 호출하면 WM_KEYDOWN 메시지 중에서 문자 키에 관한 것일 때 WM_CHAR를 발생시켜 줍니다.
이에 관한 사항은 컨트롤(edit 컨트롤)을 다루면서 다시 소개할게요.
edit 컨트롤처럼 문자를 입력할 때 입력기에 따라 입력 문자열을 표시합니다.
한글은 현재 초성까지 입력한 상태인지 중성까지 입력한 상태인지 등에 따라 처리하는 것이 매우 까다롭습니다.
이러한 부분을 개발자가 매 번 구현하는 것은 어렵고 비용이 많이 들겠죠.
edit 컨트롤에서는 WM_CHAR 메시지가 발생하면 내부적으로 입력기를 이용해 화면에 표시해 줍니다.
WM_KEYDOWN 메시지의 WPARAM은 가상 키 코드, LPARAM은 다양한 상태 정보를 제공합니다.
다음은 LPARAM에서 각 비트 별로 어떠한 의미를 갖는지 나타낸 표입니다. MSDN 참조
비트 | 의미 |
0~15 | 현재 메시지 반복 횟수 |
16~23 | 스캔 코드 |
24 | 확장된 키 여부 |
25~28 | 사용하지 않음 |
29 | Context 코드(WM_KEYDOWN에서는 항상 0) |
30 | 이전 키 상태 |
31 | 전환 상태 |
다음은 누른 키의 가상 키 코드와 스캔 코드를 출력하는 코드입니다.
void OnKeyDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
HDC hdc = GetDC(hWnd);
RECT rt;
GetClientRect(hWnd, &rt);
Rectangle(hdc, 0, 0, rt.right, rt.bottom);
WCHAR buf[256];
wsprintf(buf, TEXT("가상 키 코드:%#X"), wParam);
TextOut(hdc, 10, 10, buf, lstrlen(buf));
wsprintf(buf, TEXT("스캔 코드:%#X"), (lParam>>16)&0xFF);
TextOut(hdc, 10, 40, buf, lstrlen(buf));
ReleaseDC(hWnd, hdc);
}
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
switch (iMessage)
{
case WM_KEYDOWN: OnKeyDown(hWnd, wParam, lParam); return 0;
case WM_DESTROY: OnDestroy(hWnd); return 0;
}
return DefWindowProc(hWnd, iMessage, wParam, lParam);
}
다음은 전체 소스 코드입니다.
//Windows API
//키보드 메시지 출력기
//키보드를 누르면 메시지 정보를 출력하시오.
#include <Windows.h>
#define MY_DEF_STYLE CS_HREDRAW | CS_VREDRAW|CS_DBLCLKS
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
void RegMyWndClass(LPCWSTR cname);
void MakeWindow(LPCWSTR cname);
void MsgLoop();
INT APIENTRY WinMain(HINSTANCE hIns, HINSTANCE hPrev, LPSTR cmd, INT nShow)
{
RegMyWndClass(TEXT("MyWindow"));
MakeWindow(TEXT("MyWindow"));
MsgLoop();
}
void RegMyWndClass(LPCWSTR cname)
{
//윈도우 클래스 속성 설정
WNDCLASS wndclass = { 0 };
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.hInstance = GetModuleHandle(0);
wndclass.hIcon = LoadIcon(0, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(0, IDC_ARROW);
wndclass.lpfnWndProc = MyWndProc;
wndclass.lpszMenuName = 0;
wndclass.lpszClassName = cname;
wndclass.style = MY_DEF_STYLE;
//윈도우 클래스 등록
RegisterClass(&wndclass);
}
void MakeWindow(LPCWSTR cname)
{
//윈도우 개체 생성
HWND hWnd = CreateWindow(cname,//클래스 이름
TEXT("키보드 메시지 출력기"),//타이틀 명
WS_OVERLAPPEDWINDOW,//윈도우 스타일
100, 30, 700, 600,//Left, Top, Width, Height
0, //부모 윈도우 핸들
0,//메뉴
GetModuleHandle(0),//모듈 핸들
0 //WM_CREATE에 전달할 인자
);
//윈도우 개체 시각화
ShowWindow(hWnd, SW_SHOW);
}
void MsgLoop()
{
MSG Message;
while (GetMessage(&Message, 0, 0, 0))//응용 큐에서 메시지를 꺼내오기
{
DispatchMessage(&Message);//메시지 수행(콜백 가동)
}
}
void OnDestroy(HWND hWnd)
{
PostQuitMessage(0);
}
void OnKeyDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
HDC hdc = GetDC(hWnd);
RECT rt;
GetClientRect(hWnd, &rt);
Rectangle(hdc, 0, 0, rt.right, rt.bottom);
WCHAR buf[256];
wsprintf(buf, TEXT("가상 키 코드:%#X"), wParam);
TextOut(hdc, 10, 10, buf, lstrlen(buf));
wsprintf(buf, TEXT("스캔 코드:%#X"), (lParam>>16)&0xFF);
TextOut(hdc, 10, 40, buf, lstrlen(buf));
ReleaseDC(hWnd, hdc);
}
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
switch (iMessage)
{
case WM_KEYDOWN: OnKeyDown(hWnd, wParam, lParam); return 0;
case WM_DESTROY: OnDestroy(hWnd); return 0;
}
return DefWindowProc(hWnd, iMessage, wParam, lParam);
}
'C & C++ > Windows API 예제' 카테고리의 다른 글
7. 첫 번째 실습 – 도형 이동 시키기 [Windows API] (1) | 2024.01.26 |
---|---|
6. 타이머 입력 [Windows API] (0) | 2024.01.26 |
4. 마우스 입력 (0) | 2024.01.25 |
3. 기본 그리기 [Windows API] (1) | 2024.01.24 |
2. 윈도우 클래스 등록 및 윈도우 개체 생성 (0) | 2024.01.24 |
1. Windows API 소개 (1) | 2023.12.26 |
테트리스 처음부터 끝까지 [C++, Windows API] (0) | 2023.12.25 |