Click here to Skip to main content
15,881,248 members
Articles / Desktop Programming / MFC

FreeImage Display Demo

Rate me:
Please Sign up or sign in to vote.
3.98/5 (20 votes)
4 Jun 2008Public Domain17 min read 97.1K   10.4K   54  
How to display a bitmap in your MFC SDI application using FreeImage. Various rescaling algorithms considered.
//	FreeImage Display Demo v3.3

//	Copyright (C) 2008 monday2000@yandex.ru
//
//	This program is free software; you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation; either version 2 of the License, or
//	(at your option) any later version.
//
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with this program; if not, write to the Free Software
//	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//	http://www.gnu.org/copyleft/gpl.html

// fi_testView.cpp : implementation of the CFi_testView class
//

#include "stdafx.h"
#include "fi_test.h"

#include "fi_testDoc.h"
#include "fi_testView.h"

#include "MainFrm.h" // <- added for void OnInitialUpdate()

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CFi_testView

IMPLEMENT_DYNCREATE(CFi_testView, CScrollView)

BEGIN_MESSAGE_MAP(CFi_testView, CScrollView)
//{{AFX_MSG_MAP(CFi_testView)
	ON_WM_ERASEBKGND()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_MOUSEWHEEL()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFi_testView construction/destruction

CFi_testView::CFi_testView()
{
	// TODO: add construction code here	
}

CFi_testView::~CFi_testView()
{
}

BOOL CFi_testView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs
/*
// MSDN article Q131991 HOWTO: Change the Mouse Pointer for a Window in MFC
// Used here to change the view's background color

// Unfortunately this works only under Windows 98 - and does not
// work under WinXP (???)
// Instead modifying the background-erase color is chosen

CBrush BackgroundBrush(RGB(160, 160, 160));

cs.lpszClass = AfxRegisterWndClass(
            CS_DBLCLKS | CS_BYTEALIGNWINDOW | CS_BYTEALIGNCLIENT, // | CS_HREDRAW | CS_VREDRAW, // use any window styles
            AfxGetApp()->LoadStandardCursor(IDC_ARROW),
            (HBRUSH) BackgroundBrush);       // background brush

*/
	return CScrollView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CFi_testView drawing

void CFi_testView::OnDraw(CDC* pDC)
{
	CFi_testDoc* pDoc = GetDocument();

	ASSERT_VALID(pDoc);

	// TODO: add draw code for native data here

if ((HBITMAP)pDoc->m_OffscreenBitmap)
{

  CRect rcClip;

  pDC->GetClipBox(rcClip);

  pDC->BitBlt(rcClip.left, rcClip.top, rcClip.Width(), rcClip.Height(),
			&pDoc->m_dcOffscreen, rcClip.left, rcClip.top, SRCCOPY);

}

}

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

void CFi_testView::OnInitialUpdate()
{
	CScrollView::OnInitialUpdate();
	
    // TODO: calculate the total size of this view

	SetScrollSizes(MM_TEXT, CSize(0, 0));

	CMainFrame* pFr = (CMainFrame*)(AfxGetApp()->m_pMainWnd);
	
	ASSERT_VALID(pFr);

	CMenu* pMenu = pFr->GetMenu();

	CMenu* pSubMenu1 = pMenu->GetSubMenu(1);

	pSubMenu1->EnableMenuItem(5, MF_BYPOSITION | MF_GRAYED);

	CMenu* pSubMenu2 = pSubMenu1->GetSubMenu(5);

	pSubMenu2->CheckMenuItem(0, MF_BYPOSITION | MF_CHECKED);
}
//////////////////////////////////////////////////////////////////////
// CFi_testView diagnostics

#ifdef _DEBUG
void CFi_testView::AssertValid() const
{
	CScrollView::AssertValid();
}

void CFi_testView::Dump(CDumpContext& dc) const
{
	CScrollView::Dump(dc);
}

CFi_testDoc* CFi_testView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFi_testDoc)));
	return (CFi_testDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CFi_testView message handlers

BOOL CFi_testView::OnEraseBkgnd(CDC* pDC) 
{
	CFi_testDoc* pDoc = GetDocument();

	ASSERT_VALID(pDoc);

	// TODO: Add your message handler code here and/or call default
	
	if (pDoc->m_dib && pDoc->m_NoEraseFlag)
	{
		pDoc->m_NoEraseFlag = false;
/*
When a bitmap is loaded - DO NOT erase the background of 
the clipping region (prior to OnDraw) WHILE the bitmap is 
SCROLLED (!). This is VERY IMPORTANT - because this technique
eliminates the unwanted annoying flickering - within the current 
clipping region - due to an optical illusion.
*/
		return true; // <- set this "true" to 
//"CScrollView::OnEraseBkgnd(pDC)" and recompile - if you want
// to see the "clipping-region-flickering"

	}

	else
	{
	// MSDN: Visual C++/MFC Frequently Asked Questions
	// Version 5.0, updated 5/15/97
	// "How do I change the background color of a view?"
	//
    // Set brush to desired background color.
    CBrush BackgroundBrush(RGB(160, 160, 160));
    // Save old brush.
    CBrush* pOldBrush = pDC->SelectObject(&BackgroundBrush);
    CRect rcClient;
    pDC->GetClipBox(&rcClient);     // Erase the area needed.
    pDC->PatBlt(rcClient.left, rcClient.top, rcClient.Width(), 
    rcClient.Height(), PATCOPY);
    pDC->SelectObject(pOldBrush);

    return TRUE;

	//return CScrollView::OnEraseBkgnd(pDC);

	}
}

//////////////////////////////////////////////////////////////////////
// User added message handler

void CFi_testView::SetNewScrollSizes()
{
	CFi_testDoc* pDoc = GetDocument();

	ASSERT_VALID(pDoc);

	// TODO: calculate the total size of this view

	CSize sizeTotal;

	sizeTotal.cx = pDoc->m_zdib_width - 1; // minus 1 - so that 
	// the background 1-pixel-wide line would not be visible 
	// at the bitmap right side by the max scroll-right
		
    sizeTotal.cy = pDoc->m_zdib_height - 1; // same for height

	SetScrollSizes(MM_TEXT, sizeTotal);
}

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

void CFi_testView::ResetScrollSizes()
{

	CSize sizeTotal;
	// TODO: calculate the total size of this view

	sizeTotal.cx = 0;
		
    sizeTotal.cy = 0;

	SetScrollSizes(MM_TEXT, sizeTotal);    
}

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

BOOL CFi_testView::OnScrollBy(CSize sizeScroll, BOOL bDoScroll) 
{
	// TODO: Add your specialized code here and/or call the base class

	CFi_testDoc* pDoc = GetDocument();

	ASSERT_VALID(pDoc);

	// check whether the scrolling really occurred
		
	BOOL res = CScrollView::OnScrollBy(sizeScroll, bDoScroll);

    if (res) pDoc->m_NoEraseFlag = true;	

	return res;
}

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

void CFi_testView::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default

	CFi_testDoc* pDoc = GetDocument();

	ASSERT_VALID(pDoc);

	if (!pDoc->m_dib) pDoc->OnFileOpen();
	
	CScrollView::OnLButtonDblClk(nFlags, point);
}

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

BOOL CFi_testView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
{
	// TODO: Add your message handler code here and/or call default

CFi_testDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if (pDoc->m_dib)
{
	double zoom = pDoc->m_zoom;

	if (zDelta > 0) // MouseWheel Up

		zoom *= 1.1; // Zoom Out (Smaller)

	else // MouseWheel Down
	
		zoom /= 1.1; // Zoom In (Bigger)

	if (zoom < 0.05 * pDoc->m_zoom_fit || 
		zoom > 50 * pDoc->m_zoom_fit)
		
		return true;

	pDoc->m_dcOffscreen.SelectObject(pDoc->m_pOldBitmap);
	
	pDoc->m_OffscreenBitmap.DeleteObject();

	pDoc->m_pOldBitmap = NULL;

	
	pDoc->m_NoEraseFlag = true;


	double temp = zoom - pDoc->m_zoom_fit;

	if (temp < 0) temp*= -1; // not using fabs() - for speed
	
	// it the current zoom value is "zoom-fit" - assign the stored
    // zoom-fit value to it - to correct the accumulated rounding error
	if (temp < 0.05) zoom = pDoc->m_zoom_fit;


	pDoc->DisplayBitmap(zoom);
}
	return true;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication


Written By
Russian Federation Russian Federation
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions