贝壳库——资源库

给一下开源代码的路径http://code.ijinshan.com/trac/browser#bksafevul/publish,需要的同学可以完整下载,或者下bkres文件夹中的代码

资源处理的文件,一共9个,如下

bkbmppool.h
bkextraresdef.h
bkfontpool.h
bkjpgpool.h(这个目前没有)
bkpngpool.h
bkres.h
bkres.rc
bkresutil.h
bkstringpool.h

 

所谓“池”,即把资源统一放到某个地方,需要的时候取出,取出的逻辑有两种形式

a)懒汉式——即池中开始没资源,需要的时候才加载,一旦加载完,即成为缓存。以后只需读缓存,不需要再次加载

b)饿汉式——即初始化的时候,已经把所有资源投放到池里,第一次需要花费多些时间和存储空间,但是以后都只需要读缓存即可

一 总概

bkbmppool,bkfontpool,bkjpgpool,bkpngpool 四个资源池,使用的都是懒汉式,因为图片资源都比较大,需要的死后加载能减少内存。

bkstringpool则是饿汉式,原因很明显,文字内容毕竟是小空间的资源,一次加载完毕,可以加快速度。

bkextraresdef.h定义了扩展模块的接口,用做换肤,以后章节再详细说。

bkres.h文件包含了bkwinres.rc2和bkwinres.h,前者把资源打进本模块(比如dll),后者主要用来定义一些id宏,为了程序上能快速定位和统一使用资源id。

bkresutil.h封装了资源的加载顺序和方式

 

二 分析

1 字体资源池 bkfontpool.h

下面这段代码是实现“懒汉式”资源缓存的方式,很简单,通过一个static的CAtlMap<WORD, HFONT>类型m_mapFont存储

    static HFONT GetFont(WORD uKey)
    {
     // 查看资源池中有没制定字体 _TypeFontPool::CPair
* pPairRet = _Instance()->m_mapFont.Lookup(uKey); HFONT hftRet = NULL; if (NULL == pPairRet) { hftRet = _Instance()->_CreateNewFont( BKF_ISBOLD(uKey), BKF_ISUNDERLINE(uKey), BKF_ISITALIC(uKey), BKF_GETADDING(uKey) ); if (hftRet) _Instance()->m_mapFont[uKey] = hftRet; } else hftRet = pPairRet->m_value; return hftRet; }

支持三种常用字体样式,分别是加粗、下划线和斜体

#define BKF_BOLD        0x0004U
#define BKF_UNDERLINE   0x0002U
#define BKF_ITALIC      0x0001U

 

2 图片资源池 bkbmppool,bkjpgpool,bkpngpool

这几个资源池的处理方法大同小异,处理方式和bkfontpool.h差不多

看到include头

#include <GdiPlus.h>
#pragma comment(lib, "gdiplus.lib")

就知道是通过Gdi+的方式来处理图片的,有一个地方需要注意的是

BkResManager::LoadResource(nID, strResource, BKRES_PNG_TYPE);

加载资源是通过bkresutil.h里面的LoadResource实现的,这个函数做了加载方式的封装,且看下文

3 资源应用类bkresutil.h

LoadResource函数使用两种方式加载资源,一种是从路径中加载,即当有外部路径,且资源名是id名时,直接加载资源文件。第二种是加载打进模块的资源,在bkwinres.rc2中定义的资源。只要两个地方有一个找到资源,就返回。_Instance()这个是单实例,返回static成员。

        if (!_Instance()->m_strResourcePath.IsEmpty())
        {
            CString strFileName;

            strFileName.Format(L"%s\\%d.bmp", _Instance()->m_strResourcePath, uResID);

            hBitmap = (HBITMAP)::LoadImage(NULL, strFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

            if (NULL != hBitmap)
                return TRUE;
        }

        if (_Instance()->m_hInstanceRes)
        {
            hBitmap = ::LoadBitmap(_Instance()->m_hInstanceRes, MAKEINTRESOURCE(uResID));
            if (NULL != hBitmap)
                return TRUE;
        }

路径和模块句柄设置入口

    31     static void SetResourcePath(LPCTSTR lpszPath)
    32     {
    33         _Instance()->m_strResourcePath = lpszPath;
    34     }
    35 
    36     static void SetResourceDLL(LPCTSTR lpszPath)
    37     {
    38         if (_Instance()->m_hInstanceRes)
    39             ::FreeLibrary(_Instance()->m_hInstanceRes);
    40 
    41         _Instance()->m_hInstanceRes = ::LoadLibrary(lpszPath);
    42     }

 

三 总结

感觉资源处理的文件很少,很简要。主要使用的技术是单实例,及资源池的概念,并不复杂。下一篇将介绍bkwin的内容,这个比bkres可要复杂很多

 

 

 

 

 

 

 

 

 

posted @ 2012-05-06 22:32  叶浪听风  阅读(503)  评论(0编辑  收藏  举报