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

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

    错误日志如下: N版存在问题,其它版本不知道 解决方法(代码问题): /usr/lib/python2.7/site-packages/neutron/common/utils.py 在这个方法上(d ...

  2. Linux命令学习<不断更新>

    没有系统的学习过Linux命令,遇到了就学习一下,慢慢积累. 1.echo 命令,学习网站『https://linux.cn/article-3948-1.html』. echo单词有回声.共鸣的意思 ...

  3. 解决同伴收获&解决同伴问题补分博客

    解决同伴问题 要求: 查看同组同学的课堂笔记,尝试解决同伴的问题,格式如下: 我的同组同学是XXXX学号XXXX同学 同组同学的问题是XXXX 我理解他的意思是XXXX 他的问题我有一个小建议是XXX ...

  4. [BZOJ5109]大吉大利,晚上吃鸡!

    [BZOJ5109]大吉大利,晚上吃鸡! 题目大意: 一张\(n(n\le5\times10^4)\)个点\(m(m\le5\times10^4)\)条边的无向图,节点编号为\(1\)到\(n\),边 ...

  5. java的反射机制(第二篇)

    本文转载自:http://c.biancheng.net/cpp/html/1781.html 要理解RTTI在Java中的工作原理,首先必须知道类型信息在运行时是如何表示的,这项工作是由“Class ...

  6. python开发_tkinter_单选按钮

    这篇blog主要是描述python中tkinter的单选按钮操作 下面是我做的demo 运行效果: ====================================== 代码部分: ===== ...

  7. BZOJ 1007: [HNOI2008]水平可见直线 栈/计算几何

    1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec  Memory Limit: 162 MB 题目连接 http://www.lydsy.com/JudgeOnline ...

  8. Codechef December Challenge 2014 Chef and Apple Trees 水题

    Chef and Apple Trees Chef loves to prepare delicious dishes. This time, Chef has decided to prepare ...

  9. MYSQL 源代码编绎脚本

    http://blog.csdn.net/hopingwhite/article/details/5808101

  10. MVC把表格导出到Excel

    有关Model: namespace MvcApplication1.Models { public class Coach { public int Id { get; set; } public ...