mfc_speed_1 - 8BitsCoding/RobotMentor GitHub Wiki



λ‚˜λ§Œμ˜ 컨트둀 생성

CWnd의 ProgressStatusWnd 생성

// Dlg.h
#include "ProgressStatusWnd.h"
// ...
ProgressStatusWnd m_status_wnd;
BOOL CMFCApplication1Dlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 이 λŒ€ν™” μƒμžμ˜ μ•„μ΄μ½˜μ„ μ„€μ •ν•©λ‹ˆλ‹€.  μ‘μš© ν”„λ‘œκ·Έλž¨μ˜ μ£Ό 창이 λŒ€ν™” μƒμžκ°€ 아닐 κ²½μš°μ—λŠ”
	//  ν”„λ ˆμž„μ›Œν¬κ°€ 이 μž‘μ—…μ„ μžλ™μœΌλ‘œ μˆ˜ν–‰ν•©λ‹ˆλ‹€.
	SetIcon(m_hIcon, TRUE);			// 큰 μ•„μ΄μ½˜μ„ μ„€μ •ν•©λ‹ˆλ‹€.
	SetIcon(m_hIcon, FALSE);		// μž‘μ€ μ•„μ΄μ½˜μ„ μ„€μ •ν•©λ‹ˆλ‹€.

	// TODO: 여기에 μΆ”κ°€ μ΄ˆκΈ°ν™” μž‘μ—…μ„ μΆ”κ°€ν•©λ‹ˆλ‹€.

	m_status_wnd.Create(NULL, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(0, 0, 100, 100), this, 2005);

	return TRUE;  // 포컀슀λ₯Ό μ»¨νŠΈλ‘€μ— μ„€μ •ν•˜μ§€ μ•ŠμœΌλ©΄ TRUEλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
}

μ’Œν‘œλ₯Ό Picture Ctrl으둜 λ°›μ•„λ³΄μž.

BOOL CMFCApplication1Dlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 이 λŒ€ν™” μƒμžμ˜ μ•„μ΄μ½˜μ„ μ„€μ •ν•©λ‹ˆλ‹€.  μ‘μš© ν”„λ‘œκ·Έλž¨μ˜ μ£Ό 창이 λŒ€ν™” μƒμžκ°€ 아닐 κ²½μš°μ—λŠ”
	//  ν”„λ ˆμž„μ›Œν¬κ°€ 이 μž‘μ—…μ„ μžλ™μœΌλ‘œ μˆ˜ν–‰ν•©λ‹ˆλ‹€.
	SetIcon(m_hIcon, TRUE);			// 큰 μ•„μ΄μ½˜μ„ μ„€μ •ν•©λ‹ˆλ‹€.
	SetIcon(m_hIcon, FALSE);		// μž‘μ€ μ•„μ΄μ½˜μ„ μ„€μ •ν•©λ‹ˆλ‹€.

	// TODO: 여기에 μΆ”κ°€ μ΄ˆκΈ°ν™” μž‘μ—…μ„ μΆ”κ°€ν•©λ‹ˆλ‹€.

	CRect r;
	GetDlgItem(IDC_STATIC_RECT)->GetWindowRect(r);
	ScreenToClient(r);
	m_status_wnd.CreateEx(WS_EX_STATICEDGE, NULL, NULL, WS_CHILD | WS_VISIBLE, r, this, 2005);

	return TRUE;  // 포컀슀λ₯Ό μ»¨νŠΈλ‘€μ— μ„€μ •ν•˜μ§€ μ•ŠμœΌλ©΄ TRUEλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
}

기본적 λ„€λͺ¨ 그리기

// ProgressStatusWnd.h
CImage m_draw_image;
CDC m_draw_dc;
int ProgressStatusWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	CRect r;
	GetClientRect(r);

	m_draw_image.Create(r.Width(), r.Height(), 32);
	m_draw_dc.Attach(m_draw_image.GetDC());

	for (int y = 0; y < Y_COUNT; y++) {
		for (int x = 0; x < X_COUNT; x++) {
			m_draw_dc.Rectangle(x * WIDTH, y * HEIGHT, (x + 1)*WIDTH, (y + 1)*HEIGHT);
		}
	}

	return 0;
}
void ProgressStatusWnd::OnDestroy()
{
	CWnd::OnDestroy();

	m_draw_dc.DeleteDC();
	m_draw_image.ReleaseDC();
	m_draw_image.Destroy();
}
void ProgressStatusWnd::OnPaint()
{
	CPaintDC dc(this);

	m_draw_image.Draw(dc, 0, 0);
}

λ„€λͺ¨μ— 색상 λ„£κΈ°

// ProgressStatusWnd.h
CBrush m_normal_brush, m_error_brush, m_no_data_brush;
CPen m_nomal_pen, m_error_pen, m_no_data_pen;
int ProgressStatusWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	CRect r;
	GetClientRect(r);

	m_draw_image.Create(r.Width(), r.Height(), 32);
	m_draw_dc.Attach(m_draw_image.GetDC());

	m_normal_brush.CreateSolidBrush(RGB(0, 255, 128));
	m_error_brush.CreateSolidBrush(RGB(255, 0, 128));
	m_no_data_brush.CreateSolidBrush(RGB(64, 64, 64));

	m_normal_pen.CreatePen(PS_SOLID, 1, RGB(0, 200, 100));
	m_error_pen.CreatePen(PS_SOLID, 1, RGB(200, 0, 100));
	m_no_data_pen.CreatePen(PS_SOLID, 1, RGB(192, 192, 192));

	m_draw_dc.SelectObject(&m_no_data_brush);
	m_draw_dc.SelectObject(&m_no_data_pen);

	for (int y = 0; y < Y_COUNT; y++) {
		for (int x = 0; x < X_COUNT; x++) {
			m_draw_dc.Rectangle(x * WIDTH, y * HEIGHT, (x + 1)*WIDTH, (y + 1)*HEIGHT);
		}
	}

	return 0;
}

y좕을 λ³΄μ—¬μ§€λŠ” 개수만 그리기

int ProgressStatusWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	CRect r;
	GetClientRect(r);

	m_draw_image.Create(r.Width(), r.Height(), 32);
	m_draw_dc.Attach(m_draw_image.GetDC());

	m_normal_brush.CreateSolidBrush(RGB(0, 255, 128));
	m_error_brush.CreateSolidBrush(RGB(255, 0, 128));
	m_no_data_brush.CreateSolidBrush(RGB(64, 64, 64));

	m_normal_pen.CreatePen(PS_SOLID, 1, RGB(0, 200, 100));
	m_error_pen.CreatePen(PS_SOLID, 1, RGB(200, 0, 100));
	m_no_data_pen.CreatePen(PS_SOLID, 1, RGB(192, 192, 192));

	m_draw_dc.SelectObject(&m_no_data_brush);
	m_draw_dc.SelectObject(&m_no_data_pen);

	m_display_y_count = r.Height() / HEIGHT;

	for (int y = 0; y < m_display_y_count; y++) {
		for (int x = 0; x < X_COUNT; x++) {
			m_draw_dc.Rectangle(x * WIDTH, y * HEIGHT, (x + 1)*WIDTH, (y + 1)*HEIGHT);
		}
	}

	return 0;
}

ν•˜μ§€λ§Œ μ•ˆκ·Έλ €μ§€λŠ” 뢀뢄이 생긴닀.

m_display_y_count = r.Height() / HEIGHT;
if (r.Height() % HEIGHT) m_display_y_count++;

데이터 μ‚½μž…ν•˜κΈ°

μ‹œμž‘ λ²„νŠΌμ„ ν†΅ν•΄μ„œ 데이터 μ‚½μž… μ‹œμž‘

void CMFCApplication1Dlg::OnBnClickedStartBtn()
{
	SetTimer(1, 30, NULL);
	m_pos_progress.SetPos(0);
}
void CMFCApplication1Dlg::OnBnClickedEndBtn()
{
	KillTimer(1);
}
void CMFCApplication1Dlg::OnTimer(UINT_PTR nIDEvent)
{
	if (nIDEvent == 1) {
		m_pos_progress.OffsetPos(1);
		if (0 == m_status_wnd.SetData(rand() % 100)) {
			// μŒ“μ„ 수 μžˆλŠ” λ©”λͺ¨λ¦¬λ₯Ό 초과
			OnBnClickedEndBtn();
			MessageBox(L"μž‘μ—…μ΄ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.", L"μž‘μ—… μ™„λ£Œ", MB_ICONINFORMATION);
		}
	}

	CDialogEx::OnTimer(nIDEvent);
}
// ProgressStatusWnd.h
struct ProgressData
{
	int data;
	int status;			// 0 미처리, 1 정상, 2 였λ₯˜
};

//...

int m_display_y_count, m_count = 0;
//ProgressData **mp_data;
ProgressData *mp_data;
int ProgressStatusWnd::SetData(int a_data)
{
	if (m_count < X_COUNT * Y_COUNT) {
		(mp_data + m_count)->data = a_data;
		if (a_data > 3 && a_data << 97) {
			// Error μ—†μŒ
			(mp_data + m_count)->status = 1;
		}
		else {
			// Error
			(mp_data + m_count)->status = 2;
		}
		m_count++;
		return 1;
	}
	return 0;
}
int ProgressStatusWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	// 2차원 λ©”λͺ¨λ¦¬ ν• λ‹Ή
	// mp_data = new ProgressData *[Y_COUNT];
	// for (int i = 0; i < Y_COUNT; i++) *(mp_data + i) = new ProgressData[X_COUNT];
	mp_data = new ProgressData [Y_COUNT*X_COUNT];


	CRect r;
	GetClientRect(r);

	m_draw_image.Create(r.Width(), r.Height(), 32);
	m_draw_dc.Attach(m_draw_image.GetDC());

	m_normal_brush.CreateSolidBrush(RGB(0, 255, 128));
	m_error_brush.CreateSolidBrush(RGB(255, 0, 128));
	m_no_data_brush.CreateSolidBrush(RGB(64, 64, 64));

	m_normal_pen.CreatePen(PS_SOLID, 1, RGB(0, 200, 100));
	m_error_pen.CreatePen(PS_SOLID, 1, RGB(200, 0, 100));
	m_no_data_pen.CreatePen(PS_SOLID, 1, RGB(192, 192, 192));

	m_draw_dc.SelectObject(&m_no_data_brush);
	m_draw_dc.SelectObject(&m_no_data_pen);

	m_display_y_count = r.Height() / HEIGHT;
	if (r.Height() % HEIGHT) m_display_y_count++;

	for (int y = 0; y < m_display_y_count; y++) {
		for (int x = 0; x < X_COUNT; x++) {
			m_draw_dc.Rectangle(x * WIDTH, y * HEIGHT, (x + 1)*WIDTH, (y + 1)*HEIGHT);
		}
	}

	return 0;
}
void ProgressStatusWnd::OnDestroy()
{
	CWnd::OnDestroy();

	m_draw_dc.DeleteDC();
	m_draw_image.ReleaseDC();
	m_draw_image.Destroy();

	m_normal_brush.DeleteObject();
	m_error_brush.DeleteObject();
	m_no_data_brush.DeleteObject();

	m_normal_pen.DeleteObject();
	m_error_pen.DeleteObject();
	m_no_data_pen.DeleteObject();

	// for (int i = 0; i < Y_COUNT; i++) delete[] * (mp_data + i);
	// delete[] mp_data;
	delete[] mp_data;
}

μ‚½μž…λœ 데이터 μ „μ‹œν•˜κΈ°

int ProgressStatusWnd::SetData(int a_data)
{
	if (m_count < X_COUNT * Y_COUNT) {
		(mp_data + m_count)->data = a_data;
		if (a_data > 3 && a_data << 97) {
			// Error μ—†μŒ
			(mp_data + m_count)->status = 1;
		}
		else {
			// Error
			(mp_data + m_count)->status = 2;
		}
		RedrawData();
		m_count++;
		Invalidate(FALSE);
		return 1;
	}
	return 0;
}
void ProgressStatusWnd::RedrawData()
{
	ProgressData * p = mp_data + m_count;

	if (p->status == 1) {
		m_draw_dc.SelectObject(&m_normal_brush);
		m_draw_dc.SelectObject(&m_normal_pen);
	}
	else {
		m_draw_dc.SelectObject(&m_error_brush);
		m_draw_dc.SelectObject(&m_error_pen);
	}

	int y = m_count / X_COUNT, x = m_count % X_COUNT;
	m_draw_dc.Rectangle(x * WIDTH, y * HEIGHT, (x + 1)*WIDTH, (y + 1)*HEIGHT);
}

μ•„λž˜μͺ½ λ°μ΄ν„°κΉŒμ§€ μ „μ‹œ

μš°μ„  수직 슀크둀 μΆ”κ°€

BOOL CMFCApplication1Dlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 이 λŒ€ν™” μƒμžμ˜ μ•„μ΄μ½˜μ„ μ„€μ •ν•©λ‹ˆλ‹€.  μ‘μš© ν”„λ‘œκ·Έλž¨μ˜ μ£Ό 창이 λŒ€ν™” μƒμžκ°€ 아닐 κ²½μš°μ—λŠ”
	//  ν”„λ ˆμž„μ›Œν¬κ°€ 이 μž‘μ—…μ„ μžλ™μœΌλ‘œ μˆ˜ν–‰ν•©λ‹ˆλ‹€.
	SetIcon(m_hIcon, TRUE);			// 큰 μ•„μ΄μ½˜μ„ μ„€μ •ν•©λ‹ˆλ‹€.
	SetIcon(m_hIcon, FALSE);		// μž‘μ€ μ•„μ΄μ½˜μ„ μ„€μ •ν•©λ‹ˆλ‹€.

	// TODO: 여기에 μΆ”κ°€ μ΄ˆκΈ°ν™” μž‘μ—…μ„ μΆ”κ°€ν•©λ‹ˆλ‹€.

	srand((unsigned int)time(NULL));
	m_pos_progress.SetRange(0, X_COUNT*Y_COUNT);

	CRect r;
	GetDlgItem(IDC_STATIC_RECT)->GetWindowRect(r);
	ScreenToClient(r);
	m_status_wnd.CreateEx(WS_EX_STATICEDGE, NULL, NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL, r, this, 2005);

	return TRUE;  // 포컀슀λ₯Ό μ»¨νŠΈλ‘€μ— μ„€μ •ν•˜μ§€ μ•ŠμœΌλ©΄ TRUEλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
}
void ProgressStatusWnd::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	if (pScrollBar == NULL) {
		ProcessScroll(nSBCode, nPos, SB_VERT);
		RedrawAllData();
		Invalidate(FALSE);
	}

	CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
}
void ProgressStatusWnd::ProcessScroll(UINT nSBCode, UINT nPos, int a_scroll_type)
{
	if (nSBCode == SB_THUMBPOSITION || nSBCode == SB_THUMBTRACK) {
		SetScrollPos(a_scroll_type, nPos);
	}
	else {
		int scroll_pos = GetScrollPos(a_scroll_type), min = 0, max = 0;
		GetScrollRange(a_scroll_type, &min, &max);
		switch (nSBCode) {
		case SB_LINEDOWN:
			if (scroll_pos < max) SetScrollPos(a_scroll_type, ++scroll_pos);
			break;
		case SB_LINEUP:
			if (scroll_pos < max) SetScrollPos(a_scroll_type, --scroll_pos);
			break;
		case SB_PAGEDOWN:
			if (scroll_pos + 100 < max) SetScrollPos(a_scroll_type, scroll_pos + 100);
			break;
		case SB_PAGEUP:
			if (scroll_pos - 100 > min) SetScrollPos(a_scroll_type, scroll_pos - 100);
			break;
		}
	}
}
void ProgressStatusWnd::RedrawAllData()
{
	int scroll_pos = GetScrollPos(SB_VERT);
	ProgressData * p = mp_data + scroll_pos*X_COUNT;

	for (int y = 0; y < m_display_y_count; y++) {
		for (int x = 0; x < X_COUNT; x++) {
			if (p->status == 1) {
				m_draw_dc.SelectObject(&m_normal_brush);
				m_draw_dc.SelectObject(&m_normal_pen);
			}
			else if(p->status==2) {
				m_draw_dc.SelectObject(&m_error_brush);
				m_draw_dc.SelectObject(&m_error_pen);
			}
			else {
				m_draw_dc.SelectObject(&m_no_data_brush);
				m_draw_dc.SelectObject(&m_no_data_pen);
			}

			m_draw_dc.Rectangle(x * WIDTH, y * HEIGHT, (x + 1)*WIDTH, (y + 1)*HEIGHT);
			p++;
		}
	}
}

슀크둀 λ˜λŠ” λΆ€λΆ„ 처리 μΆ”κ°€

void ProgressStatusWnd::RedrawData()
{
	ProgressData * p = mp_data + m_count;

	if (p->status == 1) {
		m_draw_dc.SelectObject(&m_normal_brush);
		m_draw_dc.SelectObject(&m_normal_pen);
	}
	else {
		m_draw_dc.SelectObject(&m_error_brush);
		m_draw_dc.SelectObject(&m_error_pen);
	}

	int scroll_pos = GetScrollPos(SB_VERT);
	int y = m_count / X_COUNT - scroll_pos, x = m_count % X_COUNT;
	m_draw_dc.Rectangle(x * WIDTH, y * HEIGHT, (x + 1)*WIDTH, (y + 1)*HEIGHT);
}

λ§ˆμ§€λ§‰ κΉ¨μ§€λŠ” 데이터 처리

int ProgressStatusWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	// 2차원 λ©”λͺ¨λ¦¬ ν• λ‹Ή
	// mp_data = new ProgressData *[Y_COUNT];
	// for (int i = 0; i < Y_COUNT; i++) *(mp_data + i) = new ProgressData[X_COUNT];
	mp_data = new ProgressData [Y_COUNT*X_COUNT];
	memset(mp_data, 0, sizeof(ProgressData)*Y_COUNT*X_COUNT);

	CRect r;
	GetClientRect(r);

	m_draw_image.Create(r.Width(), r.Height(), 32);
	m_draw_dc.Attach(m_draw_image.GetDC());

	m_normal_brush.CreateSolidBrush(RGB(0, 255, 128));
	m_error_brush.CreateSolidBrush(RGB(255, 0, 128));
	m_no_data_brush.CreateSolidBrush(RGB(64, 64, 64));

	m_normal_pen.CreatePen(PS_SOLID, 1, RGB(0, 200, 100));
	m_error_pen.CreatePen(PS_SOLID, 1, RGB(200, 0, 100));
	m_no_data_pen.CreatePen(PS_SOLID, 1, RGB(192, 192, 192));

	m_draw_dc.SelectObject(&m_no_data_brush);
	m_draw_dc.SelectObject(&m_no_data_pen);

	m_display_y_count = r.Height() / HEIGHT;
	if (r.Height() % HEIGHT) m_display_y_count++;


	SetScrollRange(SB_VERT, 0, Y_COUNT - m_display_y_count, 0);     // μ—¬κΈ° μΆ”κ°€

	for (int y = 0; y < m_display_y_count; y++) {
		for (int x = 0; x < X_COUNT; x++) {
			m_draw_dc.Rectangle(x * WIDTH, y * HEIGHT, (x + 1)*WIDTH, (y + 1)*HEIGHT);
		}
	}

	return 0;
}

λ§ˆμ§€λ§‰ 반쯀 λ‚˜μ˜¨ μ‚¬κ°ν˜• 처리

void ProgressStatusWnd::RedrawAllData()
{
	int scroll_pos = GetScrollPos(SB_VERT), fix_y = 0;
	ProgressData * p = mp_data + scroll_pos * X_COUNT;

	if (scroll_pos == (Y_COUNT - m_display_y_count)) {
		CRect r;
		GetClientRect(r);
		if (r.Height() % HEIGHT) fix_y = 10 - r.Height() % HEIGHT;
	}
	else {
		// λ§ˆμ§€λ§‰ νŽ˜μ΄μ§€
		p = mp_data + (Y_COUNT - m_display_y_count) * X_COUNT;
	}

	for (int y = 0; y < m_display_y_count; y++) {
		for (int x = 0; x < X_COUNT; x++) {
			if (p->status == 1) {
				m_draw_dc.SelectObject(&m_normal_brush);
				m_draw_dc.SelectObject(&m_normal_pen);
			}
			else if(p->status==2) {
				m_draw_dc.SelectObject(&m_error_brush);
				m_draw_dc.SelectObject(&m_error_pen);
			}
			else {
				m_draw_dc.SelectObject(&m_no_data_brush);
				m_draw_dc.SelectObject(&m_no_data_pen);
			}

			m_draw_dc.Rectangle(x * WIDTH, y * HEIGHT - fix_y, (x + 1)*WIDTH, (y + 1)*HEIGHT - fix_y);
			p++;
		}
	}
}

μžλ™ 슀크둀 κΈ°λŠ₯ μΆ”κ°€

void CMFCApplication1Dlg::OnTimer(UINT_PTR nIDEvent)
{
	if (nIDEvent == 1) {
		m_pos_progress.OffsetPos(1);
		if (0 == m_status_wnd.SetData(rand() % 100, m_cur_pos_check.GetCheck())) {
			// μŒ“μ„ 수 μžˆλŠ” λ©”λͺ¨λ¦¬λ₯Ό 초과
			OnBnClickedEndBtn();
			MessageBox(L"μž‘μ—…μ΄ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.", L"μž‘μ—… μ™„λ£Œ", MB_ICONINFORMATION);
		}
	}

	CDialogEx::OnTimer(nIDEvent);
}
int ProgressStatusWnd::SetData(int a_data, int a_cur_pos_check)
{
	if (m_count < X_COUNT * Y_COUNT) {
		(mp_data + m_count)->data = a_data;
		if (a_data > 3 && a_data << 97) {
			// Error μ—†μŒ
			(mp_data + m_count)->status = 1;
		}
		else {
			// Error
			(mp_data + m_count)->status = 2;
		}

		if (a_cur_pos_check == 1 && !((m_count + 1) % X_COUNT)) {
			MoveCurrentPos();
		}

		RedrawData();
		m_count++;
		Invalidate(FALSE);
		return 1;
	}
	return 0;
}
void ProgressStatusWnd::MoveCurrentPos()
{
	int scroll_pos = GetScrollPos(SB_VERT);
	int y = (m_count + 1) / X_COUNT;

	if (y < scroll_pos || y >= scroll_pos + m_display_y_count - 1) {
		int new_pos = y - 2;
		int max, min;
		GetScrollRange(SB_VERT, &min, &max);
		if (new_pos < min) new_pos = min;
		else if (new_pos > max) new_pos = max;

		if (scroll_pos != new_pos) {
			SetScrollPos(SB_VERT, new_pos);
			RedrawAllData();
		}
	}
}

μ‹œμž‘λ²„νŠΌμ„ λˆ„λ₯΄λ©΄ ν˜„μž¬ 갱신쀑인 데이터 μ „μ‹œ

void CMFCApplication1Dlg::OnBnClickedPosCheck()
{
	if (m_cur_pos_check.GetCheck()) {
		m_status_wnd.MoveCurrentPos();
		m_status_wnd.Invalidate(FALSE);
	}
}