[windowsAPI] 2주차, DC와 무효영역

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

 

 

 

1. 지난 실습코드에서 사각형의 브러쉬 색상을 지정해주자

(1) 코드소스

/* CALLBACK WndProc 함수 */
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{

	HDC hdc;
	PAINTSTRUCT ps;
    HBRUSH hBrush; // 내부 색상 설정
	HPEN hPen; // 테두리 설정
	int x, y;
	switch (iMessage) {
	case WM_CREATE:
		hWndMain = hWnd;
		return 0;

	case WM_LBUTTONDOWN:
		// 특정윈도우의 그리기 관련 정보
		hdc = GetDC(hWnd);	//모든 그리기 함수에세 cd를 전달

		//x = LOWORD(lParam); // Macro
		//x = (WORD)(lParam);  //casting
		x = (short)(lParam);  //casting
		//y = HIWORD(lParam);
		y = ((lParam) >> 16); //bitwise oprator

		p[iCount].x = x;
		p[iCount].y = y;
		iCount++;
        
        /* 색 지정과 적용 */
		hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
		SelectObject(hdc, hPen);
		hBrush = CreateSolidBrush(RGB(0, 0, 255));
		SelectObject(hdc, hBrush);
        
		Rectangle(hdc, x - 20, y - 20, x + 20, y + 20);
		return 0;

	case WM_PAINT: //BeginPaint()로 DB열기
		hdc = BeginPaint(hWnd, &ps);

		/* 다시 그릴 때도 색 지정과 적용 */
		hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
		SelectObject(hdc, hPen);
		hBrush = CreateSolidBrush(RGB(0, 0, 255));
		SelectObject(hdc, hBrush);

		for (int i = 0; i < iCount; i++)
		{
			Rectangle(hdc, p[i].x - 20, p[i].y - 20, p[i].x + 20, p[i].y + 20);
		}

		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}

 

(2) 실행결과

 

 

2. KEY_DOWN, 키다운 이벤트를 사용하자

새로운 프로젝트(Key_Down)을 만들고 시작한다

(1) 사전에 속성을 건드려주자. (vs2017부터 코드안정성을 위해 오류가 일어난다)

프로젝트 > 속성 > C/C++ > 언어 > 준수모드 > 아니요 > 적용 및 확인

 

(2) 소스코드

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	static int x = 100;
	static int y = 100;

	switch (iMessage) {
	case WM_KEYDOWN : // 0x0100:
		switch (wParam) {
		case VK_LEFT: // 37: // 0x25: 
			x -= 8;
			break;
		case VK_RIGHT:
			x += 8;
			break;
		case VK_UP:
			y -= 8;
			break;
		case VK_DOWN:
			y += 8;
			break;

		case VK_SPACE:
			if (toggle == TRUE) {
				toggle = FALSE;
			}
			else	toggle = TRUE;
			break;
		}
		//InvalidateRect(hWnd,NULL,TRUE);
		InvalidateRect(hWnd, NULL, FALSE); // hWnd handle을 가진 윈도우로 WM_PAINT message를 발생시키기
		return 0;
	case WM_PAINT:
		if (toggle == TRUE) {
			str = TEXT("#");
		}
		else str = TEXT("A");
		hdc = BeginPaint(hWnd, &ps);
		TextOut(hdc, x, y, str, 1); // 출력하는 문자(A)의 개수 = 1 표시
		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
  • toggle변수는 스페이스바로 작동하며, 눌릴 때마다 A와 #을 번갈아서 출력함
  • InvalidateRect( HAWD hwnd, const RECT *lpRect, BOOL bErase ). 무효영역 다루기
    hwnd: 클라이언트 영역을 갱신할 윈도우 핸들 값
    *lpRect: 클라이언트 영역에서 갱신하고 싶은 영역의 좌표(RECT구조체 형식)
    bErase: 해당 영역의 배경까지 갱신할 것인지의 여부 (FALSE = 현재 상태 유지)
  • lnInvalidateRect(hWnd, NULL, TRUE) =>  A가 한 개씩만 출력
    lnInvalidateRect(hWnd, NULL, FALSE) => A가 자취를 남기며 출력

 

(3) 실행결과

키보드에 따라 문자가 이동되면서 자취를 남김.

 

 

3. 무효영역을 이용하여 사각형그리기 파일을 다시 수정하자

(1) 소스코드

/* CALLBACK WndProc의 switch문 수정 */

switch (iMessage) {
	case WM_CREATE:
		hWndMain = hWnd;
		return 0;

	case WM_LBUTTONDOWN:
		// 특정윈도우의 그리기 관련 정보
		hdc = GetDC(hWnd);	//모든 그리기 함수에세 cd를 전달

		//x = LOWORD(lParam); // Macro
		//x = (WORD)(lParam);  //casting
		x = (short)(lParam);  //casting
		//y = HIWORD(lParam);
		y = ((lParam) >> 16); //bitwise oprator

		p[iCount].x = x;
		p[iCount].y = y;
		iCount++;

		InvalidateRect(hWnd, NULL, FALSE);  //무효영역 지정
		/*
		hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
		SelectObject(hdc, hPen);
		hBrush = CreateSolidBrush(RGB(0, 0, 255));
		SelectObject(hdc, hBrush);
		Rectangle(hdc, x - 20, y - 20, x + 20, y + 20);
		return 0; */

	case WM_PAINT: //BeginPaint()로 DB열기
		hdc = BeginPaint(hWnd, &ps);

		hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
		SelectObject(hdc, hPen);
		hBrush = CreateSolidBrush(RGB(0, 0, 255));
		SelectObject(hdc, hBrush);

		for (int i = 0; i < iCount; i++)
		{
			Rectangle(hdc, p[i].x - 20, p[i].y - 20, p[i].x + 20, p[i].y + 20);
		}

		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}

invalidate를 사용해줬다

실행결과는 정상적.

 

 

4. DC를 알아보자

(1) 용어

DC(Device Context): 출력에 필요한 모든 정보를 가지는 데이터 구조체다

 

(2) 쓰임

HDC hdc;

/* 방법2 */
hdc = GetDc(hWnd);
RelealseDC()ReleaseDC(hWnd,hdc);

/* 방법1 */
hdc = BeginPaint(hWnd, $ps);
EndPaint(hWnd, $ps);