학원/경일게임아카데미

17. 열두번째 수업

셩잇님 2022. 12. 21. 23:13
반응형

경일게임아카데미 프로그래밍반 28기 12일차 수업 (2021. 04. 23)

 

 


 

 

WIN32 API 펜, 색칠, 픽셀

#include <Windows.h>

HINSTANCE _hInstance;
HWND _hWnd;
LPCTSTR _lpszClass = TEXT("경일 28기 :-) ");
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int cmdShow)
{
	_hInstance = hInstance;

	MSG message;
	WNDCLASS wndClass;

	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 = hInstance;
	wndClass.lpfnWndProc = (WNDPROC)WndProc;
	wndClass.lpszClassName = _lpszClass;
	wndClass.lpszMenuName = NULL;
	wndClass.style = CS_HREDRAW | CS_VREDRAW;

	RegisterClass(&wndClass);

	_hWnd = CreateWindow(
		_lpszClass,
		_lpszClass,
		WS_OVERLAPPEDWINDOW,
		50,
		50,	
		800,
		600,
		NULL,
		(HMENU)NULL,
		hInstance,
		NULL);

	ShowWindow(_hWnd, cmdShow);

	while (GetMessage(&message, 0, 0, 0))
	{
		TranslateMessage(&message);
		DispatchMessage(&message);
	}
	return message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT 	ps;
	HDC		hdc;

	switch (iMessage)
	{
	case WM_PAINT:
	{
		hdc = BeginPaint(hWnd, &ps);
		
		// 펜(PEN)
		// 인자값(펜 스타일 / 굵기 / 색상)
		HPEN pen = CreatePen(PS_DOT, 5, RGB(0, 0, 255));
		HPEN oldPen = (HPEN)SelectObject(hdc, pen);
		
		MoveToEx(hdc, 100, 100, NULL);
		LineTo(hdc, 200, 200);
		
		SelectObject(hdc, oldPen);
		DeleteObject(pen);

		// 도형 색칠
		HBRUSH brush = CreateSolidBrush(RGB(50, 50, 100));
		HBRUSH oldBrush = (HBRUSH)SelectObject(hdc, brush);
		
		Ellipse(hdc, 200, 200, 400, 400);
		Rectangle(hdc, 10, 10, 100, 100);
		
		SelectObject(hdc, oldBrush);
		DeleteObject(brush);
		
		// 픽셀 1개를 찍는다는 전설의 SetPixel();
		SetPixel(hdc, 50, 50, RGB(255, 0, 0));
		for (int i = 0; i < 10; i++)
		{
			SetPixel(hdc, 50 + i, 50, RGB(255, 0, 0));
		}
		EndPaint(hWnd, &ps);
	}
	break;

	// 윈도우 창 부수는 화면
	case WM_DESTROY:
	{
		// 윈도우 종료 함수
		PostQuitMessage(0);
	}
	return 0;
	}
    
	return (DefWindowProc(hWnd, iMessage, wParam, lParam));
}

펜은 HPEN을 이용하여 사용할 수 있다.
각각의 인자 값은 펜 스타일과, 굵기, 색상을 나타내며
펜 스타일 부분에 F12키를 눌러 참조하면 다양한 펜 스타일 들이 있으며 이 때 펜의 굵기는 정수값을 이용하여 조절한다
색상은 RGB를 이용하여 원하는 값을 입력하여 본인만의 색상을 나타낼 수 있다.

도형 색칠은
HBRUSH를 이용하여 사용할 수 있다.
HBRUSH를 사용한 이후부터 만드는 도형들은 정해진 색상으로 생성된다.
인자 값은 색상을 나타내는 RGB 값 밖에 없다.

픽셀은 SetPixel을 이용하여 사용 할 수 있다.
인자 값으로는 hdc, 위치좌표 x, 위치좌표 y, 색상이다.
픽셀은 하나의 점을 얘기하는데 해당 기능을 이용하여 그림을 그리거나 하는 행동들은 힘들기 때문에 주로 반복문을 이용하여 사용한다.

 

 


 

 

WIN32 API 매크로와 함수를 이용하여 선, 사각형, 원 만들기

#include "stdafx.h"

HINSTANCE _hInstance;
HWND _hWnd;
LPCTSTR _lpszClass = TEXT("경일 28기 :-) ");

void setWindowsSize(int x, int y, int width, int height);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int cmdShow)
{
	_hInstance = hInstance;

	MSG message;
	WNDCLASS wndClass;

	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 = hInstance;
	wndClass.lpfnWndProc = (WNDPROC)WndProc;
	wndClass.lpszClassName = WINNAME;
	wndClass.lpszMenuName = NULL;
	wndClass.style = CS_HREDRAW | CS_VREDRAW;

	RegisterClass(&wndClass);

	_hWnd = CreateWindow(
		WINNAME,
		WINNAME,
		WS_OVERLAPPEDWINDOW,
		WINSTARTX,
		WINSTARTY,
		WINSIZEX,
		WINSIZEY,
		NULL,
		(HMENU)NULL,
		hInstance,
		NULL);

	setWindowsSize(WINSTARTX, WINSTARTY, WINSIZEX, WINSIZEY);
	ShowWindow(_hWnd, cmdShow);

	while (GetMessage(&message, 0, 0, 0))
	{
		TranslateMessage(&message);
		DispatchMessage(&message);
	}
	return message.wParam;
}


LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT 	ps;
	HDC		hdc;

	switch (iMessage)
	{
	case WM_PAINT:
	{
		hdc = BeginPaint(hWnd, &ps);

		// 선
		//LineMake(hdc, 50, 50, 200, 200);
		//LineMake(hdc, 250, 250, 400, 200);

		// 사각형
		//RectangleMake(hdc, WINSIZEX / 2, WINSIZEY / 2, 100, 100);
		//RectangleMakeCenter(hdc, WINSIZEX / 2, WINSIZEY / 2, 100, 100);

		// 원
		//EllipseMake(hdc, WINSIZEX / 2, WINSIZEY / 2, 500, 500);
		EllipseMakeCenter(hdc, WINSIZEX / 2, WINSIZEY / 2, 500, 500);
		EllipseMakeCenter(hdc, WINSIZEX / 2, WINSIZEY / 2, 450, 450);

		EndPaint(hWnd, &ps);
	}
	break;
	//윈도우 창 부수는 함수 
	case WM_DESTROY:
		//윈도우 종료함수
		PostQuitMessage(0);
		return 0;
	}
	return (DefWindowProc(hWnd, iMessage, wParam, lParam));
}


void setWindowsSize(int x, int y, int width, int height)
{
	RECT winRect;
	winRect.left = 0;
	winRect.top = 0;
	winRect.right = width;
	winRect.bottom = height;

	//얘가 실제 클라이언트 영역 조정 들어가는 함수
	AdjustWindowRect(&winRect, WINSTYLE, false);

	//조정된 영역으로 다시 한 번 윈도우 위치 잡아주는 함수
	SetWindowPos(_hWnd, NULL, x, y, (winRect.right - winRect.left), (winRect.bottom - winRect.top), SWP_NOZORDER | SWP_NOMOVE);
}

이 전에는 사용자 PC의 모니터의 크기가 다 다르므로 함수들 사이에 설정되어있던 윈도우 사이즈를 매번 귀찮게 변경해줘야 했다. 그렇지만 매크로(#define)을 이용하여 윈도우 창 시작좌표(Left, TOP), 윈도우 가로, 세로 크기를 설정하여 매크로 내 설정된 값만 변경해주면 된다.

아래는 코드는 매크로 기능을 이용한 윈도우 시작좌표와 크기 설정이다.

#define WINNAME (LPTSTR)(TEXT("28기 API"))
#define WINSTARTX 50	// 윈도우 창 시작좌표 (LEFT)
#define WINSTARTY 50	// 윈도우 창 시작좌표 (TOP)
#define WINSIZEX 1024	// 윈도우 가로크기
#define WINSIZEY 768	// 윈도우 세로크기
#define WINSTYLE WS_CAPTION | WS_SYSMENU

이를 이용하면 윈도우를 생성할때에도 아래와 같이 사용하면 매우 편리해진다.

_hWnd = CreateWindow(
	WINNAME,
	WINNAME,
	WS_OVERLAPPEDWINDOW,
	WINSTARTX,
	WINSTARTY,
	WINSIZEX,
	WINSIZEY,
	NULL,
	(HMENU)NULL,
	hInstance,
	NULL);

 

 

 


 

 

아울러 헤더와 함수를 이용하여 main 함수 내에서는 함수를 호출하여 선, 원, 사각형을 만드는 작업을 해보자.

commonMacroFunction.h

#pragma once

//============================================
// ## 21.04.23 ## commonMacroFunction ##
//============================================

// 선긋기 함수
inline void LineMake(HDC hdc, int x1, int y1, int x2, int y2)
{
	MoveToEx(hdc, x1, y1, NULL);
	LineTo(hdc, x2, y2);
}

// 사각형
// x, y축을 기준으로 하는 사각형이 생성된다
inline void RectangleMake(HDC hdc, int x, int y, int width, int height)
{
	Rectangle(hdc, x, y, x + width, y + height);
}

// x, y축을 중점으로 크기만큼의 사각형이 생성됨
inline void RectangleMakeCenter(HDC hdc, int x, int y, int width, int height)
{
	Rectangle(hdc, x - (width / 2), y - (height / 2), x + (width / 2), y + (height / 2));
}

// 원
// x, y축을 기준으로 하는 원이 생성됨
inline void EllipseMake(HDC hdc, int x, int y, int width, int height)
{
	Ellipse(hdc, x, y, x + width, y + height);
}

// x, y 좌표를 중점으로 크기만큼의 원이 생성됨
inline void EllipseMakeCenter(HDC hdc, int x, int y, int width, int height)
{
	Ellipse(hdc, x - (width / 2), y - (height / 2), x + (width / 2), y + (height / 2));
}

매크로 함수.h를 이용하여 함수를 선언한 후 메인함수가 있는 cpp에서는 해당 헤더파일을 걸어주고 꺼내 쓴다.

// 선
//LineMake(hdc, 50, 50, 200, 200);
//LineMake(hdc, 250, 250, 400, 200);

// 사각형
//RectangleMake(hdc, WINSIZEX / 2, WINSIZEY / 2, 100, 100);
//RectangleMakeCenter(hdc, WINSIZEX / 2, WINSIZEY / 2, 100, 100);

// 원
//EllipseMake(hdc, WINSIZEX / 2, WINSIZEY / 2, 500, 500);
EllipseMakeCenter(hdc, WINSIZEX / 2, WINSIZEY / 2, 500, 500);
EllipseMakeCenter(hdc, WINSIZEX / 2, WINSIZEY / 2, 450, 450);

위 함수들은 매크로 함수.h파일에 있는 내용들을 메인 함수에서 호출하는 일이다.
이렇게 사용하면 메인함수를 매우 간결하게 사용할 수 있으며 가독성도 좋아진다.

 

 

 

반응형