Recipe 9.7 Create Animated Buttons
9.7.1 Problem
You'd like to add some
pizzazz to your application. You've seen animated
buttons in other applications; how do you create them on your forms?
9.7.2 Solution
Access command buttons have an
under-documented property called PictureData that stores the bitmap
displayed on the button face. This solution examines two ways to use
this property. First, you will learn how to create
"two-state" buttons with pictures
that change when you click on them. Next, you will learn how to
create continuously animated buttons that cycle through a set of
pictures at all times, using the form's Timer event
to display a smooth succession of bitmaps.
Load 09-07.MDB and open frmAnimateDemo in
form view (Figure 9-20). The top two buttons are
two-state buttons whose pictures change when you click them. The Copy
button (on the top left) shows a second document, and the Exit button
(on the top right) shows the door closing just before it closes the
form. The bottom two buttons are examples of animated button faces.
(Only the Exit button on this form actually does anything when you
press it.)
9.7.2.1 Two-state buttons
To add a
two-state animated button to your form, follow these steps:
Open your form in design view. Place a
pair of command buttons on the form. The first button should be sized
correctly for your pictures and be located where you want the button
to be displayed. The second button can be located anywhere and can be
any size. For example, the two-state command button in the top left
corner of frmAnimateDemo was created with cmdCopy and cmdCopy2. The
cmdCopy button is shown selected in design view in Figure 9-21; cmdCopy2, which has been reduced in size to
save space, is located just to the left of cmdCopy. Set the Visible
property of the second command button to No.
Click on the first
command button of the pair, select the Picture property on its
properties sheet, and click the Build button (...) to the right of
the property. When the Picture Builder Wizard appears, select the
face you want your button to have in its unselected state (see Figure 9-22). You can use the Browse button to choose from
bitmap files on your disk.
Click on the second command button of the pair, select the Picture
property, and load the face you want your button to have when it is
depressed, again using the Build button. Create an
event procedure attached to the MouseDown event of the first button.
(If you're unsure of how to do this, see Section
P.5.5 in the the preface of this book.) Add the following code to the
event procedure: Private Sub cmdCopy_MouseDown(Button As Integer, _
Shift As Integer, X As Single, Y As Single)
Call SwapPictures(Me.cmdCopy, Me.cmdCopy2)
End Sub Replace cmdCopy and cmdCopy2 with the names of your buttons. Create the
following event procedure attached to the MouseUp property of the
first button: Private Sub cmdCopy_MouseUp(Button As Integer, _
Shift As Integer, X As Single, Y As Single)
Call SwapPictures(Me.cmdCopy, Me.cmdCopy2)
End Sub Again, replace cmdCopy and cmdCopy2 with the names of your buttons. Add the following subprocedure to the form's module: Private Sub SwapPictures(cmdButton1 As CommandButton, _
cmdButton2 As CommandButton)
Dim varTemp As Variant
varTemp = cmdButton1.PictureData
cmdButton1.PictureData = cmdButton2.PictureData
cmdButton2.PictureData = varTemp
Me.Repaint
End Sub
9.7.2.2 Continuously animated buttons
To add a continuously animated button to your form, follow these
steps:
From 09-07.MDB, import tblButtonAnimation,
frmButtonFaceChooser, basAnimate, and basCommonFile into your own
database. Open frmButtonFaceChooser (Figure 9-23) and select eight images for use on your
animated button. You can type the filenames directly into the text
boxes, or click on the numbered buttons to select files from the
common file dialog. The pictures will appear on the command buttons
as you choose them. The buttons are sized for standard 32 32-pixel
icons or bitmaps, but you may use images of any size.
When you have selected eight bitmaps, enter an animation name to
refer to this set of pictures (for example,
"clock") and click on the Save
button. Create a new blank form and place a
command button on it. Set the form's properties as
shown in Table 9-5.
Table 9-5. Property settings for animated button form|
OnLoad
|
Event Procedure
|
OnTimer
|
Event Procedure
|
TimerInterval
|
250
|
Enter the following code in the
declarations section of the form's module: Private Const acbcImageCount = 8
Private mintI As Integer
Private abinAnimation1(1 To acbcImageCount) As Variant Create the following event procedure attached to the
form's Load event: Private Sub Form_Load( )
Dim db As DAO.Database
Dim rstAnimation As DAO.Recordset
Dim intI As Integer
mintI = 0
Set db = CurrentDb( )
Set rstAnimation = db.OpenRecordset("tblButtonAnimation", _
dbOpenDynaset)
' Loop through the table, and load
' the animation images
With rstAnimation
.MoveFirst
.FindFirst "AnimationName='checkmark'"
For intI = LBound(abinAnimation1) To UBound(abinAnimation1)
abinAnimation1(intI) = .Fields("Face" & intI)
Next intI
.Close
End With
End Sub Replace 'checkmark' with the animation name you
used in Step 3. Create the following event procedure
attached to the form's Timer event: Private Sub Form_Timer( )
' mintI is 0-based, but the arrays are 1-based, so add 1.
Me.cmdCheck.PictureData = abinAnimation(mintI + 1)
' Bump to the next value, wrapping around at acbcImages
' (8, in this example).
mintI = (mintI + 1) Mod acbcImages
End Sub Replace cmdCheck with the name of the command
button you created in Step 4. Save the form and open it in form view. You should see your animation
running on the face of the button.
9.7.3 Discussion
Access stores the picture
displayed on a command button in the PictureData property. This
property is a binary representation of the bitmap displayed and is
read/write in all views. To store the bitmap elsewhere, there are
three choices: you can store it on another button, in a variable of
the Variant data type, or in a table field of the OLE Object data
type.
In this solution, you use all three of
these techniques. The two-state buttons work by storing the normal
image on the button you can see and parking the second image in a
small, invisible button. You can still read and write the PictureData
property of an invisible button. When you click the visible button,
its MouseDown event procedure is called, which swaps the pictures on
the visible and invisible buttons. The MouseUp event code swaps the
pictures again to return the original picture to the button face.
For
continuously animated buttons, the eight different button faces are
stored in a table as Long Binary Data (this is what Access tells you
if you open the table in datasheet view) in OLE Object fields. The
form's Load event procedure reads these button faces
into an array of variants, and its Timer event is used to fetch the
next button face every 250 milliseconds in round-robin fashion.
In frmButtonFaceChooser,
you'll find an easy way to load bitmaps into the
tblButtonAnimation table. You can load a button's
PictureData property by setting its Picture property to the name of
any bitmap or icon file. The command buttons on this form use the
Windows API common dialog functions to invoke the common file dialog.
If you care to dig into these details, you'll find
the common file dialog code in the basCommonFile module.
You can extend the animated button technique in several directions:
By including multiple hidden buttons on your form, you can create a
three-state button with a picture that changes when it is the
currently selected button as well as when it is pushed. You can modify the event
procedure to allow for animated buttons with more or less than eight
frames of animation. To do this, break up the table of frames into
two related tables, one holding the name of the animation and the
number of frames, and the other holding the actual picture data. The sample form shows how to use
two arrays and some additional code to have two continuously animated
buttons on the same form. You might generalize this code as well, but
watch out—forms with too many animated buttons look busy.
If you open the sample form and hold down
any button, you'll see that the animations stop for
as long as you keep the button depressed. This prevents the
form's Timer events from firing.
|
To see the effects of the MouseDown event, you must call the
form's Repaint method, which tells Access to
complete any pending screen updates. On the other hand, you
don't need to do this in the MouseUp event (although
it doesn't hurt if you do)—Access
automatically repaints the screen after a MouseUp event.
|
|
|