2013-03-02 55 views
2

我有一個使用WinAPI創建的程序。在程序中,我嵌入了一個位圖作爲資源,程序加載該資源並通過bitblt將其顯示爲背景圖像。在exe中替換位圖資源

下面,我創建了一個控制檯程序來替換WinAPI程序中的背景。它成功替換了位圖,但現在WinAPI程序不再顯示背景。我知道替換工作,因爲使用ResourceHacker,我可以點擊資源,它顯示它很好。

該截圖顯示,它已成功取代: enter image description here

但是,如果我用ResourceHacker到回保存圖片到磁盤,圖像無法預覽或任何編輯器打開:

enter image description here

如果我使用resourcehacker替換WinAPI程序中的圖像,它工作得很好,程序將其顯示爲背景。

有了這麼說,任何人都可以解釋我在下面做錯了什麼?

//In my resource file of the WINAPI PROGRAM: 
//IDI_ICON  ICON    "Resources/Icon.ico" 
//IDB_BACKGROUND BITMAP DISCARDABLE "Resources/BackgroundImg.bmp" 

#include <windows.h> 
#include <iostream> 
#include <fstream> 
#include <vector> 

using namespace std; 

bool Update(int ResourceID, std::string ModulePath, string FilePath) 
{ 
    HANDLE hResource = BeginUpdateResource(ModulePath.c_str(), false); 

    if (hResource != nullptr) 
    { 
     std::fstream File(FilePath.c_str(), std::ios::in | std::ios::binary); 
     if (File.is_open()) 
     { 
      File.seekg(0, std::ios::end); 
      std::size_t FileSize = File.tellg(); 
      File.seekg(0, std::ios::beg); 
      std::vector<std::uint8_t> Data(FileSize); //Also used a pointer.. makes no difference.. 
      File.read(reinterpret_cast<char*>(Data.data()), FileSize); 
      File.close(); 

      if (UpdateResource(hResource, RT_BITMAP, MAKEINTRESOURCE(ResourceID), MAKELANGID(0x0409, 0x1), Data.data(), FileSize)) 
      { 
       EndUpdateResource(hResource, false); 
       return true; 
      } 
     } 
    } 
    return false; 
} 

int main() 
{ 
    if (Update(1001, "Module.exe", "Resources/BackgroundImg.bmp")) 
    { 
     std::cout<<"Updated Successfully"; 
    } 
    else 
    { 
     std::cout<<"Failed To Update"; 
    } 
    return 0; 
} 
+0

我在你的代碼中看不到明顯的錯誤,但是如果我正確理解你有一個工作正常的原始位圖(一個原始的)和一個工作不正常的位圖,你可能會明智地檢查差異這兩個位圖之間。相同的尺寸/格式? – 2013-03-02 08:00:41

+0

我試圖甚至用完全相同的位圖替換它..仍然沒有工作:l – Brandon 2013-03-02 17:21:44

回答

6

GAAHHH!我解決了它!只是任何人閱讀,這就是答案。它是在微軟的支持舊KB-文章:http://support.microsoft.com/default.aspx?scid=kb%3ben-us%3b67883

現在,如果你不明白:

它說,從文件中位圖之間的唯一區別並且作爲資源存儲的位圖是一個是DIB,另一個是打包的DIB。這兩者之間的區別在於一個有BITMAPFILEHEADER,另一個沒有。這些資源存儲在沒有FileHeaders的地方,因此它們必須被刪除。

因此,更新的位圖的資源時,必須刪除BITMAPFILEHEADER(注意下面sizeof運算的偏移):

bool UpdateBitmap(int ResourceID, std::string ModulePath, string FilePath) 
{ 
    HANDLE hResource = BeginUpdateResource(ModulePath.c_str(), false); 

    if (hResource != nullptr) 
    { 
     std::fstream File(FilePath.c_str(), std::ios::in | std::ios::binary); 
     if (File.is_open()) 
     { 
      File.seekg(0, std::ios::end); 
      std::size_t FileSize = File.tellg(); 
      File.seekg(0, std::ios::beg); 
      std::vector<std::uint8_t> Data(FileSize); 
      File.read(reinterpret_cast<char*>(Data.data()), FileSize); 
      File.close(); 

      if (UpdateResource(hResource, RT_BITMAP, MAKEINTRESOURCE(ResourceID), MAKELANGID(0x0409, 0x1), Data.data() + sizeof(BITMAPFILEHEADER), FileSize - sizeof(BITMAPFILEHEADER))) //Notice the sizeof. 
      { 
       EndUpdateResource(hResource, false); 
       return true; 
      } 
     } 
    } 
    return false; 
} 

此代碼和所述一個在OP之間的唯一區別是在通過的sizeof偏移( BITMAPFILEHEADER)。