풍쿠 winapi 게임프로그래밍 3강 키다운 키업
// winmain.cpp
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
//함수 프로토타입
// Function prototypes
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
bool CreateMainWindow(HINSTANCE, int);
LRESULT WINAPI WinProc(HWND, UINT, WPARAM, LPARAM);
//전역 변수
// Global variables
HINSTANCE hinst;
HDC hdc; // 디바이스 컨텍스트의 핸들 handle to device context
TCHAR ch = ' '; // 입력한 문자 character entered
RECT rect; // 사각형 구조체 rectangle
PAINTSTRUCT ps; // WM_PAINT 에서 사용 used in WM_PAINT
bool vkKeys[256]; // 가상 키들의 상태 state of virtual keys, 거짓 혹은 참 false or true
//상수
// Constants
const char CLASS_NAME[] = "Keyboard";
const char APP_TITLE[] = "Keys Down"; //제목 표시줄의 텍스트
const int WINDOW_WIDTH = 400; // 윈도우의 폭 width of window
const int WINDOW_HEIGHT = 400; // 윈도우의 높이 height of window
//=============================================================================
// 윈도우 애플리케이션의 시작 위치 Starting point for a Windows application
//=============================================================================
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
//메인 윈도우 생성
// Create the main window
if (!CreateMainWindow(hInstance, nCmdShow))
return false;
for (int i=0; i<256; i++) // 가상 키 배열 초기화 initialize virtual key array
vkKeys[i] = false;
//메인 메시지 루프
// main message loop
int done = 0;
while (!done)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
//종료 메시지 찾는다.
//look for quit message
if (msg.message == WM_QUIT)
done = 1;
//해석한뒤 메시지를 WinProc에 전달한다.
//decode and pass messages on to WinProc
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
//=============================================================================
// 윈도우 이벤트 콜백 함수 window event callback function
//=============================================================================
LRESULT WINAPI WinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
short nVirtKey; // 가상 키 코드 virtual-key code
const short SHIFTED = (short)0x8000;
TEXTMETRIC tm; // 텍스트 매트릭스의 구조체 structure for text metrics
DWORD chWidth = 20; // 문자들의 폭 width of characters
DWORD chHeight = 20; // 문자들의 높이 height of characters
switch( msg )
{
case WM_CREATE:
//텍스트 매트릭스를 가져온다.
// get the text metrics
hdc = GetDC(hwnd);
GetTextMetrics(hdc, &tm);
ReleaseDC(hwnd, hdc);
chWidth = tm.tmAveCharWidth; // 평균 문자 폭 average character width
chHeight = tm.tmHeight; // 문자 높이 character height
return 0;
case WM_DESTROY:
//윈도우에 말한다 이 프로그램 죽이라고 tell Windows to kill this program
PostQuitMessage(0);
return 0;
case WM_KEYDOWN: // 키를 누른 경우 key down
vkKeys[wParam] = true;
switch(wParam)
{
case VK_SHIFT: // 쉬프트 shift 키 key
nVirtKey = GetKeyState(VK_LSHIFT); // 왼쪽 쉬프트의 상태 를 가져온다 get state of left shift
if (nVirtKey & SHIFTED) // 만약 왼쪽 쉬프트를 눌렀다면 if left shift
vkKeys[VK_LSHIFT] = true;
nVirtKey = GetKeyState(VK_RSHIFT); // 오른쪽 쉬프트의 상태를 가져온다. get state of right shift
if (nVirtKey & SHIFTED) // 만약 오른쪽 쉬프트를 눌렀다면 if right shift
vkKeys[VK_RSHIFT] = true;
break;
case VK_CONTROL: // 컨트롤 키 control key
nVirtKey = GetKeyState(VK_LCONTROL);
if (nVirtKey & SHIFTED) // 만약 왼쪽 컨트롤을 눌렀다면 if left control
vkKeys[VK_LCONTROL] = true;
nVirtKey = GetKeyState(VK_RCONTROL);
if (nVirtKey & SHIFTED) // 만약 오른쪽 컨트롤을 눌렀다면 if right control
vkKeys[VK_RCONTROL] = true;
break;
}
InvalidateRect(hwnd, NULL, TRUE); // WM_PAINT를 강제한다. force WM_PAINT
return 0;
break;
case WM_KEYUP: // 키를 뗀 경우 key up
vkKeys[wParam] = false;
switch(wParam)
{
case VK_SHIFT: // 쉬프트 키 shift key
nVirtKey = GetKeyState(VK_LSHIFT);
if ((nVirtKey & SHIFTED) == 0) // 만약 왼쪽 쉬프트를 눌렀다면 if left shift
vkKeys[VK_LSHIFT] = false;
nVirtKey = GetKeyState(VK_RSHIFT);
if ((nVirtKey & SHIFTED) == 0) // 만약 오른쪽 쉬프트를 눌렀다면 if right shift
vkKeys[VK_RSHIFT] = false;
break;
case VK_CONTROL: // 컨트롤 키 control key
nVirtKey = GetKeyState(VK_LCONTROL);
if ((nVirtKey & SHIFTED) == 0) // 만약 왼쪽 컨트롤을 눌렀다면 if left control
vkKeys[VK_LCONTROL] = false;
nVirtKey = GetKeyState(VK_RCONTROL);
if ((nVirtKey & SHIFTED) == 0) // 만약 오른쪽 컨트롤을 눌렀다면 if right control
vkKeys[VK_RCONTROL] = false;
break;
}
InvalidateRect(hwnd, NULL, TRUE); // WM_PAINT 를 강제한다. force WM_PAINT
return 0;
break;
case WM_CHAR: // 한 문자가 키보드에 눌러졌다면 a character was entered by the keyboard
switch (wParam) // 그 문자는 더블유파람에 들어간다 the character is in wParam
{
case 0x08: // 백스페이스backspace
case 0x09: // 탭tab
case 0x0A: // 라인피드linefeed
case 0x0D: // 캐리지 리턴 carriage return
case 0x1B: // 이스케이프escape
return 0; // 비 표시 문자 non displayable character
default: // 표시 문자 displayable character
ch = (TCHAR) wParam; // 문자 가져오기 get the character
InvalidateRect(hwnd, NULL, TRUE); // WM_PAINT 강제 force WM_PAINT
return 0;
}
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps); // 디바이스 컨텍스트의 핸들을 가져온다 get handle to device context
TextOut(hdc, 0, 0, &ch, 1); // 문자를 표시한다 display the character
// 가상키들 배열의 상태를 보여준다 Display the state of vkKeys array
// 만약 키가 눌러지고 그리고 F 가 키가 떼어지면 'T'를 보여준다. Display 'T' if key is down and 'F' is key is up
for (int r=0; r<16; r++)
{
for (int c=0; c<16; c++)
{
if (vkKeys[r*16+c])
{
SetBkMode(hdc, OPAQUE); // 불투명한 텍스트 배경 opaque text background
TextOut(hdc,c*chWidth+chWidth*2,r*chHeight+chHeight*2,"T ", 2);
} else {
SetBkMode(hdc, TRANSPARENT); // 투명한 텍스트 배경 transparent text background
TextOut(hdc,c*chWidth+chWidth*2,r*chHeight+chHeight*2,"F ", 2);
}
}
}
EndPaint(hwnd, &ps);
return 0;
default:
return DefWindowProc( hwnd, msg, wParam, lParam );
}
}
//=============================================================================
// 윈도우 생성 Create the window
// 에러 발생시 false를 반환Returns: false on error
//=============================================================================
bool CreateMainWindow(HINSTANCE hInstance, int nCmdShow)
{
WNDCLASSEX wcx;
HWND hwnd;
// 윈도우 클래스 구조체 안을 매개변수로 채운다 Fill in the window class structure with parameters
// 메인 윈도우를 묘사하는 that describe the main window.
wcx.cbSize = sizeof(wcx); // 구조체 크기 size of structure
wcx.style = CS_HREDRAW | CS_VREDRAW; // 크기가 변경되면 다시 그린다 redraw if size changes
wcx.lpfnWndProc = WinProc; // 윈도우 프로시저를 가리킨다 points to window procedure
wcx.cbClsExtra = 0; // 여분의 클래스 메모리 노필요 no extra class memory
wcx.cbWndExtra = 0; // 여분의 윈도우 메모리 노필요 no extra window memory
wcx.hInstance = hInstance; // 인스턴스의 핸들 handle to instance
wcx.hIcon = NULL;
wcx.hCursor = LoadCursor(NULL,IDC_ARROW); // 미리 정의된 화살표 predefined arrow
//배경 브러쉬
wcx.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); // 회색 배경 브러쉬 gray background brush
wcx.lpszMenuName = NULL; // 메뉴 리소스의 이름 name of menu resource
wcx.lpszClassName = CLASS_NAME; // 윈도우 클래스의 이름 name of window class
wcx.hIconSm = NULL; // 작은 클래스 아이콘 small class icon
// 윈도우 클래스를 등록한다 Register the window class.
// RegisterClassEx 함수는 에러가 발생할 경우 0을 반환한다 returns 0 on error.
if (RegisterClassEx(&wcx) == 0) // 만약 에러 나면 if error
return false;
//윈도우 생성
// Create window
hwnd = CreateWindow(
CLASS_NAME, // 윈도우 클래스의 이름 name of the window class
APP_TITLE, // 제목 표시줄의 텍스트 title bar text
WS_OVERLAPPEDWINDOW, // 윈도우 스타일 window style
CW_USEDEFAULT, // 윈도우의 기본 수평 위치 default horizontal position of window
CW_USEDEFAULT, // 윈도우의 기본 수직 위치 default vertical position of window
WINDOW_WIDTH, // 윈도우의 폭 width of window
WINDOW_HEIGHT, // 윈도우의 높이 height of the window
(HWND) NULL, // 부모 윈도우 없음 no parent window
(HMENU) NULL, // 메뉴 없음 no menu
hInstance, // 애플리케이션 인스턴스의 핸들 handle to application instance
(LPVOID) NULL); // 윈도우 매개변수 없음 no window parameters
// 만약 윈도우를 생성하는 동안 에러가 발생한다면 if there was an error creating the window
if (!hwnd)
return false;
//윈도우를 표시한다
// Show the window
ShowWindow(hwnd, nCmdShow);
//윈도우 프로시저에게 WM_PAINT 메시지를 보낸다.
// Send a WM_PAINT message to the window procedure
UpdateWindow(hwnd);
return true;
}
너는 왜 발전이 없냐