Windows/DLL,MFC

[MFC] Bitmap 이미지 출력하기

별빛의온기 2022. 11. 5. 01:56
반응형

MFC를 하다보면 Bitmap Image를 직접 출력하고 싶을 때가 있습니다.  

 

아래는 이미지를 출력 하기 위한 방법 및 소스입니다. 확대(Zoom in)와 축소(Zoom out)의 기능도 추가하였으니 참고바랍니다! 

 

1. Picture Control을 선택하여 다이얼로그에 그려줍니다.

 

 

2. 그려놓은 Picture Control의 ID값을 기억해 놓습니다. 예제에서는 IDC_BITMAP_CTRL로 정하였습니다.

 

 

 

ID가 IDC_BITMAP_CTRL

 

3. 프로젝트에 아래 소스 및 헤더를 추가합니다. (BitmapCtrl.cpp, BitmapCtrl.h)

 

 

//BitmapCtrl.cpp

#include "stdafx.h"
#include "BitmapCtrl.h"

float Magnification[] = { 0.5, 0.8, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0 };

CBitmapCtrl::~CBitmapCtrl()
{
	if(memDC.GetSafeHdc() != NULL)
	{
		memDC.SelectObject(pOldBitmap);
		if(pBitmap != NULL)
			delete pBitmap;
	}
}

BEGIN_MESSAGE_MAP(CBitmapCtrl, CWnd)
	//{{AFX_MSG_MAP(CBitmapCtrl)
	ON_WM_PAINT()
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

BOOL CBitmapCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd) 
{
	scrollbar_width = GetSystemMetrics(SM_CXVSCROLL);
	
	// create window
	BOOL ret;
	static CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,AfxGetApp()->LoadStandardCursor(IDC_ARROW));
	ret = CWnd::CreateEx(WS_EX_CLIENTEDGE,className,NULL,dwStyle, 
		rect.left,rect.top,rect.right - rect.left,rect.bottom - rect.top,
		pParentWnd->GetSafeHwnd(),0);
	// init virtual screen
	GetClientRect(rcClient);
	CClientDC dc(this);
	if(memDC.GetSafeHdc() == NULL)
	{
		memDC.CreateCompatibleDC(&dc);
		memZoomDC.CreateCompatibleDC(&memDC);
		if((pBitmap = new CBitmap()) == NULL) return FALSE;
		pBitmap->CreateCompatibleBitmap(&dc,rcClient.Width(),rcClient.Height());
		pOldBitmap = memDC.SelectObject(pBitmap);
		memDC.SelectStockObject(ANSI_VAR_FONT);
		memDC.SetBkMode(TRANSPARENT);
	}
	x_offset = 0;
	y_offset = 0;
	memDC.FillSolidRect(&rcClient,RGB(128,128,128));

	MagnificationIdx = 2;
	nZoomMagnification = Magnification[MagnificationIdx];

	return ret;
}

void CBitmapCtrl::OnPaint() 
{
	CPaintDC dc(this);
	if(memDC.GetSafeHdc() != NULL)
		dc.BitBlt(0,0,rcClient.Width(),rcClient.Height(),&memDC,0,0,SRCCOPY);
}

void CBitmapCtrl::SetNewBitmap(HBITMAP hBmp)
{
	MagnificationIdx = 2;
	nZoomMagnification = Magnification[MagnificationIdx];

	SetBitmap(hBmp);
}

void CBitmapCtrl::SetBitmap(HBITMAP hBmp)
{
	
	//reset offsets
	x_offset = 0;
	y_offset = 0;

	//reset scrollbar
	SCROLLINFO si;
	si.fMask = SIF_PAGE | SIF_RANGE;
	si.nMin = 0;
	si.nMax = 0;
	si.nPage = 0;
	SetScrollInfo(SB_HORZ, &si, TRUE);
	SetScrollInfo(SB_VERT, &si, TRUE);
	
	//redraw background
	GetClientRect(&rcClient);
	memDC.FillSolidRect(&rcClient,RGB(128,128,128));
		
	//get bitmap handle
	hBitmap = hBmp;

	if (hBitmap == 0)
	{
		memDC.TextOut(0,0,_T("File not found."));
		Invalidate();
		return;
	}
	
	//get image size
	CPoint point(x_offset,y_offset);
	BITMAP bmpInfo;
	CBitmap::FromHandle(hBitmap)->GetBitmap(&bmpInfo);
	image_size.cx = bmpInfo.bmWidth;
	image_size.cy = bmpInfo.bmHeight;
	
	//check image size
	BOOL x_fit;
	BOOL y_fit;
	int test = rcClient.Width();
	x_fit = (bmpInfo.bmWidth <= rcClient.Width());
	if (!x_fit)
		rcClient.bottom -= scrollbar_width;
	y_fit = (bmpInfo.bmHeight <= rcClient.Height());
	if (!y_fit)
	{
		rcClient.right -= scrollbar_width;
		x_fit = (bmpInfo.bmWidth <= rcClient.Width());
	}
	if (!x_fit)
	{
		// show scrollbar
		ShowScrollBar(SB_HORZ);
	/*CRect scroll_rect;
	GetScrollBarCtrl(SB_HORZ)->GetWindowRect(&scroll_rect);
	char sz[256];
	sprintf(sz,"%d",scroll_rect.left - scroll_rect.right);
	MessageBox(sz);*/
		// update scrollbar
		SCROLLINFO si;
		si.fMask = SIF_PAGE | SIF_RANGE;
		si.nMin = 0;
		si.nMax = (bmpInfo.bmWidth-1)* (float)nZoomMagnification;
		si.nPage = rcClient.Width();
		SetScrollInfo(SB_HORZ, &si, TRUE);
	}
	if (!y_fit)
	{
		// show scrollbar
		ShowScrollBar(SB_VERT);
		// update scrollbar
		SCROLLINFO si;
		si.fMask = SIF_PAGE | SIF_RANGE;
		si.nMin = 0;
		si.nMax = (bmpInfo.bmHeight-1)* (float)nZoomMagnification;
		si.nPage = rcClient.Height();
		SetScrollInfo(SB_VERT, &si, TRUE);
	}
	
	DrawBitmap();
}

void CBitmapCtrl::DrawBitmap()
{
	CBitmap  bitmap;
	bitmap.m_hObject=hBitmap;

	CPoint point(-x_offset,-y_offset);

	memZoomDC.SelectObject(&bitmap);
	memDC.StretchBlt(-x_offset,-y_offset,image_size.cx * (float)nZoomMagnification,  image_size.cy* (float)nZoomMagnification, &memZoomDC, 0, 0, image_size.cx , image_size.cy, SRCCOPY);

	Invalidate();
}

void CBitmapCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	int nSmall = 1;
	int nLarge = 20;

	if(pScrollBar == GetScrollBarCtrl(SB_HORZ))
	{
		if(nSBCode == SB_LEFT || nSBCode == SB_LINELEFT)
			x_offset -= nSmall;
		if(nSBCode == SB_PAGELEFT)
			x_offset -= nLarge;
		if(nSBCode == SB_RIGHT || nSBCode == SB_LINERIGHT)
			x_offset += nSmall;
		if(nSBCode == SB_PAGERIGHT)
			x_offset += nLarge;
		if(nSBCode == SB_THUMBPOSITION)
			x_offset = (int)nPos;
		if(nSBCode == SB_THUMBTRACK)
			x_offset = (int)nPos;
		if (x_offset<0)
			x_offset = 0;
		if (x_offset>image_size.cx * (float)nZoomMagnification - rcClient.Width())
			x_offset = image_size.cx - rcClient.Width();
		SetScrollPos(SB_HORZ, x_offset, TRUE);
		DrawBitmap();
	}
}

void CBitmapCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	int nSmall = 1;
	int nLarge = 20;

	if(pScrollBar == GetScrollBarCtrl(SB_VERT))
	{
		if(nSBCode == SB_TOP || nSBCode == SB_LINEUP)
			y_offset -= nSmall;
		if(nSBCode == SB_PAGEUP)
			y_offset -= nLarge;
		if(nSBCode == SB_BOTTOM || nSBCode == SB_LINEDOWN)
			y_offset += nSmall;
		if(nSBCode == SB_PAGEDOWN)
			y_offset += nLarge;
		if(nSBCode == SB_THUMBPOSITION)
			y_offset = (int)nPos;
		if(nSBCode == SB_THUMBTRACK)
			y_offset = (int)nPos;
		if (y_offset<0)
			y_offset = 0;
		if (y_offset>image_size.cy * (float)nZoomMagnification - rcClient.Height())
			y_offset = image_size.cy - rcClient.Height();
		SetScrollPos(SB_VERT, y_offset, TRUE);
		DrawBitmap();
	}
}

void CBitmapCtrl::LoadFile(CString filename)
{
	HBITMAP hBitmap = (HBITMAP) LoadImage(NULL, filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
	SetBitmap(hBitmap);
}

void CBitmapCtrl::ZoomInOut(int nInOut)
{
	
	switch ( nInOut )
	{
		case 0 : //in
			if (MagnificationIdx < (sizeof(Magnification)/sizeof(float)) -1 )
				MagnificationIdx++;
			break;
		case 1 : //out
			if (0 < MagnificationIdx  )
				MagnificationIdx--;
			break;
	}

	nZoomMagnification = Magnification[MagnificationIdx];

	SetBitmap(hBitmap);
}

 

 

// BitmapCtrl.h : header file
//

#pragma once
/////////////////////////////////////////////////////////////////////////////
// CBitmapCtrl window
#include "afxwin.h"

class CBitmapCtrl : public CWnd
{
public:
	void SetNewBitmap(HBITMAP hBmp);
	void SetBitmap(HBITMAP hBmp);
	void DrawBitmap();
	void ZoomInOut(int nInOut);
	
	CRect rcClient;
	int scrollbar_width;
	int x_offset;
	int y_offset;
	CSize image_size;
	HBITMAP hBitmap;
	float nZoomMagnification;
	int MagnificationIdx;
private:
	

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CBitmapCtrl)
	public:
	virtual BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd);
	//}}AFX_VIRTUAL

// Implementation
public:
	void LoadFile(CString filename);
	virtual ~CBitmapCtrl();

	// Generated message map functions
protected:
	//{{AFX_MSG(CBitmapCtrl)
	afx_msg void OnPaint();
	afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
	afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()

	CDC memDC;
	CDC memZoomDC;
	CBitmap* pBitmap;
	CBitmap* pOldBitmap;
};

/////////////////////////////////////////////////////////////////////////////

 

4. 이제 다이얼로그 소스에 아래 구문을 추가합니다.

 

 

//다이얼로그.cpp

BOOL Dlg::OnInitDialog()
{

....생략

	//create bitmap control
	CRect brect;
	GetDlgItem(IDC_BITMAP_CTRL)->GetWindowRect(brect);
	ScreenToClient(brect);
	m_bmpCtrl.Create(WS_CHILD|WS_VISIBLE,brect,this);

}


void Dlg::BtnLoadImage()
{

    unsigned char pBmpImage[100000];
    
 ..생략  
 
    pBmpImage = //BmpImage를 로드하여 pBmpImage 버퍼에 저장.
    
	//View
	HBITMAP hbmp = Create_DiBitmapWithBitmapData(pBmpImage);  
	m_bmpCtrl.SetNewBitmap(hbmp);
    
}

 

5. 이후 실행하면 이미지를 보여줍니다.

 

 

이미지 출력 완료

 

 

참 쉽죠? 잘 활용하시길 바랍니다. :) 

 

 

반응형