๋ฐ˜์‘ํ˜•

 

์ด๋ฏธ์ง€์˜ ํŠน์ • ํ–‰(Row) ๋˜๋Š” ์—ด(Column)์—์„œ ํ”„๋กœํŒŒ์ผ(Profile) ๋ฐ์ดํ„ฐ๋ฅผ ํš๋“ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ข…์ข… ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ๋กœ ์กฐ๋ช… ๋˜๋Š” ์นด๋ฉ”๋ผ์˜ ๊ท ์ผ๋„, ์ด๋ฌผ ์œ ๋ฌด ๋“ฑ์„ ๋ณด๊ธฐ ์œ„ํ•จ์ธ๋ฐ์š”.

๋‹จ์ˆœํžˆ ์—๋””ํŠธ ์ปจํŠธ๋กค(Edit control)์— ๋ผ์ธ์˜ ์œ„์น˜ ๊ฐ’์„ ์ž…๋ ฅํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์ง€๋งŒ, 

์‚ฌ์šฉ์ž ์ž…์žฅ์—์„œ๋Š” ์Šคํฌ๋กค๋ฐ” ๋˜๋Š” ์Šฌ๋ผ์ด๋” ์ปจํŠธ๋กค์„ ์ด์šฉํ•˜์—ฌ ํ”„๋กœํŒŒ์ผ ๋ผ์ธ์„ ์›€์ง์ด๋Š” ๋ฐฉ๋ฒ•์ด ๋”์šฑ ์‚ฌ์šฉํ•˜๊ธฐ ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

 

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ์Šฌ๋ผ์ด๋” ์ปจํŠธ๋กค๋กœ Vertical Line์„ ์›€์ง์ด๋Š” ์˜ˆ์ œ๋ฅผ ๋ณด์—ฌ๋“œ๋ฆฌ๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

โ€ป ์˜ˆ์ œ ์ฝ”๋“œ๋Š” ํ•˜๋‹จ์— ์ฒจ๋ถ€๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ดํ•ด๋ฅผ ๋•๊ธฐ ์œ„ํ•ด ์•„๋ž˜ ๋งํฌ๋ฅผ ๊ผญ ์ฝ์–ด์ฃผ์„ธ์š”.

 

๋”ฐ๋ผํ•˜๊ธฐ

Dialog Base์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”. ์ด๋ฆ„์€ 'DoubleBuffering'์œผ๋กœ ์ง€์—ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  UI ๋ฐฐ์น˜๋Š” ๊ฐ„๋‹จํ•˜๊ฒŒ Button / Picture Control / Slider Control(Horizontal) ์ด๋ ‡๊ฒŒ 3๊ฐœ๋งŒ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

 

ํ—ค๋”์— ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณ€์ˆ˜์™€ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

// DobuleBufferingDlg.h
public :
	CImage m_img; // ์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์œ„ํ•œ CImage ๊ฐ์ฒด.
	int m_nPos; // Horizontal Slider Control์˜ ์œ„์น˜.
	float m_fHorizontalRatio; // Picture Control๊ณผ ์ด๋ฏธ์ง€์™€์˜ ๋ฐฐ์œจ.

	void OnDrawImage(); // Double Buffering ๊ทธ๋ฆฌ๋Š” ์ž‘์—….
	void DrawVerticalLine(CDC* pDC); // Double Buffering ๋‚ด Vertical Line์„ ๊ทธ๋ฆฌ๋Š” ์ž‘์—….
	void DrawImage(CDC* pDC); // Double Buffering ๋‚ด ์ด๋ฏธ์ง€๋ฅผ ๊ทธ๋ฆฌ๋Š” ์ž‘์—….

 

๊ทธ๋ฆฌ๊ณ  ๋ณ€์ˆ˜๋ฅผ ์ดˆ๊ธฐํ™” ํ•ฉ๋‹ˆ๋‹ค.

// DoubleBufferingDlg.cpp
CDoubleBufferingDlg::CDoubleBufferingDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(IDD_DOUBLEBUFFERING_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	m_nPos = 0;
	m_fHorizontalRatio = 0;
}

๋ฒ„ํŠผ์„ ๋”๋ธ” ํด๋ฆญํ•˜์—ฌ ์ด๋ฒคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜จ ํ›„ ๊ทธ๋ ค์ง€๋Š” Picture Control์˜ ํฌ๊ธฐ์™€ ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ ๋น„์œจ์„ ๊ณ„์‚ฐํ•˜์—ฌ, ์Šฌ๋ผ์ด๋“œ ์ปจํŠธ๋กค์˜ ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

// DoubleBufferingDlg.cpp
void CDoubleBufferingDlg::OnBnClickedBtnLoadimage()
{
	// ์ด๋ฏธ์ง€ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ.
	m_img.Load(_T("test.jpg"));

	// Picture Control ํฌ๊ธฐ ์–ป๊ธฐ.
	CRect rect;
	GetDlgItem(IDC_PC_IMAGE)->GetClientRect(&rect);

	// Picture Control ๊ฐ€๋กœ ํฌ๊ธฐ & ์ด๋ฏธ์ง€ ๊ฐ€๋กœ ํฌ๊ธฐ ๋น„์œจ ๊ณ„์‚ฐํ•˜๊ธฐ.
	m_fHorizontalRatio = (float)rect.Width() / m_img.GetWidth();

	// Slider Control์˜ ๋ฒ”์œ„ ์ง€์ •ํ•˜๊ธฐ.
	CSliderCtrl* pCtrl = (CSliderCtrl*)GetDlgItem(IDC_HSL_VERTICALLINE);
	pCtrl->SetRange(0, m_img.GetWidth()*m_fHorizontalRatio);
	
	//Invalidate();
}

์ด๋ฒˆ์—๋Š” ๋”๋ธ” ๋ฒ„ํผ๋ง์œผ๋กœ ๊ทธ๋ฆฌ๋Š” ์ž‘์—…์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

// DoubleBufferingDlg.cpp
void CDoubleBufferingDlg::OnDrawImage()
{
	// Picture Control DC๋ฅผ ์ƒ์„ฑ.
	CClientDC dc(GetDlgItem(IDC_PC_IMAGE));
	
	// Picture Control ํฌ๊ธฐ๋ฅผ ์–ป๋Š”๋‹ค.
	CRect rect;
	GetDlgItem(IDC_PC_IMAGE)->GetClientRect(&rect);

	CDC memDC;
	CBitmap *pOldBitmap, bitmap;

	// Picture Control DC์— ํ˜ธํ™˜๋˜๋Š” ์ƒˆ๋กœ์šด CDC๋ฅผ ์ƒ์„ฑ. (์ž„์‹œ ๋ฒ„ํผ)
	memDC.CreateCompatibleDC(&dc);

	// Picture Control์˜ ํฌ๊ธฐ์™€ ๋™์ผํ•œ ๋น„ํŠธ๋งต์„ ์ƒ์„ฑ.
	bitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());

	// ์ž„์‹œ ๋ฒ„ํผ์—์„œ ๋ฐฉ๊ธˆ ์ƒ์„ฑํ•œ ๋น„ํŠธ๋งต์„ ์„ ํƒํ•˜๋ฉด์„œ, ์ด์ „ ๋น„ํŠธ๋งต์„ ๋ณด์กด.
	pOldBitmap = memDC.SelectObject(&bitmap);

	// ์ž„์‹œ ๋ฒ„ํผ์— ๊ฒ€์€์ƒ‰์œผ๋กœ ์ฑ„์›€.
	memDC.PatBlt(0, 0, rect.Width(), rect.Height(), BLACKNESS);

	// ์ž„์‹œ ๋ฒ„ํผ์— ๊ทธ๋ฆฌ๋Š” ๋™์ž‘์„ ์ˆ˜ํ–‰.
	DrawImage(&memDC);
	DrawVerticalLine(&memDC);

	// ์ž„์‹œ ๋ฒ„ํผ๋ฅผ Picture Control์— ๊ทธ๋ฆฐ๋‹ค.
	dc.BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);

	// ์ด์ „ ๋น„ํŠธ๋งต์œผ๋กœ ์žฌ์„ค์ •.
	memDC.SelectObject(pOldBitmap);

	// ์ƒ์„ฑํ•œ ๋ฆฌ์†Œ์Šค ํ•ด์ œ.
	memDC.DeleteDC();
	bitmap.DeleteObject();
}

DrawImage()์™€ DrawVerticalLine()๋„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

// DoubleBufferingDlg.cpp
void CDoubleBufferingDlg::DrawVerticalLine(CDC* pDC)
{
	CRect rect;
	GetDlgItem(IDC_PC_IMAGE)->GetClientRect(&rect);

	// ๊ตต๊ธฐ 1, ๋นจ๊ฐ„์ƒ‰, ์‹ค์„  ์ƒ์„ฑํ•˜๊ธฐ.
	CPen *pOldPen, pen;
	pen.CreatePen(PS_SOLID, 1, RGB(255, 0, 0));

	pOldPen = pDC->SelectObject(&pen);

	pDC->MoveTo(m_nPos, 0);
	pDC->LineTo(m_nPos, rect.Height());

	pDC->SelectObject(pOldPen);

	pen.DeleteObject();
}

void CDoubleBufferingDlg::DrawImage(CDC* pDC)
{
	CRect rect;
	GetDlgItem(IDC_PC_IMAGE)->GetClientRect(&rect);

	m_img.Draw(pDC->GetSafeHdc(), rect);
}

๋งˆ์ง€๋ง‰์œผ๋กœ, 'Ctrl+Shift+X' ๋˜๋Š” 'Class Wizard'๋ฅผ ์‹คํ–‰ํ•˜์—ฌ 'OnHScroll' ์ด๋ฒคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์†Œ์Šค๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

// DoubleBufferingDlg.cpp
void CDoubleBufferingDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	CSliderCtrl* pCtrl = (CSliderCtrl*)GetDlgItem(IDC_HSL_VERTICALLINE);
	if (pScrollBar->GetSafeHwnd() == pCtrl->GetSafeHwnd())
	{
		m_nPos = pCtrl->GetPos();
		// OnPaint()์—์„œ ๊ทธ๋ฆฌ๋Š” ์ž‘์—…์„ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ.
		//Invalidate(FALSE);
		
		// ์ง์ ‘ Picture Control์— ๊ทธ๋ฆฌ๋Š” ์ž‘์—…์„ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ.
		OnDrawImage();
	}

	CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
}

๋ชจ๋“  ์ž‘์—…์ด ์™„๋ฃŒ๋์Šต๋‹ˆ๋‹ค. Build๋ฅผ ํ•˜๊ณ  ์‹คํ–‰ํ•ด ๋ณผ๊นŒ์š”?

 

OnPaint()์—์„œ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ

 

OnDrawImage()๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ

 

ํ˜น์‹œ ์ฐจ์ด์ ์ด ๋Š๊ปด์ง€์‹œ๋‚˜์š”?

OnPaint()์—์„œ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด Picture Control ํ…Œ๋‘๋ฆฌ๊ฐ€ ๋ฆฌํ”„๋ ˆ์‰ฌ(Refresh) ๋˜๋Š” ๊ฒƒ์ด ๋ณด์ž…๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด OnDrawImage()๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด ๊ทธ๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ์ „ํ˜€ ์—†์Šต๋‹ˆ๋‹ค.

 

๋ณดํ†ต '๊ทธ๋ฆฌ๋Š” ์ž‘์—…'์ด๋ผ๊ณ  ํ•˜๋ฉด OnPaint()์—์„œ ์ฒ˜๋ฆฌํ•˜๋ผ๊ณ  ํ•˜๋Š”๋ฐ์š”.

OnPaint()์—์„œ ๊ทธ๋ฆฌ๋Š” ์ž‘์—…์„ ํ˜ธ์ถœํ•˜๋ ค๋ฉด Invalidate()๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•˜๋Š”๋ฐ,

์ด ๊ฒฝ์šฐ ์ „์ฒด ์ปจํŠธ๋กค๋“ค์— ์˜ํ–ฅ์„ ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๊นœ๋นก์ด๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ €๋Š” ๋‘ ๋ฒˆ์งธ์™€ ๊ฐ™์ด ๊ทธ๋ฆฌ๋Š” ํ•จ์ˆ˜๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•˜๋Š” ํŽธ์ž…๋‹ˆ๋‹ค.

DoubleBuffering.zip
๋‹ค์šด๋กœ๋“œ

 

๋ฐ˜์‘ํ˜•