每当我的应用程序尝试创建 DIB 部分时,无论是通过调用 CreateDIBSection(),还是通过使用以下命令调用 LoadImage() LR_CREATEDIBSECTION flag,看来返回成功了。这 HBITMAP 它返回是有效的,我可以很好地操作和显示它。

但是,调用 GetLastError() 将返回 8: Not enough storage is available to process this command. 从第一次调用到最后一次调用都会发生这种情况。所请求的位图的大小似乎无关紧要;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 );

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

有帮助吗?

解决方案

我认为你没有遵循文档所说的内容(来自 创建DIB节):

如果函数成功,返回值是新创建的dib的处理, *ppvBits 指向位图位值。

如果功能失败,返回值为 NULL, , 和 *ppvBitsNULL.

该函数可以返回以下值。[...]

如果返回值不是 NULL, ,函数成功。呼唤 GetLastError 不一定会返回任何有关成功的可靠且有意义的信息(来自 获取最后一个错误):

如果未记录该函数以设置最后一个错误代码,则此函数返回的值只是设置的最新最后一个错误代码。某些功能将最后一个错误代码设置为成功,而另一些功能则没有。

其他提示

还等什么? CreateDIBSection是一个复杂的函数,它利用许多其他的Windows API的完成其工作。一些的的的API可以设置的最后一个错误,以反映的及其的内部状态。 CreateDIBSection不会清除错误,只是使得可以返回0时,它不会失败。

在合同说,当出现故障时,GetLastError函数设置为一个有意义的值。这并不是说,过去的错误值有什么意义时CreateDIBSection不会返回调用者

它很可能是,如果存在一个缺乏存储器,一个异常获取引发和/或简化代码的最后误差值简单地被抢先设置靠近分配的顶部上,使得它的正确设置,没有进一步的努力应的分配失败或抛出异常。

我记得,在某些情况下,为了调用任何API函数之前得到GetLastError你必须调用SetLastError(0)可靠的值,再后来你会得到正确的错误with GetLastError()。因为在该情况下它成功它没有被更新。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top