在构造函数中创建hbitmap返回NULL

SelectObject returns NULL with hbitmap created in constructor

本文关键字:返回 NULL hbitmap 创建 构造函数      更新时间:2023-10-16

我有一个位图类,它有一个加载函数,用于从文件路径或资源ID加载位图。

    void GtBitmap::Load()
    {
        LPTSTR szFileName;
        szFileName = (LPTSTR)m_strPath.c_str();
        // Check for valid .BMP file path
        if (m_strPath.size() > 0)
        {
            // Open .BMP file
            m_pFile = fopen(m_strPath.c_str(), ("rb"));
            if (m_pFile != NULL)
            {
                m_hBitmap = (HBITMAP)LoadImage  (GetModuleHandle(NULL), szFileName, IMAGE_BITMAP, 0, 0, LR_SHARED | LR_LOADFROMFILE);
                GetObject(m_hBitmap, sizeof(m_bmap), &m_bmap);
                int i = 1;
            }   
        }
        else if (m_intResourceID != 0)
        {
            m_hBitmap = (HBITMAP)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(m_intResourceID), IMAGE_BITMAP, 0, 0, LR_SHARED);
            GetObject(m_hBitmap, sizeof(m_bmap), &m_bmap);
            int i = 1;
        }
    }

然而,当我试图在我的代码块中呈现它时,SelectObject返回null。下面是painter类那一部分的代码。

    void  GtPainterGDI::GtDrawBitmap(GtRectI & target, GtBitmap & bitmap, bool blnOffset)
    {
        GtCanvas topCv = m_arrCanvas.back();
        HDC hdcMem = CreateCompatibleDC(topCv.m_hdcParent);
        HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, bitmap.m_hBitmap);
        DWORD lastError = GetLastError();
        bool success = BitBlt(hdcMem, target.GetLeft(), target.GetTop(), 
            target.Width(), target.Height(), hdcMem, 0, 0, SRCCOPY);
        SelectObject(hdcMem, bitmap.m_hBitmap);
        DeleteDC(hdcMem);
    };

SelectObject()返回null并且不绘制图像。如果我在那个paint函数中使用LoadImage(),我只能让图像显示出来。但是,我不想每次想要绘制时都加载图像。我应该能够在load函数或位图的构造函数中加载图像一次,然后在paint函数中使用句柄。

如果有人可以提供一个在构造函数中加载图像的例子,然后在代码WM_PAINT或等效绘画函数的其他地方绘制它,我会很感激。该代码是GT图形用户界面库的新版本。我计划在未来几天左右在codeproject上发布一个新版本。我得先打扫一下……

从文件中加载图像时,LoadImage中的HINSTANCE参数应为NULL

仅在从资源加载时使用GetModuleHandle(NULL)
m_hBitmap = (HBITMAP)LoadImage(NULL, m_strPath.c_str(), 
    IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if (!m_hBitmap)
{
    //report error
}

这里也不需要LR_SHARED

当测试文件是否存在时,可以使用std::ifstream。例子:

#include <fstream>
...
bool test = std::ifstream(m_strPath).good();

这将测试文件并立即关闭文件句柄。

请确保在删除hdcMem之前选择hbmOld:

HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, bitmap.m_hBitmap);
BitBlt(...)
//SelectObject(hdcMem, bitmap.m_hBitmap); <<= remove this
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);