Click here to Skip to main content
15,879,535 members
Articles / Desktop Programming / MFC

QuickFill: An Efficient Flood Fill Algorithm

Rate me:
Please Sign up or sign in to vote.
4.84/5 (71 votes)
12 Mar 200413 min read 525.8K   12K   103  
Design and implementation of efficient flood fill algorithms.
// QuickFillDemoView.cpp : implementation of the CQuickFillDemoView class
//

#include "stdafx.h"
#include "QuickFillDemo.h"
#include "MainFrm.h"

#include "QuickFillDemoDoc.h"
#include "QuickFillDemoView.h"
#include "DlgMasks.h"

#pragma warning( disable : 4201 )
#include <Mmsystem.h>
#pragma warning( default : 4201 )

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

static const LG_MAXMAG = 10;
static const LG_SELPENWIDTH = 3;

/////////////////////////////////////////////////////////////////////////////
// CQuickFillDemoView

IMPLEMENT_DYNCREATE(CQuickFillDemoView, CScrollView)

BEGIN_MESSAGE_MAP(CQuickFillDemoView, CScrollView)
	//{{AFX_MSG_MAP(CQuickFillDemoView)
	ON_WM_ERASEBKGND()
	ON_WM_LBUTTONDOWN()
	ON_COMMAND(ID_OPENPATTERN, OnOpenpattern)
	ON_UPDATE_COMMAND_UI(ID_OPENPATTERN, OnUpdateOpenpattern)
	ON_COMMAND(ID_SLOWMODE, OnSlowmode)
	ON_UPDATE_COMMAND_UI(ID_SLOWMODE, OnUpdateSlowmode)
	ON_COMMAND(ID_FILLCOLOR, OnFillcolor)
	ON_UPDATE_COMMAND_UI(ID_FILLCOLOR, OnUpdateFillcolor)
	ON_COMMAND(ID_PATTERNCLEARCOLOR, OnPatternclearcolor)
	ON_UPDATE_COMMAND_UI(ID_PATTERNCLEARCOLOR, OnUpdatePatternclearcolor)
	ON_COMMAND(ID_CLOSEPATTERN, OnClosepattern)
	ON_UPDATE_COMMAND_UI(ID_CLOSEPATTERN, OnUpdateClosepattern)
	ON_COMMAND(ID_VIEW_MAG1, OnViewMag1)
	ON_UPDATE_COMMAND_UI(ID_VIEW_MAG1, OnUpdateViewMag1)
	ON_COMMAND(ID_VIEW_MAG2, OnViewMag2)
	ON_UPDATE_COMMAND_UI(ID_VIEW_MAG2, OnUpdateViewMag2)
	ON_COMMAND(ID_VIEW_MAG3, OnViewMag3)
	ON_UPDATE_COMMAND_UI(ID_VIEW_MAG3, OnUpdateViewMag3)
	ON_COMMAND(ID_VIEW_MAG4, OnViewMag4)
	ON_UPDATE_COMMAND_UI(ID_VIEW_MAG4, OnUpdateViewMag4)
	ON_COMMAND(ID_VIEW_MAG5, OnViewMag5)
	ON_UPDATE_COMMAND_UI(ID_VIEW_MAG5, OnUpdateViewMag5)
	ON_COMMAND(ID_VIEW_MAG6, OnViewMag6)
	ON_UPDATE_COMMAND_UI(ID_VIEW_MAG6, OnUpdateViewMag6)
	ON_COMMAND(ID_VIEW_MAG7, OnViewMag7)
	ON_UPDATE_COMMAND_UI(ID_VIEW_MAG7, OnUpdateViewMag7)
	ON_COMMAND(ID_VIEW_MAG8, OnViewMag8)
	ON_UPDATE_COMMAND_UI(ID_VIEW_MAG8, OnUpdateViewMag8)
	ON_COMMAND(ID_VIEW_MAG9, OnViewMag9)
	ON_UPDATE_COMMAND_UI(ID_VIEW_MAG9, OnUpdateViewMag9)
	ON_COMMAND(ID_VIEW_MAG10, OnViewMag10)
	ON_UPDATE_COMMAND_UI(ID_VIEW_MAG10, OnUpdateViewMag10)
	ON_COMMAND(ID_FILLMASK, OnFillmask)
	ON_UPDATE_COMMAND_UI(ID_FILLMASK, OnUpdateFillmask)
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONUP()
	ON_COMMAND(ID_SHOWREVISIT, OnShowrevisit)
	ON_UPDATE_COMMAND_UI(ID_SHOWREVISIT, OnUpdateShowrevisit)
	//}}AFX_MSG_MAP
	ON_UPDATE_COMMAND_UI(ID_INDICATOR_POS, OnUpdatePos)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CQuickFillDemoView construction/destruction

CQuickFillDemoView::CQuickFillDemoView() :
	m_rcPos(4,4,4,4), m_nMag(2)
{
	m_clrFill = RGB(255,0,0);
	m_dSeconds = 0.0;		// Fill time in miliseconds.
	memset(&m_AnchorPoint,0,sizeof(m_AnchorPoint));
	memset(&m_rcSelect,0,sizeof(m_rcSelect));
	m_bSelected = m_bSelecting = FALSE;
}

CQuickFillDemoView::~CQuickFillDemoView()
{
}

BOOL CQuickFillDemoView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CScrollView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CQuickFillDemoView drawing

void CQuickFillDemoView::DrawSelectRect(CDC* pDC)
{
	// Draw selection rectangle
	if( pDC && m_bSelected )
	{
		CPen whitePen(PS_SOLID, LG_SELPENWIDTH, RGB(128, 128, 128));
		CPen* pOldPen = pDC->SelectObject(&whitePen);
		CGdiObject* pOldBrush = pDC->SelectStockObject(NULL_BRUSH);
		int nOldMode = pDC->SetROP2(R2_XORPEN);

		m_rcSelect.InflateRect(0,0,LG_SELPENWIDTH,LG_SELPENWIDTH);
		pDC->Rectangle(&m_rcSelect);
		m_rcSelect.InflateRect(0,0,-LG_SELPENWIDTH,-LG_SELPENWIDTH);
		
		pDC->SetROP2(nOldMode);
		pDC->SelectObject(pOldBrush);
		pDC->SelectObject(pOldPen);
	}
}

void CQuickFillDemoView::OnDraw(CDC* pDC)
{
	CQuickFillDemoDoc* pDoc = GetDocument();

	// TODO: add draw code for native data here
	BITMAP bm;
	CDC dcTemp;
	
	if( pDoc
		&& pDoc->m_Bitmap.GetSafeHandle() // avoid assertion
		&& pDoc->m_Bitmap.GetBitmap(&bm)
		&& dcTemp.CreateCompatibleDC(pDC) )
	{
		CBitmap* pOldBitmap = dcTemp.SelectObject(&pDoc->m_Bitmap);
		if( pOldBitmap )
		{
			CDC dcGrid;
			CBitmap bmpGrid, *pOldBmpGrid = NULL;
			if( m_nMag < 4
				|| !dcGrid.CreateCompatibleDC(&dcTemp)
				|| !bmpGrid.CreateCompatibleBitmap(
						&dcTemp, m_rcPos.Width(), m_rcPos.Height())
				// ignore warning C4706 here
				|| !(pOldBmpGrid=dcGrid.SelectObject(&bmpGrid)) )
			{
				pDC->StretchBlt(
					m_rcPos.left, m_rcPos.top,
					m_rcPos.Width(), m_rcPos.Height(),
					&dcTemp, 0, 0, bm.bmWidth, bm.bmHeight,
					SRCCOPY);
				dcTemp.SelectObject(pOldBitmap);
				DrawSelectRect(pDC);
			}
			else
			{
				// Copy to grid DC
				dcGrid.StretchBlt(
					0, 0, m_rcPos.Width(), m_rcPos.Height(),
					&dcTemp, 0, 0, bm.bmWidth, bm.bmHeight,
					SRCCOPY);
				dcTemp.SelectObject(pOldBitmap);

				// Draw grid lines
				CPen sepPen(PS_SOLID, 1, RGB(0x80, 0x80, 0x80));
				CPen* pOldPen = dcGrid.SelectObject(&sepPen);
				int bottom = m_rcPos.Height() - 1;
				int right = m_rcPos.Width() - 1;
				for( int x = 0; x <= right; x += m_nMag )

				{
					dcGrid.MoveTo(x, 0);
					dcGrid.LineTo(x, bottom);
				}
				for( int y = 0; y <= bottom; y += m_nMag )
				{
					dcGrid.MoveTo(0, y);
					dcGrid.LineTo(right, y);
				}

				dcGrid.SelectObject(pOldPen);

				DrawSelectRect(&dcGrid);

				// Copy grid to client DC
				pDC->BitBlt(
					m_rcPos.left, m_rcPos.top,
					m_rcPos.Width(), m_rcPos.Height(),
					&dcGrid, 0, 0, SRCCOPY);

				dcGrid.SelectObject(pOldBmpGrid);
			}

			// Exclude bitmap area from furthur drawing
			pDC->ExcludeClipRect(&m_rcPos);
		}
	}

#ifdef QUICKFILL_TEST
	// Show progress info
	int x = m_rcPos.right + 8, y = m_rcPos.top;
	//x += GetScrollPos(SB_HORZ);
	//y += GetScrollPos(SB_VERT);
	CString csInfo;
	CSize size;
	pDC->SetBkColor(::GetSysColor(COLOR_WINDOW));
	csInfo.Format(_T("Seconds: %lf"),m_dSeconds);
	size = pDC->TabbedTextOut(x, y, csInfo, 0, NULL, 0);
	pDC->ExcludeClipRect(x, y, x + size.cx, y + size.cy);
	y += 20;
	csInfo.Format(_T("Current Stack Size: %d"),m_Fill.GetStackSize());
	size = pDC->TabbedTextOut(x, y, csInfo, 0, NULL, 0);
	pDC->ExcludeClipRect(x, y, x + size.cx, y + size.cy);
	y += 20;
	csInfo.Format(_T("Maximum Stack Size: %d"),m_Fill.GetMaxStackSize());
	size = pDC->TabbedTextOut(x, y, csInfo, 0, NULL, 0);
	pDC->ExcludeClipRect(x, y, x + size.cx, y + size.cy);
	y += 20;
	csInfo.Format(_T("Visit List Size: %d"),m_Fill.GetVisitSize());
	size = pDC->TabbedTextOut(x, y, csInfo, 0, NULL, 0);
	pDC->ExcludeClipRect(x, y, x + size.cx, y + size.cy);
	y += 20;
	csInfo.Format(_T("Current Line: %d"),m_Fill.GetCurrentLine());
	size = pDC->TabbedTextOut(x, y, csInfo, 0, NULL, 0);
	pDC->ExcludeClipRect(x, y, x + size.cx, y + size.cy);
	y += 20;
	csInfo.Format(_T("Pixels Revisited: %d"),m_Fill.GetRevisitCount());
	size = pDC->TabbedTextOut(x, y, csInfo, 0, NULL, 0);
	pDC->ExcludeClipRect(x, y, x + size.cx, y + size.cy);
	y += 20;
	if( m_Fill.GetDirection() < 0 )
	{
		csInfo = _T("Direction: Up");
		size = pDC->TabbedTextOut(x, y, csInfo, 0, NULL, 0);
		pDC->ExcludeClipRect(x, y, x + size.cx, y + size.cy);
		y += 20;
	}
	else if( m_Fill.GetDirection() > 0 )
	{
		csInfo = _T("Direction: Down");
		size = pDC->TabbedTextOut(x, y, csInfo, 0, NULL, 0);
		pDC->ExcludeClipRect(x, y, x + size.cx, y + size.cy);
		y += 20;
	}
#endif


	// Draw background
	CRect rcClient;
	pDC->GetClipBox(&rcClient);
	pDC->FillSolidRect(
		rcClient.left,rcClient.top,
		rcClient.Width(),rcClient.Height(),
		::GetSysColor(COLOR_WINDOW));
}

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

	CSize sizeTotal;
	CQuickFillDemoDoc* pDoc = GetDocument();
	
	if( m_nMag < 1 ) // simple safety
		m_nMag = 1;

	BITMAP bm;
	if(  pDoc
		&& pDoc->m_Bitmap.GetSafeHandle() // avoid assertion
		&& pDoc->m_Bitmap.GetBitmap(&bm) )
	{
		m_rcPos.SetRect(m_rcPos.left, m_rcPos.top,
			m_rcPos.left + m_nMag * bm.bmWidth,
			m_rcPos.top + m_nMag * bm.bmHeight);
	}
	sizeTotal.cx = m_rcPos.Width() + 2 * m_rcPos.left;
	sizeTotal.cy = m_rcPos.Height() + 2 * m_rcPos.top;
	SetScrollSizes(MM_TEXT, sizeTotal);
}

/////////////////////////////////////////////////////////////////////////////
// CQuickFillDemoView diagnostics

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

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

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

/////////////////////////////////////////////////////////////////////////////
//
void CQuickFillDemoView::Magnify(int nMag)
{
	if( 0 < nMag && nMag <= LG_MAXMAG )
	{
		CSize sizeTotal;
		CQuickFillDemoDoc* pDoc = GetDocument();

		BITMAP bm;
		if(  pDoc
			&& pDoc->m_Bitmap.GetSafeHandle() // avoid assertion
			&& pDoc->m_Bitmap.GetBitmap(&bm) )
		{
			m_rcPos.SetRect(m_rcPos.left, m_rcPos.top,
				m_rcPos.left + nMag * bm.bmWidth,
				m_rcPos.top + nMag * bm.bmHeight);
			if( m_bSelected )
				m_bSelected = FALSE;
		}
		sizeTotal.cx = m_rcPos.Width()  + 2 * m_rcPos.left;
		sizeTotal.cy = m_rcPos.Height() + 2 * m_rcPos.top;
		SetScrollSizes(MM_TEXT, sizeTotal);

		m_nMag = nMag;
		Invalidate();
	}
}

/////////////////////////////////////////////////////////////////////////////
// CQuickFillDemoView message handlers

BOOL CQuickFillDemoView::OnEraseBkgnd(CDC* /*pDC*/) 
{
	// TODO: Add your message handler code here and/or call default
	
	//return CScrollView::OnEraseBkgnd(pDC);
	return TRUE;
}

void CQuickFillDemoView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	CPoint pt = point;
	pt.x += GetScrollPos(SB_HORZ);
	pt.y += GetScrollPos(SB_VERT);
	if( !m_bSelected )
	{
		m_AnchorPoint = pt;
		m_bSelecting  = FALSE;
	}
	else
	{
		m_rcSelect.InflateRect(0,0,LG_SELPENWIDTH,LG_SELPENWIDTH);
		if( m_rcSelect.PtInRect(pt) )
			m_rcSelect.InflateRect(0,0,-LG_SELPENWIDTH,-LG_SELPENWIDTH);
		else
		{
			m_rcSelect.InflateRect(0,0,-LG_SELPENWIDTH,-LG_SELPENWIDTH);
			m_AnchorPoint = pt;
			m_bSelecting  = FALSE;
			m_bSelected   = FALSE;
			::ReleaseCapture();
			InvalidateRect(&m_rcPos);
			UpdateWindow();
		}
	}
	CScrollView::OnLButtonDown(nFlags, point);
}

void CQuickFillDemoView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	if( m_bSelecting )
	{
		m_bSelecting = FALSE;
		::ReleaseCapture();
		CScrollView::OnLButtonUp(nFlags, point);
		return;
	}

	CQuickFillDemoDoc* pDoc = GetDocument();

	// Get adjusted rectangle - compensates for scrolled DC
	CRect rc = m_rcPos;
	if( m_bSelected )
	{
		rc = m_rcSelect;
		rc.InflateRect(0,0,LG_SELPENWIDTH,LG_SELPENWIDTH);
	}
	rc.OffsetRect(-GetScrollPos(SB_HORZ), -GetScrollPos(SB_VERT));
	if( pDoc
		&& pDoc->m_Bitmap.GetSafeHandle()
		&& pDoc->m_BitmapBackup.GetSafeHandle()
		&& rc.PtInRect(point) )
	{
		rc = m_rcPos;
		rc.OffsetRect(-GetScrollPos(SB_HORZ), -GetScrollPos(SB_VERT));

		// restore backup
		CDC dc1, dc2;
		BITMAP bm;
		pDoc->m_Bitmap.GetBitmap(&bm);
		dc1.CreateCompatibleDC(NULL);
		CBitmap* old1 = dc1.SelectObject(&pDoc->m_Bitmap);
		dc2.CreateCompatibleDC(&dc1);
		CBitmap* old2 = dc2.SelectObject(&pDoc->m_BitmapBackup);
		dc1.BitBlt(0,0,bm.bmWidth,bm.bmHeight,&dc2,0,0,SRCCOPY);
		dc1.SelectObject(old1);
		dc2.SelectObject(old2);
		dc1.DeleteDC();
		dc2.DeleteDC();
		InvalidateRect(&m_rcPos);

		if( m_nMag < 1 ) // simple safety
			m_nMag = 1;

		// Start timing
		TIMECAPS timeCaps = { 0U, 0U };
		timeGetDevCaps(&timeCaps,sizeof(timeCaps));
		timeBeginPeriod(timeCaps.wPeriodMin);
		DWORD dwTime = timeGetTime();
		
		// Quick fill image
		if( m_bSelected )
		{
			CRect rcSelect = m_rcSelect;
			rcSelect.OffsetRect(-rc.left,-rc.top);
			rcSelect.OffsetRect(-GetScrollPos(SB_HORZ), -GetScrollPos(SB_VERT));
			rcSelect.InflateRect(-m_nMag,-m_nMag,0,0);
			rcSelect.left   /= m_nMag;
			rcSelect.top    /= m_nMag;
			rcSelect.right  /= m_nMag;
			rcSelect.bottom /= m_nMag;
			m_Fill.QuickFill(
				&pDoc->m_Bitmap, &rcSelect,
				(point.x - rc.left)/m_nMag,
				(point.y - rc.top )/m_nMag,
				m_clrFill);
		}
		else
		{
			m_Fill.QuickFill(
				&pDoc->m_Bitmap,
				(point.x - rc.left)/m_nMag,
				(point.y - rc.top )/m_nMag,
				m_clrFill);
		}

		// Stop timing
		m_dSeconds = timeGetTime() - dwTime;
		if( timeCaps.wPeriodMin )
			m_dSeconds /= (1000/timeCaps.wPeriodMin);
		timeEndPeriod(1);

		// Show result
		Invalidate();
	}
	CScrollView::OnLButtonUp(nFlags, point);
}

void CQuickFillDemoView::OnMouseMove(UINT nFlags, CPoint point) 
{
	CStatusBar* pStat = NULL;
	CMainFrame* pFrame = DYNAMIC_DOWNCAST(CMainFrame,AfxGetApp()->m_pMainWnd);
	if( pFrame )
		pStat = pFrame->GetStatusBar();
	if( pStat )
	{
		if( GetDocument() && m_rcPos.PtInRect(point) )
		{
			// Update position pane on status bar
			CRect rc = m_rcPos;
			rc.OffsetRect(-GetScrollPos(SB_HORZ), -GetScrollPos(SB_VERT));
			CString strPos;
			strPos.Format( _T("%d, %d"),
				(point.x - rc.left)/m_nMag,
				(point.y - rc.top)/m_nMag );
			pStat->SetPaneText(pStat->CommandToIndex(ID_INDICATOR_POS),strPos);

			if( !(nFlags & MK_LBUTTON) )
			{
				m_bSelecting = FALSE;
			}
			else
			{
				// Update selection rectangle if mouse cursor has moved
				if( !m_bSelected )
				{
					rc.SetRect(m_AnchorPoint,m_AnchorPoint);
					rc.InflateRect(2,2);
					m_bSelecting = !rc.PtInRect(point);
				}
				else
				{
					InvalidateRect(&m_rcPos);
				}
			}
		}
		else
		{
			pStat->SetPaneText(pStat->CommandToIndex(ID_INDICATOR_POS),_T("0, 0"));
			if( m_bSelecting )
				m_bSelecting = m_bSelecting; // break here
		}

		if( nFlags & MK_LBUTTON )
		{
			if( m_bSelecting )
			{
				SetCapture();
				m_bSelected = TRUE;
				CPoint pt = point;
				pt.x += GetScrollPos(SB_HORZ);
				pt.y += GetScrollPos(SB_VERT);
				m_rcSelect.SetRect(m_AnchorPoint,pt);
				m_rcSelect.NormalizeRect();
				
				if( point.x < m_rcPos.left )
					m_rcSelect.left = m_rcPos.left;
				else if( point.x > m_rcPos.right )
					m_rcSelect.right = m_rcPos.right;
				if( point.y < m_rcPos.top )
					m_rcSelect.top = m_rcPos.top;
				else if( point.y > m_rcPos.bottom )
					m_rcSelect.bottom = m_rcPos.bottom;

				// Adjust selection rectangle based on magnification
				m_rcSelect.OffsetRect(-m_rcPos.left,-m_rcPos.top);
				m_rcSelect.left   = m_nMag * (m_rcSelect.left/m_nMag);
				m_rcSelect.top    = m_nMag * (m_rcSelect.top /m_nMag);
				m_rcSelect.right  = m_nMag * ((m_rcSelect.right +m_nMag-1)/m_nMag);
				m_rcSelect.bottom = m_nMag * ((m_rcSelect.bottom+m_nMag-1)/m_nMag);
				m_rcSelect.OffsetRect(m_rcPos.left,m_rcPos.top);
			}

			if( m_bSelected )
			{
				InvalidateRect(&m_rcPos);
				UpdateWindow();
			}
		}
	}
	CScrollView::OnMouseMove(nFlags, point);
}

void CQuickFillDemoView::OnOpenpattern() 
{
	CFileDialog dlgFile(TRUE,_T("bmp"),NULL,
		OFN_HIDEREADONLY | OFN_ENABLESIZING | OFN_FILEMUSTEXIST,
		_T("Bitmap Files (*.bmp)|*.bmp||"));
	if( IDOK == dlgFile.DoModal() )
		m_Fill.SetPatternBitmap(dlgFile.GetFileName());
}

void CQuickFillDemoView::OnUpdateOpenpattern(CCmdUI* pCmdUI) 
{
	CQuickFillDemoDoc* pDoc = GetDocument();
	pCmdUI->Enable( pDoc && pDoc->m_Bitmap.GetSafeHandle() );
}

void CQuickFillDemoView::OnSlowmode() 
{
#ifdef QUICKFILL_SLOW
	m_Fill.SetSlowMode(!m_Fill.IsSlowMode());
#endif
}

void CQuickFillDemoView::OnUpdateSlowmode(CCmdUI* pCmdUI) 
{
#ifdef QUICKFILL_SLOW
	pCmdUI->Enable();
	pCmdUI->SetCheck(m_Fill.IsSlowMode());
#else
	pCmdUI->Enable(FALSE);
#endif
}

void CQuickFillDemoView::OnFillcolor() 
{
	CColorDialog dlg(m_clrFill);
	if( IDOK == dlg.DoModal() )
		m_clrFill = dlg.GetColor();
}

void CQuickFillDemoView::OnUpdateFillcolor(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(!m_Fill.HasPattern());
}

void CQuickFillDemoView::OnPatternclearcolor() 
{
	CColorDialog dlg(m_Fill.GetPatternClearColor());
	if( IDOK == dlg.DoModal() )
		m_Fill.SetPatternClearColor(dlg.GetColor());
}

void CQuickFillDemoView::OnUpdatePatternclearcolor(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(m_Fill.HasPattern());
}

void CQuickFillDemoView::OnClosepattern() 
{
	// Frees pattern bitmap and invalidates pattern clear color.
	m_Fill.SetPatternBitmap();
}

void CQuickFillDemoView::OnUpdateClosepattern(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(m_Fill.HasPattern());
}

void CQuickFillDemoView::OnViewMag1() 
{
	Magnify(1);
}

void CQuickFillDemoView::OnUpdateViewMag1(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(1 <= LG_MAXMAG);
	pCmdUI->SetCheck(m_nMag==1);
}

void CQuickFillDemoView::OnViewMag2() 
{
	Magnify(2);
}

void CQuickFillDemoView::OnUpdateViewMag2(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(2 <= LG_MAXMAG);
	pCmdUI->SetCheck(m_nMag==2);
}

void CQuickFillDemoView::OnViewMag3() 
{
	Magnify(3);
}

void CQuickFillDemoView::OnUpdateViewMag3(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(3 <= LG_MAXMAG);
	pCmdUI->SetCheck(m_nMag==3);
}

void CQuickFillDemoView::OnViewMag4() 
{
	Magnify(4);
}

void CQuickFillDemoView::OnUpdateViewMag4(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(4 <= LG_MAXMAG);
	pCmdUI->SetCheck(m_nMag==4);
}

void CQuickFillDemoView::OnViewMag5() 
{
	Magnify(5);
}

void CQuickFillDemoView::OnUpdateViewMag5(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(5 <= LG_MAXMAG);
	pCmdUI->SetCheck(m_nMag==5);
}

void CQuickFillDemoView::OnViewMag6() 
{
	Magnify(6);
}

void CQuickFillDemoView::OnUpdateViewMag6(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(6 <= LG_MAXMAG);
	pCmdUI->SetCheck(m_nMag==6);
}

void CQuickFillDemoView::OnViewMag7() 
{
	Magnify(7);
}

void CQuickFillDemoView::OnUpdateViewMag7(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(7 <= LG_MAXMAG);
	pCmdUI->SetCheck(m_nMag==7);
}

void CQuickFillDemoView::OnViewMag8() 
{
	Magnify(8);
}

void CQuickFillDemoView::OnUpdateViewMag8(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(8 <= LG_MAXMAG);
	pCmdUI->SetCheck(m_nMag==8);
}

void CQuickFillDemoView::OnViewMag9() 
{
	Magnify(9);
}

void CQuickFillDemoView::OnUpdateViewMag9(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(9 <= LG_MAXMAG);
	pCmdUI->SetCheck(m_nMag==9);
}

void CQuickFillDemoView::OnViewMag10() 
{
	Magnify(10);
}

void CQuickFillDemoView::OnUpdateViewMag10(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(10 <= LG_MAXMAG);
	pCmdUI->SetCheck(m_nMag==10);
}

void CQuickFillDemoView::OnFillmask() 
{
	// TODO: Add your command handler code here
	CDlgMasks dlg;
	if( dlg.DoModal() == IDOK )
	{
		BYTE mask[8];
		if( dlg.GetMask(mask,sizeof(mask)) )
			m_Fill.SetFillMask(mask);
	}
}

void CQuickFillDemoView::OnUpdateFillmask(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable();
}

void CQuickFillDemoView::OnUpdatePos(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable();
}

void CQuickFillDemoView::OnShowrevisit() 
{
#ifdef QUICKFILL_TEST
	m_Fill.SetShowRevisit(!m_Fill.GetShowRevisitFlag());
#endif
}

void CQuickFillDemoView::OnUpdateShowrevisit(CCmdUI* pCmdUI) 
{
#ifdef QUICKFILL_TEST
	pCmdUI->Enable();
	pCmdUI->SetCheck(m_Fill.GetShowRevisitFlag()?1:0);
#endif
}

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.


Written By
Software Developer (Senior)
United States United States
I am a senior software engineer who has been designing and developing software for many years, mostly in C/C++. You might say that I think in code; which is why I am passionate about my first rule of coding: “First do no harm”. So if I get carried away in my explanations, please realize that it is just part of my personality. I enjoy learning new things and, when I have the time, passing that knowledge onto others.

Comments and Discussions