在VC環境中除了我們所常用的Dialog、Menu和Bitmap等標準資源類型之外,它還支持自定義資源類型(Custom Resource),我們自定義的資源類型能做些什麼呢?呵呵,用處多多。
1. 默認的皮膚壓縮包或語言包。一些支持換膚的軟件特別是一些媒體播放器常常有自定義的皮膚文件(你可以嘗試將Media Player或千千靜聽等軟件的Skins目錄下的文件的擴展名改爲.zip,然後使用WinZip打開看一下),但爲了防止Skin文件丟失導致軟件無 法顯示,他們常常會在EXE文件中內置一套Skin作爲默認的皮膚文件。同樣,一些支持多語言的EXE文件中存在默認語言包也是這個道理(當然也可以使用 "String Table"資源類型);
2. 做爲一些病毒/木馬程序的寄生方式。如果不小心執行了帶有病毒/木馬的程序,它們會在你運行時釋放出病毒/木馬文件。當然許多病毒是將自身寫入PE文件頭來實現;
3. 合併EXE與它所需要的DLL文件。出於某些原因程序作者有時可能需要將DLL文件嵌入到可執行的EXE文件中,這可以通過使用自定義資源來實現;
4. 其它需要在程序中播放一個AVI動畫等等,都可以通過將二進制的數據文件作爲自定義資源加入到可執行文件中來實現;
二、添加
三、使用
要使用自定義資源,我們可能要用到的幾個API函數有FindResource、LoadResource和LockResource等,這裏每一個函數的返回值分別作爲下一個函數的參數,我來簡要介紹一下。
1. FindResource用來在一個指定的模塊中定位所指定的資源:
2. HRSRC FindResource(
3. HMODULE hModule, //包含所需資源的模塊句柄,如果是程序本身,可以置爲NULL
4. LPCTSTR lpName, //可以是資源名稱或資源ID
5. LPCTSTR lpType //資源類型,在這裏也就是我們自己指定的資源類型
6. );
7. LoadResource用來將所指定的資源加載到內存當中;
8. HGLOBAL LoadResource(
9. HMODULE hModule, //模塊句柄,同上
10. HRSRC hResInfo //需要加載的資源句柄,這裏也就是FindResource的返回值
11. );
12. LockResource用來鎖定內存中的資源數據塊,它的返回值也就是我們要使用的直系指向資源數據的內存指針;
13. LPVOID LockResource(
14. HGLOBAL hResData //指向內存中要鎖定的資源數據塊,這裏也就是LoadResource的返回值
15. );
另外我們還需要用SizeofResource來確定資源的尺寸,我們在操作資源時要用到它。在資源使用完畢後我們不需要使用 UnlockResource和FreeResource來手動地釋放資源,因爲它們都是16位Windows遺留下來的,在Win32中,在使用完畢後系統會自動回收。它們的使用很簡單,大致上是這個樣子的:
BOOL UseCustomResource()
{
//定位我們的自定義資源,這裏因爲我們是從本模塊定位資源,所以將句柄簡單地置爲NULL即可
HRSRC hRsrc = Findresource(null, MAKEINTRESOURCE(IDR_ITEMID1), TEXT("ITEMID"));
if (NULL == hRsrc)
return FALSE;
//獲取資源的大小
DWORD dwSize = SizeofResource(NULL, hRsrc);
if (0 == dwSize)
return FALSE;
//加載資源
HGLOBAL hGlobal = LoadResource(NULL, hRsrc);
if (NULL == hGlobal)
return FALSE;
//鎖定資源
LPVOID pBuffer = LockResource(hGlobal);
if (NULL == pBuffer)
return FALSE;
//我們用剛纔得到的pBuffer和dwSize來做一些需要的事情。可以直接在內存中使
//用,也可以寫入到硬盤文件。這裏我們簡單的寫入到硬盤文件,如果我們的自定
//義資源是作爲嵌入DLL來應用,情況可能要複雜一些。
BOOL bRt = FALSE;
FILE* fp = _tfopen(_T("demo.exe"), _T("wb"));
if (fp != NULL)
{
if (dwSize == fwrite(pBuffer, sizeof(char), dwSize, fp))
bRt = TRUE;
fclose(fp);
}
//FreeResource(hGlobal);
return bRt;
}
提醒:
最後將數據寫入文件的時候,最好不要用fwrite函數,因爲雖然此函數是二進制寫入的,但遇到資源是exe文件的時候,從資源中寫入文件的exe是運行不了的,不知道爲什麼,但用WriteFile就可以。。。
- HANDLE hFile = CreateFile(pszPath, GENERIC_WRITE,FILE_SHARE_WRITE,NULL,
- CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
- if ( hFile == INVALID_HANDLE_VALUE )
- {
- return FALSE;
- }
- WriteFile(hFile,lpBuff,dSrcSize,&dwWrite,NULL);
- CloseHandle(hFile);