在VC項(xiàng)目中使用自定義資源
作者:飄鷗
下載源代碼
關(guān)鍵字:VC 自定義資源
一、前言
在VC環(huán)境中除了我們所常用的Dialog、Menu和Bitmap等標(biāo)準(zhǔn)資源類型之外,它還支持自定義資源類型(Custom Resource),我們自定義的資源類型能做些什么呢?呵呵,用處多多。
- 默認(rèn)的皮膚壓縮包或語言包。一些支持換膚的軟件特別是一些媒體播放器常常有自定義的皮膚文件(你可以嘗試將Media Player或千千靜聽等軟件的Skins目錄下的文件的擴(kuò)展名改為.zip,然后使用WinZip打開看一下),但為了防止Skin文件丟失導(dǎo)致軟件無法顯示,他們常常會在EXE文件中內(nèi)置一套Skin作為默認(rèn)的皮膚文件。同樣,一些支持多語言的EXE文件中存在默認(rèn)語言包也是這個(gè)道理(當(dāng)然也可以使用"String Table"資源類型);
- 做為一些病毒/木馬程序的寄生方式。如果不小心執(zhí)行了帶有病毒/木馬的程序,它們會在你運(yùn)行時(shí)釋放出病毒/木馬文件。當(dāng)然許多病毒是將自身寫入PE文件頭來實(shí)現(xiàn);
- 合并EXE與它所需要的DLL文件。出于某些原因程序作者有時(shí)可能需要將DLL文件嵌入到可執(zhí)行的EXE文件中,這可以通過使用自定義資源來實(shí)現(xiàn);
- 其它需要在程序中播放一個(gè)AVI動畫等等,都可以通過將二進(jìn)制的數(shù)據(jù)文件作為自定義資源加入到可執(zhí)行文件中來實(shí)現(xiàn);
二、添加
添加資源時(shí)選擇自定義,IDE會為你生成一個(gè)新的二進(jìn)制資源,然后你就可以將你已經(jīng)存在的二進(jìn)制文件作為自定義的資源類型導(dǎo)入到項(xiàng)目中來了。
三、使用
要使用自定義資源,我們可能要用到的幾個(gè)API函數(shù)有FindResource、LoadResource和LockResource等,這里每一個(gè)函數(shù)的返回值分別作為下一個(gè)函數(shù)的參數(shù),我來簡要介紹一下。
- FindResource用來在一個(gè)指定的模塊中定位所指定的資源:
HRSRC FindResource(HMODULE hModule, //包含所需資源的模塊句柄,如果是程序本身,可以置為NULLLPCTSTR lpName, //可以是資源名稱或資源IDLPCTSTR lpType //資源類型,在這里也就是我們自己指定的資源類型);
- LoadResource用來將所指定的資源加載到內(nèi)存當(dāng)中;
HGLOBAL LoadResource(HMODULE hModule, //模塊句柄,同上HRSRC hResInfo //需要加載的資源句柄,這里也就是FindResource的返回值);
- LockResource用來鎖定內(nèi)存中的資源數(shù)據(jù)塊,它的返回值也就是我們要使用的直系指向資源數(shù)據(jù)的內(nèi)存指針;
LPVOID LockResource(HGLOBAL hResData //指向內(nèi)存中要鎖定的資源數(shù)據(jù)塊,這里也就是LoadResource的返回值);
另外我們還需要用SizeofResource來確定資源的尺寸,我們在操作資源時(shí)要用到它。在資源使用完畢后我們不需要使用UnlockResource和FreeResource來手動地釋放資源,因?yàn)樗鼈兌际?6位Windows遺留下來的,在Win32中,在使用完畢后系統(tǒng)會自動回收。它們的使用很簡單,大致上是這個(gè)樣子的:
BOOL UseCustomResource(){ //定位我們的自定義資源,這里因?yàn)槲覀兪菑谋灸K定位資源,所以將句柄簡單地置為NULL即可 HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(ITEMID), TEXT("MyType")); 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來做一些需要的事情。可以直接在內(nèi)存中使 //用,也可以寫入到硬盤文件。這里我們簡單的寫入到硬盤文件,如果我們的自定 //義資源是作為嵌入DLL來應(yīng)用,情況可能要復(fù)雜一些。 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;}
四、實(shí)例
下面我們準(zhǔn)備用自定義資源來做兩件事情:一件是用我們生成的可執(zhí)行文件的自定義資源中來釋放一個(gè)Hello World程序(類似于木馬程序釋放服務(wù)端);另一件是從自定義資源中解壓縮一個(gè)壓縮包(類似于換膚軟件釋放默認(rèn)的皮膚文件)。這里我們模擬WinZip的Self-Extractor工具的界面和功能來完成它(呵呵,不過請不要誤會,WinZip嵌入到壓縮包的自解壓工具可不是像我們這樣實(shí)現(xiàn)的,這里只是來演示一下從自定義資源解壓縮多個(gè)文件的一個(gè)過程而已),具體的實(shí)現(xiàn)可以參考本文所附帶的源代碼。它最終運(yùn)行起來大概是這么個(gè)樣子:
圖四 模仿Self-Extractor界面的運(yùn)行結(jié)果
運(yùn)行后,點(diǎn)擊"Release"按鈕會在當(dāng)前目錄下釋放一個(gè)Win32版的Hello World程序;點(diǎn)擊"Unzip"按鈕則會在指定目錄釋放本Demo的工程文件及項(xiàng)目的所有源代碼,而編譯這個(gè)工程則恰恰得到了上面的可執(zhí)行文件。
本工程在WinXP + VC.Net 2003 + WTL7.5環(huán)境下編譯并運(yùn)行通過。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點(diǎn)擊舉報(bào)。