www.gusucode.com > 类似Windows拷贝文件一样的进度条VC实现-源码程序 > 类似Windows拷贝文件一样的进度条VC实现-源码程序/code/IconProgress.cpp

    // IconProgress.cpp : implementation file
// Download by http://www.NewXing.com

#include "stdafx.h"
#include "IconProgressApp.h"
#include "IconProgress.h"

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

// Constants
const int CIconProgress::HORIZONTAL = 0;
const int CIconProgress::VERTICAL   = 1;

// Message map
BEGIN_MESSAGE_MAP(CIconProgress, CWnd)
	//{{AFX_MSG_MAP(CIconProgress)
	ON_WM_PAINT()
	ON_WM_ERASEBKGND()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// Constructor

CIconProgress::CIconProgress()
{
	upper    = 100;
	lower    = 0;
	position = 0;
	step     = 10;
}

/////////////////////////////////////////////////////////////////////////////
// Destructor

CIconProgress::~CIconProgress()
{
	background_brush.DeleteObject();
}

/////////////////////////////////////////////////////////////////////////////
// SetInitial - default colour

void CIconProgress::Attach(UINT control_id, CWnd *parent, UINT icon_id, int increment, int stagger)
{
	Attach(control_id, parent, icon_id, increment, GetSysColor(COLOR_3DFACE), stagger);
}

/////////////////////////////////////////////////////////////////////////////
// SetInitial - specified colour

void CIconProgress::Attach(UINT control_id, CWnd *parent, UINT icon_id, int increment, COLORREF background, int stagger)
{
	SubclassDlgItem(control_id, parent);

	// Store the parameters.
	icon_increment    = increment;
	background_colour = background;
	stagger_distance  = stagger;

	// Create the background brush.
	background_brush.CreateSolidBrush(background_colour);

	// Get the icon handle.
	hicon = AfxGetApp()->LoadIcon(icon_id);

	// Find the client window size.
	GetClientRect(&window_rect);

	// Set the orientation and the major and minor axis.
	// Major is in the direction of progress.
	if (window_rect.right > window_rect.bottom)
	{
		orientation = HORIZONTAL;
	}
	else
	{
		orientation = VERTICAL;
	}
	
	switch (orientation)
	{
		case HORIZONTAL:
		{
			icon_major   = GetSystemMetrics(SM_CXICON);
			icon_minor   = GetSystemMetrics(SM_CYICON);
			window_minor = window_rect.bottom;
			window_major = window_rect.right;
			break;
		}
	
		case VERTICAL:
		{
			icon_minor   = GetSystemMetrics(SM_CXICON);
			icon_major   = GetSystemMetrics(SM_CYICON);
			window_major = window_rect.bottom;
			window_minor = window_rect.right;
			break;
		}
	}

	// Adjust for daft icon increment.
	if (icon_increment == 0)
	{
		icon_increment = 1;
	}

	// Find the number of icons that will fit in the window.
	total_number_of_icons = 1;
	while (((total_number_of_icons * icon_increment) + icon_major) < window_major)
	{
		total_number_of_icons++;
	}

	// Fill the icon array with the default icon
	hicon_array.SetSize(total_number_of_icons);
	for (int i = 0; i < total_number_of_icons; i++)
	{
		hicon_array[i] = hicon;
	}

	// Find the start points.
	switch (orientation)
	{
		case HORIZONTAL:
		{
			// Left.
			start_major = (window_major - (((total_number_of_icons - 1) * icon_increment) + icon_major)) / 2;
			break;
		}

		case VERTICAL:
		{
			// Bottom.
			start_major = ((window_major + (((total_number_of_icons - 1) * icon_increment) + icon_major)) / 2) - icon_major;
		}
	}

	start_minor = (window_minor - icon_minor - stagger_distance) / 2;
}

/////////////////////////////////////////////////////////////////////////////
// SetPos

int CIconProgress::SetPos(int new_position)
{
	int old_position;
		
	old_position    = position;
	position        = new_position;
	position        = min(upper, max(lower, position)); 
	number_of_icons = GetNumberOfIcons(position);
	
	Invalidate();

	return old_position;
}

/////////////////////////////////////////////////////////////////////////////
// OffsetPos

int CIconProgress::OffsetPos(int offset)
{
	int old_position;
	
	old_position    = position;
	position       += offset;
	position        = min(upper, max(lower, position)); 
	number_of_icons = GetNumberOfIcons(position);
	
	Invalidate();

	return old_position;
}

/////////////////////////////////////////////////////////////////////////////
// SetRange

void CIconProgress::SetRange(short lower_range, short upper_range)
{
	SetRange32(lower_range, upper_range);
}

/////////////////////////////////////////////////////////////////////////////
// SetRange32

void CIconProgress::SetRange32(int lower_range, int upper_range)
{
	lower           = lower_range;
	upper           = upper_range;
	position        = min(upper, max(lower, position)); 
	number_of_icons = GetNumberOfIcons(position);
	
	Invalidate();
}

/////////////////////////////////////////////////////////////////////////////
// SetIconChange

void  CIconProgress::SetIconChange(UINT icon_id, int position)
{
	HICON hicon = AfxGetApp()->LoadIcon(icon_id);

	// Where to start from
	int change_icon_index = GetNumberOfIcons(position);

	// Fill part of the array with the new icon
	for (int i = change_icon_index; i < total_number_of_icons; i++)
	{
		hicon_array[i] = hicon;
	}
}

/////////////////////////////////////////////////////////////////////////////
// SetStep

int CIconProgress::SetStep(int new_step)
{
	int old_step;
	
	old_step = step;
	step     = new_step;

	return old_step;
}

/////////////////////////////////////////////////////////////////////////////
// StepIt

int CIconProgress::StepIt()
{
	int old_position;
	
	old_position    = position;
	position       += step;
	position        = min(upper, max(lower, position)); 
	number_of_icons = GetNumberOfIcons(position);
	
	Invalidate();

	return old_position;
}

/////////////////////////////////////////////////////////////////////////////
// GetPos

int CIconProgress::GetPos()
{
	return position;
}

/////////////////////////////////////////////////////////////////////////////
// GetRange

void CIconProgress::GetRange(int &lower_range, int &upper_range)
{
	lower_range = lower;
	upper_range = upper;
}

/////////////////////////////////////////////////////////////////////////////
// GetNumberOfIcons

int CIconProgress::GetNumberOfIcons(int position)
{
	int   n_icons;
	float delta = (float)(position - lower);
	float range = (float)(upper - lower + 1);
	
	float range_per_icon = range / total_number_of_icons;

	// Just in case of rounding errors
	if (position == upper)
	{
		n_icons = total_number_of_icons;
	}
	else
	{
		n_icons = (int)(delta / range_per_icon);
	}

	return n_icons;
}

/////////////////////////////////////////////////////////////////////////////
// CIconProgress message handlers

void CIconProgress::OnPaint() 
{
	CPaintDC dc(this);
	CDC		 memdc;
	CBitmap	 bitmap;
	int		 x, y, count;
	BOOL	 do_stagger = FALSE;

	// Create a memory copy to draw to.
	memdc.CreateCompatibleDC(&dc);
	bitmap.CreateCompatibleBitmap(&dc, window_rect.right, window_rect.bottom);
	memdc.SelectObject(&bitmap);

	// Clear the background.
	memdc.FillRect(&window_rect, &background_brush);
	
	// Draw the icons.
	switch (orientation)
	{
		case HORIZONTAL:
		{
			for (x = start_major, count = 0; count < number_of_icons; x += icon_increment, count++)
			{
				if (do_stagger)
				{
					memdc.DrawIcon(x, start_minor + stagger_distance, hicon_array[count]);
				}
				else
				{
					memdc.DrawIcon(x, start_minor, hicon_array[count]);
				}

				do_stagger = !do_stagger;
			}
			break;
		}

		case VERTICAL:
		{
			for (y = start_major, count = 0; count < number_of_icons; y -= icon_increment, count++)
			{
				if (do_stagger)
				{
					memdc.DrawIcon(start_minor + stagger_distance, y, hicon_array[count]);
				}
				else
				{
					memdc.DrawIcon(start_minor, y, hicon_array[count]);
				}

				do_stagger = !do_stagger;
			}
			break;
		}
	}

	// Copy it to the screen.
	dc.BitBlt(0, 0, window_rect.right, window_rect.bottom, &memdc, 0, 0, SRCCOPY);

	// Delete the tempory resources.
	memdc.DeleteDC();
	bitmap.DeleteObject();
}

BOOL CIconProgress::OnEraseBkgnd(CDC* pDC) 
{
	// Indicate that it is already erased.
	return TRUE;
}