2

我有一个使用 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;
}
4

1 回答 1

6

啊啊啊!我解决了!对于任何阅读的人来说,这就是答案。这是一篇关于微软支持的旧 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) 的偏移量。

于 2013-03-02T19:29:18.390 回答