BitMap to Control in Paint Event

G

Guest

I am trying to implement drawing on a bitmap and using bitblt to transfer
it to the control graphics object in the paint event. It seems to draw on
the bitmap ok but doesn't get transferred to the control graphics object in
the paint event. Any help would be appreciated. Here is my code:

public class as mycontrol

Private Declare Auto Function BitBlt Lib "GDI32.DLL" (ByVal hdcDest As
IntPtr, ByVal nxDest As Integer, ByVal nyDest As Integer, ByVal nWidth As
Integer, ByVal nHeight As Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc As
Integer, ByVal nYSrc As Integer, ByVal dwRop As Int32) As Boolean

Private v_BackImage As Bitmap = New Bitmap(Me.Width, Me.Height,
Me.CreateGraphics)
Private gph As Graphics = Graphics.FromImage(v_BackImage)

'do some drawing on gph

Private Sub Panel_Paint(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
'Get Device contexts for Source and Memory Graphics Objects
Dim hdcSrc As IntPtr = gph.GetHdc
Dim hdcDest As IntPtr = e.Graphics.GetHdc
BitBlt(hdcDest, 0, 0, Me.Width, Me.Height, hdcSrc, Me.Width, Me.Height,
13369376)
'Clean Up
gph.ReleaseHdc(hdcSrc)
e.Graphics.ReleaseHdc(hdcDest)
end sub

end class
 
Q

Qwert

Private Declare Function SelectObject Lib "gdi32" Alias "SelectObject"
(ByVal hdc As IntPtr, ByVal hObject As IntPtr) As IntPtr
Private Declare Function DeleteObject Lib "gdi32" Alias "DeleteObject"
(ByVal hObject As IntPtr) As Integer
....
Dim hdcBitmap, hdcControl, hdcOriginal As IntPtr
....
hdcBitmap = gph.GetHdc
hdcControl = e.Graphics.GetHdc
hdcOriginal = SelectObject(hdcBitmap, v_BackImage.GetHbitmap)
BitBlt(hdcControl, 0, 0, v_BackImage.Width, v_BackImage.Height, hdcBitmap,
0, 0, &HCC0020)
SelectObject(hdcBitmap, hdcOriginal)
DeleteObject(hdcOriginal)
e.Graphics.ReleaseHdc(hdcControl)
gph.ReleaseHdc(hdcBitmap)
....
gph.Dispose() ' When you're done.
 
G

Guest

Thanks a lot for the reply...I know it took a lot of you time. I included it
into my program and it works fine except for one problem. The line
"DeleteObject(hdcOriginal)" somehow causes the form containing my control to
lose it's identity such that it throw an exception "Object not set to
reference" when I try to access it's properties such as me.Enabled. If I
delete the line "DeleteObject(hdcOriginal)" then it works fine.
 
Q

Qwert

Yeah, i looked at it some more and the code is not correct. Two things are
incorrect:

First of all, you don't need 'hdcOriginal', because you release 'hdcBitmap'
anyway. So the line becomes:

SelectObject(hdcBitmap, v_BackImage.GetHbitmap)

and you can remove:

DeleteObject(hdcOriginal)

but you already did that.

Secondly, and more importantly, you need to delete the handle to the bitmap:

Dim hdcBitmapHandle As IntPtr = v_BackImage.GetHbitmap
....
SelectObject(hdcBitmap, hdcBitmapHandle )
....
DeleteObject(hdcBitmapHandle)

If you don't do this, you're application will run for a while, but then you
will get an error somthing like "Error: object still in use.".

Off-topic remark:
If speed is important for you application, notice that the line
"SelectObject(hdcBitmap, hdcBitmapHandle )" takes up about 85% of the total
time to perform this. You might consider creating a class that holds and
releases the handle to the bitmap only 1 time. First I thought keeping a
handle to a bmp would cause problems, but it seems to work ok. Now BitBlt is
40% faster then DrawImage method.
 
G

Guest

This is what I ended up with..is this correct? Just curious, but what does
the SelctObject statement do? I would have thought the BitBlt statement
would copy the pixels from the bitmap graphics object to the screen graphics
object with the need for further manipulation but I guess I'm wrong.

Dim hdcBitmap, hdcControl As IntPtr
Dim hdcBitmapHandle As IntPtr = v_BackImage.GetHbitmap 'Takes 85% of time
hdcBitmap = gph.GetHdc
hdcControl = e.Graphics.GetHdc
BitBlt(hdcControl, 0, 0, v_BackImage.Width, v_BackImage.Height, hdcBitmap,
0, 0,
&HCC0020)
SelectObject(hdcBitmap, hdcBitmapHandle)
DeleteObject(hdcBitmapHandle)
e.Graphics.ReleaseHdc(hdcControl)
gph.ReleaseHdc(hdcBitmap)
 
Q

Qwert

BitBlt copies the graphic data to a Device Context. A Device Context is a
data structure maintained by GDI. A device context is associated with a
particular display device, such as a printer or video display. For a video
display, a device context is ussually associated with a particular window on
the display, but it can also be an offscreen display.
What you do, is create a Device Context and then associated a Bitmap with
the Device Context ( with SelectObject ). Then you draw to the Device
Context ( using BitBlt ) to alter the Bitmap. You can't use GDI functions to
directly draw to a bitmap.
After using a Device Context, you need to clean stuff up ( release and
delete ). Or else the device context stays locked and other attempts to draw
again will fail. And not cleaning up will result in memory leaks.

I hope this is correct. If not, I am sure another reader of this newsgroup
will be kind enough to correct it.


Dim hdcBitmapHandle, hdcBitmapDC, hdcControl As IntPtr
REM Get the handle to the device context associated with form Graphics
object.
hdcControl = e.Graphics.GetHdc
REM Get the handle to the device context associated with bitmap Graphics
object.
hdcBitmapDC = gph.GetHdc
REM Create the Windows HBITMAP from the image. You must de-allocate the
HBITMAP with Windows.DeleteObject(handle).
hdcBitmapHandle = v_BackImage.GetHbitmap
REM Link Device Context to Bitmap handle.
SelectObject( hdcBitmapDC , hdcBitmapHandle )
REM Use BitBlt to copy bits from one Device Context to another.
REM The first DeviceContext is attached to the form, the second Device
Context is attached to the bitmap.
BitBlt(hdcControl, 0, 0, v_BackImage.Width, v_BackImage.Height, hdcBitmapDC,
0, 0,
&HCC0020)
REM In general, when you clean things up, you do it in opposite order they
where created.
DeleteObject(hdcBitmapHandle)
e.Graphics.ReleaseHdc(hdcBitmapDC )
e.Graphics.ReleaseHdc(hdcControl)
 
G

Guest

Thanks a lot for the explaination. It was the SelectObject statement after
the BitBlt that was confusing me. I see now that it goes before the BitBlt.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top