#include <Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); HINSTANCE g_hlnst; LPCTSTR lpszClass = TEXT("WINAPI"); // 창이름
int APIENTRY WinMain(HINSTANCE hlnstance, HINSTANCE hPrevlnstance, LPSTR lpszCmdParam, int nCmdShow) { HWND hWnd; // window handler MSG Message; WNDCLASS WndClass; // 윈도우에 관련된 정보를 저장하는 구조체 g_hlnst= hlnstance;
// 1. 창의 스타일 값 셋팅 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 = hlnstance; WndClass.lpfnWndProc = WndProc; //메시지 처리 함수를 지정 WndClass.lpszClassName = lpszClass; WndClass.lpszMenuName = NULL; WndClass.style = CS_HREDRAW | CS_VREDRAW |CS_DBLCLKS; // CS_DBLCLKS는 마우스 더블클릭메시지를 받을때 추가 해주어야 함 //CS_HREDRAW | CS_VREDRAW :윈도우의 수직(또는 수평)크기가 변할 경우 창을 다시 그린다는 뜻 RegisterClass(&WndClass);// 2. WndClass구조체변수 값을 등록
hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, NULL,(HMENU)NULL, hlnstance, NULL); // 3.창 생성
ShowWindow(hWnd, nCmdShow); //4.창 출력 //Message Loop //5.창에 들어오는 메시지를 처리 while(GetMessage(&Message, NULL,0,0))// GetMessage : 메시지 큐에서 메시지를 읽어들임 { TranslateMessage(&Message); DispatchMessage(&Message); //DispatchMessage : 메시지 큐에서 꺼낸 메시지를 윈도우의 메시지 처리함수 } return (int)Message.wParam; }
#define NUMBER 8
//iMessage : 어떤 종류의 메시지가 발생했는지.. //wParam, lParam : 메시지 종류에 따라 부수적인 정보값이 들어옴 LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; static int x = 100; static int y = 100; static BOOL bNowDraw = FALSE; SYSTEMTIME st; // 현재 시간을 구할때 필요한 구조체 변수 static TCHAR sTime[128]; switch(iMessage) { case WM_DESTROY: // 창 닫을때 종료처리 KillTimer(hwnd,1); //타이머 파괴
PostQuitMessage(0); return 0; WM_KEYDOWN 메시지는 키보드를 누를 때 마다 모든 키에 대해서 발생 ( 단, Alt 키와 윈도우 키 , 한영 전환키 등의 특수 키 몇가지는 제외) wParam으로 가상키코드(Virtual Key Code)가 전달됨 ※ 가상 키코드 : 시스템에 장착된 키보드의 종류에 상관없이 키를 입력받기 위해 만들어진 범용적인 코드값 ※ 영문자의 경우는 대문자 코드와 일치되어 있으므로 반드시 대문자와 비교해야한다. WM_KEYDOWN 테스트 wParam의 값과 가상키코드값을 비교해 봄으로써 어떤 키가 눌러졌는지를 알아낼수 있음 TranslateMessage | 키보드에서 A키를 눌렀다가 뗐다고 해보자. 메시지는 순서대로 WM_KEYDOWN, WM_CHAR, WM_KEYUP 세가지이다. 이중 WM_CHAR 메시지는 WM_KEYDOWN에 의해 추가로 메시지이며 메시지 루프에서 인위적으로 생성된다. TranslateMessage 함수는 전달된 메시지가 WM_KEYDOWN인지와 눌러진 키가 문자키인지 검사해 보고 조건이 맞을 경우 WM_CHAR 메시지를 추가로 발생시킨다. 물론 문자 입력이 아닐 경우는 아무일도 하지 않는다. |
case WM_KEYDOWN: switch(wParam) { case VK_LEFT: x = x-NUMBER; break;
case VK_RIGHT: x = x+NUMBER; break;
case VK_UP: y = y-NUMBER; break;
case VK_DOWN: y = y+NUMBER; break; } InvalidateRect(hWnd, NULL, TRUE); // InvalidateRect()는 강제로 WM_PAINT 메세지를 발생 시킴 해방 방향키를 누르면 x, y 값이 바뀌고 WM_PAINT로 새로 출력하면 마치 문자가 움직이는 것과 같은 효과를 낼수 있음 return 0; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); //TextOut(hdc, x, y, TEXT("A"), 1); //WM_KEYDOWN 메시지 테스트용 TextOut(hdc, 100, 100, sTime, lstrlen(sTime)); // WM_TIMER 메시지 테스트용 EndPaint(hWnd, &ps); return 0;
case WM_LBUTTONDOWN: // 마우스 왼쪽 버튼이 눌러졌을때 메세지가 발생하면 x = LOWORD(lParam); // 현재 마우스 좌표를 x, y에 임시 저장 y = HIWORD(lParam); bNowDraw = TRUE; // 마우스 버튼이 계속 눌러져 있음을 구분하기 위해 셋팅 return 0;
case WM_MOUSEMOVE: // 마우스 커서가 이동하면 발생하는 메세지 if(bNowDraw == TRUE) // 마우스 왼쪽 버튼이 눌러져 있는 동안의 좌표를 따라 선을 그림 { hdc = GetDC(hWnd); MoveToEx(hdc, x, y, NULL); x = LOWORD(lParam)-20; y = HIWORD(lParam)-20;
※ 마우스 입력에 관한 메시지 ※ WM_MOUSEWHEEL : 마우스 휠에 의한 메시지 // 마우스 메시지는 lParam의 상위워드에 마우스 버튼이 눌러진 y좌표, 하위 워드에 x좌표를 가짐
//wParam에는 마우스 버튼의 상태와 키보드 조합키(shift, Ctrl)의 상태가 전달됨
상하위 비트를 나눠주는 매크로 | #define LOWORD(I) ((WORD)(I)) #define HIWORD(I) ((WORD)(((DWORD)(w) >> 16) & 0xFFFF)) #define LOBYTE(w) ((BYTE)(w)) #define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF)) | 반대로 두개의 비트값을 가지고 조립해야할 경우 #define MAKEWORD(a,b) ((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8)) #define MAKELONG(a,b) ((LONG)(((WORD)(a)) | ((DWORD)((WORD)(b))) << 16)) |
LineTo(hdc, x, y);
ReleaseDC(hWnd, hdc); } return 0;
case WM_LBUTTONUP: // 마우스 왼쪽 버튼을 눌렀다가 뗄때 bNowDraw = FALSE; return 0;
case WM_LBUTTONDBLCLK: // 마우스 왼쪽 버튼을 더블클릭할때 InvalidateRect(hWnd, NULL, TRUE); return 0;
case WM_CREATE: // WM_CREATE 메시지는 해당 윈도우가 생성될때 제일 처음 딱 한번만 호출됨 SetTimer(hWnd,1,1000, NULL); // 1은 타이머의 번호이고, 1000은 메시지가 발생할 간격 시간을 1000ms로 함 return 0;
case WM_TIMER: //setTimer()에서 지정해놓은 셋팅값에 의해 호출되는 메시지 GetLocalTime(&st); wsprintf(sTime, TEXT("지금 시간은 %d:%d:%d입니다"), st.wHour, st.wMinute, st.wSecond); InvalidateRect(hWnd, NULL, TRUE); return 0;
} return (DefWindowProc(hWnd, iMessage,wParam,lParam)); //DefWindowProc : WndProc에서 처리하지 않은 나머지 메시지에 관한 처리를 함 }
|