Why does CreateCompatibleBitmap fail?

02-02-2005, 02:10 PM
On my friend's machine (1gb RAM) it fails to create the compatible bitmap I need. I guess it's because the bitmap's dimensions are too big for VB6 to hold? But then again, my machine (1gb RAM also, and another with 256mb RAM) does create the bitmap. If my friend resizes the graphic loaded into imgAU1 to half its size it works. Maybe I should explain how it works and maybe then you can think of why it fails or if there is a more efficient, less memory intensive method.

intScrnWidth = Screen.Width / Screen.TwipsPerPixelX
intScrnHeight = Screen.Height / Screen.TwipsPerPixelY

'Step 1, create my main buffer, (myBackBuffer (backbuffer park demo))
myBackBuffer = CreateCompatibleDC(GetDC(0))

'Step 2, create the compatible bitmap for myBackBuffer, size of the screen with:
myBufferBMP = CreateCompatibleBitmap(GetDC(0), intScrnWidth, intScrnHeight)
'this one works fine

'Step 3, select them together with:
SelectObject(myBackBuffer, myBufferBMP)

'Step 4) loads the main graphic in my program, which is 3260 pixels wide by 5880 pixels tall, huge
imgAU1 = LoadGraphicDC(strImageName)
'LoadGraphicDC function from backbuffer park demo, below. This also loads fine by itself

'before the objects are loaded, create the object buffer, like above, with these:
myObjectBuffer = CreateCompatibleDC(GetDC(0)) 'works fine
myObjectBMP = CreateCompatibleBitmap(GetDC(0), imgInfo.BmWidth, imgInfo.BmHeight) 'THIS is the one that fails
SelectObject myObjectBuffer, myObjectBMP 'this also fails because myObjectBMP failed
'imgInfo is the User Defined Type BITMAPINFO that was used with GetObject earlier. They are set right.

The program works mainly by the Draw() sub below.. It basically fills the buffer with black, draw the appropriate part of imgAU1 that the person wants to see then overlays the objects on top it just like the image. The Draw() sub only happens when someone pans/scrolls, zooms or at other drawing related times, like after the objects are loaded onto the buffer.

Public Function LoadGraphicDC(strFileName As String) As Long
Dim lngDCtemp As Long

lngDCtemp = CreateCompatibleDC(GetDC(0))

'load the graphic file into the DC...
SelectObject lngDCtemp, LoadPicture(strFileName)

'return the address of the file
LoadGraphicDC = lngDCtemp

End Function

Public Sub Draw()

'should first fill it with black
BitBlt myBackBuffer, 0, 0, udtLayout.Width, udtLayout.Height, 0, 0, 0, vbWhiteness

'this will load the big layout graphic into the backbuffer
StretchBlt myBackBuffer, 0, 0, udtLayout.Width, udtLayout.Height, imgAU1, _
udtLayout.XSrc, udtLayout.YSrc, udtLayout.Width / sngZoom, _
udtLayout.Height / sngZoom, vbSrcPaint

'draw the objects on top of the layout
TransparentBlt myBackBuffer, 0, 0, udtLayout.Width, udtLayout.Height, myObjectBuffer, _
udtLayout.XSrc, udtLayout.YSrc, udtLayout.Width / sngZoom, udtLayout.Height / sngZoom, _
GetPixel(myObjectBuffer, 0, 0)

'loads the completed backbuffer onto the form
BitBlt Me.hdc, udtLayout.XDest, udtLayout.YDest, udtLayout.Width, udtLayout.Height, myBackBuffer, 0, 0, vbSrcCopy


End Sub

Hope this explains it.. If not, I will be happy to try again because I'm stumped.. :confused:

02-02-2005, 02:44 PM
Maybe this is why:

Windows 95/98/Me: The created bitmap cannot exceed 16MB in size


(Yeah, thats C code, but it's the same API function) :)

02-02-2005, 02:54 PM
Hmm.. my friend doesn't have Win9x. And, the .jpg it loads into imgAU1 is 1.1mb. Although 58mb as a .bmp and in memory ;) and it always succeeds.. It just that CreateCompatibleBitmap sometimes fails. Yeah, just talked to him and he said it worked??

So the question now is.. why does it fail "sometimes"? Hmm..

02-02-2005, 02:57 PM
For one, you've created a nice memory leak by calling GetDC(0) and not storing the return for a later call to ReleaseDC. And you're also passing different DCs to the functions, since GetDC is called more than once.

02-02-2005, 03:30 PM
Ahh.. never thought of that.. :o Always assumed the way rpgnewbie did it in the backbuffer park demo was correct :(

So would this work? I guess I could use Me.hwnd for myBackBuffer as its being drawn to the screen, and use 0 for imgAU1 (in LoadGraphicDC() ) and myObjectBuffer since they will remain in memory? If not, could you give a quick example? Thanks. :)

lngRet = GetDC(Me.hwnd)
myBackBuffer = CreateCompatibleDC(lngRet)
ReleaseDC(Me.hwnd, lngRet)

lngRet = GetDC(Me.hwnd)
myBufferBMP = CreateCompatibleBitmap(lngRet, intScrnWidth, intScrnHeight)
ReleaseDC(Me.hwnd, lngRet)

SelectObject(myBackBuffer, myBufferBMP)

Sorry if I'm a pain but this is my first graphical program and I need to start somewhere.. :)

02-03-2005, 09:44 PM
Thank goodness you at least looked at rpgnewbie's BackBufferPark example. :)

But the SelectObject is actually not used to clear the bitmap from memory (at least not by itself).

It is the DeleteObject API that actually performs the function of releasing the bitmap from memory during cleanup.

Here's a couple tutorials related to working with DCs (Device Contexts):

btw - in the last tutorial "DDB" standards for "Device Dependent Bitmap", which is your basic, standard, run-of-the-mill, bitmap. Nothing special. The DDB term is just used to differentiate the old style bitmaps from the more recent DIBs (Device Independent Bitmaps)

02-04-2005, 01:28 AM
I never was using SelectObject to delete the DC?? That I took from the backbuffer park thing. What I posted last time was just my startup part so I could use DCs to hold graphical data for my program.

Anyway, maybe I should have also posted my form_unload which has always, I thought, cleaned up the DCs/bitmaps after use..

DeleteDC myBackBuffer
DeleteObject myBufferBMP

However, I will still look at those tutorials as I guess I've made sooo many mistakes that I'm suprised that my program actually works as I've inteded..

Sorry.. :( No hard feelings.. just frustrated.. Thanks for all your help everyone. :)

EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum