Creating an Animation Control

An animation control belongs to the ANIMATE_CLASS window class. You create this control by using the CreateWindow or CreateWindowEx function, by using the Animate_Create macro, or, in MFC, by using the Create member function on your CAnimateCtrl object. The Animate_Create macro positions the animation control in the upper left corner of the parent window and, if you don't specify the ACS_CENTER style, sets the width and height of the control based on the dimensions of a frame in the AVI clip.

More likely, though, you will be creating your animation control to run in a dialog box. You can use the dialog box editor to place an animation control right in your dialog box and then set the styles of the control through the control properties. If you create an animation control within a dialog box or from a dialog box resource, the control is automatically destroyed when the user closes the dialog box. If you create an animation control within a window, you must explicitly destroy the control. Otherwise, you'll be guilty of being a resource hog.

You can use these window styles with animation controls:

I wrote my sample to demonstrate the animation control first in MFC (MFCANIM), and then I ported it back to C (ANIMAT). My design goals included the following:

You can see this sample in Figure 2-9.

Figure 2-9.

The ANIMAT sample.

Writing this sample was very easy. In fact, the most difficult part was finding an animation that would work. Beginning on the following page is the code I used in the MFC sample to play the animation, stop the playback, and single-step through the frames. I chose to allow the user to single-step from the beginning through the last frame. Notice that because I put my animation control in a dialog box, I did not have to call the Create member function. (Don't forget to include AFXCMN.H in your STDAFX.H file to define the class.)

// CMfcanimView message handlers

void CMfcanimView::OnDemo ()
{
CDemo demoDlg;

// Run the Animation Demo dialog box.
demoDlg.DoModal ();
}

// CDemo dialog
CDemo::CDemo (CWnd *pParent /*=NULL*/)
: CDialog (CDemo::IDD, pParent)
{
// {{AFX_DATA_INIT (CDemo)
// NOTE: ClassWizard will add member initialization here.
// }}AFX_DATA_INIT
m_bStart = FALSE; // BOOL--whether or not animation has started
m_iSeek = 1; // used for single-stepping through the frames
}

void CDemo::OnSeek ()
{
// If the animation is running...
if (m_bStart)
{
// Seek to the specified frame.
m_AnimateCtrl.Seek (m_iSeek);
if (m_iSeek < NUM_FRAMES)
m_iSeek++;
}
}

void CDemo::OnStart ()
{
// If the animation hasn't started yet...
if (! m_bStart)
{
m_bStart = TRUE;
// Open the animation file.
m_AnimateCtrl.Open (IDR_AVICLIP);
// Play it from beginning to end with infinite replay.
m_AnimateCtrl.Play (0, (UINT)(-1), (UINT)(-1));
}
}

void CDemo::OnStop ()
{
// If the animation has started...
if (m_bStart)
{
m_bStart = FALSE;
// Stop it.
m_AnimateCtrl.Stop ();
}
}

In the preceding code, I passed an identifier to the AVI resource rather than passing in the name of the AVI file. This means that the clip will be built into the sample. When I first wrote the code, I passed in the name of the clip. But this wasn't the best option because I had to pass in the full path. (If you don't pass in the full path, the call to open the AVI file will fail and the clip will not run.) To add the clip to my resource, I inserted the following line in my MFCANIM.RC2 file:

// Add manually edited resources here...
IDR_AVICLIP AVI res\win95.avi

I then added the symbol for the AVI file to the resource by choosing Symbols from the Resource menu. When you click the New button in the Symbol Browser, a second dialog box prompts you to add the new symbol, as shown in Figure 2-10.

Figure 2-10.

Adding a symbol to your resource.

Rebuild after you've added the new symbol. Don't forget to scan all of your dependencies before doing this. I forgot at first; the project did not build all that it should have, and the sample didn't run.

The code in the C sample, ANIMAT, is quite similar. The dialog procedure handles all the manipulation of the animation control. You must include the COMMCTRL.H header file, and the COMCTL32.LIB file must be in your list of libraries.

BOOL APIENTRY Demo (
HWND hDlg,
UINT message,
UINT wParam,
LONG lParam)
{
static BOOL bStart;
static int iSeek;

switch (message)
{
case WM_INITDIALOG:
bStart = FALSE;
iSeek = 1;
return TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
EndDialog (hDlg, TRUE);
return TRUE;
}

else if (HIWORD(wParam) == BN_CLICKED)
{
switch (LOWORD(wParam))
{
case IDC_PLAY:
if (! bStart)
{
bStart = TRUE;
Animate_Open (GetDlgItem (hDlg, IDC_ANIMATE),
"WIN95.AVI");
Animate_Play (GetDlgItem (hDlg, IDC_ANIMATE),
0, -1, -1);
}
break;

case IDC_STOP:
if (bStart)
{
bStart = FALSE;
Animate_Stop(GetDlgItem(hDlg, IDC_ANIMATE));
}
break;

case IDC_SEEK:
if (bStart)
{
Animate_Seek(GetDlgItem(hDlg, IDC_ANIMATE), iSeek);
if (iSeek < NUM_FRAMES)
iSeek++;
}
break;
}
}
break;

default:
return FALSE;
}
}

That's about all there is to it. If you build and run the sample, you will see a really cool animation (thanks to Jonathan Cluts).