BitBlt Explained

You can skim through this tutorial just learning how to use bitblt if you want. I myself however wondered for a period of time just how this fancy bitblt thing worked. Since I wondered that I learnt a bit of boolean stuff and so I took a look at the underlying way that the mask to get a partly transparent image works. I will endeavour to explain this as I go along. If you don't have a clue about logic gates, boolean algebra or binary then you could well get a bit lost. If you find this happens I would recommend looking on the howstuffworks website as it has an excellent clear description of logic gates and binary.

First things first you need to know that bitblt is an API so it must be declared. Here is the declaration. The only bit that you should change is the private part depending on where you are using the function.
Public Declare Function BitBlt Lib "gdi32" _
 (ByVal hDestDC As Long, ByVal X As Long, _
 ByVal Y As Long, ByVal nWidth As Long, _
 ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc _
 As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
As you can see its a mighty long function but thankfully its got mostly easy components.
hDestDC - This is the hDC reference of the destination picture/canvas. To get and objects hDC just use its hDC property (form1.hDC). If an object doesn't have a hDC property then you can't use it. I think only pictureboxes and forms have it. For the techy people a hDC reference is the address in the computers memory where the objects drawing data is stored.
X - This is just the X coordinate of where the picture will be put in the destination.
Y - Same but the Y coordinate.
nWidth - The width of the picture to be copied (The picture will be cropped not scaled, if larger than the source then the function takes the bit of the screen the is next to it).
nHeight - Same but height.
hSrcDC - The hDC reference of the source picture.
xSrc - The X coordinate of the chosen rectangle in the source picture.
ySrc - Same but the y coordinate.
dwRop - Tells the function how to copy the stuff.

dwRop

Here are the options for dwRop:

vbDstInvert - Inverts the destination rectangle.
vbMergeCopy - Merges the colors of the source rectangle with the objects current brush using Boolean AND.
vbMergePaint - Combines the inverted source bitmap with the destination bitmap by using Boolean OR.
vbNotSrcCopy - Copies the inverted source bitmap to the destination bitmap.
vbNotSrcErase - Inverts the result of combining the destination and source bitmaps by using OR
vbPatCopy - Copies the objects current brush onto the destination bitmap
vbPatInvert - Combines the destination bitmap with the objects current brush by using XOR
vbPatPaint - Combines the inverted source bitmap with the objects current brush by using Or. It then Combines the result of this operation with the destination bitmap by using Boolean OR.
vbSrcAnd - Combines the destination and source bitmaps by using Boolean AND
vbSrcCopy - Copies the source bitmap to the destination bitmap.
vbSrcErase - Inverts the destination bitmap and combines the result with the source bitmap using Boolean AND.
vbSrcInvert - Combines the destination and source bitmaps by using Boolean XOR.
vbSrcPaint - Combines the destination and source bitmaps by using Boolean OR.

Drawing a simple rectangular picture

This is a very basic use for bitblt. It just copies a rectangle from one place to another. You coudl use it in something like a tile engine for drawing the tiles.

In the example you will need a picture box called sourcepic with a picture in it. If you make the picturebox invisible make sure you set autoredraw to true. I have put a nice picture of some grass below which provides a nice background for what we will do below.

Grass picture

The dwRop for this is vbSrcCopy which just replaces the destination bits with the ones from the source.
Private Declare Function BitBlt Lib "gdi32" _
 (ByVal hDestDC As Long, ByVal X As Long, _
 ByVal Y As Long, ByVal nWidth As Long, _
 ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc _
 As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long

Private Sub Form_Load()
Me.AutoRedraw = True
BitBlt Me.hDC, 10, 10, 250, 250, SourcePic.hDC, 0, 0, vbSrcCopy
End Sub
You should see your picture drawn onto the form when you run the project.

Remember that the units are all in pixels not twips.

Using a picture and mask

There are in fact two ways of doing this with each one using the function calls in the opposite order. I will only tell you about one in detail.

First you will need to prepare your pictures (or use mine below). The main picture should have a black background (if all of your pictures have a white background then I would recommend using the second method to save the bother). For your mask you should have a white background with the object in centre being filled in with black.

giraffe picture giraffe mask

Now you should load your two pictures into pictureboxes ready for running. If you set the pictureboxes visible to false then you must set autoredraw to true (It took me ages to debug but I did learn how to use the picture object in VB to do this very task). Here is a function I made that will draw a masked picture.
Private Sub DrawMasked(Dest As Object, Source As Object, SourceMask As Object, X As Long, Y As Long, Width As Long, Height As Long, Optional SourceX As Long, Optional SourceY As Long)
BitBlt Dest.hDC, X, Y, Width, Height, SourceMask.hDC, SourceX, SourceY, vbSrcAnd
BitBlt Dest.hDC, X, Y, Width, Height, Source.hDC, SourceX, SourceY, vbSrcPaint
End Sub
What you have to feed this function is Dest, which is where the picture goes. Source is the place where the main picture will be. SourceMask is where the pictures mask is. X is the x coordinate in the destination. Y is the y coordinatte in the destination. Width is the width of the rectangle. Height is the height of the rectangle. SourceX is the x coordinate of the source rectangle (main and mask). SourceY is the y coordinate of the source rectangle (main and mask). Tend to have the pictures in the top left of the source rectangle anyway which is why I set them optional.

So what the function does is call bitblt twice, first for the mask and then for the main picture. You will notice however that there is a different function call for each. The thing changed is of course the dwRop value that we feed it. This is the main bit which needs explaining.

The first function call tells bitblt to use the boolean AND operator to combine the bits. Heres the truth table for the AND operator:
A  B  Q
0  0  0
0  1  0
1  0  0
1  1  1
You will notice that when you have 1's first then the second input isn't affected but when you have 0's the second input is blanked. This means that the black areas of the mask will turn the picture black because all the bits will become 0 but where the white parts of the mask are there will be no change because 1's don't affect the other bit.

So by this stage we have our picture exactly the same but with a black area where the visible part our our picture will go.

Now, with the second function call we are telling bitblt to use the OR operator to combine the bits. Here is the truth table for OR:
A  B  Q
0  0  0
0  1  1
1  0  1
1  1  1
Here you can see that it is the opposite of the AND in terms of what black and white do. The 0's or black does not affect the second bit but the white changes it to white.

This is why we put a black background onto our main picture. The black will not interfere with the colours so all of the black area will be transparent.

Now we can see why we needed to apply the mask first. We have already worked out that black areas do not affect coloured areas. Also we know that our mask left a black area on the background exactly the same shape as our coloured picture. This means that our picture will stay exactly the same when it is applied.

Here is an example which will fit with the previous program. Create two more pictureboxes one called 'MaskSrc' and the other 'PicSrc'. Place this code straight after the first bitblt call.
DrawMasked Me, PicSrc, MaskSrc, 70, 30, 62, 114
So by now you should have a program which looks like this:
Private Declare Function BitBlt Lib "gdi32" _
 (ByVal hDestDC As Long, ByVal X As Long, _
 ByVal Y As Long, ByVal nWidth As Long, _
 ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc _
 As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long

Private Sub Form_Load()
Me.AutoRedraw = True
BitBlt Me.hDC, 10, 10, 250, 250, SourcePic.hDC, 0, 0, vbSrcCopy
DrawMasked Me, PicSrc, MaskSrc, 70, 30, 62, 114
End Sub

Private Sub DrawMasked(Dest As Object, Source As Object, SourceMask As Object, X As Long, Y As Long, Width As Long, Height As Long, Optional SourceX As Long, Optional SourceY As Long)
BitBlt Dest.hDC, X, Y, Width, Height, SourceMask.hDC, SourceX, SourceY, vbSrcAnd
BitBlt Dest.hDC, X, Y, Width, Height, Source.hDC, SourceX, SourceY, vbSrcPaint
End Sub
Well that just about sums up the most common features of bitblt. I hope you found this tutorial useful. If you can think of anything I have missed or just want to comment on this tutorial please use the sites forums or the contact form to let me know.

Other Visual Basic tutorials

© Jonathan Waller 2005; QuantumState Visual Basic