반응형

빨간팬, 백스페이스로 선 하나 지우기


typedef struct _line {
	POINT p[500];
	int iCount;
	COLORREF pColor;
} line;

line lines[1000];

//int iTempCount;
int iLines;

COLORREF iCurrentPenColor = RGB(255, 0, 0);

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	static int x;
	static int y;
	//static BOOL bNowDraw=FALSE;
	HPEN hPen;

	switch (iMessage) {
	case WM_COMMAND:
		switch (LOWORD(wParam)){
			case IDM_RED:
				iCurrentPenColor = RGB(255, 0, 0); 
			
				break;
			case IDM_GREEN:
				iCurrentPenColor = RGB(0, 255, 0);
			
				break;
			case IDM_BLUE:
				iCurrentPenColor = RGB(0, 0, 255);
			
				break;
		}
	case WM_LBUTTONDOWN:
		x=LOWORD(lParam);
		y=HIWORD(lParam);
		lines[iLines].pColor = iCurrentPenColor;
		lines[iLines].p[lines[iLines].iCount].x = x;
		lines[iLines].p[lines[iLines].iCount].y = y;
		return 0;
	case WM_MOUSEMOVE:
		if (wParam & MK_LBUTTON) {
			hdc=GetDC(hWnd);
			hPen = CreatePen(PS_SOLID, 3, iCurrentPenColor);
			hPen=(HPEN)SelectObject(hdc, hPen);
			MoveToEx(hdc,x,y,NULL);
			x=LOWORD(lParam);
			y=HIWORD(lParam);
			lines[iLines].iCount++;
			lines[iLines].p[lines[iLines].iCount].x = x;
			lines[iLines].p[lines[iLines].iCount].y = y;
			LineTo(hdc,x,y);
			DeleteObject(SelectObject(hdc, hPen));
			ReleaseDC(hWnd,hdc);
		}
		return 0;
	case WM_LBUTTONUP:
		iLines++;
		return 0;
		// 내가 생성한 GDI Object는 사용후반드시 삭제한다, 단 선택해제후
	case WM_KEYDOWN:
		switch (wParam) {
		case VK_BACK:
			if (iLines > 0)
			{
				iLines--;
			}
			InvalidateRect(hWnd, NULL, TRUE);
			lines[iLines].iCount = 0;
			break;
		}

	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		for (int i = 0; i < iLines; i++)
		{
			hPen = CreatePen(PS_SOLID, 3, lines[i].pColor);
			hPen = (HPEN)SelectObject(hdc, hPen);  //선택한다.
			MoveToEx(hdc, lines[i].p[0].x, 
					lines[i].p[0].y, NULL);
			for (int j = 1; j <= lines[i].iCount; j++)
			{
				
				LineTo(hdc, lines[i].p[j].x, lines[i].p[j].y);
			}
			 //선택해제...
			DeleteObject(SelectObject(hdc, hPen));  //그리고 삭제한다...
		}
		return 0;

	case WM_LBUTTONDBLCLK:
		InvalidateRect(hWnd, NULL, TRUE);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

펜 스타일(색, 크기) 지정

API Default 펜 스타일

윈도우의 Default 펜의 값은 색=검정, 크기=1 pixel이다.

색과 크기를 바꾸기 위해서는 그리기 도구 통(DC)에 다른 펜을 만들어서 줘야 한다.

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	HPEN hPen, oldPen; //HPEN hPen, oldPen선언
	static int x;
	static int y;
}

윈도우 프로시져를 호출하면

1. hPen과 oldPen을  선언해준다.

case WM_MOUSEMOVE:
		if (wParam & MK_LBUTTON) {
			hdc=GetDC(hWnd);
			hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));//1
			oldPen = (HPEN)SelectObject(hdc, hPen); //2
			MoveToEx(hdc,x,y,NULL);
			x=LOWORD(lParam);
			y=HIWORD(lParam);
			lines[iLines].p[lines[iLines].iCount].x = x;
			lines[iLines].p[lines[iLines].iCount].y = y;
			lines[iLines].iCount++;
			//iTempCount++;
			LineTo(hdc,x,y);
			SelectObject(hdc, oldPen); //3.선택해제
			DeleteObject(hPen);// 4. 삭제
			ReleaseDC(hWnd,hdc);
		}
		return 0;

왼쪽마우스를 누른 상태로 마우스를 움직이면

1. hPen은 실선 / 3pixel / 빨간색의 펜으로 설정한다.

2. hdc그리기 도구통에 hPen을 넣고 oldPen에는 디폴트 값을 리턴한다.

3. hdc그리기 도구통에 oldPen에 있는 디폴트 값을 넣는다.

4. hPen을 삭제한다.

이렇게 펜을 반납하지 않으면 오버플로가 나서 결국 WM_PAINT하다 선이 사라지거나 그리는 도중에 사라지기 때문에 꼭 사용한 펜은 반납하자

 

백스페이스바로 선하나 지우기

	case WM_KEYDOWN:
		switch (wParam) {
		case VK_BACK:
			if (iLines > 0)
			{
				iLines--;
			}	
			InvalidateRect(hWnd, NULL, TRUE);
			lines[iLines].iCount = 0;
			break;
		}
		return 0;

백스페이스 입력시 (iLines=3이다)

1. iLine이 0보다 크다면 선의 갯수를 하나 줄이고 // iLines=2이다

2. WM_PAINT가 아까전보다 1선 작은 그림을 그린다. //선을 2개 그린다

3. 점 갯수를 0으로 초기화시킨다 

 -왼쪽버튼을 눌렸을때 3번째 선에 iCount 0부터 왼쪽버튼을 땔때까지 좌표를 저장한다 이미 저장되 있던 좌표는 뒤로 밀려난다. (지우기전 점개수가 20이고 새로찍은 점갯수가 10이면 새로찍은 좌표는 p[0~9]까지 저장되고 전에 점은 p[10~30]까지 저장된다.)

- 새로 찍은 점의 갯수는 10이라 10까지의 선만을 불러온다.

  

메뉴 창에서 색 바꾸기

리소스 추가

새항목 추가 - 리소스 - 리소스 파일을 추가한다.

리소스 추가

 

메뉴
속성창에서 ID를 꼭 입력해줘야 한다.

메뉴 리소스 받기

	switch (iMessage) {
	case WM_COMMAND:
		switch (LOWORD(wParam)){
			case IDM_RED:
				iCurrentPenColor = RGB(255, 0, 0); 
				break;
			case IDM_GREEN:
				iCurrentPenColor = RGB(0, 255, 0);
				break;
			case IDM_BLUE:
				iCurrentPenColor = RGB(0, 0, 255);
				break;
		}

WM_COMMAND는 리소스를 받는 이벤트이다

여기서 방금 입력한 아이디 값을 받아오면 거기에 맞는 iCurrentPenColor의 색상 값을 변경한다.

여기서 또 문제가 생기는데 WM_PAINT에서 빨간색으로만 그리도록 해놨기 때문에 선의 색을 저장하는 배열을 만들어서 선의 색을 저장해줘야한다.

 

다른 색상의 선 저장

typedef struct _line {
	POINT p[500];
	int iCount;
	COLORREF pColor; // 1
} line;

line lines[1000];
int iLines;
COLORREF iCurrentPenColor = RGB(255, 0, 0); //2

선의 색을 저장하는 자료구조

1. 선마다의 색을 저장해줄 구조체 변수이다

2. 색을 변수로 지정해 메뉴에서 다른 색상 값을 선택하면 색상 값이 바뀐게 해준다.

	case WM_LBUTTONDOWN:
		x=LOWORD(lParam);
		y=HIWORD(lParam);
		lines[iLines].pColor = iCurrentPenColor; //1
		lines[iLines].p[lines[iLines].iCount].x = x;
		lines[iLines].p[lines[iLines].iCount].y = y;
		return 0;

왼쪽 버튼클릭시

1. 현재 선의 색상을 저장해준다.

case WM_MOUSEMOVE:
		if (wParam & MK_LBUTTON) {
			hdc=GetDC(hWnd);
			hPen = CreatePen(PS_SOLID, 3, iCurrentPenColor);//1
			hPen=(HPEN)SelectObject(hdc, hPen);
			MoveToEx(hdc,x,y,NULL);
			x=LOWORD(lParam);
			y=HIWORD(lParam);
			lines[iLines].iCount++;
			lines[iLines].p[lines[iLines].iCount].x = x;
			lines[iLines].p[lines[iLines].iCount].y = y;
			LineTo(hdc,x,y);
			DeleteObject(SelectObject(hdc, hPen));
			ReleaseDC(hWnd,hdc);
		}

마우스가 움직일때

1. 내가 선택한 색상의 선을 그린다.

case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		for (int i = 0; i < iLines; i++)
		{
			hPen = CreatePen(PS_SOLID, 3, lines[i].pColor); //1
			hPen = (HPEN)SelectObject(hdc, hPen);  //선택한다.
			MoveToEx(hdc, lines[i].p[0].x, 
					lines[i].p[0].y, NULL);
			for (int j = 1; j <= lines[i].iCount; j++)
			{
				
				LineTo(hdc, lines[i].p[j].x, lines[i].p[j].y);
			}
			 //선택해제...
			DeleteObject(SelectObject(hdc, hPen));  //그리고 삭제한다...
		}
		return 0;

무효영역에 들어왔을때

1. 사용할 팬의 색상을 지금 그리는 선의 color값을 가져온다.

반응형

+ Recent posts