Замена растрового ресурса в exe

У меня есть программа, созданная с использованием WinAPI. В программу я встроил растровое изображение в качестве ресурса, и программа загружает этот ресурс и отображает его как фоновое изображение с помощью bitblt.

Ниже я создал консольную программу для замены фона в программе WinAPI. Он успешно заменяет растровое изображение, но теперь программа WinAPI больше не отображает фон. Я знаю, что замена сработала, потому что с помощью ResourceHacker я могу нажать на ресурс, и он будет отображаться нормально.

Этот скриншот показывает, что он был успешно заменен:
введите описание изображения здесь

Однако, если я использую ResourceHacker для сохранения изображения обратно на диск, изображение не может быть предварительно просмотрено или открыто с помощью любых редакторов:

введите описание изображения здесь

Если я использую 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;
}

2

Решение

GAAHHH! Я решил это! Просто для тех, кто читает, это ответ. Это старая статья о поддержке Microsoft: 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 — это смещение по размеру (BITMAPFILEHEADER).

6

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector