Program Language/API | MFC

[MFC] 따라하기 06. 순차적으로 원 그리기

야곰야곰+책벌레 2022. 3. 9. 14:38
728x90
반응형

1. 프로젝트 예제에 사용되는 내용

  • 구동하는 시스템 제어하기
  • 순차적으로 구동하는 시스템 만들기
 

[MFC] 따라하기 05. 여러 개의 원 그리기

1. 프로젝트 예제에 사용되는 내용 구동하는 시스템 제어하기 여러 시스템 구동하기 [MFC] 따라하기 04. 원이 그려지는 동작 만들기 1. 프로젝트 예제에 사용되는 내용 원을 이루는 함수 구하기 Clie

stormpy.tistory.com

2. flag로 동작 구현하기

기존에 Timer의 동작으로 구동하던 방법을 bool 변수를 사용하여 그리기/멈추기를 구현해 보자. 3개의 start_flag를 배열로 만들어서 그리기 동작을 제어할 수 있다. 하나가 작업이 끝나면 다음 작업이 실시될 수 있도록 만들자.

BOOL CDrawCircleDlg::OnInitDialog()
{
	...
    
	SetTimer(0, 5, NULL);
	SetTimer(1, 20, NULL);
	SetTimer(2, 10, NULL);
    
    return TRUE;
}

SetTimer는 다이얼로그가 시작할 때 모두 호출한다.

void CDrawCircleDlg::OnTimer(UINT_PTR nIDEvent)
{
	if (pauseDraw)
		return;
        
	switch (nIDEvent)
	{        
		case 0:
		{
			if (!start_flag[0])
				return;

			drawCircle(cntAngle[0]++, radius, vertex, 0 * (2 * radius + 10));
			if (cntAngle[0] > vertex)
			{
				start_flag[0] = false; // KillTimer(0);
				start_flag[1] = true;
			}
			break;
		}
        
        ...
	}
}

타이머 ID마다 start_flag를 체크해서 계속 동작할 것인지 결정한다. 다 그려지면 KillTimer()를 호출하는 대신 start_flag를 false 시킴으로써 그리기를 정지시킨다.

3. Serial Sequence 만들기

각각의 원을 하나의 task라고 하고 하나의 serial sequence를 만들어 보자.

  • 첫 번째 원은 자신의 task가 끝나면 다음 원으로 작업을 넘겨준다.
  • 첫 번째 원은 자신의 task가 남은 원으로 작업을 넘겨주면 다시 바로 작업을 시작한다.
  • 두 번째, 세 번째 원은 이전 원의 작업을 넘겨받아야만 시작할 수 있다.
void CDrawCircleDlg::OnTimer(UINT_PTR nIDEvent)
{
	if (pauseDraw)
		return;

	double radius = 50; // 반지름
	int vertex = 365; // 꼭지점

	switch (nIDEvent)
	{
		case 0:
		{
			// 첫 번째 원 그리기
			// 그리기 시작하지 않거나 완료 플래그가 SET되어 있으면 그리기는 대기한다.
			if (!start_flag[0] || done_flag[0])
			{
				// 두 번째 원을 그리지 않고, 완료 플래그가 SET 되어 있지 않고
				// 첫 번째 원 그리기가 완료되어 있다면, 두 번째 원 그리기를 실행한다.
				if (!start_flag[1] && !done_flag[1] && done_flag[0])
				{
					done_flag[0]  = false;
					start_flag[1] = true;

					CRect rt(0 * (2 * radius + 10), 10, 1 * (2 * radius + 10), (2 * radius + 10));
					InvalidateRect(rt);
				}
				return;
			}

			// 원 그리기를 끝나면 done_flag를 살린다.
			if (cntAngle[0] > vertex)
			{
				done_flag[0] = true;
				cntAngle[0]  = 0;
			}
			else
				drawCircle(cntAngle[0]++, radius, vertex, 0 * (2 * radius + 10));

			break;
		}

		case 1:
		{
			// 두 번째 원 그리기
			// 그리기 시작하지 않거나 완료 플래그가 SET되어 있으면 그리기는 대기한다.
			if (!start_flag[1] || done_flag[2])
			{
				// 세 번째 원을 그리지 않고, 완료 플래그가 SET 되어 있지 않고
				// 두 번째 원 그리기가 완료되어 있다면, 세 번째 원 그리기를 실행한다.
				if (!start_flag[2] && !done_flag[2] && done_flag[1])
				{
					done_flag[1]  = false;
					start_flag[2] = true;

					CRect rt(1 * (2 * radius + 10), 10, 2 * (2 * radius + 10), (2 * radius + 10));
					InvalidateRect(rt);
				}

				return;
			}

			// 원 그리기를 끝나면 done_flag를 살린다.
			if (cntAngle[1] > vertex)
			{
				start_flag[1] = false;
				done_flag[1]  = true;
				cntAngle[1]   = 0;
			}
			else
				drawCircle(cntAngle[1]++, radius, vertex, 1 * (2 * radius + 10));

			break;
		}

		case 2:
		{
			if (!start_flag[2])
				return;

			// 원 그리기를 끝나면 done_flag를 살린다.
			if (cntAngle[2] > vertex)
			{
				start_flag[2] = false; // KillTimer(2);
				cntAngle[2]   = 0;

				CRect rt(2 * (2 * radius + 10), 10, 3 * (2 * radius + 10), (2 * radius + 10));
				InvalidateRect(rt);
			}
			else
				drawCircle(cntAngle[2]++, radius, vertex, 2 * (2 * radius + 10));

			break;
		}
	}

	CDialogEx::OnTimer(nIDEvent);
}

06. 순차적으로 원 그리기.zip
0.13MB

728x90
반응형