Amazon Honor System Click Here to Pay Learn More

VB Advanced Chapter 1
by David McNally

What I would like to do in this series is focus on VB animation techniques and some very interesting projects you can do using VB and Windows API functions. I will need to assume you have a basic understanding of using Windows API’s as I will not get into details about how they work unless I think they might warrant a further explanation.

I will also assume you know your way around VB enough to be able to create forms, modules, etc. and set up basic controls within them if needed.

Our first discussion will focus on the framework I will use to create most of the animations. The framework takes into account that it is a simple structure to implement, flicker less animations, frame rate control, and overall processing speed.

To begin, create a new project in VB 6. Add two forms and a module to your project. Please make sure to make form1 your startup object form in the project properties.

Now add the following code to the modules general declaration section:

 

' Declare some Windows functions used in the demo

' These functions help increase the speed since VB

' is pretty slow when dealing with graphics

Public Declare Function SetPixel Lib "gdi32" (ByVal hdc As Long, _

ByVal x As Long, ByVal y As Long, _

ByVal crColor As Long) As Long

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

'Constants used by the BitBlt Function

Public Const SRCAND = &H8800C6

Public Const SRCCOPY = &HCC0020

Public Const SRCERASE = &H440328

Public Const SRCINVERT = &H660046

Public Const SRCPAINT = &HEE0086

*Note that there is one space in front of each underscore character that is at the ends of each line.

 

Almost all of the projects I have worked on use the above two functions. The setpixel API has a little bit more speed then the VB pixel command. The BitBlt function is known to be one of the fastest pixel copy routines Windows has.

The idea for most of the animations is simple. Set up a second invisible page (also known as a back buffer) where all your erasing and drawing will take place. Then, use the Bitblt function to copy the results to a second form, which is visible to the user. This will reduce the "flicker" effect and also let you do other more complicated behind the scenes work (such as masking) without being seen. Only the final result of the frame is actually viewed by the audience. You can actually set up an invisible buffer in memory (without using a second form), but this requires a bit more work and will be the topic of a later article.

 

Now lets look at the two forms we need. Set the properties on the two forms as follows:

 

Form 1

Form 2

Clip Control false false
Control Box false false
Caption Erase this field – no text Erase this field – no text
Scale mode 3 - pixel 3 - pixel
Show In Taskbar true false
Auto Redraw false true

 

Now add three buttons across the bottom of form1. Label them "Start", "Stop", and "Quit" respectively.

Also, you will need to add a timer control to form1 with an interval of 50. The timer control is what keeps the animation rate constant and "on beat" if you will. When the timer is enabled, the interval counts down to zero. When zero is reached, the timer’s timer event gets triggered. It is here will instruct the computer to prepare the next frame of animation.

Form2 does not need any code, so just add the following code in form1:

 

' This is in our general declarations section

'

' set a flag to determine if the animation is currently

‘ in progress

Dim animation As Boolean

Private Sub Command1_Click()

' This button press will be used to start the animation process.

' All we need to do is turn on the timer. When the time

' interval has elapsed, the Timer1_Timer function is called.

' As long as the timer is turned on, the animation will

' continue on.

Timer1.Enabled = True

End Sub

Private Sub Command2_Click()

' To stop the animation, just disable the timer control

Timer1.Enabled = False

End Sub

Private Sub Command3_Click()

' Quit the demo

End

End Sub

Private Sub Form_Load()

' The trick here is to make a second form that is

' the same as the first form, but invisible.

'

' That way, we can draw and erase on it without anyone

' seeing what is going on. This is referred to as a

' back buffer.

Form2.ScaleWidth = Form1.ScaleWidth

Form2.ScaleHeight = Form1.ScaleHeight - 50

Form2.BackColor = vbBlack

Form2.ForeColor = vbRed

Form2.Visible = False

'setup random number generator

Randomize

End Sub

Private Sub Timer1_Timer()

' This is where most of the animation work is done.

' A timer provides a way to create a constant frame rate

' within the animation

'

' Since the timer event could fire again before we

' have finished the previous frame, we will set the

' animation flag to true until the new old is done. This

' allows us to skip frames if needed.

If animation = False Then

animation = True

Call Update_Frame

Call Update_Screen

animation = False

End If

End Sub

Private Sub Update_Frame()

' Here is where you add the actual drawing and erasing of

' the new scene. Notice all work is done on the invisible

' back buffer (in this case form2).

'

' For this example, I will plot a bunch of random dots

' using the set_pixel API I declared in the module.

Dim dmy As Long

Dim x, y, c As Long

'clear the old frame if needed

Form2.Cls

'randomly plot some pixels

c = vbRed

For t% = 1 To 200

x = Int(Rnd(1) * Form2.ScaleWidth)

y = Int(Rnd(1) * Form2.ScaleHeight)

dmy = SetPixel(Form2.hdc, x, y, c)

Next t%

End Sub

Private Sub Update_Screen()

' Here is where we copy the invisible back buffer (which

' is now done being redrawn) to the visible page. The

' BitBlt API function is the fastest way to do this.

Dim dmy As Long

dmy = BitBlt(Form1.hdc, 0, 0, Form2.Width, Form2.ScaleHeight - 50, Form2.hdc, 0, 0, SRCCOPY)

End Sub

 

I have commented the routines well, so you should be able to see what is going on here. I did subtract 50 pixels from the calculations to leave room for the three buttons on the bottom of the form. We will remove those in later animations, but for now it makes it a little easier to demonstrate how the timer events play the important roll of stopping, starting, and controlling frame rate.

Also notice the flag I added into the timer routine. While this has little use now, it helps prevent page tearing and incomplete scenes when working with larger animation projects, so it is a good habit to get into. The idea here is that if another timer event fires before the prior drawing routines have completed, we just skip the event, and wait for the next one. This may be more the case with slower machines.

One last thing to note here is the use of the Auto redraw=true on the second form. While not apparent in this example, this will later allow us to use the persistent bitmap feature in VB to refresh background images for us.

If you want to experiment with this animation framework, all you need to do is add all your drawing commands with the Update_Frame subroutine. I just drew a bunch of random dots to keep things simple and to focus more on the structure and setup of the code. For speed, you may need to experiment with more API functions as well.

< Sample Code >

HOME       FIRST CHAPTER

Amazon Honor System Click Here to Pay Learn More