VBfx / Common / BitBlt


You probably heard of that famous API call before or saw small (but funny) games that use it. So what is BitBlt and what is it capable of? And even better, what does BitBlt mean? Well the last question is easy to answer: BitBlt stands for Bit-Block transfer which actually means nothing more than copying memory. And this is exactly what it does.

What BitBlt does

BitBlt is used to draw (copy) pictures from one DC (device context) to another. You can think of a DC being a canvas or image buffer. In fact it's just a reference to such a buffer but you won't ever get in touch with this. Now don't get confused because we talked about copying memory before, even DCs (pictures) are stored in memory. So BitBlt does nothing more than copy parts of a DC to another.

Extended options

BitBlt can do more than just copy the memory! There's a number of logical operations such as AND and OR that can be done, however we'll just have a look at the most important 3 options:

vbSrcCopy: Of course this means no special operation, just overwrite the target memory.

vbSrcAnd: This may be a little confusing. What it does is using the logical AND operator to combine the colors. So how does AND work for colors? Well imagine a neon blue pixel that has RGB( 128, 0, 255 ) and another orange pixel that has RGB( 255, 128, 0 ). Using AND we'll get RGB( 128, 0, 0 ) since this is the minimum of each RGB pair. Special colors for these operation are: white (always returns the other color) and black (always returns black). You don't have to care about the math stuff but keep in mind about the special colors!

vbSrcPaint: This one represents the logical OR operation. It'll return the maximum value of each RPG pair, so if we mix up RGB( 0, 128, 255 ) and RGB( 128, 0, 0 ) we'll get RGB( 128, 128, 255 ). Here again the 2 specials colors are black (always returns the other color) and white (always returns white). Sounds quite similar huh?

Note that I used prepared numbers for the example - in real you have to do a binary AND and OR to get the correct result (and not just look which number is bigger or smaller).

BitBlt in action

Before using BitBlt you have to include the reference declaration in your program. You can get this line from your API Text Viewer coming with your Visual Studio. If you don't have that application you can use the online API reference found on www.allapi.net. However, here's the declaration:

Public Declare Function BitBlt Lib "gdi32" ( _
    ByVal DestDC as Long, _
    ByVal DestX as Long, _
    ByVal DestY as Long, _
    ByVal W as Long, _
    ByVal H as Long, _
    ByVal SourceDC as Long, _
    ByVal SourceX as Long, _
    ByVal SourceY as Long, _
    ByVal Rop as Long ) as Long

Now don't be scared! Yes, there are many parameters but they all are quite easy to use. Let's go through it step by step. Note that this was a Public declaration, therefore it goes into a Module. If you want to add the declaration to your Form directly you'll have to change Public to Private!

DestDC: This is the destination DC where we want to copy the picture to. If it's a PictureBox you can use the .hDC property, Picture1.hDC for example.

DestX and DestY: This is simply the position where we want to copy the picture to.

W and H: Stands for width and height. You have to submit BitBlt how big the area you want to copy is. Using this parameters we can copy a small 32x32 block out of a bigger picture which is usefull eg. when placing more than one sprite on bitmap.

SourceDC: As the name says, the DC that holds the source picture.

SourceX and SourceY: The position where we want to copy from the source picture. Again this can be used when there is more than one graphic on the same DC.

Rop: Rop stands for Raster operation which means the logical operations mentioned above. Usual values are: vbSrcCopy, vbSrcPaint, vbSrcAnd. This constants are pre-defined in VB6.


Still no idea where to get the DC and how to use BitBlt? Let's make a little example then! Open a new project and add two PictureBoxes and a Button to the Form. In the first box load any picture you like, draw something in MS Paint if you have no picture ready. Now insert the BitBlt declaration above into your Form (remember changing Public into Private). Finally use this code for the button:

Private Sub Command1_Click()
    'Set background color to red
    Picture2.BackColor = RGB( 255, 0, 0 )
    'Copy 100x100 pixels from position 50,10 on the first picture to position 4,4 on the second
    BitBlt Picture2.hDC, 4, 4, 100, 100, Picture1.hDC, 50, 10, vbSrcPaint
    'Copy another 20x40 pixels from position 0,0 on the first picture to position 20,80 on the second
    BitBlt Picture2.hDC, 20, 80, 20, 40, Picture1.hDC, 0, 0, vbSrcAnd
End Sub

Now run the project and see what happens. Play around with the numbers to understand what they do exactly. Also try to change the Rop into vbSrcPaint or vbSrcAnd - this won't help you much but it looks funny. Note again that the Rop works as a binary operator, that's why I chose a pure RGB color for the background. Using other colors will result in odd results but feel free to try it.


The last example is quite usefull, it shows you how to copy the screen contents using BitBlt. The trick is to get the DC of the desktop and then just copy from this DC to your PictureBox or wherever you want to copy it to. Note that you can also use the desktop DC as the target DC, this would result in drawing "on the screen".

For the following example you just need a (big) PictureBox and a Button. But first we need the API calls again:

Private Declare Function BitBlt Lib "gdi32" (  _
    ByVal DestDC as Long, ByVal DestX as Long, ByVal DestY as Long, _
    ByVal W as Long, ByVal H as Long, _
    ByVal SourceDC as Long, ByVal SourceX as Long, ByVal SourceY as Long, _
    ByVal Rop as Long ) as Long

Private Declare Function GetDesktopWindow Lib "user32" () as Long
Private Declare Function GetWindowDC Lib "user32" ( ByVal Window as Long ) as Long

Finally the code for the button. Since it's well-commented I won't explain it any further. The example gets your screen size by dividing the screen size by the Twips/Pixel constant. This is neccessary because the Screen.Width and .Height are in Twips. Stupid, but we'll just live with it.

Private Sub Command1_Click()
    Dim DesktopDC as Long
    Dim DesktopWindow as Long
    Dim ScreenW as Long
    Dim ScreenH as Long
    'Get desktop window
    DesktopWindow = GetDesktopWindow()
    'Get DC of this "window"
    DesktopDC = GetWindowDC( DesktopWindow )
    'Get screen size
    ScreenW = Screen.Width / Screen.TwipsPerPixelX
    ScreenH = Screen.Height / Screen.TwipsPerPixelY
    'Copy the contents
    BitBlt Picture1.hDC, 0, 0, ScreenW, ScreenH, DesktopDC, 0, 0, vbSrcCopy
End Sub

Run the code and press the button. Press the button again if your Form is within the copied area and see what happens.


We're done with this part and you should now know how to use BitBlt to copy parts of one DC to another. You don't have to know about the special operations we discussed but you should know what the colors black and white do when using vbSrcPaint and vbSrcAnd. We'll need this later when doing transparent backgrounds for sprites and tiles.