如何将HBITMAP从GDI+ Bitmap中分离,避免原对象销毁后失效?
解决GDI+ Bitmap转HBITMAP后对象失效的问题
问题根源在于:GetHBITMAP返回的HBITMAP与原GDI+ Bitmap共享底层像素数据,当原Bitmap对象超出作用域被析构时,其占用的内存会被释放,导致关联的HBITMAP失效。要实现HBITMAP与原Bitmap完全分离,需要创建一个独立的HBITMAP并复制像素数据,彻底解绑依赖关系。
实现思路
- 获取原GDI+ Bitmap的像素数据与格式信息
- 创建独立的DIBSection类型HBITMAP(该类型拥有独立内存空间,不依赖原对象)
- 将原Bitmap的像素数据完整复制到新HBITMAP的缓冲区
- 确保原Bitmap销毁后,新HBITMAP可正常使用
完整代码示例
#include <GdiPlus.h> #include <cstring> #pragma comment(lib, "Gdiplus.lib") HBITMAP GDIBITMAPToIndependentHBitmap() { int width = 500; int height = 500; // 创建原GDI+ Bitmap并执行绘图操作 Gdiplus::Bitmap myBitmap(width, height, Gdiplus::PixelFormat32bppRGB); Gdiplus::Graphics g(&myBitmap); Gdiplus::Pen blackpen(Gdiplus::Color(255, 0, 0, 0), 3); g.DrawRectangle(&blackpen, 10, 10, width - 20, height - 20); // 锁定原Bitmap获取像素数据 Gdiplus::BitmapData bitmapData; Gdiplus::Rect rect(0, 0, width, height); if (myBitmap.LockBits(&rect, Gdiplus::ImageLockModeRead, Gdiplus::PixelFormat32bppRGB, &bitmapData) != Gdiplus::Status::Ok) { return nullptr; } // 构造BITMAPINFO用于创建独立HBITMAP BITMAPINFO bmpInfo = {0}; bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmpInfo.bmiHeader.biWidth = width; bmpInfo.bmiHeader.biHeight = -height; // 负高度表示原点在图像顶部,与GDI+一致 bmpInfo.bmiHeader.biPlanes = 1; bmpInfo.bmiHeader.biBitCount = 32; bmpInfo.bmiHeader.biCompression = BI_RGB; bmpInfo.bmiHeader.biSizeImage = width * height * 4; void* pNewBits = nullptr; HBITMAP hIndependentBitmap = CreateDIBSection(nullptr, &bmpInfo, DIB_RGB_COLORS, &pNewBits, nullptr, 0); if (!hIndependentBitmap || !pNewBits) { myBitmap.UnlockBits(&bitmapData); return nullptr; } // 复制像素数据到新HBITMAP memcpy(pNewBits, bitmapData.Scan0, bmpInfo.bmiHeader.biSizeImage); // 解锁原Bitmap myBitmap.UnlockBits(&bitmapData); return hIndependentBitmap; }
关键注意事项
- 使用
LockBits/UnlockBits是安全访问GDI+ Bitmap像素数据的标准方式,避免直接内存访问的风险 CreateDIBSection创建的HBITMAP拥有独立内存,完全脱离原GDI+ Bitmap的依赖- 使用完独立HBITMAP后,必须调用
DeleteObject(hIndependentBitmap)释放内存,避免泄漏
内容的提问来源于stack exchange,提问作者user20716902
相关产品推荐
相关产品推荐

