Win32 Loadimage 生成错误 1812 和 1813

Posted

技术标签:

【中文标题】Win32 Loadimage 生成错误 1812 和 1813【英文标题】:Win32 Loadimage generates error 1812 and 1813 【发布时间】:2015-08-06 14:31:53 【问题描述】:

我在编写扫雷游戏时遇到了这个问题。我使用位图来表示数字、地雷和空白。我想我已经在资源文件中正确注册了它们

IDI_0                   BITMAP                  "D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\empty.bmp"
IDI_1                   BITMAP                  "D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\1.bmp"
IDI_2                   BITMAP                  "D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\2.bmp"
IDI_3                   BITMAP                  "D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\3.bmp"

还有头文件

#define IDI_0                           200
#define IDI_1                           201
#define IDI_2                           202
#define IDI_3                           203

我像这样加载它们

h0 = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(IDI_0), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
h1 = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(IDI_1), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
h2 = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(IDI_2), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
h3 = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(IDI_3), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);

我还用resourcehacker检查了exe文件,发现里面所有的位图。

我不明白的是,只有在我运行游戏时有时(~50%)才会弹出

Error 1812: The specified image file did not contain a resource section. 

Error 1813: The specified resource type cannot be found.

但是如果我从这样的文件中加载它们

h0 = (HBITMAP)LoadImage(NULL, L"D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\empty.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
h1 = (HBITMAP)LoadImage(NULL, L"D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\1.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
h2 = (HBITMAP)LoadImage(NULL, L"D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\2.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
h3 = (HBITMAP)LoadImage(NULL, L"D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\3.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);

一切正常。

任何想法或建议将不胜感激。谢谢!

【问题讨论】:

可能你的hInst参数不正确,你可以记录下所有参数,用FindResource判断资源是否存在。 @Jichao 感谢您的回复!我使用了vs2013生成的starter code,包括window class init和registers。我有什么需要改变的吗?以及为什么它只出错一半的任何想法? 只是猜测;但是您愿意将 LR_CREATEDDIBSECTION 更改为 LR_DEFAULTCOLOR 吗?我只是不熟悉这个值。 您可以尝试将 hInst 替换为 GetMoudleHandle(NULL)。如果这不起作用,请尝试创建一个 MCVE,您可能会这样发现自己的错误:***.com/help/mcve 您应该弄清楚为什么 hInst 值不正确。您可能正在超出缓冲区或其他内容。 【参考方案1】:

我个人会考虑使用 GDI+ 来加载您的图像。您仍然可以从磁盘文件或应用程序的资源部分加载。它还使您可以访问 Windows 原生支持的所有图像格式(BMP、GIF、JPEG、PNG、TIFF、Exif、WMF 和 EMF)

要使用它,您只需先初始化 GDI+,然后在程序退出前执行关机。

这是我用来从磁盘文件加载的函数:

// BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF
HBITMAP mLoadImageFile(wchar_t *filename)

    HBITMAP result = NULL;
    Bitmap bitmap(filename, false);
    bitmap.GetHBITMAP(0, &result);
    return result;

如果我们有一个包含以下内容的资源文件:

IDR_PNG1           RT_PNG            ".\\girl.png"
IDR_JPG1           RT_JPG            ".\\rssLogo.jpg"

然后我们可以这样加载每个图像:

HBITMAP png = loadImgResource(IDR_PNG1, L"RT_PNG");
HBITMAP jpg = loadImgResource(IDR_JPG1, L"RT_JPG");

还有我用来从资源加载的两个函数。您会注意到我在第二个函数的 GetModuleHandle(0) 中进行了硬编码 - 如果您想从当前模块以外的任何模块(dll、exe)中读取,请更改此设置。

// BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF
HBITMAP loadImgResource(wchar_t *pName, wchar_t *pType, HMODULE hInst)

    Gdiplus::Bitmap *m_pBitmap;
    HBITMAP result=NULL;

    HRSRC hResource = FindResource(hInst, pName, pType);
    if (!hResource)
        return NULL;

    DWORD imgSize = SizeofResource(hInst, hResource);
    if (!imgSize)
        return NULL;

    const void *pResourceData = LockResource(LoadResource(hInst, hResource));
    if (!pResourceData)
        return NULL;

    HANDLE m_hBuffer = GlobalAlloc(GMEM_MOVEABLE, imgSize);
    if (m_hBuffer)
    
        void* pBuffer = GlobalLock(m_hBuffer);
        if (pBuffer)
        
            CopyMemory(pBuffer, pResourceData, imgSize);
            IStream* pStream = NULL;
            if (CreateStreamOnHGlobal(m_hBuffer, FALSE, &pStream) == S_OK)
            
                m_pBitmap = Gdiplus::Bitmap::FromStream(pStream);
                pStream->Release();
                if (m_pBitmap)
                
                    if (m_pBitmap->GetLastStatus() == Gdiplus::Ok)
                    
                        m_pBitmap->GetHBITMAP(0, &result);
                        delete m_pBitmap;
                    
                
            
            GlobalUnlock(m_hBuffer);
        
        GlobalFree(m_hBuffer);
    
    return result;


HBITMAP loadImgResource(WORD resNum, LPWSTR pType)

    return loadImgResource(MAKEINTRESOURCE(resNum), pType, GetModuleHandle(0));//hInst);

【讨论】:

为什么选择 GDI+,而不是 Windows Imaging Component? (a) 因为我已经熟悉它,(b) 因为使用 WIC 的代码看起来很重的 COM 接口。从来都不是一件特别令人愉快的事情——尤其是使用非微软工具。什么,如果使用 WIC 有什么好处?我仍然可以在不使用诸如 crinkler 之类的外来链接器或诸如 UPX 之类的 exe 打包器的情况下抽出一个 10kb 以下的 exe 吗? 为什么 WIC 会比 GDI+ 添加更多有效负载?这不像按需解码器以某种方式静态链接到可执行映像中。至于涉及的 COM:您需要CoCreate 工厂,要求基于文件流的解码器,并解码您感兴趣的帧。这很容易使用任何工具集。如果您有兴趣,请参阅WIC Image Viewer Using Direct2D Sample。或者看看一些decoder sample code。 我不太了解 WIC。如果一个 DLL 导出的函数比另一个 DLL 少,并且使用了所有导出的函数,那么静态大小会有所不同,不是吗?至于样本 - 来自 MS 站点的 WIC 复制/粘贴样本无法编译 - 未找到 Wincodecsdk.h 文件。另一方面,GDI+ 的东西直接开箱即用,与 MASM 一起使用很简单。 Direct2D 是另一种我并不完全迷恋的技术。 GDI+ 可以正常工作,并且在我需要的情况下使用,比您迄今为止提出的任何方法都简单得多。你有答案,还是只是问题? 另外,对于一个如此讨厌 COM 的人来说,见证他们对IStreams 的热爱是令人惊讶的。有了这个,您可以将 IStream 与 WIC 一起使用,然后在其上调用 CreateDecoderFromStream。这几乎没有更多的努力。另一个(潜在)优势:WIC 可用于 Windows 应用商店应用程序,而 GDI+ 不可用。

以上是关于Win32 Loadimage 生成错误 1812 和 1813的主要内容,如果未能解决你的问题,请参考以下文章

win32创建工具栏的自定义图标

从 Win32 项目中的 *.bmp 文件加载 HBITMAP

win32—— hIcon hCursor hbrBackground

在python中使用win32在内存中创建一个图标

基于GDI显示png图像

win32: 制作带ALPHA通道的bmp,添加到静态文本控件上,达到背景透明效果