The Bitmap Animation framework (bmpanim.dll
) uses the font and bitmap server (fbscli.dll
) to provide the bitmap images (CFbsBitmap
s).
An animation DLL (bmpansrv.dll
), loaded by the Window Server, is used to perform the animation.
The animation DLL uses the bitgdi component (bitgdi.dll
) to draw the bitmaps.
To use a bitmap animation in your application you need to:
define one or more animation frames, each of which owns a bitmap,
assign the frames to an animation container,
create an animation player object and pass the animation container to it. This communicates with the window server to start and stop playing the animation inside a window.
Collectively, these steps make up the Bitmap Animation framework. The key client side classes that are involved in these steps are:
The rest of this document describes each of these steps, starting with the animation frame.
The CBitmapFrameData
class represents a single frame in an animation. The following properties of a frame can be set:
the bitmap image,
the mask, which is used for making parts of the image transparent,
the time the frame is displayed, in milliseconds,
the position in the window where the frame is displayed.
These properties can either be set in CBitmapFrameData::NewL()
or by calling various setter functions, described below.
The following code loads the bitmap and mask from a multi bitmap file, and constructs the frame, setting its bitmap and mask, which it takes ownership of:
CFbsBitmap* bitmap=new (ELeave) CFbsBitmap; // load the image bitmap from an mbm file
CleanupStack::PushL(bitmap);
User::LeaveIfError(bitmap->Load(KMBMFileName, EMbmAnimFrame1));
CFbsBitmap* mask=new (ELeave) CFbsBitmap; // load the mask from the same mbm file
CleanupStack::PushL(mask);
User::LeaveIfError(mask->Load(KMBMFileName, EMbmAnimFrameMask1));
CBitmapFrameData* frame1 = CBitmapFrameData::NewL(bitmap, mask);
CleanupStack::Pop(2); // bitmap, mask
CBitmapFrameData::SetBitmap()
and CBitmapFrameData::SetMask()
could alternatively be used.
An animation can have multiple frames, each of which has an image and mask bitmap. Each frame stores a flag to indicate whether
or not it owns the bitmaps. If the frame owns the bitmaps, they are deleted in the frame’s destructor. This flag can be set
or unset by calling CBitmapFrameData::SetBitmapsOwnedExternally()
. By default, bitmaps are owned by the frame.
The mask is used in the standard way for a bitmap mask, so pixels in the bitmap image that map to black pixels in the mask are drawn, while pixels that map to white pixels in the mask are not, so appear transparent.
The time period for the frame to be displayed on the screen is set in milliseconds:
frame1->SetInterval(125);
Note that a default time interval can be set in the frame container (described in the next section) by calling CBitmapAnimClientData::SetFrameInterval()
. Any value set in the container will apply to frames that have not set an interval themselves.
The position of the frame relative to the animation window is set using CBitmapFrameData::SetPosition()
:
TPoint framePos(3,6);
frame1->SetPosition(framePos);
Note that the position can also be specified in RBitmapAnim
; if so, this value applies to all frames.
When you have finished defining the animation frame(s), use the frame container class, CBitmapAnimClientData
, to create the animation.
Frames are grouped into an animation frame container (CBitmapAnimClientData
), which allows the following behaviour to be set:
append frames to the container,
set a default display interval for all frames, (note that the time interval set by an individual frame takes precedence, for that frame, over the default interval),
set one of the following play modes for the animation: play once, loop or bounce (plays forwards and backwards),
set the animation to flash,
provide an additional bitmap frame to use for the background to the animation (explained below).
First, create the frame container, and append the frame(s) to it in the correct sequence:
CBitmapAnimClientData* animFrames=CBitmapAnimClientData::NewL();
CleanupStack::PushL(animFrames);
animFrames->AppendFrameL(*frame1);
animFrames->AppendFrameL(*frame2); // etc.
A default display interval can be set for the animation:
animFrames->SetFrameInterval(100);
This applies only to frames which have not specified their own interval (using CBitmapFrameData::SetInterval()
). In this example, the default interval for frames without their own interval is 100 milliseconds (0.1 second). It can be
used to ensure that all frames are displayed for the same length of time.
There are three play modes: play once, play repeatedly in the same direction ('loop') and play forwards and backwards repeatedly ('bounce'). This code sets the animation to play once:
animFrames->SetPlayMode(CBitmapAnimClientData::EPlay);
CBitmapAnimClientData::SetFlash()
and CBitmapAnimClientData::SetBackgroundFrame()
are used to set/unset the flash flag and the background frame, respectively. The flash flag determines whether the animation
should flash or not.
The background frame, which is optional, is used to clear the current frame before drawing the next one. If no background frame is provided by the client, the window server creates its own background frame using the original screen contents, and updates it when the animation window is redrawn.
If the client-provided background frame contains an image bitmap and a mask, the background image used is a combination of the screen contents and the supplied background bitmap. If the client-provided background frame has a bitmap but no mask, the bitmap is used as the background.
When the animation is ready to play, it must be packaged and sent to the window server’s animation DLL. This is done through
an animation player (RBitmapAnim
) object.
RBitmapAnim
allows you to do the following:
specify the window in which the animation is displayed,
associate the animation with an RAnimDll
object, which provides a connection to the window server,
pass the animation object to the window server’s animation DLL,
specify the number of times the animation should play,
start and stop playing the animation. Optionally the animation can start playing from a particular frame.
Note that after the animation object has been set up and passed to the window server, the general attributes of the animation,
namely the flash property, the default display time for each frame and the play mode can still be changed, using the following
RBitmapAnim
functions:
SetFlashL()
,
SetFrameIntervalL()
,
SetPlayModeL()
.
Any changes to these properties made using RBitmapAnim
will override the values previously set in CBitmapAnimClientData
.
RAnimDll
is a handle to the server-side animation DLL. It is used to load the window server animation DLL, bmpansrv.dll
, which provides the functions that perform the frames animation. The RAnimDll
instance is passed to the RBitmapAnim
constructor.
RAnimDll animDLL(iEikonEnv->WsSession()); // session is used to interact with the window server
_LIT(KDllName, "BMPANSRV.DLL");
User::LeaveIfError(animDll.Load(KDllName));
RBitmapAnim animPlayer(animDLL);
animPlayer.ConstructL(Window());
The animation frame container (CBitmapAnimClientData
) should be passed via the RBitmapAnim
object to the window server. This is done using the function SetBitmapAnimDataL()
. Note that calling this function does not cause the animation to start playing:
animPlayer.SetBitmapAnimDataL(*animFrames);
If the animation should play more than once, the number of cycles should be set:
animPlayer.SetNumberOfCyclesL(10);
Note that if the animation's play mode is 'bounce', the number of cycles must be set to at least two to ensure a complete animation routine.
To set the animation’s position, use SetPositionL()
. This value is an offset from the origin of the animation window.
TPoint animPos(20,40);
animPlayer.SetPositionL(animPos);
The RBitmapAnim::StartL()
and RBitmapAnim::StopL()
functions send commands to the animation DLL to start/stop the animation routine.
Calling RBitmapAnim::DisplayFrameL()
before the animation has started sets the frame from which the animation should start playing.
After they have been finished with, Close()
should be called on the RAnimDll
and RBitmapAnim
objects.
animPlayer.Close();
animDLL.Close();