CreateDIBSection deixando 'o suficiente Não armazenamento' de erro, mas parece ainda funcionar de qualquer maneira

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

Pergunta

Sempre que minhas tentativas de aplicativos para criar uma seção DIB, quer chamando CreateDIBSection (), ou ligando para LoadImage () com o sinalizador LR_CREATEDIBSECTION, parece retornar com sucesso. O HBITMAP ele retorna é válido, e eu posso manipular e exibi-lo muito bem.

No entanto, chamadas para GetLastError () irá retornar 8: Not enough storage is available to process this command. Isso acontece desde a primeira chamada para o último. O tamanho do bitmap solicitada parece irrelevante; 800x600 ou 16x16, mesmo resultado. Imediatamente antes da chamada de função, GetLastError () retorna nenhum erro; Além disso, chamar SetLastError (0) antes da chamada de função tem o mesmo resultado.

Eu encontrei outras pessoas fazendo perguntas semelhantes, mas ele quer Acontece que eles estão usando CreateCompatibleBitmap () e o problema desaparece quando mudar para CreateDIBSection (), ou eles já estão usando CreateDIBSection () eo resultado ele retorna é inválido e, portanto, não está funcionando.

Uma vez que as coisas parecem estar a trabalhar, eu pensei que eu poderia simplesmente ignorá-la (e SetLastError chamada (0) depois de chamadas para qualquer função), mas poderia haver algum problema sutil estou com vista ao fazê-lo.

E, claro, aqui está parte do código básico que eu estou usando. Em primeiro lugar, a chamada para LoadImage (), que faz parte de uma classe de bitmap básico que eu uso para um monte de coisas, e que eu simplifiquei um pouco para mostrar os aspectos mais relevantes:

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 );
}

As chamadas para CreateDIBSection são tipicamente feito ao atualizar uma janela em camadas:

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 );

Os ponteiros sobre qualquer coisa que eu estou completamente fora da base sobre seria apreciada.

Foi útil?

Solução

Eu acho que você não está seguindo o que diz a documentação (de CreateDIBSection ):

Se a função tiver êxito, o retorno valor é um identificador para o recém-criado DIB, e *ppvBits aponta para o bitmap bit valores.

Se a função falhar, o retorno valor é NULL e *ppvBits é NULL.

Esta função pode retornar o seguinte valor. [...]

Se o valor de retorno não é NULL, a função sucedido. Chamando GetLastError não vai necessariamente retornar qualquer informação confiável significativa em caso de sucesso (de GetLastError ):

Se a função não está documentada para definir o último código de erro, o valor retornado por esta função é simplesmente o mais recente código último erro para foram criados; algumas funções definir o último código de erro para 0 em caso de sucesso e outros não.

Outras dicas

Então, o que? CreateDIBSection é uma função complicada que faz uso de muitas APIs outras janelas fazer o seu trabalho. Alguns dos os APIs poderia definir o último erro para refletir sua estado interno. CreateDIBSection não vai eliminar o erro, apenas para que a 0 pode ser devolvido quando não falham.

diz que o contrato, quando ele falhar, GetLastError é definida para um valor significativo:. Ela não diz que o último valor de erro tem qualquer significado para o chamador quando CreateDIBSection faz retorno

Sua bastante possível que, se há uma falta de memória, uma exceção é jogado e / ou para simplificar o código do último valor de erro simplesmente fica preventivamente situado perto do topo das atribuições tal que a sua corretamente configurado sem mais esforço devem as alocações falhar ou lançar uma exceção.

Lembro-me que, em alguns casos, a fim de obter um valor fiável de GetLastError você tem que SetLastError(0) chamada antes de chamar qualquer função de API e depois você começa a with GetLastError() de corrigir o erro. Porque em caso que o sucedeu não estava sendo atualizado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top