duilib制作窗体动画效果

转载请说明原出处,谢谢~·http://blog.csdn.net/zhuhongshu/article/details/49026605

最近一段时间没写博客了,感觉最近没有遇到什么必须解决的bug。在一年前我把自己写的仿酷狗音乐播放器Demo写到博客时,我在博客末尾写过以后会做异形窗体和窗体动画的功能。异形窗体在半年前大概做完并且集成到我的库里了,但是窗体动画Demo没有写到博客。之前就有网友问我窗体动画的制作方法,一直懒着没写,不好意思···。

今天把窗体动画的制作思路和Demo说明一下。实际上,异形窗体写完了,也就可以说窗体动画功能也写完了,因为窗体动画效果只是在使用半透明异形窗体技术基础上的一个应用。关于异形窗体的博客:使用duilib开发半透明异形窗体程序(附源码和demo)

首先把效果图展示一下,本来是有79个特效,但是由于csdn博客的图片限制,只能录一小部分了···:

这里特别声明,我使用的这个动画特效算法不是自己写的,而是使用了开源的界面库UiFeature的特效算法组件,非常感觉UiFeature作者的开源(UiFeature的下载地址:http://yunpan.cn/cZLr5zDIdW8ZT (提取码:ec84)),这同样是个很不错的界面库,UiFeature的动画特效是其一大亮点,而动画特效是个独立的DLL,我这里直接移植到我的Duilib窗体动画Demo里。

       说明一下窗体动画的开发步骤和注意点:

1、开启窗体半透明异形功能(原生DuiLib不支持,不过包括我在内的不少维护Duilib的朋友的库都支持,其他的很多界面库也都支持),这个是根本,因为使用UpdateLayeredWindow函数使窗体拥有半透明异形功能后,就可以使用位图来绘制出窗体,而动画实际上就是有规律变化的连续位图。所以把动画位图定时贴到异形窗体上,就是窗体动画了~~。

2、自定义一个容器控件,作为窗体的根容器

3、开始动画时,截取自定义控件的渲染位图,用来计算动画效果

4、为自定义容器增加一个定时器来用动画算法定时计算动画效果

5、重写控件的DoPaint方法,把计算后的动画位图绘制出来

      实际上窗体动画是属于控件动画的范畴,在半透明异形窗体中,根容器的效果无疑就是窗体的效果,所以窗体动画的开发实际就转变为了控件动画的开发。把上述方法的根容器改为控件,那就是控件动画的开发步骤。

代码讲解:

首先我的库支持透明异性功能,这满足了第一个要求。接下来定义一个容器控件,只要把他作为窗体xml的根容器,就可以做出窗体动画

class AnimLayout : public CVerticalLayoutUI, public IUIEffectCallBack
{
public:
	AnimLayout();
	~AnimLayout();

	virtual LPCTSTR GetClass() const override;
	virtual LPVOID GetInterface(LPCTSTR pstrName) override;
	virtual void DoPaint(HDC hDC, const RECT& rcPaint) override;
	virtual void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue) override;

	bool StartEffect();
	void OnTimer(int iCurFrame);

public:
	// 每一 个 动画开始时回调
	virtual void OnUiEffectBegin(WPARAM effectKey, DWORD animaType) override;
	// 每一 个 动画结束时回调
	virtual void OnUiEffectEnd(WPARAM effectKey, DWORD animaType) override;
	// 每一 帧 动画绘制时回调
	virtual void OnUiEffectDraw() override;

private:
	bool				m_bPlaying;
	HDC					m_hMemDc;
	HBITMAP				m_hOldBitmap;
	HBITMAP				m_hTransBitmap;

	DWORD						m_dwEffectNum;
	IUiEffectManagerImpl*		m_pEffectManager;
	IUIEffect*					m_pEffect;

public:
	static const LPCTSTR kAnimLayoutClass;
	static const LPCTSTR kAnimLayoutInterface;
};

当需要使用动画特效时,调用StartEffect函数,函数源码为:

bool AnimLayout::StartEffect()
{
	if (m_bPlaying)
		return false;
	if (m_dwEffectNum > 80)
	{
		m_dwEffectNum = 2;
		return false;
	}

	//LPDWORD pBmpBits = NULL;
	m_hMemDc = ::CreateCompatibleDC(m_pManager->GetPaintDC());
	m_hTransBitmap = CRenderEngine::GenerateBitmap(m_pManager, this, m_rcItem);
	if (m_hTransBitmap == NULL)
		return false;
	m_hOldBitmap = (HBITMAP) ::SelectObject(m_hMemDc, m_hTransBitmap);

	BITMAP bmDst;
	GetObject(m_hTransBitmap, sizeof(bmDst), &bmDst);
	SIZE szMemDc = { bmDst.bmWidth, bmDst.bmHeight };

	//修补一下Alpha通道,一些控件(Richedit)会让Alpha为0
	RECT rcRestore = m_rcItem;
	CRenderEngine::RestoreAlphaColor((LPBYTE)bmDst.bmBits, bmDst.bmWidth, &rcRestore);

	// 填充动画参数
	AnimationParam animParam;
	animParam.effectKey = (WPARAM)this;				//控件指针
	animParam.animationEffect = m_dwEffectNum++;	//动画类型,从2-80,1为自定义动画,并没有移植过来
	animParam.animationFrequency = 20;				//动画间隔
	animParam.bShow = TRUE;							//动画顺序
	animParam.hBitmap = m_hTransBitmap;
	animParam.pBmpData = (BYTE*)bmDst.bmBits;
	animParam.bmpSize = szMemDc;
	animParam.hdc = m_hMemDc;

	BOOL bRet = m_pEffect->AppendAnimation(animParam);
	ASSERT(bRet);

	m_bPlaying = true;

	// 这里是同步执行的,Animation函数在动画完毕后返回
	bRet = m_pEffect->Animation(dynamic_cast<IUIEffectCallBack*>(this), 0);
	ASSERT(bRet);

	// 递归演示所有动画效果,这只是为了演示效果,实际开发不要这样做!
	StartEffect();

	return true;
}

在代码里可以看到,开启动画时,调用CRenderEngine类的GenerateBitmap静态函数,使用这个函数可以获取到某个控件的渲染位图,这就满足了第三个要求。接下来应该是开启定时器来使用算法来定时计算位图,如果要精度要求不高那就可以直接调用CPaintManagerUI类的SetTimer方法,并且在自定义控件里响应定时消息来计算位图,计算后调用Invalidate函数来刷新控件。

不过UiFeature的这个特效组件的Animation函数,已经自带了定时功能,并且在填充了参数后会自动计算了位图,只要重写IUIEffectCallBack接口的OnUiEffectDraw方法来刷新窗体就可以了。所以和正常开发步骤有一些区别。

最后重写DoPaint函数:

void AnimLayout::DoPaint(HDC hDC, const RECT& rcPaint)
{
	if (!m_bPlaying)
	{
		__super::DoPaint(hDC, rcPaint);
		return;
	}

	typedef BOOL(WINAPI *LPALPHABLEND)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION);
	static LPALPHABLEND lpAlphaBlend = (LPALPHABLEND) ::GetProcAddress(::GetModuleHandle(_T("msimg32.dll")), "AlphaBlend");

	BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };

	lpAlphaBlend(hDC, m_rcItem.left, m_rcItem.top, m_rcItem.right - m_rcItem.left, m_rcItem.bottom - m_rcItem.top, m_hMemDc,
		0, 0, m_rcItem.right - m_rcItem.left, m_rcItem.bottom - m_rcItem.top, bf);

}

在函数里,判断如果正在使用动画特效,就不进行控件的正常绘制,而是直接调用AlphaBlend函数把计算后的位图贴到窗体dc上,就完成了第五步。至此就做完了窗体动画!

总结:

只要窗体动画的原理弄懂了,其实还是很简单的,几乎是比较固定的步骤,而动画制作的重点就转变为了动画算法。只要能找到或者设计出好的位图变换算法,就能做出很漂亮的窗体动画。

我在做窗体动画Demo时做了两个,一个是文本提到的79变动画,另一个是仿QQ的窗体翻转动画(道理都是一样的,只是换了算法库,我就不另外说了)文中的Demo我会提交到我个人的Duilib库中:点击打开链接

Redrain QQ:491646717 2015.10.10

??

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-04 23:07:03

duilib制作窗体动画效果的相关文章

3D Grid Effect – 使用 CSS3 制作网格动画效果

今天我们想与大家分享一个小的动画概念.这个梦幻般的效果是在马库斯·埃克特的原型应用程序里发现的??.实现的基本思路是对网格项目进行 3D 旋转,扩展成全屏,并呈现内容.我们试图模仿应用程序的行为,因此创建了两个演示,分别演示垂直和水平旋转网格项. 温馨提示:为保证最佳的效果,请在 IE10+.Chrome.Firefox 和 Safari 等现代浏览器中浏览. 您可能感兴趣的相关文章 创意无限!一组网页边栏过渡动画[附源码下载] 真是好东西!13种非常动感的页面加载动画效果 你见过吗?9款超炫的

CSS3+Jquery制作的动画效果电子表

<!DOCTYPE HTML> <html> <head> <title>CSS3+Jquery制作的动画效果电子表丨石家庄网络公司-河北品牌策划公司</title> <style type="text/css"> body{ background:#202020; font:bold 12px Arial, Helvetica, sans-serif; margin:0; padding:0; min-width

使用CSS3 BACKFACE-VISIBILITY属性制作翻转动画效果

摘要: 通过backface-visibility:hidden;属性,我们可以使一个元素在翻转之后消失,这是可以使用另一个元素放在它的背面,从而制作出一种元素翻转之后出现另一个元素的效果. ... 使用CSS3 backface-visibility属性我们可以制作出许多有趣的动画效果.当你翻转一个元素的时候,你看到的是什么?通常情况下,我们应该看到的是元素的背面,这是正常的情况,但是有时候我们希望翻转一个元素后看到的是另一个元素. 查看演示  插件下载 使用CSS3 backface-vis

【C#】窗体动画效果

通过调用API可以实现C#窗体的动画效果,主要调用user32.dll的行数AnimateWindow 1.函数申明 [System.Runtime.InteropServices.DllImport("user32")] private static extern bool AnimateWindow(IntPtr hwnd, int dwTime, int dwFlags); hwnd       界面上控件的句柄 dwTime   窗体特效执行的持续时间(单位毫秒) dwFlag

CSS3 制作网格动画效果

在线演示      源码下载

css3制作有动画效果的面板

.show-panel .slide-panels{ right: 0px; } .slide-panels{ z-index: 101; background: #fff; position: fixed; top: 60px; bottom: 0px; right: -100%; -webkit-transition: all 0.3s ease-out; transition: all 0.3s ease-out; }

Core Animation 动画效果介绍

在开始之前呢,先了解一下UIView和CALayer大体的区别(重点列举了以下四点): UIView继承自 UIResponder,因此UIView 可以处理响应事件,而CALayer继承自NSObject,所以它只是负责内容的创建,绘制. UIView负责对内容的管理,而CALayer则是对内容的绘制 UIView中有关位置的属性只有frame.bounds.center,而CALayer除了具备这些属性之外还有anchorPoint.position. 通过修改CALayer可以实现UIVi

12个来自 Codrops 的创新交互和动画效果

产品的用户体验是否被用户所接受,很大一部分取决于交互界面的设计,交互界面设计是整个产品设计中的核心,对于产品品质有着决定性的影响.这里集合了12个来自 Codrops 的创新的界面交互和动画效果,值得我们去研究和使用. 温馨提示:为保证最佳的效果,请在 IE10+.Chrome.Firefox 和 Safari 等现代浏览器中浏览. 您可能感兴趣的相关文章 Web 前端开发人员和设计师必读文章集锦 经典网页设计:25个应用视差滚动单页网站 经典网页设计:20个新鲜出炉 HTML5 网站 经典网页

酷炫的css3图标loading动画效果代码

css3 svg图标制作环形loading加载动画特效 绿色的css3动画加载图标代码 css3加载动画制作loading加载Android动画效果 jQuery css3预加载动画制作css3动画图标页面加载效果 css3加载动画特效制作css3 win8加载动画特效 css3加载动画效果制作loading动画效果代码 8种超炫css3加载动画代码_css3 loading动画效果代码 5个CSS3加载动画_css3网页加载动画图标下载 css3 Loading加载动画制作动态Loading阶