CreateDIBSection verlassen ‚nicht genügend Speicher‘ Fehler, scheint aber trotzdem noch arbeiten

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

Frage

Jedes Mal, wenn meine Anwendung versucht, einen DIB-Abschnitt, entweder durch den Aufruf CreateDIBSection () oder telefonisch unter Loadimage () mit der LR_CREATEDIBSECTION Flagge zu erstellen, so scheint es, erfolgreich zurückzukehren. Die HBITMAP kehrt gültig ist, und ich kann es manipulieren und zeigen nur in Ordnung.

Allerdings ruft GetLastError () wird 8: Not enough storage is available to process this command. zurückkehren Das zur letzten vom ersten Anruf passiert. Die Größe der Bitmap angefordert scheint belanglos; 800x600 oder 16x16, das gleiche Resultat. Unmittelbar vor dem Funktionsaufruf, GetLastError () gibt keinen Fehler; zusätzlich Aufruf SetLastError (0) vor dem Funktionsaufruf hat das gleiche Ergebnis.

Ich habe andere Leute zu fragen ähnliche Fragen gefunden, aber es entweder stellt sich heraus, sie CreateCompatibleBitmap () verwenden und das Problem verschwindet, wenn sie zu CreateDIBSection wechseln (), oder sie sind bereits CreateDIBSection () und das Ergebnis kehrt mit ist ungültig und so ist gar nicht funktioniert.

Da die Dinge scheinen zu funktionieren, ich habe gedacht, ich konnte es einfach ignorieren (und rufen SetLastError (0) nach Anrufen zu jeder Funktion), aber es gibt einige subtile Problem sein, die ich mit Blick auf bin von so tun.

Und natürlich ist hier einige der grundlegenden Code Ich verwende. Zunächst wird der Aufruf von Loadimage (), der Teil einer grundlegenden Bitmap-Klasse, die ich für eine Menge Dinge zu verwenden, und die ich ziemlich viel vereinfachte, um die relevanten Aspekte zeigen:

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

Anrufe zu CreateDIBSection sind in der Regel durchgeführt, wenn ein geschichtetes Fenster Aktualisierung:

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

Alle Hinweise über alles, was ich völlig off-base bin über geschätzt würde.

War es hilfreich?

Lösung

Ich glaube, Sie folgen nicht, was die Dokumentation sagt (von CreateDIBSection ):

  

Wenn die Funktion erfolgreich ist, die Rückkehr   Wert ist ein Handgriff in die neu geschaffenen   DIB und *ppvBits Punkte der Bitmap   Bit-Werte.

     

Wenn die Funktion fehlschlägt, die Rückkehr   Wert ist NULL und *ppvBits ist NULL.

     

Diese Funktion kann den folgenden Wert zurück. [...]

Wenn der Rückgabewert nicht NULL gelang es die Funktion. GetLastError Aufruf wird jede zuverlässig aussagekräftige Informationen über den Erfolg nicht unbedingt zurückkehren (von

Andere Tipps

So what? CreateDIBSection ist eine komplizierte Funktion, die Verwendung von vielen anderen Windows-APIs seine Aufgabe macht. Einige von jene APIs könnte den letzten Fehler auf reflektieren ihren internen Zustand. CreateDIBSection nicht den Fehler löschen gehen, nur so, dass eine 0 zurückgegeben werden können, wenn es nicht ausfällt.

Der Vertrag sagt, wenn es fehlschlägt, GetLastError auf einen sinnvollen Wert gesetzt wird. Es nicht sagen, dass der letzte Fehlerwert keine Bedeutung für den Anrufer hat, wenn CreateDIBSection zurückkehrt

Seine durchaus möglich, dass, wenn es einen Mangel an Speicher vorhanden ist, wird eine Ausnahme ausgelöst und / oder den Code der letzte Fehlerwert einfach präventiv in der Nähe der Spitze der Zuweisungen eingestellt wird vereinfacht, so dass seine korrekt ohne weiteren Aufwand gesetzt die Zuweisungen ausfallen sollte oder eine Ausnahme auslösen.

Ich erinnere mich, dass in einigen Fällen, um einen zuverlässigen Wert von GetLastError erhalten Sie SetLastError(0) vor dem Aufruf jede api-Funktion aufrufen und dann später erhalten Sie den richtigen Fehler with GetLastError(). Denn in dem Fall, dass es gelungen, es wurde nicht aktualisiert.

scroll top