Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Using BitBlt to Copy and Paste Graphics

0.00/5 (No votes)
5 May 2010 1  
This article will demonstrate how to use BitBlt. and provide some technical pointers
Sample Image - Bitblt_wrapper_class.jpg

Introduction

As most of you already know, the .NET environment offers us to Frameworks to do all kinds of cool stuff, including the Drawing classes and objects. BUT?

When we want to use the graphics on a high frame rate, the DrawImage method just won't do, it's too slow (I am not sure why but it is :] ). So as very well introduced by Matthew Hazlett, the BitBlt comes to our aid by doing stuff VERY fast. (His article which is very informative and was the foundation for this article and code is located here.)

What I will try to do here is to take it just one step further, give out some guidelines and pointers. Plus - this sample code will provide a very clean and well commented class you can use to learn or even implement in your projects.

In the demo project, I have created a class which copies to memory, and from memory using BitBlt, it's well documented and easy to understand.

A Quick Run Through The Basics

Just to get things stated, in order to use the BitBlt function we have to declare it, as it is not a part of the Frameworks, but a part of the Window's API. The function is located at the "GDI32.dll" library, and that's about it. The declaration goes like this:

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

Now what we do is to copy Bitmaps from one location in the memory to another, these locations are called a Device Context, as they are directly connected to a Graphical Device on the system, for instance - a Picture Box or a Form.

What are all the other parameters? There are the X, Y, Width, Height which tell BitBlt what is the area we wish to copy, and X and Y parameters to Where to copy at the target Device Context (which is used as our canvas).

Creating a Device Context is Not That Complicated

So for us to be able to use BitBlt, we need 2 Device Contexts (hard to pronounce isn't it?) To create those, we first need a Graphics object, we create that one from (almost) any object we want, for example, we can use a picture box:

 PictureBox1.CreateGraphics

' But we need to keep a reference to it, so we will use this:
Dim GrpObj as Graphics = PictureBox1.CreateGraphics

Now we have GrpObj as a Graphics object, which we can use to create the Device Context:

Dim MyDeviceContext as IntPtr ' Creating the
  ' variable to keep the DC address
MyDeviceContext = GrpObj.GetHdc()

(Note: Hdc = Handle of Device Context)

Now what did we just do? We created an Object in Memory which represents the Graphical Object GrpObj. Now we can use the Device Context to BitBlt.

RULE NUMBER 1

While we have a Device Context in use, the Parent Object (in this case GrpObj) cannot be accessed directly, an attempts to draw to it (like using the .DrawArc method) will result in an exception! We DO NOT want that.

So - right after creating and using a Device Context, we make sure to Release it:

GrpObj.ReleaseHdc (MyDeviceContext)

Note that the Parent of GrpObj is also locked until the Device Context is released. AND we have to dispose of it too, to keep our memory leaks to the minimum. ;)

GrpObj.Dispose()

Now we need another Device Context to copy to. To do so, we will create an invisible Device Context in the memory very easily.

 ' We Create a Bitmap object at the desired size,
Dim srcBmp As New Bitmap(Size.Width, Size.Height, GrpObj)

 ' Creating Graphics Objects
MemoryGrpObj = Graphics.FromImage(srcBmp) 'Create a Graphics object

 ' Creating a Device Context
MemoryHdc = MemoryGrpObj.GetHdc 'Get the Device Context

BitBliting the Images

Now we can copy anything we want to or from this Device Context. Providing

RULE NUMBER 2

After Blitting to memory, we have to keep the Device Context in scope, because when we Blit to memory, the changes will reset after we release the device context. THUS- we either keep the MemoryHDC as a Global variable or use it in the same procedure.

Still we mustn't forget to release the Device Context so we also have to make sure to keep the Graphics object MemotyGrpObj reference as well, ok?

Now we can Actually Blit

BitBlt(MemoryHDC, 0, 0, width, Height, MyDeviceContext, 0, 0, SRCCOPY)
        ^ Target ^                        ^ Source ^

This will copy From MyDeviceContext To MemoryHdc.

A quick side note: The 'SRCCOPY' is one of the many raster operations BitBlt can do for us, this (the most commonly used) operation copies an exact copy of the bitmap, I have declared SRCCOPY as a Const, this is the value.

Dim SRCCOPY as Integer = &HCC0020 ' Hex
    or
Dim SRCCOPY as Integer = 13369376 ' Dec

We can also use BitBlt to create masks, transparency and some more cool stuff (FYI).

All we need to do now is to create our target Device Context, and BitBlt to it from the memory, we can keep an array of Device Contexts, just remember to follow the rules!

To finish up, note that if you want to draw on a specific location, here is the syntax:

BitBlt(TargetHdc, Xpos, Ypos, width, Height, MemoryHDC, 0, 0, SRCCOPY)
            ^                                ^
'(Assuming the TargetHdc is our target Device Context,
'and Xpos and Ypos are the location to draw at)

The sample project will demonstrate it all and maybe save you the trouble. Good luck.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here