Virtual Developer Workshop: Containerized Development with Docker
We've all come across the need for a timer in one or more of the applications that we write. In this article, you are going to look at some of the basics of timers, as well as look at a few examples of how to use a timer effectively.
The first problem that I've noticed in the years that I've been assisting beginners on the forum, is that many think of the Timer Control as a Stopwatch timer, or a count down timer. THIS IT IS NOT; the timer is a control that simply raises an event every X milliseconds.
But first, what does the timer actually do? It's a control that has no display during run time; it does not count or calculate. It will raise an event only every X ms where you as the programmer must now do the displaying, counting, and/or calculating.
The timer has very few properties, and only two of them are of any interest when programming, Interval and Enabled.
Enabled simply switches the timer on and off.
Interval is the time in ms between events, with a max time of 65535ms, or 6.5 seconds. Also something to note, the Timer control is linked into a hardware timer that is raised every 16ms and therefore is accurate only up to every 16th ms.
The first example you will look at is how to use a timer to keep a time display updated.
Update on Screen Time
To display the current date and time in a label on your form, that is regularly updated and no more than one second out.
You add a label to your form, and name it Time1; you also add a timer to the form. The timer control can be placed anywhere; however, I find it more convenient to place it just off the bottom or side so that visually it's out the way.
In your form load event, you initiate the timer so that it shows the current time from the moment your application starts. You enable the timer and set the interval for the timer to 500ms. The interval could be set at every 1000ms (1 second); however, this raises the small issue of accuracy, although the displayed time will never be more than 1 second out. There are some circumstances where the timer will not occur exactly one second later, and the display will tend to skip a second; although not critical, for myself personally this is a visual pain.
Listing 1 shows the key code required for the timer to operate correctly.
[Form_Load] Timer1.Interval = 500 Timer1.Enabled = True [Timer1_Timer] Time1.Caption = "Date: " & Date & " - Time: " & Time
When the application is now run, the time will be constantly updated on your form, the CPU usage is minimal, and any other functions on the form will not be affected.
In the second example, you will look at using a timer to move items/pictures/animation around using key presses.
Note: The H key is used for left movement, K is right, U is up, and M is down.
To move a picture around inside a picturebox using the keyboard as the move triggers (W A S D X).
For this, you use a picturebox inside a picturebox. You also set the form's Keypreview to True so that you can have a single function to handle the key presses.
You place your first picturebox so that it almost fills the form and set its Scalemode to '3-Pixel'. Then, you place the second, smaller picturebox inside the first. You also add a timer to the form, again just off the edge of the form.
Now, the coding gets a little interesting here. You create a tristate type, similar to a Boolean type, but you now have three possibilities: Forward, Stop, and Backwards. Or rather, you use positive (+1), zero (0), and negative (-1) so that you have a direction multiplier.
You create two variables with your tristate type, namely P1UD for the up/down movement of the picture and P1LR for the left/right movement.
You now use the form's keydown event to capture the key presses. And, depending on the keys pressed, you set your tristate variables according to the following list.
- W: P1UD = Negative (up)
- A: P1LR = Negative (left)
- D: P1LR = Positive (Right)
- X: P1UD = Positive (Down)
- S: Both P1UD and P1LR = Zero.
With this setup, you now can tap any of the above letters and the appropriate variable will bet set for forward or backward motion. Pressing 'S', the center key, will set both your variables to stop the motion.
This setup will allow constant motion, with the picture moving until the 'S' stop key is pressed. You also can set up that, when a key is released, the motion stops. For this, you use the form's keyup event to set your variables to zero according to the following list.
- W, X: P1UD = Zero
- A, D: P1LR = Zero
With all the theory behind you, look at the code. Listing 2 shows all the key bits of code and declarations required to make the picturebox move around.
[General] Private Enum Tristate Neg = -1 Zero = 0 Pos = 1 End Enum Private P1UD As Tristate Private P1LR As Tristate Private AutoStop As Boolean [Form_Load] Picture2.Picture = LoadPicture(App.Path & "/pic1.bmp") Timer1.Interval = 50 Timer1.Enabled = True SPM = 1 'steps per timed tick [Form_KeyDown] Select Case KeyCode Case 65 P1LR = neg Case 68 P1LR = pos Case 87 P1UD = neg Case 88 P1UD = pos Case 83 P1LR = zero P1UD = zero End Select [Form_KeyUp] If AutoStop Then Select Case KeyCode Case 65, 68 P1LR = zero Case 87, 88 P1UD = zero End Select End If [Timer1_Timer] Picture2.Top = Picture2.Top + SPM * P1UD If Picture2.Top <= 0 Then P1UD = pos If Picture2.Top >= Picture1.ScaleHeight Then P1UD = neg Picture2.Left = Picture2.Left + SPM * P1LR If Picture2.Left <= 0 Then P1LR = pos If Picture2.Left >= Picture1.ScaleWidth Then P1LR = neg
You also will notice that in the timer event I'm checking for the borders and changing the direction of movement to keep the picture within the borders.
The variable SPM is used to set the steps per movement, or how many pixels the picture will move with each timer tick.
Again, using a timer in this method reduces the CPU usage and gives a smoother movement without affecting too much of the rest of the application's events.