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

今天在做单子是。客户要求做换肤功能,为此我专门写了一个换肤函数,而且把各种皮肤资源压缩为各个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

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

  1. 解决duilib使用zip换肤卡顿的问题:修改duilib并使用资源文件换肤

    转载请说明原出处,谢谢~~ 今天在做单子是,客户要求做换肤功能,为此我专门写了一个换肤函数,并且把各种皮肤资源压缩为各个zip文件来换肤.但是客户反映程序运行缓慢,我测试后发现的确明显可以看出慢了不少 ...

  2. 解决MyEclipse启动慢,使用卡顿问题

    卡顿原因: 1.启动的服务和插件过多,导致启动和运行缓慢,电脑配置较差的直接会卡死没有响应 2.软件运行内存设置不足,导致没有足够的空间运行软件,致使软件卡顿 解决方法: windows --> ...

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

    最近在做ListView分页显示,其中包括图片 和文字(先下载解析文字内容,再异步加载图片)发现每次点击下一页后,文字内容加载完毕,马上向下滑动,由于这时后台在用线程池异步下载图片,我每页有20条,也 ...

  4. 解决Mac下AndroidStudio内容时卡顿

    Mac下AndroidStudio在写代码的时候出现卡顿,小圆圈会一直转,此时我们应该检查下AndroidStudio的内存使用情况了. 1.点击左上角 AndroidStudio -- Prefer ...

  5. 解决无法安装cnpm,cnpm卡顿问题

    # 注册模块镜像 npm set registry https://registry.npm.taobao.org # node-gyp 编译依赖的 node 源码镜像 npm set disturl ...

  6. 解决windows 1903 alt + tab 切换卡顿

    右击此电脑图标 选择管理 服务和应用程序 服务 禁用system interface foundation service

  7. 关于myeclipse加载building workspace卡顿的解决办法

    在MyEclipse的使用中,在建立新文件或者改动代码后,经常会出现building workspace半天卡顿不动的情况,如果开的程序过多,经常会发生失去响应,电脑要是再烂点,直接死机的情况也常有发 ...

  8. 解决页面使用overflow: scroll,overflow-y:hidden在iOS上滑动卡顿的问题

    解决页面使用overflow: scroll,overflow-y:hidden在iOS上滑动卡顿的问题 div{ width: 100%; overflow-y: hidden; -webkit-o ...

  9. Android中插件开发篇之----应用换肤原理解析

    一.前言 今天又到周末了,感觉时间过的很快呀.又要写blog了.那么今天就来看看应用的换肤原理解析.在之前的一篇博客中我说道了Android中的插件开发篇的基础:类加载器的相关知识.没看过的同学可以转 ...

随机推荐

  1. awk 基本函数用法

    gsub函数有点类似于sed查找和替换.它允许替换一个字符串或字符为另一个字符串或字符,并以正则表达式的形式执行.第一个函数作用于记录$0,第二个gsub函数允许指定目标,然而,如果未指定目标,缺省为 ...

  2. 4144: [AMPPZ2014]Petrol (多源最短路+最小生成树+启发式合并)

    4144: [AMPPZ2014]Petrol Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 752  Solved: 298[Submit][Sta ...

  3. BZOJ.1032.[JSOI2007]祖码(区间DP)

    题目链接 BZOJ 洛谷 AC代码: 区间DP,f[i][j]表示消掉i~j需要的最少珠子数. 先把相邻的相同颜色的珠子合并起来. 枚举方法一样,处理一下端点可以碰撞消除的情况就行. 当然合并会出现问 ...

  4. 【提权思路】绕过SecureRDP限制远程连接

    工具可以在百度上下载 直接步入正题 配置好的SecureRDP是限制远程登录的用户 原理是判断来访的计算机名是否在白名单中 如果不在,便出现如上图所示 网上也有绕过方法(https://weibo.c ...

  5. bzoj 3956: Count

    3956: Count Description Input Output Sample Input 3 2 0 2 1 2 1 1 1 3 Sample Output 0 3 HINT M,N< ...

  6. bzoj 2178

    这题调精度真痛苦啊(向管理员要了数据才调出来). 用的是hwd在WC2015上讲的方法,考虑将原图分割,根据每个圆的左右边界和圆与圆交点的横坐标来分割,这样原图就被分成很多竖着的长条,并且每一条中间都 ...

  7. Codeforces Round #313 (Div. 1) C. Gerald and Giant Chess DP

    C. Gerald and Giant Chess Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest ...

  8. configure: error: lzo enabled but missing

    注意:yum安装的无效,需要手动下载源码安装. wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.06.tar.gz tar zx ...

  9. Android 上SuperUser获取ROOT权限原理解析

    Android 上SuperUser获取ROOT权限原理解析 一. 概述 本文介绍了android中获取root权限的方法以及原理,让大家对android 玩家中常说的“越狱”有一个更深层次的认识. ...

  10. 《C预处理》Linux内核中可变参数宏的用法

    http://blog.csdn.net/tankai19880619/article/details/12015305