www.gusucode.com > 包含近30种图像特效的VC++小程序源码程序 > 包含近30种图像特效的VC++小程序源码程序/code/MirrorInWater.cpp

    //Download by http://www.NewXing.com
//////////////////////////////////////////////////
//类名:CMirrorInWater
//功能:水中倒影特效对话框实现
//作者:徐景周(jingzhou_xu@163.net)
//组织:未来工作室(Future Studio)
//日期:2004.12.1
//////////////////////////////////////////////////
#include "stdafx.h"
#include "helptip.h"
#include "MirrorInWater.h"

#include "WaterRoutine.h"				// 水纹特效头文件
#include "DIBSectionLite.h"				// DIB位图处理头文件
#include <complex>						// 复数结构头文件
//#include <math.h>

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

// 匿名名字空间,可存放全局成员(变量或涵数)
namespace
{
	const int TIMER_MIRRORINWATER = 21;	// 水中倒影定时器ID
	
	using std::complex;					// using声明complex直接可用
}

// ---------------------------------------------------------
//	类名: CMirrorInWaterImpl
//	功能: CMirrorInWater中镶套类,实现编译时间缩减的防火墙类
//	附注: 可以将CMirrorInWater类中所有私有成员(包括变量和涵数),
//		  全部放入此类中,虚涵数和保护成员不要放入。
//	编写: 徐景周(jingzhou_xu@163.net)
//  组织: 未来工作室(Future Studio)
//	日期: 2002.1.8
// ---------------------------------------------------------
class CMirrorInWater::CMirrorInWaterImpl
{
public:
	// 获取指定范围内的随机数
	inline int GetRandomRange(int nMin,int nMax)
	{
		srand((unsigned)time(NULL));
		return (rand() % ((nMax+1)-nMin))+nMin;
	}

	// 自平方分形算法,模拟云朵移动效果
	void SelfSquare(CDC* pDC, complex<double> lambda, complex<double> z, int count);
	// 自平方分形算法中点计算
	void CalculatePoint(complex<double> lambda, complex<double>& z);

	// 水平或垂直方向镜像位图(默认水平镜像)
	HBITMAP GetInvertedBitmap(HBITMAP hBitmap, BOOL bLateral = TRUE);

	CDIBSectionLite		m_bmpRenderSource;		// 源参照图
	CDIBSectionLite		m_bmpRenderTarget;		// 目标效果图
	CWaterRoutine		m_Water;				// 水纹效果对象

	int					m_bmpWidth;				// 载入位图宽度
	int					m_bmpHeight;			// 载入位图高度

	CBitmap				m_bmp;					// 正常位图
	CBitmap				m_bmpMirror;			// 垂直镜像后的位图

	double				m_dbMove;				// 云朵移动速度
};

// ---------------------------------------------------------
//	名称: CMirrorInWater
//	功能: 构造涵数,初始化工作
//	参数: 无
//	返回: 无
//	编写: 徐景周
//	日期: 2002.1.8
// ---------------------------------------------------------
CMirrorInWater::CMirrorInWater(CWnd* pParent /*=NULL*/)
	: CDialog(CMirrorInWater::IDD, pParent)
	, pImpl( new CMirrorInWaterImpl)
{
	//{{AFX_DATA_INIT(CMirrorInWater)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}

// ---------------------------------------------------------
//	名称: ~CMirrorInWater
//	功能: 退出时清除工作
//	参数: 无
//	返回: 无
//	编写: 徐景周
//	日期: 2002.1.8
// ---------------------------------------------------------
CMirrorInWater::~CMirrorInWater() throw()
{
	// 由于pImpl为智能指针,不用在此自己清除
//	delete pImpl;
//	pImpl = NULL;
}

// ---------------------------------------------------------
//	名称: CMirrorInWater
//	功能: 拷贝构造涵数,拷贝赋值工作
//	参数: other	-- 同类型要拷贝参数
//	返回: 无
//	编写: 徐景周
//	日期: 2002.1.8
// ---------------------------------------------------------
CMirrorInWater::CMirrorInWater(const CMirrorInWater& other)
	: pImpl(other.pImpl)
{

}

// ---------------------------------------------------------
//	名称: operator=
//	功能: 拷贝赋值运算符,进行赋值工作,具有强烈异常安全性
//	参数: other	-- 同类型要赋值参数
//	返回: 赋值后的值
//	编写: 徐景周
//	日期: 2002.1.8
// ---------------------------------------------------------
CMirrorInWater& CMirrorInWater::operator=(const CMirrorInWater& other)
{
	CMirrorInWater temp(other);
	Swap(temp);

	return *this;
}

// ---------------------------------------------------------
//	名称: Swap
//	功能: 异常安全的进行值交换工作,不抛出异常
//	参数: other	-- 同类型要交换值参数
//	返回: 无
//	编写: 徐景周
//	日期: 2002.1.8
// ---------------------------------------------------------
void CMirrorInWater::Swap(CMirrorInWater& other) throw()
{
	std::auto_ptr<CMirrorInWaterImpl> temp(pImpl);
	pImpl		= other.pImpl;
	other.pImpl	= temp;
}

void CMirrorInWater::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMirrorInWater)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CMirrorInWater, CDialog)
	//{{AFX_MSG_MAP(CMirrorInWater)
	ON_WM_PAINT()
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMirrorInWater message handlers
// ---------------------------------------------------------
//	名称: OnInitDialog
//	功能: 初始化水中倒影对话框
//	参数: 无
//	返回: TRUE --成功,FALSE -- 失败
//	编写: 徐景周(jingzhou_xu@163.net)
//  组织: 未来工作室(Future Studio)
//	日期: 2002.1.8
// ---------------------------------------------------------
BOOL CMirrorInWater::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	// 获取载入位图的宽度、高度
	BITMAP bm;
	pImpl->m_bmp.LoadBitmap(IDB_ADVERTISE);
	pImpl->m_bmp.GetObject(sizeof(BITMAP), &bm);
	pImpl->m_bmpWidth  = bm.bmWidth;
	pImpl->m_bmpHeight = bm.bmHeight;

	// 获取边框及标题栏大小
	int nBorderHeight  = GetSystemMetrics(SM_CYBORDER);
	int nBorderWidth   = GetSystemMetrics(SM_CXBORDER);
	int nCaptionHeight = GetSystemMetrics(SM_CYCAPTION);
	
	// 初始置窗体大小为背景位图大小(高度为位图高度2倍)
	CRect rcWindowRect,rcDeskTopWnd;
	rcWindowRect.SetRect(0,
		0,
		pImpl->m_bmpWidth + 2*nBorderWidth,
		(2*pImpl->m_bmpHeight + nCaptionHeight + 2*nBorderHeight));
	
	::GetWindowRect(::GetDesktopWindow(),&rcDeskTopWnd);

	// 居中放置
	int nHeight			= rcWindowRect.Height();
	int nWidth			= rcWindowRect.Width();
	rcWindowRect.top	= rcDeskTopWnd.Height()/2 - nHeight/2;
	rcWindowRect.bottom = rcWindowRect.top + nHeight;
	rcWindowRect.left	= rcDeskTopWnd.Width()/2 - nWidth/2;
	rcWindowRect.right	= rcWindowRect.left + nWidth;

	// 置窗体为显示及其大小位置
	MoveWindow(rcWindowRect,FALSE);

	// 将位图垂直镜像后放到m_bmpMirror中
	pImpl->m_bmpMirror.Attach(pImpl->GetInvertedBitmap(pImpl->m_bmp,FALSE));

	// 初始化特效位图
	CPictureHolder TmpPicture;
	TmpPicture.CreateFromBitmap(pImpl->m_bmpMirror);
	pImpl->m_bmpRenderSource.Create32BitFromPicture(&TmpPicture,pImpl->m_bmpWidth,pImpl->m_bmpHeight);
	pImpl->m_bmpRenderTarget.Create32BitFromPicture(&TmpPicture,pImpl->m_bmpWidth,pImpl->m_bmpHeight);
	
	// 创建水纹对象
	pImpl->m_Water.Create(pImpl->m_bmpWidth,pImpl->m_bmpHeight);

	pImpl->m_dbMove = 0.01;

	// 启动定时器,显示默认特效
	SetTimer(TIMER_MIRRORINWATER,100,NULL);
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

// ---------------------------------------------------------
//	名称: OnPaint
//	功能: 刷新窗体背景位图
//	参数: 无
//	返回: 无
//	编写: 徐景周(jingzhou_xu@163.net)
//  组织: 未来工作室(Future Studio)
//	日期: 2002.1.8
// ---------------------------------------------------------
void CMirrorInWater::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	
	// 绘制窗体上半部分正常显示位图
	CDC memDC;
	memDC.CreateCompatibleDC(&dc);
	CBitmap* pOldBitmap = memDC.SelectObject(&pImpl->m_bmp);
	
	dc.BitBlt(0, 0, pImpl->m_bmpWidth, pImpl->m_bmpHeight, &memDC, 0, 0, SRCCOPY);

	// 恢复及清扫工作
	memDC.SelectObject(pOldBitmap);         
	memDC.DeleteDC();

	// 绘制窗体下半部分垂直镜像后的位图
	CPoint ptOrigin(0,pImpl->m_bmpHeight);
	pImpl->m_bmpRenderTarget.Stretch(&dc,ptOrigin,CSize(pImpl->m_bmpWidth,pImpl->m_bmpHeight));
}

// ---------------------------------------------------------
//	名称: OnTimer
//	功能: 定时更新显示
//	参数: nIDEvent	--	定时器ID
//	返回: 无
//	编写: 徐景周(jingzhou_xu@163.net)
//  组织: 未来工作室(Future Studio)
//	日期: 2002.1.8
// ---------------------------------------------------------
void CMirrorInWater::OnTimer(UINT nIDEvent) 
{
	if(TIMER_MIRRORINWATER == nIDEvent)
	{	
		int nTemp	= pImpl->GetRandomRange(0,2);
		int nX		= pImpl->GetRandomRange(5,pImpl->m_bmpWidth-5);
		int nY		= pImpl->GetRandomRange(5,pImpl->m_bmpHeight-5);
		if(0 == nTemp)					// 仅随机显示各种水纹效果
			pImpl->m_Water.WarpBlob(nX,nY,20,300,pImpl->m_Water.m_iHpage);
		else if(1 == nTemp)
			pImpl->m_Water.SineBlob(nX,nY,10,100,pImpl->m_Water.m_iHpage);
		else if(2 == nTemp)
			pImpl->m_Water.HeightBlob(nX,nY,10,100,pImpl->m_Water.m_iHpage);

		pImpl->m_Water.Render((DWORD*)pImpl->m_bmpRenderSource.GetDIBits(),(DWORD*)pImpl->m_bmpRenderTarget.GetDIBits());
		
		// 绘制窗体下半部分垂直镜像后的位图内部数据处理后的效果
		CClientDC dc(this);
		CPoint ptOrigin(0,pImpl->m_bmpHeight);
		pImpl->m_bmpRenderTarget.Stretch(&dc,ptOrigin,CSize(pImpl->m_bmpWidth,pImpl->m_bmpHeight));

		// 绘制窗体上半部分正常显示位图
		CDC memDC;
		memDC.CreateCompatibleDC(&dc);
		CBitmap* pOldBitmap = memDC.SelectObject(&pImpl->m_bmp);
		
		dc.BitBlt(0, 0, pImpl->m_bmpWidth, pImpl->m_bmpHeight, &memDC, 0, 0, SRCCOPY);
		
		// 恢复及清扫工作
		memDC.SelectObject(pOldBitmap);         
		memDC.DeleteDC();

		// 利用自平方分形算法,模拟云朵移动效果
		complex<double> a(1.42,1), b(2,1);
		pImpl->SelfSquare(&dc, a, b, 3000);
	}
	
	CDialog::OnTimer(nIDEvent);
}

// ---------------------------------------------------------
//	名称: PreTranslateMessage
//	功能: 截获ESC和回车键,避免按下此键时关闭对话框
//	参数: pMsg -- 消息
//	返回: 成功 -- TRUE,失败 -- FALSE
//	编写: 徐景周(jingzhou_xu@163.net)
//  组织: 未来工作室(Future Studio)
//	日期: 2002.1.8
// ---------------------------------------------------------
BOOL CMirrorInWater::PreTranslateMessage(MSG* pMsg) 
{
	//截获ESC和回车键,避免按下此键时关闭对话框
	if (pMsg->message == WM_KEYDOWN)
    { 
      if(pMsg->wParam==VK_ESCAPE)
		  return true; 
	  if(pMsg->wParam==VK_RETURN) 
	  {
		  return true; 
	  }
    } 
	
	return CDialog::PreTranslateMessage(pMsg);
}

// ---------------------------------------------------------
//	名称: GetInvertedBitmap
//	功能: 进行水平或垂直方向镜像处理
//	参数: hBitmap		: 传入要镜像的位图句柄
//		  bLateral	
//						= TRUE	:	水平方向镜像(默认值)
//						= FALSE	:	垂直方向镜像
//	返回: 传回镜像处理后的HBITMAP
//	编写: 徐景周(jingzhou_xu@163.net)
//  组织: 未来工作室(Future Studio)
//	日期: 2002.1.8
// ---------------------------------------------------------
HBITMAP CMirrorInWater::CMirrorInWaterImpl::GetInvertedBitmap(HBITMAP hBitmap, BOOL bLateral)
{
	// 创建兼容DC
	CDC sourceDC, destDC;
	sourceDC.CreateCompatibleDC(NULL);
	destDC.CreateCompatibleDC(NULL);

	// 获取位图宽、高
	BITMAP bm;
	::GetObject(hBitmap, sizeof( bm ), &bm);

	// 创建返回结果位图
	HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(NULL), 
						bm.bmWidth, bm.bmHeight);

	// 选入相应位图到DC中
	HBITMAP hbmOldSource = (HBITMAP)::SelectObject(sourceDC.m_hDC, hBitmap);
	HBITMAP hbmOldDest = (HBITMAP)::SelectObject(destDC.m_hDC, hbmResult);
	
	if( bLateral )				// 水平镜像
		destDC.StretchBlt(0, 0, bm.bmWidth, bm.bmHeight, &sourceDC, 
				bm.bmWidth-1, 0, -bm.bmWidth, bm.bmHeight, SRCCOPY);
	else						// 垂直镜像
		destDC.StretchBlt(0, 0, bm.bmWidth, bm.bmHeight, &sourceDC, 
				0, bm.bmHeight-1, bm.bmWidth, -bm.bmHeight, SRCCOPY);

	// 恢复源设置
	::SelectObject(sourceDC.m_hDC, hbmOldSource);
	::SelectObject(destDC.m_hDC, hbmOldDest);

	return hbmResult;
}

// ---------------------------------------------------------
//	名称: CalculatePoint
//	功能: 自平方分形算法点计算
//	参数: lambda -- 参数值, z -- 吸附点
//	返回: 无
//	编写: 徐景周(jingzhou_xu@163.net)
//  组织: 未来工作室(Future Studio)
//	日期: 2002.1.8
// ---------------------------------------------------------
void CMirrorInWater::CMirrorInWaterImpl::CalculatePoint(complex<double> lambda, complex<double>& z)
{ 
	double lambdaMagSq, discrMag;
	static complex<double> fourOverLambda;
	static BOOL firstPoint	= TRUE;

	if(firstPoint)
	{
		lambdaMagSq			= std::norm(lambda);
		fourOverLambda		= 4.0 * lambda/lambdaMagSq;
		firstPoint			= FALSE;
	}

	complex<double> discr;
	discr.real(1.0 - (z.real() * fourOverLambda.real() - z.imag() * fourOverLambda.imag()));
	discr.imag(z.real() * fourOverLambda.imag() + z.imag() * fourOverLambda.real());
	discrMag				= std::abs(discr);

	// 更新Z值,进行负值处理
	double tmp				= sqrt((discrMag + discr.real())/2.0);
	if(discrMag + discr.real() < 0)
		z.real(0);
	else
		z.real(tmp);

	tmp = sqrt((discrMag - discr.real())/2.0);
	if(discrMag - discr.real() < 0)
		z.imag(0);
	else
		z.imag(0.5 * tmp);

	// 随机选取一半点为负值
	if(rand() < RAND_MAX/2)
	{
		z.real(-z.real());
		z.imag(-z.imag());
	}
	if(discr.imag() < 0)
		z.real(-z.real());

	// 最终Z实部值
	z.real(0.5 * (1 - z.real()));
}

// ---------------------------------------------------------
//	名称: SelfSquare
//	功能: 自平方分形算法,模拟云朵移动效果
//	参数: pDC -- 相关DC, lambda -- 参数值, z -- 吸附点, count -- 点数
//	返回: 无
//	编写: 徐景周(jingzhou_xu@163.net)
//  组织: 未来工作室(Future Studio)
//	日期: 2002.1.8
// ---------------------------------------------------------
void CMirrorInWater::CMirrorInWaterImpl::SelfSquare(CDC* pDC, complex<double> lambda, complex<double> z, int count)
{
	ASSERT(FALSE == IsBadReadPtr(pDC, sizeof(CDC*)));

	int k;

	// 初始计算几个点
	for(k = 0; k < 10; ++k)
		CalculatePoint(lambda, z);
	// 自平方分形点计算,模似云朵
	for(k = 0; k < count; ++k)
	{
		CalculatePoint(lambda, z);
		// 绘制处理后的新点
		pDC->SetPixelV(static_cast<int>(m_dbMove * m_bmpWidth + z.real() * m_bmpWidth/2), static_cast<int>(m_bmpHeight + z.imag() * m_bmpHeight), RGB(255,0,255));
	}

	// 云朵移动速度处理
	m_dbMove += 0.01;
	if(m_dbMove > 1.0)
		m_dbMove = 0.01;
}