关闭

VC非标准资源操作

319人阅读 评论(0) 收藏 举报

转自http://blog.csdn.net/xianglitian/article/details/5618817

 

 

还记得在读书的时候我们有一个课程设计是用DirectX做游戏,我用的是win32SDK的框架然后完全通过DirectDraw绘图,DirectInput交互。那个时候第一次研究资源脚本,通过非MFC的方法实现了位图资源的加载。不过当时我有个同学做出的程序只有一个exe,拿到哪就可以直接玩,而我只实现了标准资源的处理,对于自定义资源(当时主要是wav的声音文件)我虽也能加载但是不知怎么解析数据......唉,惭愧,惭愧。

      后来东西做的多了才发现那种把什么资源都放到一个exe里的做法并不可取,不过通过纯资源的方式封装自己的软件用到的各种文件却是一个很合理且有用的方法,他可以使我们的软件更加规范和简洁,模块性也更好。最近在论坛里也看见过不少关于自定义资源的封装和解析的帖子,在回帖帮助网友解决问题的同时我也在想是不是应该把这个问题总结一下把方法封装到一个类里以方便使用。于是我按着自己的能想到的需求做了一个类,编了一个例子,写了这篇博客。

      动笔之前上网查了一下,介绍相关技术的文章还是不少的,如果说我的这篇有什么特点的话那么我想就是我是按照面向对象的思想把相关功能进行了封装,并且使这个类同时支持多字节和Unicode。说了这么多废话了,来点真格的,看看这个类的头文件。

  1. #pragma once   
  2.   
  3. #define     ERRORMSG_LEN        256   
  4.   
  5. #define     MSG_INSTANCENONE    _T("进程句柄为空!")   
  6. #define     MSG_NORESOURSE      _T("获取资源失败!")   
  7. #define     MSG_FAILGETDATA     _T("加载资源数据失败!")   
  8. #define     MSG_FILEFAIL        _T("创建文件失败!")   
  9.   
  10. #ifdef  UNICODE   
  11. #define COPYSTRING  wcscpy_s   
  12. #else    
  13. #define COPYSTRING  strcpy_s   
  14. #endif   
  15.   
  16. class CHandleRes  
  17. {  
  18.     TCHAR   m_szErrorMsg[ERRORMSG_LEN];  
  19.   
  20. public:  
  21.     CHandleRes();  
  22.     ~CHandleRes();  
  23.   
  24.     DWORD   GetResourceData(HINSTANCE hInstance, PTCHAR pszResID, PTCHAR pszResType, PBYTE& pResData);  
  25.     DWORD   GetResourceData(HINSTANCE hInstance, UINT uResID, PTCHAR pszResType, PBYTE& pResData);  
  26.     BOOL    ReleaseToFile(HINSTANCE hInstance, PTCHAR pszResID, PTCHAR pszResType, PTCHAR pszFileName);  
  27.     BOOL    ReleaseToFile(HINSTANCE hInstance, UINT uResID, PTCHAR pszResType, PTCHAR pszFileName);  
  28.   
  29.     PTCHAR  GetLastError(){return m_szErrorMsg;}  
  30. };  

从代码中可以看到,这个类只有两个主要功能GetResourceData可以让使用者获得资源数据,ReleaseToFile则实现了将资源内封装的文件释放出来。这两个函数都实现了多态,原因是为了处理不同的资源ID类型。众所周知VC下的资源ID可以是字符串也可以是一个整数,而此处的这个设计正是为了这个解决这个问题

      具体到函数的使用我们已GetResourceData为例

  1. DWORD CHandleRes::GetResourceData(HINSTANCE hInstance, PTCHAR pszResID, PTCHAR pszResType, PBYTE& pResData)  
  2. {  
  3.     DWORD   dwResSize;  
  4.   
  5.     if(!hInstance)  
  6.     {  
  7.         COPYSTRING(m_szErrorMsg, MSG_INSTANCENONE);  
  8.         return  NULL;  
  9.     }  
  10.   
  11.     HRSRC   hRsrc   = FindResource(hInstance, pszResID, pszResType);  
  12.     if(!hRsrc)  
  13.     {  
  14.         COPYSTRING(m_szErrorMsg, MSG_NORESOURSE);  
  15.         return FALSE;  
  16.     }  
  17.   
  18.     dwResSize   = SizeofResource(hInstance, hRsrc);  
  19.     pResData    = PBYTE(LoadResource(hInstance, hRsrc));  
  20.     if(!pResData)  
  21.     {  
  22.         COPYSTRING(m_szErrorMsg, MSG_FAILGETDATA);  
  23.         return NULL;  
  24.     }  
  25.   
  26.     FreeResource(hRsrc);  
  27.   
  28.     return dwResSize;  
  29. }  

hInstance指定了资源所在的进程句柄

pszResID指定了资源的ID

pszResType指定了资源的类型

pResData是指向资源数据的地址

      这里说明一下,正如我们所知,一个可执行体是可以携带资源的,资源的数据会直接加载到可执行体的进程地址空间中。因此,我们要想获得数据只需要得到资源数据在进程地址空间的地址,当然我们还会关心这个资源的大小,这正是这个函数调用成功后的返回值,如果返回值是0则说明函数执行失败。了解了这些我们就应该知道怎么使用这个类了,而且我们应该懂得pResData指向的内存是不需要我们去释放的。为了更好的了解和掌握每个函数的工作过程我仿效windows设计了GetLastError,如果函数调用失败可以通过它来获取到失败原因。

      为了演示这个类的使用我制作了一个演示实例,这个例子也是即可以通过多字节编译也可以通过Unicode编译。例子里做了一个自定义资源类型"text",然后导入了一个文本文件。程序可以实现显示文本文件的内容和将其释放到硬盘。

      应该说这个类的功能还不是很丰富,而且没有经过什么实践的检验,希望有兴趣和有经验的朋友们多提宝贵意见。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:5091次
    • 积分:78
    • 等级:
    • 排名:千里之外
    • 原创:0篇
    • 转载:17篇
    • 译文:0篇
    • 评论:0条
    文章分类