Strange case of CreateCompatibleBitmap and Mr. Hyde

Strange case of CreateCompatibleBitmap and Mr. Hyde

Post by Rober » Thu, 24 Feb 2005 19:26:07


I have a strange case on certain Windows 2003 Server machines, where a call
to CreateCompatibleBitmap will return zero (which I take as a failure
indicator), but when I call GetLastError, the message is "Operation
completed successfully".

When using the operation on the same machine, but using Terminal Services,
it works, only locally it fails.

Does anyone have a hint for me where I could start looking?

Thanks

Robert
 
 
 

Strange case of CreateCompatibleBitmap and Mr. Hyde

Post by Mike D Sut » Thu, 24 Feb 2005 19:37:54

> I have a strange case on certain Windows 2003 Server machines, where a call

VB makes all kinds of API calls behind the scenes, and as such the return value of GetLastError() seldom refers to the
last API call you made, instead use Err.LastDllError which should be the error result of the last call you made and will
hopefully indicate what the error was.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: XXXX@XXXXX.COM
WWW: http://www.yqcomputer.com/

 
 
 

Strange case of CreateCompatibleBitmap and Mr. Hyde

Post by Rober » Thu, 24 Feb 2005 21:24:08

Excellent point.

Thanks

Robert



call
Services,
value of GetLastError() seldom refers to the
error result of the last call you made and will
 
 
 

Strange case of CreateCompatibleBitmap and Mr. Hyde

Post by Rober » Fri, 25 Feb 2005 21:01:17

OK, now I received a meaningful error information: Insufficient Memory
Which is pretty strange: The machine has 2 GB of physical RAM, and only a
fraction of it is in use.

Robert



call
Services,
value of GetLastError() seldom refers to the
error result of the last call you made and will
 
 
 

Strange case of CreateCompatibleBitmap and Mr. Hyde

Post by Mike D Sut » Fri, 25 Feb 2005 23:03:08

> OK, now I received a meaningful error information: Insufficient Memory

Unless you specifically need a DDB, use CreateDIBSection() instead which imposes far fewer restrictions on memory.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: XXXX@XXXXX.COM
WWW: http://www.yqcomputer.com/
 
 
 

Strange case of CreateCompatibleBitmap and Mr. Hyde

Post by Rober » Sat, 26 Feb 2005 00:03:56

I'm not sure if a DIB can be applied in my case: Capturing the screen (or
part of it)

When I used a DIB, I'd have to capture using GetDIBits. However, that
function requires a device dependent Bitmap as a source. I have only a DC of
the screen, not a bitmap.
Is there a way to get a handle to a DD bitmap of the screen, without having
to copy the content of the screen to a new DD bitmap I created?

Here's the relevant part of my code:

' Create a memory device context for the copy process
hDCMemory = CreateCompatibleDC(hDCSource)
If (Not AssertRetval(hDCMemory, "Capture", "CreateCompatibleDC",
strErrorText)) Then
Call ReleaseDC(hWndSource, hDCSource)
Capture = False
Exit Function
End If

blnMemoryDCInUse = True

' Create a bitmap as buffer
hBuffer = CreateCompatibleBitmap(hDCSource, lngWidth, lngHeight)
If (Not AssertRetval(hBuffer, "Capture", "CreateCompatibleBitmap",
strErrorText)) Then
Call DeleteDC(hDCMemory)
blnMemoryDCInUse = False
Call ReleaseDC(hWndSource, hDCSource)
Capture = False
Exit Function
End If
blnBufferInUse = True

' Careful now...
' Need DoEvents to update VIS
blnTemp = gblnShutdownLock
gblnShutdownLock = True
DoEvents
gblnShutdownLock = blnTemp

hObjectPrev = SelectObject(hDCMemory, hBuffer)

' Copy the on-screen image into the memory DC, using the specified
offsets
lngRc = BitBlt(hDCMemory, 0, 0, lngWidth, lngHeight, hDCSource, _
lngOffsetX, lngOffsetY, vbSrcCopy)
If (Not AssertRetval(lngRc, "Capture", "BitBlt", strErrorText)) Then
Call DeleteObject(hBuffer)
Call DeleteDC(hDCMemory)
blnMemoryDCInUse = False
blnBufferInUse = False
Call ReleaseDC(hWndSource, hDCSource)
Capture = False
Exit Function
End If

lngBufferWidth = lngWidth
lngBufferHeight = lngHeight

hBuffer = SelectObject(hDCMemory, hObjectPrev)

Call ReleaseDC(hWndSource, hDCSource)


Robert



a
imposes far fewer restrictions on memory.
 
 
 

Strange case of CreateCompatibleBitmap and Mr. Hyde

Post by Mike D Sut » Sat, 26 Feb 2005 00:26:47

> I'm not sure if a DIB can be applied in my case: Capturing the screen (or

Despite what the documentation says GetDIBits() works just fine in DIB's, it's just generally more efficient to use the
image data directly when working with DIB's since unlike DDB's we get direct access to the underlying data. You can get
to this either by specifying a return pointer in the CreateDIBSection() call (by sure to make the ppvBits parameter
ByRef so it can return you the pointer, the default as in the API viewer is ByVal which is incorrect - Whoever decided
to declare a double pointer as ByVal really needs their heads looking at..), or alternatively call GetObject() on the
DIB handle which will fill out a BITMAP structure for you and the bmBits memory is a pointer to the DIB data. This is a
lot quicker than GetDIBits() since no copying to the data needs to take place and using a little bit of hacking you can
even make the data this points to 'VB friendly' by temporarily pointing an array at it - See the DIB article on my site
for more on this.


Try something like:

'***
Private Declare Function ReleaseDC Lib "User32.dll" ( _
ByVal hWnd As Long, ByVal hDC As Long) As Long
Private Declare Function GetWindowDC Lib "User32.dll" (ByVal hWnd As Long) As Long
Private Declare Function GetCurrentObject Lib "GDI32.dll" ( _
ByVal hDC As Long, ByVal uObjectType As Long) As Long

Private Const OBJ_BITMAP As Long = 7

Private Sub Form_Click()
Dim DeskDC As Long, DeskBMP As Long

DeskDC = GetWindowDC(0&)
DeskBMP = GetCurrentObject(DeskDC, OBJ_BITMAP)
Call ReleaseDC(0&, DeskDC)
End Sub
'***

Getting the handle of a currently selected Bitmap handle isn't always that useful though since a number of calls that
work with Bitmaps only work properly with un-selected Bitmaps.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: XXXX@XXXXX.COM
WWW: http://www.yqcomputer.com/
 
 
 

Strange case of CreateCompatibleBitmap and Mr. Hyde

Post by Rober » Sat, 26 Feb 2005 18:10:21

Thanks for that info. However, before rewriting my code, I'll try to find
out why I can't get sufficient memory (when all indicators tell me there's
plenty left).
Since not even the PrintScreen-Key is working, I have a strong argument why
my application can't capture...

Robert



(or
DC of
it's just generally more efficient to use the
direct access to the underlying data. You can get
call (by sure to make the ppvBits parameter
is ByVal which is incorrect - Whoever decided
at..), or alternatively call GetObject() on the
memory is a pointer to the DIB data. This is a
place and using a little bit of hacking you can
array at it - See the DIB article on my site
having
As Long
useful though since a number of calls that
 
 
 

Strange case of CreateCompatibleBitmap and Mr. Hyde

Post by Mike D Sut » Sat, 26 Feb 2005 19:44:40

> Thanks for that info. However, before rewriting my code, I'll try to find

A DDB is allocated in kernel mode paged pool and only certain amount can be allocated at any one time, a DIB on the
other hand uses user mode address space and as such is limited only on what virtual memory is available on the system.
As such DDB's are limited to around 50/60mb in total where as DIB's are only limited by the amount of system resources
(within reason.) Have a look at the following code to profile your system's GDI limits:
http://www.yqcomputer.com/
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: XXXX@XXXXX.COM
WWW: http://www.yqcomputer.com/
 
 
 

Strange case of CreateCompatibleBitmap and Mr. Hyde

Post by Rober » Sat, 26 Feb 2005 23:33:49

Thanks a lot. This info is really useful.

Robert



find
there's
why
be allocated at any one time, a DIB on the
what virtual memory is available on the system.
only limited by the amount of system resources
system's GDI limits:
 
 
 

Strange case of CreateCompatibleBitmap and Mr. Hyde

Post by Rober » Sat, 26 Feb 2005 23:40:02

Hmmm, shouldn't the output change depending on whether I have
resource-hungry applications open or not?

Robert



find
there's
why
be allocated at any one time, a DIB on the
what virtual memory is available on the system.
only limited by the amount of system resources
system's GDI limits:
 
 
 

Strange case of CreateCompatibleBitmap and Mr. Hyde

Post by Mike D Sut » Sun, 27 Feb 2005 00:38:01

> Hmmm, shouldn't the output change depending on whether I have

Once the system paging file gets filled up or you hit the limits of user mode address space (over 2gb on a 32-bit
system), yes, however I've never encountered a situation where CreateDIBSection() fails because of an out of memory
error.
Hope this helps,

Mike


- Microsoft Visual Basic MVP -
E-Mail: XXXX@XXXXX.COM
WWW: http://www.yqcomputer.com/
 
 
 

Strange case of CreateCompatibleBitmap and Mr. Hyde

Post by Rober » Tue, 01 Mar 2005 17:12:16

I mainly thought about the CreateBitmap: I always can allocate roughly 57
MB. From your previous posts I assumed this limit would be system-wide over
all applications. Did I get this wrong?

Robert




mode address space (over 2gb on a 32-bit
CreateDIBSection() fails because of an out of memory