반응형

윈도우창 생성

ApiStart.txt
0.00MB

위 텍스트 파일을 c++소스에 넣으면 옆과 같은 윈도우 어플리케이션 창이 만들어진다.

이 번 학기의 목표는 한글같이 키보드를 마우스를 누르면 반응하는 프로그램을 만드는게 목표이다.

원도우 프로그램의 소스

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
HWND hWndMain;
LPCTSTR lpszClass = TEXT("Class");

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance
	, LPSTR lpszCmdParam, int nCmdShow) //이 부분은 차후 수업에서 알아 보겠다
{
	HWND hWnd;
	MSG Message;
	WNDCLASS WndClass;
	g_hInst = hInstance;

	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	WndClass.hInstance = hInstance;
	WndClass.lpfnWndProc = WndProc;
	WndClass.lpszClassName = lpszClass;
	WndClass.lpszMenuName = NULL;
	WndClass.style = CS_HREDRAW | CS_VREDRAW;
	RegisterClass(&WndClass);

	hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, (HMENU)NULL, hInstance, NULL);
	ShowWindow(hWnd, nCmdShow);

	while (GetMessage(&Message, NULL, 0, 0)) {
		TranslateMessage(&Message);
		DispatchMessage(&Message);
	}
	return (int)Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
//당분간은 이 함수를 설명한다.
{
	HDC hdc;
	PAINTSTRUCT ps;

	switch (iMessage) {
	case WM_CREATE:
		hWndMain = hWnd;
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}

WinMain 함수는 나중에 나중에 배워보도록 하고 당분간 수업에서는 WndProc함수에 대해 본다.

 

사각형을 그리는 WndProc함수

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
//당분간은 이 함수를 설명한다.
{
	HDC hdc;
	PAINTSTRUCT ps;

	switch (iMessage) {
	case WM_CREATE:
		hWndMain = hWnd;
		return 0;
    case WM_LBUTTONDOWN: //왼쪽버튼을 누르면
		hdc=GetDC(hwnd);
        Rectangle(hdc, 10, 10, 60, 60)// 사각형을 그려라
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}

마우스 오른쪽 버튼을 눌렀을 때 사각형을 그리도록 바꾼 WndProc함수이다.

Rectangle(hdc, 좌, 상 ,우, 하)이다

 

누르는 지점에 파란색 사각형을 그리는 WndProc함수

int px[1000], py[1000]; //도형의 좌표를 기억하는 변수
int iCount; //사각형의 갯수를 저장하는 변수

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

	switch (iMessage) {
	case WM_CREATE:
		hWndMain = hWnd;
		return 0;
	case WM_LBUTTONDOWN: //왼쪽버튼을 누르면
		hdc = GetDC(hWnd); //원도우 그리기 도구 상자 얻기
		px[iCount] = x = LOWORD(lParam);
		py[iCount] = y = HIWORD(lParam);
		iCount++;
		hBrush = CreateSolidBrush(RGB(0, 0, 255));//도형의 색을 선택
		SelectObject(hdc, hBrush); // 그리기 도구 hdc의 색을 지정
		Rectangle(hdc, x-10, y-10, x+60, y+60);// 사각형을 그려라
		return 0;
	case WM_PAINT: //최소화하고 다시 그려진다
		hdc = BeginPaint(hWnd, &ps);
		for (int i = 0; i < iCount; i++)//iCount(도형의 갯수 만큼 반복해서 그림) 
		{
			hBrush = CreateSolidBrush(RGB(0, 0, 255));
			SelectObject(hdc, hBrush);
			Rectangle(hdc, px[i] - 10, py[i] - 10, px[i] + 60, py[i] + 60);
		}
		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}

 

마우스 왼쪽버튼을 누르면 px배열에  클릭한 위치의 좌표가 저장된다. iCount를 통해 다음 배열에 저장

LOWORD=x의 좌표를 HIWORD=y좌표를 두 매크로를 통해 좌표값을 받아올 수 있다.

iCount가 증가하면서 다음 배열에 클릭 횟수를 추가한다. 

HBRUSH 면을 채울 때 사용하는 GDI오브젝트 차후 수업에서 자세하게 다룬다. 여기서는 파란색으로 설정되었다.

SelcetObject 함수를 통해 hdc그리기 도구의 면 색을 hBrush로 설정해준다.

 

윈도우창을 최소화하면 그려진 사각형들이 다 사라지는데 이걸 다시 그려주는 매크로가 WM_PAINT이다.

0부터 도형의 갯수만큼 반복해서 도형을 다시 그린다. 

※ 변수 명명법

접두어 원래말  의미
cb Count of Byte 바이트 수
dw double word 부호없는 long형 정수
h handle 윈도우, 비트맵, 파일 등의 핸들
sz Null Terminated NULL 종료 문자열
ch Character 문자형
a Array 배열
w Word 부호없는 정수형
i lnteger 정수형
p, lp long pointer 포인터형
b Bool 논리형

윈도우즈 프로그래밍에서 변수에 주로 이름을 붙이는 방법이다. 꼭 이 방식으로 변수를 만들필요는 없지만 표준 함수들은 모두 이 방식대로 인수 이름을 작성하므로 접두어들을 외우고 있으면 함수의 인수가 어떤의미를 가지는 파악하기 쉽다.

 

과제

오른쪽 클릭시 파란원 / 왼쪽 클릭시 빨간원을 만드는 프로그램

최소화 했을하고 다시 띄웠을때도 파란원과 빨간원이 그대로 있어야 한다.

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
HWND hWndMain;
LPCTSTR lpszClass = TEXT("Class");

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance
	, LPSTR lpszCmdParam, int nCmdShow)
{
	HWND hWnd;
	MSG Message;
	WNDCLASS WndClass;
	g_hInst = hInstance;

	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	WndClass.hInstance = hInstance;
	WndClass.lpfnWndProc = WndProc;
	WndClass.lpszClassName = lpszClass;
	WndClass.lpszMenuName = NULL;
	WndClass.style = CS_HREDRAW | CS_VREDRAW;
	RegisterClass(&WndClass);

	hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, (HMENU)NULL, hInstance, NULL);
	ShowWindow(hWnd, nCmdShow);

	while (GetMessage(&Message, NULL, 0, 0)) {
		TranslateMessage(&Message);
		DispatchMessage(&Message);
	}
	return (int)Message.wParam;
}



int px[1000], py[1000];//빨간원 좌표
int px2[1000], py2[1000];//파란원 좌표
int iCount_Red = 0;//빨간원 갯수
int iCount_Blue = 0;//파란원 갯수

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


	switch (iMessage) {
	case WM_CREATE:
		hWndMain = hWnd;
		return 0;
	case WM_LBUTTONDOWN: //왼쪽버튼을 누르면
		hdc = GetDC(hWnd);
		px[iCount_Red] = x = LOWORD(lParam);
		py[iCount_Red] = y = HIWORD(lParam);
		iCount_Red++;
		hBrush = CreateSolidBrush(RGB(255, 0, 0));
		SelectObject(hdc, hBrush);
		Ellipse(hdc, x - 10, y - 10, x + 10, y + 10);
		return 0;
	case WM_RBUTTONDOWN: //오른쪽버튼을 누르면
		hdc = GetDC(hWnd);
		px2[iCount_Blue] = x = LOWORD(lParam);
		py2[iCount_Blue] = y = HIWORD(lParam);
		iCount_Blue++;
		hBrush = CreateSolidBrush(RGB(0, 0, 255));
		SelectObject(hdc, hBrush);
		Ellipse(hdc, x - 10, y - 10, x + 10, y + 10);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		for (int i = 0; i < iCount_Blue; i++)
		{
			hBrush = CreateSolidBrush(RGB(0, 0, 255));
			SelectObject(hdc, hBrush);
			Ellipse(hdc, px2[i] - 10, py2[i] - 10, px2[i] + 10, py2[i] + 10);
		}
		for (int i = 0; i < iCount_Red; i++)
		{
			hBrush = CreateSolidBrush(RGB(255, 0, 0));
			SelectObject(hdc, hBrush);
			Ellipse(hdc, px[i] - 10, py[i] - 10, px[i] + 10, py[i] + 10);
		}

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

		return 0;
	}
	return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}

오른쪽클릭시 생성되는 원과 왼쪽클릭시 생성되는 원에 저장되는 좌표와 갯수를 세는 변수를 다르게 해서 구현했다.

원이 2가지 밖에 없어 이런방법으로 접근해도 되지만 여러가지의 원이 있을 때도 초기화되지 않는 방법을 생각해봐야겠다.

 

반응형

+ Recent posts