[windowsAPI] 4주차, KeyEvent 다루기

교내 전공과목인 윈도우즈 API수업을 정리합니다

 

 

1. Timer프로그램을 기능개선 시켜보자.

목표: 쓸데없이 전체화면을 새로고침하지말고, 문구가 나오는 부분만 수정해주자.

 

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	SYSTEMTIME st;
	static TCHAR sTime[128];

	switch (iMessage) {
	case WM_CREATE:
		SetTimer(hWnd, 1, 1000, NULL);
		SendMessage(hWnd, WM_TIMER, 1, 0);
		return 0;
	case WM_RBUTTONDOWN:
		hdc = GetDC(hWnd);
		Ellipse(hdc, 60, 60, 200, 300);
		ReleaseDC(hWnd, hdc);
		return 0;
	case WM_TIMER:
		GetLocalTime(&st);
		hdc = GetDC(hWnd);
		//wsprintf(sTime,TEXT("지금 시간은 %d:%d:%02d 입니다."),
		wsprintf(sTime, TEXT("지금 시간은 %d:%d:%d 입니다."),
			st.wHour, st.wMinute, st.wSecond);

		GetTextExtentPoint(hdc, sTime, lstrlen(sTime), &size); //sTime의 크기 -> size에 대입
		rt.bottom = 100 + size.cy;  //문자열 높이
		rt.right = 100 + size.cx;  // 문자열 너비
		//	InvalidateRect(hWnd,NULL,TRUE);
		InvalidateRect(hWnd, &rt, TRUE);
		ReleaseDC(hWnd, hdc);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		TextOut(hdc, 100, 100, sTime, lstrlen(sTime));
		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		KillTimer(hWnd, 1);
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}

 

  • GetTextExtentPoint: 지정된 텍스 문자열의 너비와 높이를 계산함
    sTime문자열의 길이를 size에 넣기

실행결과는 전과 같으나 좀 더 효율적임.

 

 

2. 무효화 영역을 한 번 더 알아보자

(1) 소스코드

BOOL bRect = TRUE;
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hdc;
	RECT rt;
	int i;
	switch (iMessage) {
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		for (i = 0; i < 1024; i += 2) {
			MoveToEx(hdc, 0, i, NULL);
			LineTo(hdc, 1280, i);
		}
		for (i = 0; i < 1280; i += 2) {
			MoveToEx(hdc, i, 0, NULL);
			LineTo(hdc, i, 1024);
		}
		if (bRect) {
			Rectangle(hdc, 10, 10, 200, 200);
		}
		else {
			Ellipse(hdc, 10, 10, 200, 200);
		}
		EndPaint(hWnd, &ps);
		return 0;
	case WM_LBUTTONDOWN:
		bRect = !bRect;
		//SetRect(&rt,10,10,200,200);
		SetRect(&rt, 10, 10, 100, 100);

		InvalidateRect(hWnd, &rt, TRUE);
		//InvalidateRect(hWnd,NULL,TRUE); // 심한 깜빡임 발생
		//SendMessage(hWnd, WM_PAINT, 0,0);	// 이렇게 하지 말자.
		//UpdateWindow(hWnd);
		//Sleep(1000);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
  • MoveToEx(HDC hdc, int X, int Y, LPPOINT lpPoint);
    x: x좌표, y: y좌표, lpPPoint: 이전 현재 좌표를 돌려받기 위한 POINT(필요없다면 NULL전달하기)
  • LineTo(HDC hdc, int nXEnd, int nYEnd);
    nXEnd: 끝점의 X좌표, nYEnd: 끝점의 Y좌표
  • EndPaint(HWND hWnd, CONST PAINTSTRUCT *lpPaint);
    lpPaint: 그리기 정보를 갖고 있는 PAINTSTRUCT구조체의 포인터, BeginPaint함수에서 사용한 구조체를 전달
  • UpdateWindow(HWND hWnd);
    윈도우 프로시저로 WM_PAINT를 보내여 작업영역을 강제로 그리도록 한다
    WM_PAINT자체는 우선 순위가 늦어서 무효 영역이 있어도 먼저 처리해야할 다른 메시지 때문에 즉시 처리되지 않을 수도 있다. 따라서 대기순서의 영향을 주고 싶지 않을 때 사용한다.
  • Sleep
    스레드 실행을 잠시 정지시킴

 

(2)실행화면

 

 

3. KeyDown 이벤트를 유니코드 중점으로 봐보자

#include<tchar.h>
 
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	static int x=100;
	static int y=100;
	static char *c = "A";
	  // 문자열 하나 정의//MultiBytes Character Set
//	static wchar_t *c = L"A"; //Unicode Character Set
//	static TCHAR *c = TEXT("A"); //Neutral Code 
//	static wchar_t c[] = (L"가abc"); //unicode
	//static char c[] = "가abc";  
//	static TCHAR c[] = TEXT("가abc");  //Neutral Code 
	static bool s = false;
	switch (iMessage) {
	case WM_KEYDOWN:
		switch (wParam) {
		case VK_SPACE:
			s ? c = "A" : c = "#"; //MBCS
			//s ? c = L"A" : c = L"#"; //Unicode
			//s ?	c = TEXT("A"): c = TEXT("#");
			//s ? strcpy(c, "가abc") : strcpy(c, "나abc") ;  //MultiBytes Character Set
 			//s ? wcscpy(c, L"가abc") : wcscpy(c, L"나abc"); //Unicode
			//s ? _tcscpy(c, TEXT("가abc")) : _tcscpy(c, TEXT("나abc"));
			s = !s;
			break;
		case VK_LEFT:
			x-=8;
			break;
		case VK_RIGHT:
			x+=8;
			break;
		case VK_UP:
			y-=8;
			break;
		case VK_DOWN:
			y+=8;
			break;
		}
		//InvalidateRect(hWnd,NULL,TRUE);
		InvalidateRect(hWnd,NULL,FALSE);  
		return 0;
	case WM_PAINT:
		hdc=BeginPaint(hWnd,&ps);
		TextOut(hdc,x,y,c,lstrlen(c));  //strlen() <--  c runtime library
		EndPaint(hWnd,&ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

주석참고