2013-03-02 51 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)。