본문 바로가기
MFC

CScrollView를 이용한 Image Viewer 예제

by leo21c 2022. 7. 27.

JPG, BMP, PNG 등의 이미지 파일을 열어 스크롤이 가능한 화면에서 확대/축소를 하는 예제이다.

CScrollView 클래스를 이용하면 Scroll을 계산하지 않아도 된다.

 

예제는 TabCtrl에 Tab을 5개 만들고 각 탭별로 이미지를 넣고 확대/축소 기능과 함께 이미지를 보는 간단한 프로그램이다.

이미지는 CImage 클래스를 이용해서 읽는다.

 

Viewer 클래스에서 OnDraw()함수에서 확대/축소를 위한 StretchBlt 처리를 한다.

 

<주의>

CScrollView 클래스를 이용할 경우 OnInitialUpdate()함수에서 SetScrollSizes() 함수를 이용해서 크기를 초기화해야 한다.

그렇지 않으면 Scroll 처리를 위한 Size를 알수가 없어 에러가 발생한다.


void ImageViewer::OnInitialUpdate()
{
	CScrollView::OnInitialUpdate();

	//이 뷰의 전체 크기를 계산합니다.	
	//SetScrollSizes 초기화를 하지 않으면 에러 발생.
	CSize sizeTotal;
	sizeTotal.cx = sizeTotal.cy = 100;	
	SetScrollSizes(MM_TEXT, sizeTotal);
}

Image를 읽는 것은 간단하다. CImage 클래스를 이용하면 된다.

bool ImageViewer::ImageLoadFile(CString filename)
{
	if (!m_image.IsNull())
		m_image.Destroy();
	return m_image.Load(filename) != E_FAIL;
}

OnDraw(CDC* pDC) 함수에서 아래와 같이 이미지를 화면에 표시한다.


void ImageViewer::OnDraw(CDC* pDC)
{
	if (m_image.IsNull() == false)
	{
		CRect rect;
		GetClientRect(rect);

		CSize imgSize;
		imgSize.cx = m_image.GetWidth() * m_ratio;
		imgSize.cy = m_image.GetHeight() * m_ratio;

		SetScrollSizes(MM_TEXT, imgSize);

		CBrush wBrush(RGB(255, 255, 255));
		pDC->FillRect(rect, &wBrush);

		//캔버스 중앙에 오도록 계산
		int left = rect.right / 2 - imgSize.cx / 2;
		int top = rect.bottom / 2 - imgSize.cy / 2;

		//캔버스 보다 크면 0부터 그려지도록 처리.
		if (left < 0) left = 0;
		if (top < 0) top = 0;
		
		SetStretchBltMode(pDC->m_hDC, HALFTONE);
		m_image.StretchBlt(pDC->m_hDC, left, top, imgSize.cx, imgSize.cy, 0, 0, m_image.GetWidth(), m_image.GetHeight(), SRCCOPY);
	}
}

확대/축소는 Ctrl + Mouse Wheel을 이용하도록 했다.

BOOL ImageViewer::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	if ((nFlags & MK_CONTROL) == MK_CONTROL)
	{
		if (zDelta < 0)
		{
			//redraw 없이 리턴 처리. 깜박임 방지
			if (m_zoom == 300)
				return CScrollView::OnMouseWheel(nFlags, zDelta, pt);

			m_zoom += 10;
			if (m_zoom > 300) m_zoom = 300;//max 3배까지 확대 가능
		}
		else
		{
			//redraw 없이 리턴 처리. 깜박임 방지
			if (m_zoom == 1)
				return CScrollView::OnMouseWheel(nFlags, zDelta, pt);

			m_zoom -= 10;
			if (m_zoom < 1) m_zoom = 1;
		}

		m_ratio = (double)m_zoom / 100;//min는 1/100

		RedrawWindow();
	}

	return CScrollView::OnMouseWheel(nFlags, zDelta, pt);
}

위와 같은 방법으로 처리를 하면 확대/축소가 되고 이미지는 View의 가운데에 표시가 된다.

 

MFCApplication3.zip
6.15MB

예제는 Codejock control을 사용했기 때문에 관련 라이브러리가 없으면 에러가 발생한다.