Windows 95 is loaded with animation sequences. These sequences include the circling magnifying glass that you see when Windows is searching for a file, as well as the flying files that move from folder to folder when you copy files. These animation sequences have one thing in common: They are produced using Windows' new animation control. You can use the animation control in your own programs to provide dynamic feedback to the user or to just do something a little different with a dialog box or window. As you'll learn in this chapter, the animation control is surprisingly easy to use.
As I mentioned previously, the animation control is used throughout Windows 95. Figure 14.1 shows the circling hourglass, and Figure 14.2 shows the flying files. When you create your own animation sequences, they must be stored as a special AVI audio/video file. These files must contain only a single video stream with at least one animation frame and must be either uncompressed or compressed using RLE-8 compression.
The AVI file can contain an audio stream. However, the animation control ignores all audio information.
The circling magnifying glass indicates that Windows is searching for a file.
The flying files appear when Windows copies files.
Finding animation sequences that work with the animation control can be tough. All of Windows' animation sequences are hidden away somewhere (that is, they aren't available as AVI files). Moreover, most of the animation sequences you can find in the AVI format do not meet the animation control's strict requirements. Most often, you have to create your own AVI files. You can do this with special video software that comes with the Video for Windows SDK. Other, third-party video software packages might also be able to create these special AVI files.
Luckily, the Visual C++ CD-ROM includes a few suitable AVI files along with its sample applications. In this chapter, you'll use one of those animation sequences as you learn to program the animation control, which, under MFC, is represented by the CAnimateCtrl class.
To get started quickly, you'll create the first of this chapter's sample programs using Developer Studio's AppWizard. This application, called Animate, displays an animation sequence in an animation control and provides toolbar buttons for manipulating the animation. Perform the following steps to create the Animate application:
ON THE WEB
http://www.quecorp.com/semfc The complete source code and executable file for the Animate application can be found in the CHAP14\Animate directory at this book's Web site.
1. Start a new AppWizard project workspace called Animate, as shown in Figure 14.3.
Start an AppWizard project workspace called Animate.
2. Give the new project the following settings in the AppWizard dialog boxes. When you're finished, the New Project Information dialog box should look like Figure 14.4.
Step 1: Single document
Step 2: Default settings
Step 3: Default settings
Step 4: Turn off Printing and Print Preview
Step 5: Default settings
Step 6: Default settings
These are the AppWizard settings for the Animate project.
3. Using the resource editor, remove the application's Edit menu. Also remove all items from the File menu except Exit, as shown in Figure 14.5.
Use the resource editor to edit the application's menus.
4. Delete all accelerators from the application's resources.
5. Using the resource editor, remove all of the buttons, except the question mark, from the application's toolbar.
6. Use the resource editor's drawing tools to add five buttons to the application's toolbar, as shown in Figure 14.6. Give the buttons the IDs ID_OPENANIMATION, ID_STARTANIMATION, ID_STOPANIMATION, ID_STEPFORWARD, and ID_STEPBACKWARD.
Add the five buttons that will control the animation to the application's toolbar.
7. Use ClassWizard to associate the ID_OPENANIMATION command with the OnOpenanimation() message response function, as shown in Figure 14.7. Make sure that you have CAnimateView selected in the Class
Name box before you add the function.Add the OnOpenanimation() message response function to the view class.
8. Use ClassWizard to associate the ID_STARTANIMATION, ID_STOPANIMATION, ID_STEPFORWARD, and ID_STEPBACKWARD commands with the OnStartanimation(), OnStopanimation(), OnStepforward(), and OnStepbackward() functions, as shown in Figure 14.8. Again, make sure that you're adding the functions to the CAnimateView class.
Add message response functions for the other toolbar buttons.
9. Use ClassWizard to associate the WM_CREATE Windows message with the OnCreate() message response function in the view class, as shown in Figure 14.9.
Add the OnCreate() function to the view class.
10. Click the
Edit Code button, and then add the following lines to the new OnCreate() function, right after the TODO: Add your specialized creation code here comment:m_seekPos = 0; m_animateCtrl.Create(WS_CHILD | WS_VISIBLE, CRect(10, 10, 100, 100), this, 111);11. Find the OnOpenanimation() function in the AnimateView.cpp file, and then add the following line, right after the TODO: Add your command handler code here comment:
m_animateCtrl.Open("filecopy.avi");
12. Find the OnStartanimation() function, and then add the following line, right after the TODO: Add your command handler code here comment:
m_animateCtrl.Play((UINT)0, (UINT)-1, (UINT)-1);
13. Find the OnStopanimation() function, and then add the following line, right after the TODO: Add your command handler code here comment:
m_animateCtrl.Stop();
14. Find the OnStepforward() function, and then add the lines shown in Listing 14.1, right after the TODO: Add your command handler code here comment.
Listing 14.1 LST14_01.CPP Code for the OnStepforward() Function
++m_seekPos; if (m_seekPos > 16) m_seekPos = 0; m_animateCtrl.Seek(m_seekPos);15. Find the OnStepbackward() function, and then add the lines shown in Listing 14.2, right after the TODO: Add your command handler code here comment:
Listing 14.2 LST14_02.CPP Code for the OnStepbackward() Function
--m_seekPos; if (m_seekPos < 0) m_seekPos = 16; m_animateCtrl.Seek(m_seekPos);16. Load the AnimateView.h file, and then add the following lines to the class's Attributes section, right after the line CAnimateDoc* GetDocument():
protected: CAnimateCtrl m_animateCtrl; int m_seekPos;17. Copy the FILECOPY.AVI file from your Visual C++ CD's DevStudio\Vc\Samples\mfc\general\cmnctrls directory to your Animate project directory.
You've now completed the Animate application. To compile the application, select Developer Studio's Build, Build command. You then can run
the program by selecting the Build, Execute command. When you do, the application's main window appears (see Figure 14.10). Select the
toolbar's Open button to load the animation sequence. Then select the Start button to get the animation going. When you do, files start flying between the two
folders displayed on the screen (Figure 14.11). You can stop the animation at any time by clicking the toolbar's Stop button. The arrow buttons enable you to
single-step through the animation sequence, either forward or backward.
FIG. 14.10
This is Animate when you first run it.
FIG. 14.11
This is Animate after you open and run the animation sequence.
As you created the Animate application, you probably were able to figure out how most of the code worked. An animation control, after all, is limited in what it can do, which makes it easy to program. There might be a few of the details, however, that you're not clear on, so in the following sections, you can examine the Animate application more closely.
In the Animate application, the animation control is created in the OnCreate() member function, which MFC calls when Windows sends the WM_CREATE message. In OnCreate(), the program creates the control by calling its Create() member function, like this:
m_animateCtrl.Create(WS_CHILD | WS_VISIBLE, CRect(10, 10, 100, 100), this, 111);
This function's four arguments are the control's style flags, the control's position and size, a pointer to the control's parent window, and the control's ID. The style constants include the same constants that you would use for creating any type of window, with the addition of special styles used with animation controls. Table 14.1 lists these special styles.
Table 14.1 Animation Control Styles
Style | Description |
ACS_AUTOPLAY | Plays the clip automatically when it's opened. |
ACS_CENTER | Centers the animation frames inside the control without resizing or repositioning the control. Without this flag, the animation control resizes itself to accommodate the animation frames. |
ACS_TRANSPARENT | Draws the animation sequence with a transparent background. |
The flags in Table 14.1 are mostly self-explanatory. The ACS_TRANSPARENT flag is helpful when you're displaying an animation sequence such as FILECOPY.AVI in a dialog box. (See the section "Adding an Animation Control to a Dialog Box," later in this chapter.) When you add this flag, the background color used in each animation frame is replaced by the background color defined by Windows (usually gray), which makes the background blend in with the dialog box's background. You add the ACS_TRANSPARENT (or any other) flag by ORing it in with the other flags, of which WS_CHILD and WS_VISIBLE are usually required, like this:
m_animateCtrl.Create(WS_CHILD | WS_VISIBLE | ACS_TRANSPARENT, CRect(10, 10, 100, 100), this, 111);
As soon as the animation control is created, you might want to initialize related variables in some way. For example, the Animate application uses the member variable m_seekPos to help implement the single-stepping functions. That variable is initialized to 0 in OnCreate(). The CAnimateCtrl class features a number of member functions that enable you to manipulate the control in limited ways. Those member functions and their descriptions are listed in Table 14.2.
Table 14.2 Member Functions of the CAnimateCtrl Class
Function | Description |
Close() | Closes the animation sequence. |
Create() | Creates the control. |
Open() | Loads an animation sequence. |
Play() | Plays the animation sequence. |
Seek() | Displays a given animation frame. |
Stop() | Stops playing the animation sequence. |
As you can tell from Table 14.2, there's not a heck of a lot you can do with an animation control. However, the Animate program shows you how to use the control's various member functions (all except Close(), that is). You already know how to create the control. To load an animation sequence, you call the CAnimateCtrl class's Open() member function, like this:
BOOL result = m_animateCtrl.Open("filecopy.avi");
This function requires the animation sequence's file name or resource ID as its single argument. If the animation sequence loads successfully, Open() returns TRUE; otherwise, it returns FALSE.
When the animation sequence has been opened successfully, you can play it by calling the Play() member function:
BOOL result = m_animateCtrl.Play((UINT)0, (UINT)-1, (UINT)-1);
This function's three arguments are the index of the frame (starting at 0) at which the animation sequence should start playing, the number of the frame at which playing should end (with [ms]1 indicating that the animation should end with the last frame), and the number of times to play the animation sequence. A value of [ms]1 for this last argument plays the sequence continuously. The Play() method returns TRUE if everything went okay and FALSE if there were an error.
Note that all three of Play()'s arguments are unsigned integers. How can [ms]1 be an unsigned integer? Don't ask me, ask Microsoft. You'll get compiler warnings, however, if you don't make the correct type casts.
You can stop playing an animation sequence by calling the Stop() member function, like this:
BOOL result = m_animateCtrl.Stop();
This function requires no arguments and returns TRUE if successful and FALSE if unsuccessful.
One interesting thing you can do with the Animate application is to advance or reverse frame-by-frame through the animation sequence. This is done by calling the CAnimateCtrl object's Seek() member function, which enables you to display any frame of animation that you like. The Animate application uses Seek() in conjunction with a member variable, called m_seekPos, that keeps track of the currently selected frame. The program first increments m_seekPos:
++m_seekPos;
The program then checks that the variable is still within the correct range for the animation sequence:
if (m_seekPos > 16) m_seekPos = 0;
As soon as m_seekPos has a valid value, a call to Seek() displays the selected frame of animation, like this:
m_animateCtrl.Seek(m_seekPos);
The Seek() member function's single argument is the zero-based index of the frame to display. A value of [ms]1 indicates that the last frame should be displayed. The index must be less than than 65,535.
Chances are, when you need the animation control, it'll be in some sort of dialog box. When you're using Visual C++'s dialog box editor, adding an animation control to a dialog box is quick and easy. To create an application that displays a dialog box with an animation control, follow these steps:
ON THE WEB
http://www.quecorp.com/semfc The complete source code and executable file for the Animate2 application can be found in the CHAP14\Animate2 directory atthis book's Web site.
1. Start a new AppWizard project workspace called Animate2, as shown in Figure 14.12.
Start an AppWizard project workspace called Animate2.
2. Give the new project the following settings in the AppWizard dialog boxes. When you're finished, the New Project Information dialog box should look like Figure 14.13.
Step 1: Single document
Step 2: Default settings
Step 3: Default settings
Step 4: Turn off everything except 3D Controls
Step 5: Default settings
Step 6: Default settings
These are the AppWizard settings for the Animate2 project.
3. Using the resource editor, remove the application's Edit menu. Also remove all items from the File menu except for Exit.
4. Add a
Test menu to the program, with a single item calledDialog Box (see Figure 14.14). Set the Dialog Box command's ID to ID_TEST_DIALOGBOX.Use the resource editor to edit the application's menus.
5. Delete all accelerators from the application's resources.
6. Create the dialog box shown in Figure 14.15. The empty square in the upper left of the dialog box is an animation control, which you can create from the toolbox just as you create any kind of control. (On the toolbox, the animation control looks like a film strip.)
This is the dialog box that displays the animation.
7. Select the animation control and press Enter. Set the Animate button's ID to IDC_ANIMATE1 and then turn on the control's Tra
nsparent style (Figure 14.16).You need to set the animation control's style such that it doesn't appear in the dialog box with a colored background.
8. Select the dialog box, and press Ctrl+W to bring up ClassWizard.Create a class called CAnimateDlg for the dialog box, as shown in Figure 14.17.
To control the dialog box from your program, you need to create a class for the dialog box.
9. Use ClassWizard to associate the ID_TEST_DIALOGBOX command with the OnTestDialogbox() message response function, as shown in Figure 14.18. Make sure that you have CAnimate2View selected in the Class
Name box before you add the function.Add the OnTestDialogbox() message response function to the view class.
10. Click the
Edit Code button, and then add the following lines to the new OnTestDialogbox() function, right after the TODO: Add your command handler code here comment:CAnimateDlg dlg; dlg.DoModal();11. Near the top of the CAnimate2View file, add the following line, right after the #endif line:
#include "animatedlg.h"
12. Use ClassWizard to associate the dialog box's IDC_ANIMATE button with the OnAnimate() message response function, as shown in Figure 14.19. Make sure you have the CAnimateDlg class selected in the Class
Name box.Add the OnAnimate() message response function.
13. Click the
Edit Code button, and then add the following lines to the new OnAnimate() function, right after the TODO: Add your control notification handler code here comment:CAnimateCtrl* pCtrl = (CAnimateCtrl*)GetDlgItem(IDC_ANIMATE1); pCtrl->Open("filecopy.avi"); pCtrl->Play((UINT)0, (UINT)-1, (UINT)-1);14. Copy the FILECOPY.AVI file from your Animate project directory to your Animate2 project directory.
You've now completed the Animate2 application. To compile the application, select Developer Studio's Build, Build command. You then can run
the program by selecting the Build, Execute command. When you do, the application's main window appears. Select the Test, D
ialog Box command to display the dialog box containing the animation control. Then select the Animate button. When you do, the dialog box loads and runs the
animation sequence (Figure 14.20). You can stop the animation at any time by clicking the Cancel button.
The animation control in the dialog box now displays the flying files.
There's not much to know about the Animate2 application, as far as its animation control goes. Still, a quick rundown of the differences between this application and its predecessor is in order.
First, you don't have to call the animation control's Create() function when the control is part of a dialog box. MFC takes care of that detail for you. However, you do still need to tell the dialog box what to do with the animation control. Animate2 does this in response to the Animate button, which causes MFC to call the CAnimateDlg class's OnAnimate() member function. In that function, the program first associates an object of the CAnimateCtrl class with the dialog box's animation control, like this:
CAnimateCtrl* pCtrl = (CAnimateCtrl*)GetDlgItem(IDC_ANIMATE1);
The program can then manipulate the control, which it does by calling the control's Open() and Play() member functions through the pointer returned by the previous call to GetDlgItem():
pCtrl->Open("filecopy.avi"); pCtrl->Play((UINT)0, (UINT)-1, (UINT)-1);
Notice the difference that setting the animation control's Transparent style makes in this program. The animation control's background matches that of the dialog box, rather than being some other color.
That's all there is to it! If you want the animation to run when the dialog box first appears, just associate the WM_INITDIALOG Windows message with the OnInitDialog() member function, as shown in Figure 14.21. Place the animation control member-function calls in OnInitDialog(), as shown in Listing 14.3. Make sure to call the base class's version of OnInitDialog().
Use OnInitDialog() to get an animation going while MFC is initializing the dialog box.
Listing 14.3 LST14_03.CPP The OnInitDialog() Message Response Function
BOOL CAnimateDlg::OnInitDialog() { CDialog::OnInitDialog(); // TODO: Add extra initialization here CAnimateCtrl* pCtrl = (CAnimateCtrl*)GetDlgItem(IDC_ANIMATE1); pCtrl->Open("filecopy.avi"); pCtrl->Play((UINT)0, (UINT)-1, (UINT)-1); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE }
One of the trickiest parts of using the animation control is finding or creating an AVI file that suits your needs. The process of creating AVI files is beyond the scope of this book, but you can find tools on the market that'll help you with this process. The first place to look might be the Microsoft Video for Windows SDK.