1. 프로젝트 예제에 사용되는 내용
- 구동하는 시스템 제어하기
- 여러 시스템 구동하기
2. 시작, 일시정지, 정지 기능 만들기
'04. 원이 그려지는 동작 만들기' 프로젝트를 그대로 가져와서 버튼 3개를 만든다.
3개 모두 클릭 이벤트를 만들어 둔다.
- 그리기 : 원을 그리기를 처음부터 시작한다.
- 일시정지 : 원 그리기를 잠시 멈춘다.
- 정지 : 그리기를 멈춘다.
우선 그리기를 처음부터 하려면 그려진 원을 지워야 하고, 데이터를 초기화해야 한다.
void CDrawCircleDlg::OnBnClickedDraw()
{
RedrawWindow();
cntAngle = 0;
SetTimer(0, 10, NULL);
}
RedrawWindow()는 다이얼로그를 새로 그려주게 된다. CClientDC로 그렸던 원은 OnPaint에서 다시 그려지지 않으므로 완전히 지워진다.
정지의 경우에는 KillTimer()만으로 그리기를 멈출 수 있다.
void CDrawCircleDlg::OnBnClickedStop()
{
KillTimer(0);
}
위와 같이 원을 그리는 도중에 멈출 수 있다. 이것을 다시 그리려면 '그리기' 함수에서 처리했던 RedrawWindow()만 제거하면 다시 그리기를 할 수는 있지만 다른 방법을 사용해 보도록 하자.
멤버 변수로 pauseDraw를 추가하여 drawCircle에서 작업을 하지 않도록 수정해 보자.
void CDrawCircleDlg::OnTimer(UINT_PTR nIDEvent)
{
if (pauseDraw)
return;
...
pauseDraw가 true가 되면 그리기를 진행하지 않고 return 되게 만들었다.
일시정지 버튼에서는 pauseDraw의 상태만 바꿔주면 된다.
void CDrawCircleDlg::OnBnClickedPause()
{
pauseDraw ^= true;
}
Pause는 누를 때마다 true/false를 바꿔주기 위해서 XOR 한다. 현재 Pause상태를 알려주기 위해서 버튼의 Caption을 바꿔준다.
void CDrawCircleDlg::OnBnClickedPause()
{
pauseDraw ^= true;
if (pauseDraw)
SetDlgItemText(IDC_PAUSE, L"재시작");
else
SetDlgItemText(IDC_PAUSE, L"일시정지");
}
세 개의 원을 그리기 위해서 원 그리기 함수에 Offset을 매개 변수로 추가하자.
void CDrawCircleDlg::drawCircle(int count, double radius, int vertex, int offset_x)
{
CClientDC dc(this);
const double pi = 3.1415926535897932384626433832795; // PI
// 중심점은 반지름보다 (10, 10) 큰 위치
double cen_x = radius + 10 + offset_x;
double cen_y = radius + 10;
double x, y, radian;
// 시작 위치로 펜을 옮김
radian = count * 2 * pi / vertex;
x = radius * cos(radian) + cen_x;
y = radius * sin(radian) + cen_y;
dc.MoveTo(x, y);
// 원 그리기
radian = (count + 1) * 2 * pi / vertex;
x = radius * cos(radian) + cen_x;
y = radius * sin(radian) + cen_y;
dc.LineTo(x, y);
}
3개의 원을 그리기 위해서 3개의 카운트를 만들어서 적용하며, 서로 다른 시간에서 EVENT가 발생하는 타이머를 사용하여 그려보기로 한다.
void CDrawCircleDlg::OnTimer(UINT_PTR nIDEvent)
{
if (pauseDraw)
return;
double radius = 50; // 반지름
int vertex = 365; // 꼭지점
switch (nIDEvent)
{
case 0:
{
drawCircle(cntAngle[0]++, radius, vertex, 0 * (2 * radius + 10));
if (cntAngle[0] > vertex)
KillTimer(0);
break;
}
case 1:
{
drawCircle(cntAngle[1]++, radius, vertex, 1 * (2 * radius + 10));
if (cntAngle[1] > vertex)
KillTimer(1);
break;
}
case 2:
{
drawCircle(cntAngle[2]++, radius, vertex, 2 * (2 * radius + 10));
if (cntAngle[2] > vertex)
KillTimer(2);
break;
}
}
CDialogEx::OnTimer(nIDEvent);
}
타이머는 이해를 위해서 각각 만들었다.
void CDrawCircleDlg::OnBnClickedDraw()
{
RedrawWindow();
ZeroMemory(cntAngle, sizeof(cntAngle));
SetTimer(0, 5, NULL);
SetTimer(1, 20, NULL);
SetTimer(2, 10, NULL);
pauseDraw = false;
}
그리기를 누르면 세 개의 타이머가 실행되도록 한다. cntAngle을 0으로 만드는 것은 ZeroMemory를 사용했다. 배열의 값을 크기만큼 0으로 만들어 준다.
void CDrawCircleDlg::OnBnClickedStop()
{
KillTimer(0);
KillTimer(1);
KillTimer(2);
}
정지 시에도 세 개의 타이머를 모두 정지 시켜야 한다.
모든 작업이 끝났다면 실행해 보자.
서로 다른 속도로 그리는 것을 확인할 수 있다.
'코드 > MFC' 카테고리의 다른 글
(MFC) 디렉토리 선택 코드 (0) | 2024.05.22 |
---|---|
[MFC] 중국어 읽어오기 (unicode, utf-lf) (0) | 2022.11.23 |
[MFC] 따라하기 04. 원이 그려지는 동작 만들기 (0) | 2022.03.08 |
[MFC] 따라하기 03. Edit box를 이용하여 여러 개의 사각형 그리기 (0) | 2022.03.02 |
[MFC] 따라하기 02. 버튼을 이용하여 사각형 그리기/지우기 (0) | 2022.03.02 |