CreateDIBSection에서 '저장 공간 부족' 오류가 발생하지만 어쨌든 여전히 작동하는 것 같습니다.

StackOverflow https://stackoverflow.com/questions/2418776

문제

내 앱이 CreateDIBSection()을 호출하거나 LoadImage()를 호출하여 DIB 섹션을 생성하려고 할 때마다 LR_CREATEDIBSECTION 플래그가 성공적으로 반환된 것 같습니다.그만큼 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, 그리고 *ppvBits ~이다 NULL.

이 함수는 다음 값을 반환할 수 있습니다.[...]

반환값이 아닌 경우 NULL, 함수가 성공했습니다.부름 GetLastError 성공에 대해 신뢰할 수 있고 의미 있는 정보를 반드시 반환하지는 않습니다( 마지막 오류 가져오기):

기능이 최후의 오류 코드를 설정하도록 문서화되지 않은 경우,이 함수에 의해 리턴 된 값은 단순히 가장 최근의 마지막 오류 코드입니다.일부 기능은 성공에 대해 마지막 오류 코드를 0으로 설정하고 다른 기능은 그렇지 않습니다.

다른 팁

그래서 뭐?CreateDIBSection은 다른 많은 Windows API를 사용하여 작업을 수행하는 복잡한 함수입니다.일부 저것들 API는 마지막 오류를 반영하도록 설정할 수 있습니다. 그들의 내부 상태.CreateDIBSection은 오류를 지우지 않고 실패하지 않을 때 0을 반환할 수 있도록 합니다.

계약에 따르면 실패하면 GetLastError가 의미 있는 값으로 설정됩니다.CreateDIBSection이 반환될 때 마지막 오류 값이 호출자에게 어떤 의미가 있다고 말하지 않습니다.

메모리가 부족한 경우 예외가 발생하거나 코드를 단순화하기 위해 마지막 오류 값이 할당 상단 근처에 선제적으로 설정되어 추가 노력 없이 올바르게 설정될 가능성이 높습니다. 실패하거나 예외가 발생합니다.

어떤 경우에는 신뢰할 수 있는 값을 얻기 위해 GetLastError 전화해야 해 SetLastError(0) API 함수를 호출하기 전에 나중에 올바른 오류가 발생합니다. with GetLastError().성공한 경우 업데이트되지 않았기 때문입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top