【VC++游戏开发#二】2D篇 —— 平滑的幻灯片放映效果

本文由BlueCoder编写   转载请说明出处:

http://blog.csdn.net/crocodile__/article/details/12975077

我的邮箱:bluecoder@yeah.net    欢迎大家和我交流编程心得

我的微博:BlueCoder_黎小华    欢迎光临^_^

 

 

前段时间为了系统学习MFC,花了一星期的课余时间复习了c++,将<<C++ Primer>>看了一遍,感觉关于c++的见识涨了不少,毕竟看完大师级人物写的书籍确实应该有如获光明的感觉。不过由于时间的原因,有几章节没怎么祥看——当然,以后必定细细品味

 

因此感叹一句:好久没写博客了啊——呵呵

 

ok,归入正题

 

今天上午看见Yorhom用HTML5实现了一个『HTML5梦幻之旅』-滚动播放的幻灯片效果,感觉不错。于是借着他给的灵感(刚好最近在学MFC),我用MFC来实现类似的效果(思想略有不同),先上一个效果gif:

 

下面我来讲解一下具体的实现

 

 

一、编译环境

VS2008企业完整版,创建一个MFC工程(项目名称为SlideBmp):

【VC++游戏开发#二】2D篇 —— 平滑的幻灯片放映效果_第1张图片

 

 

二、剖析实现思想

先来看看我制作的一张示意图:

ClientWidth表示窗口客户区的宽度——这里就是View窗口

【VC++游戏开发#二】2D篇 —— 平滑的幻灯片放映效果_第2张图片

 

(1). 从左边出现的图片,预先放在横坐标为-ClientWidth的位置,然后启动计时器,增加横坐标,逐渐移动,直到横坐标为0——也就是到达了窗口客户区,就关闭计时器——这时图片刚好停留在客户区

(2). 同理,从右边出现的图片预先放在横坐标为ClientWidth处,后面的同(1)

 

这样实现的效果就是每次移动的图片会覆盖上一次的图片

怎么样,还是挺简单的吧?

 

 

 

三、剖析实现代码

(1). 改变MFC默认的窗口外观——在CMainFrame::PreCreateWindow中,也就是创建框架窗口之前修改——代码如下:

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	if( !CFrameWnd::PreCreateWindow(cs) )
		return FALSE;
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式

	//更改窗口外观
	CSize size;

	//获取屏幕像素大小
	size.cx = ::GetSystemMetrics(SM_CXSCREEN);
	size.cy = ::GetSystemMetrics(SM_CYSCREEN);

	//窗口风格(快捷菜单式的窗口, 无边框、标题栏)
	cs.style	= WS_POPUPWINDOW;
	//去掉菜单
	cs.hMenu	= NULL;
	//窗口标题名称
	cs.lpszName = _T("SlideBmp");

	//自定义窗口大小, 并窗口居中显示
	cs.x		= (size.cx - 486 ) / 2;
	cs.y		= (size.cy - 360) / 2;
	cs.cx		= 486;
	cs.cy		= 360;

	return TRUE;
}

 

 

(2). 因为View窗口MainFrame框架窗口的子窗口,因此应该在它上面做工作——贴图片

 

(3). 在构造函数中进行初始化工作

CSlideBmpView::CSlideBmpView()
{
	//初始化
	m_index = 0;
	m_start = 0;
	m_isStart = true;
	m_isLeft = false;
	m_isLoad = true;
}


 

 

(4). 所需变量或成员的定义,在SlideBmpView.h头文件中

全局变量

//计时器ID
#define ID_TIMER_PAINT	100

//全局变量N——表示有几张图片
const int	N = 5;
//图片的名称(这里也是路径)
const LPCTSTR pszPngName[] = {_T("0.png"), _T("1.png"), 
				_T("2.png"), _T("3.png"), _T("4.png")};

 

CSlideBmpView类私有成员

private:
	CRect	m_rClient;//客户区大小
	CImage  m_img;//用于在内存中绘图

	CDC		m_bufferDC;//缓冲DC
	CBitmap	m_bufferBmp;//缓冲Bitmap

	int		m_index;//标记图片索引
	int		m_start;//标记图片起始位置
	bool	m_isStart;//标记是否是开始
	bool	m_isLeft;//标记图片移动方向
	bool	m_isLoad;//标记是否加载图片

 


(5). 由于我是用键盘控制图片出现的方向——方向键左键表示从左边往右出现,右键表示从右边往左边出现——添加键盘消息处理函数(WM_KEYDOWN)

void CSlideBmpView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	//如果图片起始位置是起点,表示图片已经移动结束.这时才允许继续移动图片
	if(!m_start)
	{
		//如果按下左键
		if(nChar == VK_LEFT)
		{
			m_isLeft = true;
			m_start = m_rClient.Width();
		}

		//如果按下右键
		else if(nChar == VK_RIGHT)
		{
			m_isLeft = false;	
			m_start = -m_rClient.Width();
		}

		//设置定时器, 触发动画的开始
		if(nChar == VK_LEFT || nChar == VK_RIGHT)
		{
			m_index = (m_index + 1) % N;

			m_isLoad = true;
			SetTimer(ID_TIMER_PAINT, 10, NULL);
			InvalidateRect(NULL, false);
		}
	}

	CView::OnKeyDown(nChar, nRepCnt, nFlags);
}


 

(6). 响应计时器消息——WM_TIMER

void CSlideBmpView::OnTimer(UINT_PTR nIDEvent)
{
	if(m_isLeft)
	{
		m_start -= 8;		
	}
	else
	{
		m_start += 8;
	}

	//如果图片刚好布满客户区, 就停止移动
	if(!m_start)
	{
		KillTimer(ID_TIMER_PAINT);
	}

	//在移动图片时不需要加载图片
	m_isLoad = false;
	
	/*
		重绘

		因为, 每次绘制都会覆盖上一次的, 因此不需要重绘背景
		否则它会使用默认的白色画刷重绘背景, 闪屏会很厉害
	*/
	InvalidateRect(NULL, false);

	CView::OnTimer(nIDEvent);
}


 

(7). 在CSlideView::OnDraw函数中绘图——响应Win32的WM_PAINT

void CSlideBmpView::OnDraw(CDC* pDC)
{
	CSlideBmpDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
	
	//如果是窗口建立之初
	if(m_isStart)
	{
		m_isStart = false;

		GetClientRect(&m_rClient);

		//创建缓冲DC
		m_bufferDC.CreateCompatibleDC(NULL);
		//创建缓冲Bitmap
		m_bufferBmp.CreateCompatibleBitmap(pDC, 
			800, 600);
		//将缓冲Bitmap选入缓冲DC中
		m_bufferDC.SelectObject(m_bufferBmp);
	}

	//如果需要加载图片
	if(m_isLoad)
	{
		//加载图片
		m_img.Load(pszPngName[m_index]);
		//在内存中绘图(缓冲DC)
		m_img.Draw(m_bufferDC, 0, 0);
		//取消图片与m_img对象的关联, 以使下一次顺利关联下一个图片
		m_img.Detach();
	}

	//贴图
	pDC->SetStretchBltMode(COLORONCOLOR);
	pDC->StretchBlt(m_start, 0, m_rClient.Width(), m_rClient.Height(),
		&m_bufferDC, 0, 0, 800, 600, SRCCOPY);
}


 

(8). 记得回收内存资源——在析构函数中处理

CSlideBmpView::~CSlideBmpView()
{
	//在析构中回收内存资源
	m_bufferBmp.DeleteObject();
	m_bufferDC.DeleteDC();
	m_img.~CImage();
}

 

 

四、免费资源下载

点击下载项目工程及源代码 

 

欢迎对MFC感兴趣的朋友和我交流,结识志同道合的朋友是我的荣幸(^_^)

你可能感兴趣的:(C++,mfc,幻灯片,平滑播放)