替换exe中的位图资源 [英] Replacing Bitmap Resource in exe

查看:672
本文介绍了替换exe中的位图资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用WinAPI创建的程序。在程序中,我嵌入一个位图作为资源,程序加载该资源,并通过bitblt显示它作为背景图片。



下面,我创建了一个控制台程序替换WinAPI程序中的背景。它成功地替换了位图,但现在WinAPI程序不再显示一个背景了。我知道替换工作,因为使用ResourceHacker,我可以点击资源,它显示它很好。



这个截图显示它被成功替换:
< img src =http://i.stack.imgur.com/XUoNs.pngalt =enter image description here>



但是,如果我使用ResourceHacker要将图片保存到磁盘,该图片无法使用任何编辑器预览或打开:





如果我使用resourcehacker替换WinAPI程序中的图像,



<$>



<$> p $ p> //在我的WINAPI程序的资源文件中:
// IDI_ICON ICONResources / Icon.ico
// IDB_BACKGROUND BITMAP DISCARDABLEResources / BackgroundImg。 bmp

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

using namespace std;

bool更新(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 ::二进制);
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(),FileSize))
{
EndUpdateResource(hResource,假);
return true;
}
}
}
return false;
}

int main()
{
if(Update(1001,Module.exe,Resources / BackgroundImg.bmp))
{
std :: cout<<已成功更新;
}
else
{
std :: cout<<无法更新;
}
return 0;
}


解决方案

GAAHHH!我解决了!只是对于任何人阅读,这是答案。这是一个老kb文章对微软的支持: http://support.microsoft.com/default.aspx?scid=kb%3ben-us%3b67883



现在,如果您不明白它:



它说,文件的位图和存储为资源的位图之间的唯一区别是一个是DIB,另一个是打包的DIB。这两者的区别是,一个有BITMAPFILEHEADER,另一个没有。



因此,在更新位图资源时,必须删除BitmapFileHeader(注意下面的SizeOf偏移量):

/ p>

  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 ::二进制);
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)))的大小。
{
EndUpdateResource(hResource,false);
return true;
}
}
}
return false;
}

此代码与OP中的唯一区别是偏移量sizeof(BITMAPFILEHEADER)。


I have a program created using WinAPI. Within the program, I embedded a bitmap as a resource and the program loads that resource and displays it as a background image via bitblt.

Below, I created a console program to replace the background in the WinAPI program. It successfully replaces the bitmap but now the WinAPI program does not display a background anymore. I know the replacement worked because using ResourceHacker, I can click on the resource and it display it fine.

This screenshot shows that it was replaced successfully:

However, if I use ResourceHacker to save the image back to the disk, the image cannot be previewed or opened with any editors:

If I use resourcehacker to replace the image within the WinAPI program, it works just fine and the program displays it as the background.

With all that being said, can anyone explain what I did wrong below?

//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;
}

解决方案

GAAHHH! I solved it! Just for anyone reading, this is the answer.. It's an old kb-article on Microsoft's support: http://support.microsoft.com/default.aspx?scid=kb%3ben-us%3b67883

Now if you don't understand it:

It says that the only difference between a bitmap from file and a bitmap stored as a resource is that one is a DIB and the other is a packed DIB. The difference between these two is that one has the BITMAPFILEHEADER and the other does not. The resources are stored without the FileHeaders so they must be removed.

Thus, when updating a bitmap resource, you must REMOVE the BitmapFileHeader (notice the SizeOf offset below):

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;
}

The only difference between this code and the one in the OP is the offset by sizeof(BITMAPFILEHEADER).

这篇关于替换exe中的位图资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆