解决duilib使用zip换肤卡顿的问题(附将资源集成到程序中的操作方法)

转载请说明原出处,谢谢~~

       今天在做单子是,客户要求做换肤功能,为此我专门写了一个换肤函数,并且把各种皮肤资源压缩为各个zip文件来换肤。但是客户反映程序运行缓慢,我测试后发现的确明显可以看出慢了不少。最后发现问题在于把皮肤资源都集成到了zip文件中,程序在刷新界面时会重新从zip文件中读取对应的资源,导致了界面反映卡顿。之前直接把z资源放到目录里或者把zip集成到程序内部,都是没问题的。但是如果要换肤就需要用到zip来压缩资源了。

       duilib的WinImplBase类为我们提供了4种加载资源的方法:

	enum UILIB_RESOURCETYPE
	{
		UILIB_FILE=1,		// 来自磁盘文件
		UILIB_ZIP,		// 来自磁盘zip压缩包
		UILIB_RESOURCE,		// 来自资源
		UILIB_ZIPRESOURCE,	// 来自资源的zip压缩包
	};

       使用磁盘文件是最简单的方法,开发时选择这个方法,但是实际发布程序后为了资源的保密就很少这样做了;使用zip文件也是常用的方法,但是问题就在于资源比较多时界面就有明显卡顿;直接使用资源肯定是快速的,但是这个方法就太繁琐了,需要逐个去处理每个资源,用法见MenuDemo;使用资源的zip压缩包,这个是我最常用的,把资源压缩为zip然后集成到程序中,这样不但可以保密资源,而且不会有卡顿的现象。

     

一、 这里先把使用“资源的zip压缩包”方法说明一下:

        1.让自己的窗体类继承WinImplBase类,并且重写GetSkinFile、GetSkinFolder、GetResourceType、GetResourceID这四个方法

        2.在vs中添加自定义资源,找到自己的zip文件并添加,资源类型填写为“ZIPRES”,得到资源的ID号,比如这里为“IDR_ZIPRES2”

        3.GetSkinFile中返回主窗体的xml文件的名字

        4.GetSkinFolder中返回资源文件所在的目录

        5.GetResourceType中返回资源类型,此时应该写为“return UILIB_ZIPRESOURCE;”

        6.GetResourceID中返回对应的zip资源的ID,例如:“return MAKEINTRESOURCE(IDR_ZIPRES2);”

       7.编译程序,这样就可以使用资源的zip压缩包了。

    (ps:在WinMain函数里只要写一句 CPaintManagerUI::SetInstance(hInstance);代码就够了,不需要其他任何CPaintManagerUI的代码,其他代码WinImplBase会处理的!)

二、再说明一下常用的zip文件换肤方法

     使用这种方法来换肤,要求加载资源的方式使用第二种“来自磁盘的zip压缩包”方式,用法我就不说明了,duilib的多数demo都是用这种方法。

     如果要换肤,直接使用如下两句代码就可以了:

   CPaintManagerUI::SetResourceZip(_T("skin2.zip")); // 这里写入新的皮肤包的文件名就行了
   CPaintManagerUI::ReloadSkin();

三、使用“来自资源的zip压缩包”方法换肤

     这样做有两个好处,第一是不会有使用单独zip文件那种卡顿现象,第二是资源文件会相对更安全一些。

     我测试了一下,默认情况下不能让duilib使用这种方法来换肤,原因会在后面给出。接下来直接说明怎么使用这个方法:

     从常用的zip文件换肤方法中可以看出,换肤的关键就是重新设置zip文件,也就是说SetResourceZip是换肤的关键函数,他重新指定了zip文件。这个函数有两个版本,一个是加载文件中的zip,另一个是加载资源中的zip,我们需要的就是第二个版本的SetResourceZip。程序调用ReloadSkin函数后,会通知所有控件去重新加载图片资源,图片资源的加载会通过LoadImage函数,这个函数会根据加载资源类型的不同而去选择从不同的地方去试图找到资源并加载。

      在使用“资源的zip压缩包”方法的前提下,如果要换肤就使用如下函数,函数的参数是新换皮肤的资源ID,比如“IDR_ZIPRES2”,函数实际就是从程序资源中找到对应的皮肤zip文件,并且调用对应的SetResourceZip函数加载资源:

void CFrameWnd::ReloadZipResource(int ID)
{

	HRSRC hResource = ::FindResource(m_PaintManager.GetResourceDll(), MAKEINTRESOURCE(ID), _T("ZIPRES"));
	if( hResource == NULL )
		return ;
	DWORD dwSize = 0;
	HGLOBAL hGlobal = ::LoadResource(m_PaintManager.GetResourceDll(), hResource);
	if( hGlobal == NULL )
	{
#if defined(WIN32) && !defined(UNDER_CE)
		::FreeResource(hResource);
#endif
		return ;
	}
	dwSize = ::SizeofResource(m_PaintManager.GetResourceDll(), hResource);
	if( dwSize == 0 )
		return ;

	CPaintManagerUI::SetResourceZip((LPBYTE)::LockResource(hGlobal), dwSize);

#if defined(WIN32) && !defined(UNDER_CE)
	::FreeResource(hResource);
#endif

	CPaintManagerUI::ReloadSkin();
}

           理论上这就应该就可以了,但是实际测试还有问题,后来发现是SetResourceZip函数的定义有些问题:

void CPaintManagerUI::SetResourceZip(LPVOID pVoid, unsigned int len)
{
    if( m_pStrResourceZip == _T("membuffer") ) return;
    if( m_bCachedResourceZip && m_hResourceZip != NULL ) {
        CloseZip((HZIP)m_hResourceZip);
        m_hResourceZip = NULL;
    }
    m_pStrResourceZip = _T("membuffer");
    m_bCachedResourceZip = true;
    if( m_bCachedResourceZip )
        m_hResourceZip = (HANDLE)OpenZip(pVoid, len, 3);
}

          可以看到如果使用资源zip文件,那么m_pStrResourceZip变量就会保存_T("membuffer")字符串,当再次调用SetResourceZip函数时,由于第一句代码的判断就会导致函数直接返回,所以这里直接注释掉第一句代码就可以了。

         至此,就可以使用资源中的zip文件来换肤了,两全其美。这里还可以扩展,可以把zip资源都继承到一个dll文件中,然后在加载函数里先加载dll,然后从dll加载资源,这样既可以让皮肤资源独立为文件,加载也快速,并且资源也安全。这个代码很好写,我这里就不提供了。

         如有错误,请在博客留言!

         Redrain   2014.10.16

时间: 2024-10-24 09:20:05

解决duilib使用zip换肤卡顿的问题(附将资源集成到程序中的操作方法)的相关文章

求解决-CSS3动画在安卓机卡顿

问题描述 CSS3动画在安卓机卡顿 CSS3动画在安卓机卡顿现象如何解决,而在iOS中很流畅,希望安卓和iOS加载动画达到相同效果 解决方案 CSS3 莲花盛开动画css3动画实例----------------------

Android ListView只加载当前屏幕内的图片(解决list滑动时加载卡顿)

最近在做ListView分页显示,其中包括图片 和文字(先下载解析文字内容,再异步加载图片)发现每次点击下一页后,文字内容加载完毕,马上向下滑动,由于这时后台在用线程池异步下载图片,我每页有20条,也就是20张图片,会导致listview滑动卡顿! 这是用户不想看到的,我参考了网易新闻和电子市场等应用,发现它们都是只加载屏幕内的图片,不现实的不加载,于是我也仿照做了一个.我是菜鸟,我承认 呵呵,虽然不见得完全和他们的一样,但是确实解决了翻页时那一刻的卡顿现象. 因为未发现网上有相关文章,希望对朋

解决小米用蓝牙耳机听歌卡顿

今天新买了蓝牙耳机,结果有卡顿,于是果断关掉wifi,只保留蓝牙,ok,解决问题. 可能是小米1s wifi通道和蓝牙通道有冲突.关掉小米的wifi后,蓝牙听歌无卡顿.

电脑开机使用一段时间后就会变得卡顿怎么解决?

  相信大家都碰到过:电脑在一天之中使用一段时间就会变得卡顿的问题.这是因为开机使用过程中,电脑里面会不断存储许多相关数据和垃圾文件,时间长了之后越来越多,由此影响电脑运行速度.碰到这种情况,我们应该怎么办呢?下面小编就为大家介绍一下,来看看吧! 优化 首先,解决这种情况,最直接的办法就是重启电脑,重启后电脑会释放那些缓存和垃圾文件!电脑也就不还出现卡顿了. 今天主要是向大家介绍第二种方法 遇到上述情况,有时候我们不愿意去重启电脑,感觉很麻烦,时间很长!那我们怎么在不重启电脑的情况下解决这个问题

winform datagridview显示卡顿 30行15列 无数据

问题描述 放了一个datagridview在窗口内只是简单的初始化了下,也没有任何数据,但是最大化后拖拽进度条后又明显的卡顿,且选中区域也是卡的不行求解但是把col的数量从15降低到5就不卡了但是我实际工程需要31列没数据都这样有数据该怎么办啊!!publicForm1(){InitializeComponent();dataGridView1.ColumnCount=15;dataGridView1.RowCount=50;} 刚才又测试了下,datagriddock属性为fill下默认小窗口

Android 换肤技术资料整理

Android换肤技术总结 背景 纵观现在各种Android app,其换肤需求可以归为 - 白天/黑夜主题切换(或者别的名字,通常2套),如同花顺/自选股/天天动听等,UI表现为一个switcher. - 多种主题切换,通常为会员特权,如QQ/QQ空间. 对于第一种来说,目测应该是直接通过本地theme来做的,即所有图片/颜色的资源都在apk里面打包了. 而对于第二种,则相对复杂一些,由于作为一种线上服务,可能上架新皮肤,且那么多皮肤包放在apk里面实在太占体积了,所以皮肤资源会在选择后再进行

《上古世纪》换用新引擎优化系统解决画面卡顿

(编译/小熙)XL Games研发的韩国三大期待作之一的<上古世纪>换引擎啦!游戏研发商正式宣布,<上古世纪>原来使用的Cry2引擎正式升级为Cry3引擎. 三月初,在美国旧金山举行的2011游戏开发者大会上,Cry Tech公司正式公开了新一代CRY系列引擎---Cry3,并以韩国ESTsoft的<惊天动地2>.NHN的<ASTA>进行范例讲解,这让XL Games的<上古世纪>对这款全新的引擎产生极大兴趣. 目前,<惊天动地2>和

duilib入门之贴图描述、类html文本描述、动态换肤、Dll插件、资源打包

转载自duilib入门文档 贴图描述:          Duilib的表现力丰富很大程度上得益于贴图描述的简单强大.Duilib的贴图描述分为简单模式和复杂模式两种.          简单模式使用文件名做为贴图描述内容,在这种方式下,此图片将会以拉伸方式铺满控件.          复杂模式使用带属性的字符串表示贴图方式,既支持从文件中加载图片,也可以从资源中加载,具体如下:          如果是从文件加载,设置file属性,如file='XXX.png',不要写res和restype属

足记软件经常闪退怎么办?足记APP闪退卡顿解决教程

足记APP闪退问题解决办法 1.首先这款app是需要玩家联网才可以运行的,玩家需要在一个网络环境下去运行这款游戏.当玩家在游戏中使用足记的时候,如果发生了闪退的现象.玩家可以看看自己设备网络是否连接正常,玩家可以将设备上面的网络关闭然后在重启,然后在重新运行足记这款app. 2.玩家可以将设备上面一些经常不用的软甲,可以卸载掉.然后我们再清理下内存,这样就有足够的内存去运行这款游戏了.因为有的时候内存不足,也是导致软件出现闪退的一个重要的现象. 3.如果是安卓手机的话,一定要安卓版本在4.0版本