animate butterfly - yamaumima/hello.github.io GitHub Wiki

#ifndef __MEM_DC__H__
#define __MEM_DC__H__
//防止重复编译
class CMemDC : public CDC
{
	CSize m_size;
public:
	~CMemDC()
	{
		DeleteDC();
	}
	CMemDC()
	{
		m_size.cx = m_size.cy=0;
	}
	CMemDC(UINT nBitmap,CDC* pDC=NULL)
	{
		LoadBitmap(nBitmap,pDC);
	}
	CMemDC(LPCSTR szFile,CDC* pDC=NULL)
	{
		LoadBitmap(szFile,pDC);
	}
	CMemDC(int cx,int cy,CDC* pDC=NULL)
	{
		Create(cx,cy,pDC);
	}
	BOOL DeleteDC()
	{
		if(!GetSafeHdc())
			return FALSE;
		CBitmap* pBitmap = GetCurrentBitmap();
		if(pBitmap)
			pBitmap ->DeleteObject();
		return CDC::DeleteDC();
	}
	int GetWidth(){return m_size.cx;}
	int GetHeight(){return m_size.cy;}
	BOOL Create(int cx,int cy,CDC* pDC=NULL)
	{//创建空白位图
		CBitmap bmp;
		if(!bmp.CreateCompatibleBitmap(pDC,cx,cy))
			return FALSE;
		m_size.cx = cx;
		m_size.cy = cy;
		CreateCompatibleDC(pDC);
		SelectObject(&bmp);

		return TRUE;
	}
	BOOL LoadBitmap(UINT nBitmap,CDC* pDC=NULL)
	{//进程内位图资源加载
		CBitmap bmp;
		if(!bmp.LoadBitmap(nBitmap))
			return FALSE;
		BITMAP bm;
		bmp.GetBitmap(&bm);
		m_size.cx = bm.bmWidth;
		m_size.cy = bm.bmHeight;
		CreateCompatibleDC(pDC);
		SelectObject(&bmp);	
		return TRUE;
	}
	BOOL LoadBitmap(LPCSTR szFile,CDC* pDC=NULL)
	{//进程外位图图片文件加载
		HBITMAP hBitmap = (HBITMAP)LoadImage(NULL,szFile,IMAGE_BITMAP,
			0,0,LR_LOADFROMFILE);
		if(!hBitmap)
			return FALSE;
		BITMAP bm;
		GetObject(hBitmap,sizeof(bm),&bm);
		m_size.cx = bm.bmWidth;
		m_size.cy = bm.bmHeight;
		CreateCompatibleDC(pDC);
		SelectObject(hBitmap);	
		return TRUE;
	}

	void BitTrans(
		int nXDest,		// 目标起点X
        int nYDest,		// 目标起点Y
        int nWidthDest,	// 目标宽度
        int nHeightDest,// 目标高度
		CDC* pDC,		// 目标DC
        int nXSrc,		// 来源起点X
        int nYSrc,		// 来源起点Y
        COLORREF crTrans// 透明色
        )
	{
		CMemDC dcImage(nWidthDest, nHeightDest,pDC);//临时DC
		CBitmap bmpMask;
		bmpMask.CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL); 
		// 创建单色掩码位图
		CDC dcMask;//掩码DC 
		dcMask.CreateCompatibleDC(pDC);
		dcMask.SelectObject(bmpMask);
		//将载入位图的内存DC中的位图,拷贝到临时DC中
		dcImage.BitBlt( 0, 0, nWidthDest, nHeightDest, this, nXSrc, nYSrc, SRCCOPY);
		
		// 设置临时DC的透明色
		dcImage.SetBkColor(crTrans);
		//掩码DC的透明区域为白色其它区域为黑色
		dcMask.BitBlt(0, 0, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCCOPY);
		
		//临时DC透明区域为黑色,其它区域保持不变
		dcImage.SetBkColor(RGB(0,0,0));
		dcImage.SetTextColor(RGB(255,255,255));
		dcImage.BitBlt( 0, 0, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);
		
		// 目标DC透明部分保持屏幕不变,其它部分变成黑色
		pDC ->SetBkColor(RGB(255,255,255));
		pDC ->SetTextColor(RGB(0,0,0));
		pDC ->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);
		pDC ->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCPAINT);
	} 

	void StretchTrans(
		int nXDest,			// 目标起点X
		int nYDest,			// 目标起点Y
		int nWidthDest,     // 目标宽度
		int nHeightDest,    // 目标高度
		CDC* pDC,			// 目标DC
		int nXSrc,			// 来源起点X
		int nYSrc,			// 来源起点Y
		int nWidthSrc,		// 来源宽度
		int nHeightSrc,		// 来源高度
		COLORREF crTrans	// 透明色
		)
	{
		CMemDC dcImage(nWidthDest, nHeightDest,pDC);//临时DC
		CBitmap bmpMask;
		// 创建单色掩码位图
		bmpMask.CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);
		CDC dcMask;
		dcMask.CreateCompatibleDC(pDC);
		dcMask.SelectObject(bmpMask);
	
		// 将载入位图的内存DC中的位图,拷贝到临时DC中
		if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc)
			dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, this, nXSrc, nYSrc, SRCCOPY);
		else
			dcImage.StretchBlt(0, 0, nWidthDest, nHeightDest, 
				this, nXSrc, nYSrc, nWidthSrc, nHeightSrc, SRCCOPY);
		
		// 设置临时DC的透明色
		dcImage.SetBkColor( crTrans);
		//掩码DC的透明区域为白色其它区域为黑色
		dcMask.BitBlt(0,0,nWidthDest, nHeightDest,&dcImage,0,0,SRCCOPY);
		
		//临时DC透明区域为黑色,其它区域保持不变
		dcImage.SetBkColor(RGB(0,0,0));
		dcImage.SetTextColor(RGB(255,255,255));
		dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);
		
		// 目标DC透明部分保持屏幕不变,其它部分变成黑色
		pDC ->SetBkColor(RGB(255,255,255));
		pDC ->SetTextColor(RGB(0,0,0));
		pDC ->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);
		pDC ->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCPAINT);
	}	
};

#endif

// FlyDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Fly.h"
#include "FlyDlg.h"

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

/////////////////////////////////////////////////////////////////////////////
// CFlyDlg dialog

CFlyDlg::CFlyDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CFlyDlg::IDD, pParent)
{
	m_nIndex=0;
	m_pos.x = m_pos.y=0;
	//{{AFX_DATA_INIT(CFlyDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

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

BEGIN_MESSAGE_MAP(CFlyDlg, CDialog)
	//{{AFX_MSG_MAP(CFlyDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_TIMER()
	ON_WM_ERASEBKGND()
	ON_WM_NCPAINT()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFlyDlg message handlers

BOOL CFlyDlg::OnInitDialog()
{
	CDialog::OnInitDialog();
	m_dcBack.LoadBitmap("./Flys/Back.bmp");
	int i = 0;
	CString str;
	while(i<COUNT)
	{
		str.Format("./Flys/%03d.bmp",i+1);
		m_dc[i].LoadBitmap(str);
		++i;
	}
	SetTimer(0,64,NULL);
	
	int cx = GetSystemMetrics(SM_CXSCREEN);
	int cy = GetSystemMetrics(SM_CYSCREEN);
	MoveWindow(0,0,cx,cy,FALSE);
	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CFlyDlg::OnPaint() 
{
	CPaintDC dc(this);
	OnDraw(&dc);
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.http://www.fodizi.com/fofa/list/248.htm
HCURSOR CFlyDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

//为什么画面上方会产生秘密文字???

void CFlyDlg::OnTimer(UINT nIDEvent) 
{
	CClientDC dc(this);
	Invalidate(FALSE);
	CDialog::OnTimer(nIDEvent);
}

void CFlyDlg::OnDraw(CDC *pDC)
{
	CRect rect;
	GetClientRect(rect);

	CMemDC mdc(rect.Width(),rect.Height(),pDC);
	mdc.FillSolidRect(0,0,rect.right,rect.Height(),RGB(255,0,0));
	m_dcBack.StretchTrans(0,0,rect.right,rect.bottom,&mdc,0,0,m_dcBack.GetWidth(),
		m_dcBack.GetHeight(),RGB(0,0,0));	
	//m_dcBack.BitTrans(0,0,rect.right,rect.bottom,&mdc,0,0,RGB(0,0,0));
//	dc.BitBlt(0,0,m_dcBack.GetWidth(),m_dcBack.GetHeight(),&m_dcBack,0,0,SRCCOPY);
	static int cx = m_dc[m_nIndex].GetWidth();//static变量第一次进入函数式初始化
	static int cy = m_dc[m_nIndex].GetHeight();//离开函数数值不丢失
	
	static dx=5,dy=5;//运动方向
	
	m_dc[m_nIndex].BitTrans(m_pos.x,m_pos.y,cx,cy,&mdc,0,0,RGB(1,1,1));

	pDC ->BitBlt(0,0,mdc.GetWidth(),mdc.GetHeight(),&mdc,0,0,SRCCOPY);
	m_pos.Offset(dx,dy);
	if(m_pos.x + cx> rect.right || m_pos.x <0)
		dx*=-1;
	if(m_pos.y + cy> rect.bottom || m_pos.y < 0)
		dy *=-1;

	if(++m_nIndex>COUNT)
		m_nIndex=0;
}

BOOL CFlyDlg::OnEraseBkgnd(CDC* pDC) 
{
	return TRUE;
}

void CFlyDlg::OnNcPaint() 
{
}