每当我的应用程序尝试创建DIB部分时,无论是通过调用CreateDIBSection(),还是通过使用LR_CREATEDIBSECTION标志调用LoadImage(),它似乎都能成功返回。它返回的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 );任何关于我完全错误的建议都将不胜感激。
发布于 2010-03-11 01:21:49
我认为你没有按照文档所说的去做(来自CreateDIBSection
如果函数成功,则返回值是新创建的DIB的句柄,并且
*ppvBits指向位图位值。
如果函数失败,则返回值为NULL,*ppvBits为NULL。
此函数可以返回下列值。..。
如果返回值不是NULL,则函数执行成功。调用GetLastError不一定会在成功时返回任何可靠的有意义的信息(来自GetLastError
如果函数没有用于设置上一个错误代码的文档,则此函数返回的值只是最近设置的最后一个错误代码;一些函数在成功时将最后一个错误代码设置为0,而其他函数则不这样做。
发布于 2010-03-11 03:28:47
那又怎么样?CreateDIBSection是一个复杂的函数,它使用了许多其他的windows API来完成它的工作。其中一些API可以设置最后一个错误来反映它们的内部状态。CreateDIBSection不会清除错误,只是为了在不失败时返回0。
约定说,当它失败时,GetLastError被设置为一个有意义的值:当CreateDIBSection返回时,它不会说最后一个错误值对调用者有任何意义。
很有可能的是,如果内存不足,就会抛出异常,和/或为了简化代码,最后一个错误值只是在分配的顶部附近被抢先设置,以便在分配失败或抛出异常的情况下不需要进一步的努力就能正确设置。
发布于 2010-03-11 01:24:48
我记得在某些情况下,为了从GetLastError获得一个可靠的值,你必须在调用任何api函数之前调用SetLastError(0),然后你会得到正确的错误with GetLastError()。因为在它成功的情况下,它不会被更新。
https://stackoverflow.com/questions/2418776
复制相似问题