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?
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.)
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
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.
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.
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.