欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
通過(guò)代碼實(shí)現EXE文件圖標的替換

  最近,好多人問(wèn)我如何通過(guò)寫(xiě)個(gè)小程序,動(dòng)態(tài)替換可執行文件的圖標。這個(gè)問(wèn)題看起來(lái)雖小,但卻涉及到很多問(wèn)題。網(wǎng)上也只能找到一些零零散散的資料,卻沒(méi)有詳細的指導性文檔。所以我決定把這個(gè)問(wèn)題寫(xiě)下來(lái),以方便大家查閱。
  EXE文件圖標的替換有很多方法,例如用一個(gè)EXE文件的圖標替換另外一個(gè)EXE文件的圖標;用一個(gè)ICO文件內的圖標替換EXE文件的圖標。這兩種情況替換的方法不太相同,下面會(huì )詳細討論。
  EXE文件圖標的替換更一般的情形,是PE(Portable Executable)文件圖標的替換。只不過(guò)Windows操作系統只會(huì )顯示EXE文件的圖標罷了。但DLL、OCX等PE文件也都可以包含圖標資源。下面我們從ICO文件格式說(shuō)起,一步步講解替換EXE文件圖標的方法和原理。

一、.ico文件中圖標的保存格式
   對于一個(gè)擴展名是.ico的文件,大部分人會(huì )認為一個(gè)ICO文件里面只能包含一個(gè)圖標。但事實(shí)上,一個(gè)ICO文件里面可以包含很多圖標。而且,目前大部分ICO文件里面都包含有不同尺寸、不同色深的好幾個(gè)圖標。我們以MSN安裝包里的msnmsn.ico為例,這個(gè)圖標文件就包含了9個(gè)不同尺寸、不同色深的圖標,如圖所示:
 


圖表 1 msnms.ico

  這樣做的目的,是為了保證不同的操作系統、不同的桌面色深,圖標顯示均可達到最佳效果。操作系統會(huì )選擇并顯示一個(gè)最合適的圖標。Windows XP支持32位色的圖標,Windows 2000最多只支持256色的圖標。所以,如果我們開(kāi)發(fā)的軟件若要同時(shí)支持Windows XP和2000,那么為了達到視覺(jué)上的最佳效果,每一個(gè)ICO文件應至少包含兩個(gè)圖標,一個(gè)是32位色的,一個(gè)是256色的。
ICO文件頭部結構定義如下:


typedef struct
{
    WORD           idReserved;   // Reserved (must be 0)
    WORD           idType;       // Resource Type (1 for icons)
    WORD           idCount;      // How many images?
    ICONDIRENTRY   idEntries[1]; // An entry for each image (idCount of 'em)
} ICONDIR, *LPICONDIR;


idCount表示該ICO文件包含圖標的數量,所以理論上,一個(gè)ICO文件最多可以包含65535個(gè)圖標。接下來(lái),是該文件所包含的每一個(gè)圖標的描述。

typedef struct
{
    BYTE        bWidth;          // Width, in pixels, of the image
    BYTE        bHeight;         // Height, in pixels, of the image
    BYTE        bColorCount;     // Number of colors in image (0 if >=8bpp)
    BYTE        bReserved;       // Reserved ( must be 0)
    WORD        wPlanes;         // Color Planes
    WORD        wBitCount;       // Bits per pixel
    DWORD       dwBytesInRes;    // How many bytes in this resource?
    DWORD       dwImageOffset;   // Where in the file is this image?
} ICONDIRENTRY, *LPICONDIRENTRY;


ICONDIRENTRY中記錄了每一個(gè)圖標的尺寸、色深、圖標資源占用的字節數。dwImageOffset是一個(gè)文件偏移地址,指向圖標資源數據起始位置。至于每一個(gè)圖標資源內部的具體格式,與本文關(guān)系不大,這里就不再詳細介紹了。

二、PE文件中的圖標保存格式
  PE文件中的圖標保存格式與.ico文件中圖標的保存格式略有不同。PE文件中,把ICONDIR和圖標資源作為兩種資源類(lèi)型分別保存,前者是RT_GROUP_ICON類(lèi)型,后者是RT_ICON類(lèi)型。為了與.ico文件中圖標的保存格式做以區分,我們把PE文件中的圖標保存格式重新定義如下:


// #pragmas are used here to insure that the structure's
// packing in memory matches the packing of the EXE or DLL.

#pragma pack( push )
#pragma pack( 2 )
typedef struct
{
   WORD              idReserved;   // Reserved (must be 0)
   WORD              idType;       // Resource type (1 for icons)
   WORD              idount;      // How many images?
   GRPICONDIRENTRY   idEntries[1]; // The entries for each image
} GRPICONDIR, *LPGRPICONDIR;

typedef struct
{
   BYTE    bWidth;               // Width, in pixels, of the image
   BYTE    bHeight;              // Height, in pixels, of the image
   BYTE    bColorCount;          // Number of colors in image (0 if >=8bpp)
   BYTE    bReserved;            // Reserved
   WORD    wPlanes;              // Color Planes
   WORD    wBitCount;            // Bits per pixel
   DWORD   dwBytesInRes;         // how many bytes in this resource?
   WORD    nID;                  // the ID
} GRPICONDIRENTRY, *LPGRPICONDIRENTRY;
#pragma pack( pop )


  這里有一個(gè)區別,就是在.ico文件中,ICONDIRENTRY結構最后一個(gè)成員dwImageOffset表示的是圖標資源文件偏移地址。而PE文件中,GRPICONDIRENTRY結構最后一個(gè)成員nID表示的是圖標的索引ID。

三、Windows API
   Windows操作系統為我們提供了幾個(gè)API函數,用來(lái)更新PE文件中資源的函數有:BeginUpdateResource, UpdateResource, EndUpdateResource。用來(lái)枚舉PE文件中資源的函數有:EnumResourceTypes,EnumResourceNames,EnumResourceLanguages。具體的使用方法可以參見(jiàn)MSDN。

下面我們通過(guò)具體的例子,來(lái)驗證上面的方案是否可行。


四、用一個(gè)EXE中的圖標替換另外一個(gè)EXE文件的圖標
在這個(gè)例子中,我們用Windows XP自帶的記事本的圖標替換計算器的圖標。


圖表 2 記事本圖標
 


圖表 3 計算器圖標


下面代碼演示了如何替換32x32 32bits的圖標:


HMODULE hModule = ::LoadLibrary("notepad.exe");
HRSRC hResInfo = ::FindResource(hModule, MAKEINTRESOURCE(8), RT_ICON);
HGLOBAL hGlobal = ::LoadResource(hModule, hResInfo);
DWORD dwSize = ::SizeofResource(hModule, hResInfo);
void* pData = ::LockResource(hGlobal);

HANDLE hUpdate = ::BeginUpdateResource("calc.exe", FALSE);
VERIFY(::UpdateResource(hUpdate, RT_ICON, MAKEINTRESOURCE(7),
                        MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
                        pData, dwSize));
VERIFY(::EndUpdateResource(hUpdate, FALSE));

VERIFY(::FreeLibrary(hModule));


大家肯定有個(gè)疑問(wèn),上面代碼中MAKEINTRESOURCE(8)MAKEINTRESOURCE(7)是怎么來(lái)的呢?其實(shí)索引8和7分別是notepad.exe和calc.exe中,32x32 32bits圖標的索引。我們可以通過(guò)加載RT_GROUP_ICON資源,然后遍歷GRPICONDIRENTRY中每一個(gè)圖標的大小、色深,找到這個(gè)圖標的索引。為了簡(jiǎn)便,這里直接寫(xiě)死的索引號,省略了這一動(dòng)態(tài)查找的過(guò)程。
還有一個(gè)疑問(wèn)應該就是MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT)了。PE文件中,每一個(gè)資源都至少對應一種語(yǔ)言。因為我的操作系統是英文的,所以記事本和計算器中的圖標資源語(yǔ)言也是英文的。對于簡(jiǎn)體中文Windows XP操作系統所自帶的記事本和計算器,這個(gè)值應該是MAKELANGID(LANG_CHINESE, SUBLANG_SYS_DEFAULT)。
那么我們怎么才能知道一個(gè)PE文件中,圖標資源的語(yǔ)言是什么呢?我們可以通過(guò)資源枚舉API,枚舉所有圖標、語(yǔ)言??梢詤⒖忌厦嫣岬竭^(guò)的那幾個(gè)API函數,并查閱MSDN獲取這些函數的幫助文檔。
我們用記事本32x32 32bits圖標替換計算器同樣尺寸、色深的圖標后,效果如下,在Titles顯示方式下,圖標大小是48x48的,圖標沒(méi)有被改變:


圖表 4 48x48圖標

在Icons顯示方式下,圖標大小是32x32的,圖標被我們改變了:


圖表 5 32x32圖標

五、用一個(gè)ICO文件中的圖標替換另外一個(gè)EXE文件的圖標
  用ICO文件中的圖標替換EXE文件圖標稍微有點(diǎn)麻煩,我們必須借助數據結構ICONDIR和ICONDIRENTRY來(lái)完成。我們使用msnms.ico中的32x32 32bits圖標替換計算器中同樣大小色深的圖標:


DWORD dwSize = sizeof(ICONDIRENTRY);

HANDLE hFile = ::CreateFile("msnms.ico", GENERIC_READ, FILE_SHARE_READ,
                            NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
::SetFilePointer(hFile, sizeof(ICONDIR) + dwSize * 6, NULL, FILE_BEGIN);

DWORD dwRead = 0;
ICONDIRENTRY Entry;
VERIFY(::ReadFile(hFile, &Entry, dwSize, &dwRead, NULL));

::SetFilePointer(hFile, Entry.dwImageOffset, NULL, FILE_BEGIN);

void* pData = new char[Entry.dwImageOffset];
VERIFY(::ReadFile(hFile, pData, Entry.dwBytesInRes, &dwRead, NULL));

HANDLE hUpdate = ::BeginUpdateResource("calc.exe", FALSE);
VERIFY(::UpdateResource(hUpdate, RT_ICON, MAKEINTRESOURCE(7),
                        MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
                        pData, Entry.dwBytesInRes));
VERIFY(::EndUpdateResource(hUpdate, FALSE));

delete[] pData;
pData = NULL;

VERIFY(::CloseHandle(hFile));


上面代碼中,sizeof(ICONDIR) + dwSize * 6的意思是定位到第8個(gè)標結構體ICONDIRENTRY的位置,這個(gè)圖標是32x32 32bits的。我們可以通過(guò)遍歷每一個(gè)ICONDIRENTRY來(lái)判斷,到底哪個(gè)圖標是這個(gè)尺寸的。這里我們?yōu)榱撕?jiǎn)便,把這部分代碼省略了。
定位到第8個(gè)圖標結構體ICONDIRENTRY的位置后,Entry.dwImageOffset的值就是第8個(gè)圖標資源的文件偏移地址,Entry.dwBytesInRes的值是第8個(gè)圖標圖標資源的大小。然后我們將文件指針定位到Entry.dwImageOffset,并讀取Entry.dwBytesInRes大小的數據到指針pData指向的內存當中。
最后,是替換文件圖標資源的代碼,這部分代碼跟上一個(gè)例子是相同的。

本文拋磚引玉,介紹了EXE文件圖標的替換,但完全可以推廣到所有PE文件圖標的替換(包括EXE、DLL等),也可推廣到所有PE文件資源的替換(包括圖標、圖片、文字資源、對話(huà)框模板、菜單等)??晒┫嚓P(guān)人員參考。
 
(#)
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
怎么更改一個(gè)發(fā)布應用程序圖標ico
小熊首發(fā)
[紅隊tips]將你的payload隱藏在jpg中
如何將Python寫(xiě)的代碼打包成.exe可執行文件
恢復Ico圖標文件在資源管理器中的顯示
更改AW打包文件的默認圖標
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久