c++ - CreateDIBSection 留下 'Not enough storage' 错误,但似乎仍然有效

标签 c++ windows bitmap dib createdibsection

每当我的应用程序尝试通过调用 CreateDIBSection() 或使用 LR_CREATEDIBSECTION 标志调用 LoadImage() 来创建 DIB 部分时,它似乎都会成功返回。它返回的 HBITMAP 是有效的,我可以很好地操作和显示它。

但是,调用 GetLastError() 将返回 8:没有足够的存储空间来处理此命令。 从第一次调用到最后一次调用都会发生这种情况。请求的位图大小似乎无关紧要; 800x600 或 16x16,结果相同。在函数调用之前,GetLastError() 没有返回任何错误;此外,在函数调用之前调用 SetLastError(0) 具有相同的结果。

我发现其他人也问过类似的问题,但事实证明他们正在使用 CreateCompatibleBitmap() 并且当他们切换到 CreateDIBSection() 时问题就消失了,或者他们已经在使用 CreateDIBSection() 并且返回的结果是无效,因此根本不起作用。

既然一切正常,我想我可以忽略它(并在调用任一函数后调用 SetLastError(0)),但这样做可能会忽略一些细微的问题。

当然,这是我正在使用的一些基本代码。首先,调用 LoadImage(),它是我用于很多事情的基本位图类的一部分,我对其进行了相当大的简化以显示更相关的方面:

bool Bitmap::Load( const char* szBitmapName, /*...*/ )
{
   m_hBitmap = (HBITMAP)LoadImage( GetModuleHandle( NULL ), szBitmapName,
            IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE );
   //...
}
// ...
Bitmap::~Bitmap()
{
   if( m_hBitmap ) DeleteObject( m_hBitmap );
}
bool Bitmap::Draw( HDC hDC, int iDstX, int iDstY, int iDstWidth,
                   int iDstHeight, int iSrcX, int iSrcY, int iSrcWidth,
                   int iSrcHeight, bool bUseMask ) const
{
   HDC hdcMem = CreateCompatibleDC( hDC );
   if( hdcMem == NULL ) return false;
   HBITMAP hOld = (HBITMAP)SelectObject( hdcMem, m_hBitmap );
   BLENDFUNCTION blendFunc;
   blendFunc.BlendOp = AC_SRC_OVER;
   blendFunc.BlendFlags = 0;
   blendFunc.AlphaFormat = AC_SRC_ALPHA;
   blendFunc.SourceConstantAlpha = 255;
   AlphaBlend( hDC, iDstX, iDstY, iDstWidth, iDstHeight, hdcMem, iSrcX,
               iSrcY, iSrcWidth, iSrcHeight, blendFunc );
   SelectObject( hdcMem, hOld );
   DeleteDC( hdcMem );
}

对 CreateDIBSection 的调用通常在更新分层窗口时完成:

HDC hDCScreen( GetDC(0) );
POINT tSourcePos = { 0, 0 };
HDC hDCSource( CreateCompatibleDC( hDCScreen ) );
// iWidth and iHeight are used both for the bitmap size and window size
// to keep this example simpler
BITMAPINFO bi32 = {0};
bi32.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi32.bmiHeader.biWidth = iWidth;
bi32.bmiHeader.biHeight = iHeight;
bi32.bmiHeader.biPlanes = 1;
bi32.bmiHeader.biBitCount = 32;
bi32.bmiHeader.biCompression = BI_RGB;
void* pBits = NULL;
HBITMAP hBitmap = CreateDIBSection(NULL, &bi32, DIB_RGB_COLORS,
                  (void**)&pBits, NULL, NULL);

HBITMAP hOldBitmap = (HBITMAP)SelectObject( hDCSource, hBitmap );
POINT tWindowPos = { 0, 0 };
SIZE tWindowSize = { iWidth, iHeight };
BLENDFUNCTION blendFunction = {0};
blendFunction.BlendOp = AC_SRC_OVER;
blendFunction.SourceConstantAlpha = 255;
blendFunction.AlphaFormat = AC_SRC_ALPHA;
DWORD iFlags( ULW_ALPHA );

// m_tBitmap is an instance of Bitmap class previously mentioned
m_tBitmap.Draw( hDCSource, 0, 0, iWidth, iHeight, 0, 0, iWidth, iHeight );
UpdateLayeredWindow( GetHandle(), hDCScreen, &tWindowPos, &tWindowSize,
                     hDCSource, &tSourcePos, 0, &blendFunction, iFlags );
SelectObject( hDCSource, hOldBitmap );
DeleteObject( hBitmap );
DeleteDC( hDCSource );
ReleaseDC( 0, hDCScreen );

任何关于我完全偏离基础的事情的任何指示都将不胜感激。

最佳答案

我认为您没有遵循文档中的内容(来自 CreateDIBSection):

If the function succeeds, the return value is a handle to the newly created DIB, and *ppvBits points to the bitmap bit values.

If the function fails, the return value is NULL, and *ppvBits is NULL.

This function can return the following value. [...]

如果返回值不是NULL,则函数成功。调用 GetLastError 不一定会返回任何可靠且有意义的成功信息(来自 GetLastError ):

If the function is not documented to set the last-error code, the value returned by this function is simply the most recent last-error code to have been set; some functions set the last-error code to 0 on success and others do not.

关于c++ - CreateDIBSection 留下 'Not enough storage' 错误,但似乎仍然有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2418776/

相关文章:

windows - IFileDialog:添加自定义位置 - 并选择该位置

java - 如何在android中的视频上添加应用程序 Logo

c++ - 编译器是如何从 map 中找出模板类型的

c++ - 如何计算两个玩家之间的回文游戏的总分?

c++ - 在 Qt 应用程序中使用 sleep_for()

android - 当 Canvas 设置为位图时,Android.Graphics.Camera 在哪里设置其 X、Y 和 Z 轴?

android - 在android中动画位图图像

C++、三元运算符和 cout

windows - 如何更新 Perl 脚本以在 MS Windows 上运行

c++ - 如何修复 R6031 - 尝试多次初始化 CRT。这表明您的应用程序中存在错误?