資源在windowsgui的程式中隨處可見,這也是微軟為了方便把介面和邏輯分開的優秀策略。所謂的資源就是一些用於描述介面或其他特徵的說明性字元,它們有固定的格式。這點與html有相似之處。而微軟提供了處理這些資源描述字元的函式,並上公升到win32api的高度。資源有兩種存在形式,一是編譯之前,此時的資源被存放到.rc檔案(此檔案為純文字檔案)中,在程式編譯的時候,資源編譯器rc.exe把.rc檔案編譯為.res二進位制檔案,然後鏈結器把.res檔案和.obj檔案鏈結在一起,並作為資源節存在於生成的.exe檔案中。
對於.rc檔案,相信很多程式設計師都很熟悉了,可以直接用文字編輯器編輯。為了視覺化設計,微軟和其他第三方軟體廠商還提供了視覺化編輯工具,稱之為資源編輯器。vs帶的資源編輯器,相信大家都不會陌生。
對於.res檔案或者是.exe檔案中的資源節的格式,大多數程式設計師就望而卻步了。詳細介紹.exe檔案結構的資料也不多,能夠說清楚資源節格式的資料就更少了。微軟提供了findresource(), loadresource(), lockresource(), updateresource()等函式供使用者檢視修改二進位制資源節裡的資源。但是具體的用法解釋的並不清楚,網上的例子也很少。但是這方便有做的功能很晚上的軟體,如exescope,不僅可以檢視二進位制資源,還可以修改之,可惜沒有公開源**。由於專案需要,這幾天一直找相關的例子,發現象dialog,icon等資源的處理有很多成功的例子,但是對於看似簡單的字串資源的處理卻幾乎無一成功的!!!就連老外也一樣!!!於是乎,瘋狂找資料,終於找到一位明白人寫的文章,還有源**,只是有兩點可惜:一是作者是老外,國內程式設計師不一定都喜歡英語;二是程式原始碼採用vb編寫,這讓c/c++的程式源很不舒服。於是乎,對這篇文章關於字串資源的處理的部分進行研究並重新用c/c++實現的想法湧上心頭。由於我對於vb也不是很熟悉,轉換語言的過程也不太順利,不過總算是成功轉成了c/c++。技術不敢獨享,願為大家獻上,不當之處還請見諒!
不想其他資源,字串是不能單獨處理的,像updateresource()等函式要求的最小處理單位是「串組」,這是由字串資源的存放方式決定的。每16個字串為乙個串組,字串的排序以字串的資源id號為依據,0-15為第一串組,16-31位第二串組,32-47位第三串組,...。串組id號從1開始,字串id號從0開始。由此可以得到如下公式:
串組id = (取整)(字串id/16) + 1
同一串組的字串是相鄰存放的,我們以7號串組為例說明。如下圖所示:
2 你好
5 你好abc
0
1 你
中間省略
上圖列出了幾個代表的串,其中最開頭的串的id為96,乙個串有兩部分組成,前一部分佔2個位元組,用於描述本串的長度,以unicode字元為單位(也就是2個位元組),注意字串資源裡的字元都是採用unicode16位編碼的。後一部分是串的具體內容,注意沒有結尾標誌。從上圖可以看出,id號為96的串的長度為2個字元,內容為「你好」。下乙個串也就是id為97的串的長度為0,所以沒有內容;接著98號串長度為5,內容為「你好abc"(請注意,在unicode編碼方式下,所有字元都佔據2個位元組,英文本母也一樣)。最後乙個字串,也就是111號,長度為1,內容為「你」。
理解了字串資源的存放方式與處理單位,對於其處理方法也就不難了。基本思路是,首先根據字串的id號,找到所處的串組號,然後找到整個串組的內容,隨後定位到需要處理的串,修改其長度標示和內容。修改不會影響到前面的串,但卻會影響到後面的串,所以首先要把後面的所有串先備份,然後新增到修改後的串的尾部。
如上圖所示,需要修改的串顯示為紅色,串組以此串為分割點分成前後兩部分,這兩部分原樣複製,把需要修改的串修改後重新將其與前後兩部分銜接起來。
順著這個思路問題迎刃而解,具體**如下:
bool stringresourcemodify(cstring strre***epath, int id, cstring strnew, long langid)
} else //串組中有串非空,則修改
//至此,countx代表了本串之前的所有串所佔據的空間大小(位元組)
//讀出要修改串修改前的長度
::copymemory(&checklng, lpreaddata+countx, 2);
//至此,checklng代表修改前本串的長度
lpdata = new byte[countx+2+strnew.getlength()*2 + //從開頭到本串(修改後)結束的長度
( cbresource-(countx+2 + checklng*2)) ]; //從本串後乙個串開始到結束的總長度
::copymemory(lpdata, lpreaddata, countx); //讀入開頭到本串前乙個串結束
cbtext = strnew.getlength();
::copymemory(lpdata+countx, &cbtext, 2); //寫入修改後串長度
if(cbtext)
if( (cbresource - (countx+2+checklng*2)) >0 ) //修改前,本串後面還有串
} ::freelibrary(hmodule);
hresource = beginupdateresource(strre***epath, false);
ret = updateresource(hresource, rt_string, makeintresource(igroup),
langid, lpdata, lenofdata);
ret = ::endupdateresource(hresource, false);
return ret; }
C 將引用的dll嵌入到exe檔案中
通過網上查詢,將引用的dll,嵌入到exe專案中,通過編譯為單一的exe檔案。1.引用dll,將引用的dll設定為不複製 是否複製不影響使用,編譯完成後,只需要exe就可以了,旁邊的dll是否存在並不影響使用 2.將引用的dll嵌入到專案中。新建乙個專案資料夾,將引用的dll複製到此資料夾中,幷包含...
LoadImage在dll與exe中的區別
hbitmap hbitmapnormal null hinstance hinstresource null find correct resource handle hinstresource afxfindresourcehandle makeintresource nbitmapnormal...
EXE中釋放DLL中分配的記憶體
在dll中分配的記憶體,如果到其呼叫者中釋放,可能會出現crash的情況,其原因在於 在dll中的code generation如果是採用了mt 靜態載入libcrtd.lib 在該庫中維護了乙個allocator的物件對記憶體分配進行管理,當exe中呼叫free等函式對記憶體進行釋放時,他自己也維...