Symbian
Symbian Developer Library

SYMBIAN OS V9.4

Feedback

[Index] [Previous] [Next]


BitmapSprite: create a sprite by loading a bitmap file

Note: This example is designed to work properly only with techview, there is no guarantee that it will work properly with other interfaces

Found in: examples\Graphics\WS\BitmapSprite\

These are the main files contained in the examples. Some extra files may be needed to run the examples, and these will be found in the appropriate examples directory.

// AppHolder.cpp
//
// Copyright (c) 2005 Symbian Softwares Ltd.  All rights reserved.
// @ file
//
//////////////////////////////////////////////////////////////////////////////////////


#include "AppHolder.h"
#include "BitmapSprite.h"
#include <EikStart.h>
#include <gdi.h>

//
// EXPORTed functions
//

EXPORT_C CApaApplication* NewApplication()
    {
    return new CAppholderApplication;
    }


/**
 The below section is added to make the code compatible with v9.1
 This is because only exe files are compatible with v9.1
*/

GLDEF_C TInt E32Main()        
    {
    return EikStart::RunApplication(NewApplication);
    }


////////////////////////////////////////////////////////////////
//
// Application class, CAppholderApplication
//
////////////////////////////////////////////////////////////////

TUid CAppholderApplication::AppDllUid() const
    {
    return KUidAppholder;
    }

CApaDocument* CAppholderApplication::CreateDocumentL()
    {
    // Construct the document using its NewL() function, rather 
    // than using new(ELeave), because it requires two-phase
    // construction.
    return new (ELeave) CAppholderDocument(*this);
    }


////////////////////////////////////////////////////////////////
//
// Document class, CAppholderDocument
//
////////////////////////////////////////////////////////////////

// C++ constructor
CAppholderDocument::CAppholderDocument(CEikApplication& aApp)
        : CEikDocument(aApp)
    {
    }

CEikAppUi* CAppholderDocument::CreateAppUiL()
    {
    return new(ELeave) CAppholderAppUi;
    }

CAppholderDocument::~CAppholderDocument()
    {
    }

////////////////////////////////////////////////////////////////
//
// App UI class, CAppholderAppUi
//
////////////////////////////////////////////////////////////////

void CAppholderAppUi::ConstructL()
    {
    BaseConstructL();
    iClient=CExampleWsClient::NewL(ClientRect());
    }

CAppholderAppUi::~CAppholderAppUi()
    {
    delete iClient;
    }

void CAppholderAppUi::HandleCommandL(TInt aCommand)
    {
    switch (aCommand)
        {
    case EEikCmdExit: 
        Exit();
        break;
        }
    }
// Base.CPP
//
// Copyright (c) 2005-2005 Symbian Software Ltd.  All rights reserved.
// @file
//

#include <w32std.h>
#include "Base.h"

///////////////////////////////////////////////////////////////////////////////
//                          CWindow implementation
///////////////////////////////////////////////////////////////////////////////

CWindow::CWindow(CWsClient* aClient)
    : iClient(aClient)
    {
    }

void CWindow::ConstructL (const TRect& aRect, const TRgb& aColor, CWindow* aParent)
    {
    _LIT(KFontName,"Swiss");
    // If a parent window was specified, use it; if not, use the window group
    // (aParent defaults to 0).
    RWindowTreeNode* parent= aParent ? (RWindowTreeNode*) &(aParent->Window()) : &(iClient->iGroup);
    // Allocate and construct the window
    iWindow=RWindow(iClient->iWs);
    User::LeaveIfError(iWindow.Construct(*parent,(TUint32)this));
    // Store the window's extent
    iRect = aRect;
    // Set up the new window's extent
    iWindow.SetExtent(iRect.iTl, iRect.Size());
    // Set its background color
    iWindow.SetBackgroundColor (aColor);
    // Set up font for displaying text
    TFontSpec fontSpec(KFontName,200);
    User::LeaveIfError(iClient->iScreen->GetNearestFontInTwips(iFont,fontSpec));
    // Activate the window
    iWindow.Activate();
    }

CWindow::~CWindow()
    {
    iWindow.Close();
    iClient->iScreen->ReleaseFont(iFont);
    }

RWindow& CWindow::Window()
    {
    return iWindow;
    }

CWindowGc* CWindow::SystemGc()
    {
    return iClient->iGc;
    }

CWsScreenDevice* CWindow::Screen()
    {
    return iClient->iScreen;
    }

CFont* CWindow::Font()
    {
    return iFont;
    }


///////////////////////////////////////////////////////////////////////////////
//                          CWsRedrawer implementation
///////////////////////////////////////////////////////////////////////////////

CWsRedrawer::CWsRedrawer()
    : CActive(CActive::EPriorityLow)
    {
    }

void CWsRedrawer::ConstructL(CWsClient* aClient)
    {
    iClient=aClient; // remember WsClient that owns us
    CActiveScheduler::Add(this); // add ourselves to the scheduler
    IssueRequest(); // issue request to draw
    }

CWsRedrawer::~CWsRedrawer()
    {
    Cancel();
    }

void CWsRedrawer::IssueRequest()
    {
    iClient->iWs.RedrawReady(&iStatus);
    SetActive();
    }

void CWsRedrawer::DoCancel()
    {
    iClient->iWs.RedrawReadyCancel();
    }

void CWsRedrawer::RunL()
    {   
    // find out what needs to be done in response to the event
    TWsRedrawEvent redrawEvent;
    iClient->iWs.GetRedraw(redrawEvent); // get event
    CWindow* window=(CWindow*)(redrawEvent.Handle()); // get window
    if (window)
        {
        TRect rect=redrawEvent.Rect(); // and rectangle that needs redrawing
        // now do drawing
        iClient->iGc->Activate(window->Window());
        window->Window().BeginRedraw();
        window->Draw(rect);
        window->Window().EndRedraw();
        iClient->iGc->Deactivate();
        }
    // maintain outstanding request
    IssueRequest();
    }


/////////////////////////////////////////////////////////////////////////////////////
//                              CWsClient implementation
/////////////////////////////////////////////////////////////////////////////////////
CWsClient::CWsClient()
    : CActive(CActive::EPriorityStandard)
    {
    }

void CWsClient::ConstructL()
    {
    //  add ourselves to active scheduler 
    CActiveScheduler::Add(this);
    // get a session going
    User::LeaveIfError(iWs.Connect());
    // construct our one and only window group
    iGroup=RWindowGroup(iWs);
    User::LeaveIfError(iGroup.Construct(2,ETrue)); // '2' is a meaningless handle
    // construct screen device and graphics context
    iScreen=new (ELeave) CWsScreenDevice(iWs); // make device for this session
    User::LeaveIfError(iScreen->Construct()); // and complete its construction
    User::LeaveIfError(iScreen->CreateContext(iGc)); // create graphics context
    // construct redrawer
    iRedrawer=new (ELeave) CWsRedrawer;
    iRedrawer->ConstructL(this);
    // construct main window
    ConstructMainWindowL();
    // request first event and start scheduler
    IssueRequest();
    }

CWsClient::~CWsClient()
    {
    // neutralize us as an active object
    Deque(); // cancels and removes from scheduler
    // get rid of everything we allocated
    delete iGc;
    delete iScreen;
    delete iRedrawer;
    // destroy window group
    iGroup.Close(); // what's the difference between this and destroy?
    // finish with window server
    iWs.Close();
    }

void CWsClient::IssueRequest()
    {
    iWs.EventReady(&iStatus); // request an event
    SetActive(); // so we're now active
    }

void CWsClient::DoCancel()
    {
    iWs.EventReadyCancel(); // cancel event request
    }

void CWsClient::ConstructMainWindowL()
    {
    }
// BitmapSprite.CPP
//
// Copyright (c) 2005-2005 Symbian Software Ltd.  All rights reserved.
//


// This file contains implementations of derived class 
// functions for client and windows.
//
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
// PROJECT: BitmapSprite
// --------------
//
// CREATE A SPRITE USING BITMAPS LOADED FROM FILE
//
// PROJECT OVERVIEW
// ----------------
//
// Creates a sprite using bitmaps loaded from file.
// A hatched background has been drawn on the window to illustrate
// the fact that the sprite does not overlay a rectangular area, like 
// window, but only the area specified by the bitmap mask.
// The animation of the sprite does not cause a redraw event for the 
// window beneath it.
//
// The sprite can be moved around the screen using the arrow keys.
//
// Functions introduced in this project include:
//          RWsSprite::Construct()
//          RWsSpriteBase::AppendMember()
//          RWsSpriteBase::Activate()
//          RWsSpriteBase::Close()
//
// STRUCTURE
// ---------
//
// To create a sprite, an application must set up sprite members to
// contain bitmaps, and add the sprite members to the sprite. The 
// bitmaps can either be read in from files, or created using 
// off-screen bitmaps which can be drawn to via a graphics context
// in a similar way to a window. This example project uses the former
// method. 

#include <eikenv.h>
#include <w32std.h>
#include "Base.h"
#include "BitmapSprite.h"

#include <BitmapSprite.mbg>

CSprite::CSprite(CWsClient *aClient) : iClient(aClient), iSpritePos(80, 75)
    {
    }

CSprite::~CSprite()
    {
    for (TInt i=0; i<8; i++)
        {
        delete iSpriteMember[i].iBitmap;
        delete iSpriteMember[i].iMaskBitmap;
        }
    iSprite.Close();
    }

void CSprite::UpdatePos(TPoint aAdjust)
    {
    iSpritePos += aAdjust;
    iSprite.SetPosition(iSpritePos);
    }

void CSprite::ConstructL(CWindow* aWindow)
    {
    CEikonEnv* eikenv=CEikonEnv::Static();
    iSprite = RWsSprite(iClient->iWs);
    User::LeaveIfError(iSprite.Construct(aWindow->Window(), iSpritePos, 0));
    // Initialize sprite members
    _LIT(KStar,"*"); // "*" means "the <app-name>.mbm file in the app directory"
    for (TInt i=0; i<8; i++)
        {
        iSpriteMember[i].iInvertMask = EFalse;
        iSpriteMember[i].iOffset = TPoint (0,0);
        iSpriteMember[i].iInterval = TTimeIntervalMicroSeconds32 (200000);
        iSpriteMember[i].iBitmap = eikenv->CreateBitmapL(KStar, i);
        if (i%2 == 0)
            {
            iSpriteMember[i].iMaskBitmap=eikenv->CreateBitmapL(KStar, EMbmBitmapspriteMil1mask);
            }
        else
            {
            iSpriteMember[i].iMaskBitmap=eikenv->CreateBitmapL(KStar, EMbmBitmapspriteMil2mask);
            }
        User::LeaveIfError(iSprite.AppendMember(iSpriteMember[i]));
        }

    // Activate the sprite
    User::LeaveIfError(iSprite.Activate());
    }


//////////////////////////////////////////////////////////////////////////////
//                   CMainWindow implementation
//////////////////////////////////////////////////////////////////////////////


/****************************************************************************\
|   Function:    Constructor/Destructor for CMainWindow
|   Input:       aClient      Client application that owns the window
\****************************************************************************/
CMainWindow::CMainWindow (CWsClient* aClient)
: CWindow (aClient)
    {
    }


CMainWindow::~CMainWindow ()
    {
    iWindow.Close();
    }

/****************************************************************************\
|   Function:    CMainWindow::Draw
|   Purpose: Redraws the contents of CMainWindow within a given
|               rectangle.
|   Input:       aRect    Rectangle that needs redrawing
|   Output:      None
\****************************************************************************/

void CMainWindow::Draw(const TRect& aRect)
    {
    // Draw a hatched pattern to illustrate that sprite is drawn only 
    // where its bitmap mask is 0
    CWindowGc* gc=SystemGc(); // get a gc
    gc->SetClippingRect(aRect); // clip outside this rect
    gc->Clear(aRect); // clear
    gc->SetPenStyle(CGraphicsContext::ESolidPen);
    gc->SetPenColor(TRgb::Gray4(2));
    TSize size = Window().Size();
    TInt width = size.iWidth;
    TInt height = size.iHeight;
    TInt numHoriz=height/5;
    TInt numVert=width/10;
    for (TInt i=numHoriz; i>0; i--)
        {
        gc->DrawLine (TPoint(0,height/numHoriz*i), TPoint(width, height/numHoriz*i));
        }
    for (TInt j=numVert; j>0; j--)
        {
        gc->DrawLine (TPoint(width/numVert*j, 0), TPoint(width/numVert*j, height));
        }
    }


/****************************************************************************\
|   Function:    CMainWindow::HandlePointerEvent
|   Purpose: Handles pointer events for CMainWindow.
|   Input:       aPointerEvent    The pointer event!
|   Output:      None
\****************************************************************************/

void CMainWindow::HandlePointerEvent (TPointerEvent& /*aPointerEvent*/)
    {   
    }


//////////////////////////////////////////////////////////////////////////////
//                   CExampleWsClient implementation
//////////////////////////////////////////////////////////////////////////////

CExampleWsClient* CExampleWsClient::NewL(const TRect& aRect)
    {
    // make new client
    CExampleWsClient* client=new (ELeave) CExampleWsClient(aRect); 
    CleanupStack::PushL(client); // push, just in case
    client->ConstructL(); // construct and run
    CleanupStack::Pop();
    return client;
    }

/****************************************************************************\
|   Function:    Constructor/Destructor for CExampleWsClient
|               Destructor deletes everything that was allocated by
|               ConstructMainWindowL()
\****************************************************************************/

CExampleWsClient::CExampleWsClient(const TRect& aRect)
:iRect(aRect)
    {
    }

CExampleWsClient::~CExampleWsClient ()
    {
    delete iMainWindow;
    delete iSprite;
    }


/****************************************************************************\
|   Function:    CExampleWsClient::ConstructMainWindowL()
|               Called by base class's ConstructL
|   Purpose: Allocates and creates all the windows owned by this client
|               (See list of windows in CExampleWsCLient declaration).
\****************************************************************************/

void CExampleWsClient::ConstructMainWindowL()
    {
    iMainWindow=new (ELeave) CMainWindow(this);
    iMainWindow->ConstructL(iRect, TRgb (255,255,255));
    iSprite=new (ELeave) CSprite (this);
    iSprite->ConstructL(iMainWindow);
    }


/****************************************************************************\
|   Function:    CExampleWsClient::RunL()
|               Called by active scheduler when an even occurs
|   Purpose: Processes events according to their type
|               For key events: calls HandleKeyEventL() (global to client)
|               For pointer event: calls HandlePointerEvent() for window
|                                  event occurred in.
\****************************************************************************/
void CExampleWsClient::RunL()
    {
    // get the event
    iWs.GetEvent(iWsEvent);
    TInt eventType=iWsEvent.Type();
    // take action on it
    switch (eventType)
        {
    // events global within window group
    case EEventNull:
        break;
    case EEventKey:
        {
        TKeyEvent& keyEvent=*iWsEvent.Key(); // get key event
        HandleKeyEventL (keyEvent);
        break;
        }
    case EEventModifiersChanged:
        break;
    case EEventKeyUp:
    case EEventKeyDown:
    case EEventFocusLost:
    case EEventFocusGained:
    case EEventSwitchOn:
    case EEventPassword:
    case EEventWindowGroupsChanged:
    case EEventErrorMessage:
        break;
    // events local to specific windows
    case EEventPointer:
        {
        CWindow* window=(CWindow*)(iWsEvent.Handle()); // get window
        TPointerEvent& pointerEvent=*iWsEvent.Pointer();
        window->HandlePointerEvent (pointerEvent);
        break;
        }
    case EEventPointerExit:
    case EEventPointerEnter:
        break;
    case EEventPointerBufferReady:
        {
        break;
        }
    case EEventDragDrop:
        break;
    default:
        break;
        }
    IssueRequest(); // maintain outstanding request
    }

/****************************************************************************\
|   Function:    CExampleWsClient::HandleKeyEventL()
|   Purpose: Processes key events for CExampleWsClient
|               Gets the key code from the key event.  Exits on 'Escape'
\****************************************************************************/
void CExampleWsClient::HandleKeyEventL (TKeyEvent& aKeyEvent)
    {
    TUint   code = aKeyEvent.iCode;
    switch (code)
        {
        case EKeyLeftArrow:
            iSprite->UpdatePos(TPoint(-2,0));
            break;
        case EKeyRightArrow:
            iSprite->UpdatePos(TPoint(2,0));
            break;
        case EKeyUpArrow:
            iSprite->UpdatePos(TPoint(0,-2));
            break;
        case EKeyDownArrow:
            iSprite->UpdatePos(TPoint(0,2));
            break;
        }
    }
// Base.H
//
// Copyright (c) 2005-2005 Symbian Software Ltd.  All rights reserved.
// @file
//


#if !defined(__WSPRITE2_H__)
#define __WSPRITE2_H__


// Forward declarations
class CWsRedrawer;
class CWindow;


/////////////////////////////////////////////////////////////////////////
//                      Declaration of CWsClient
/////////////////////////////////////////////////////////////////////////

class CWsClient : public CActive
    {
public:
    void ConstructL();
    // destruct
    ~CWsClient();
    // main window
    virtual void ConstructMainWindowL();
    // terminate cleanly
    void Exit();
    // active object protocol
    void IssueRequest(); // request an event
    void DoCancel(); // cancel the request
    virtual void RunL() = 0; // handle completed request
    virtual void HandleKeyEventL (TKeyEvent& aKeyEvent) = 0;
protected:
    //construct
    CWsClient();
    CWsScreenDevice* iScreen;
    CWsRedrawer* iRedrawer;
    RWsSession iWs;
    TWsEvent iWsEvent;
private:
    RWindowGroup iGroup;
    CWindowGc* iGc;
    friend class CWsRedrawer; // needs to get at session
    friend class CWindow; // needs to get at session
    friend class CSprite;
    friend class CPointerCursor;
    };



////////////////////////////////////////////////////////////////////////////
//                      CWsRedrawer declaration
////////////////////////////////////////////////////////////////////////////

class CWsRedrawer : public CActive
    {
public:
    // construct/destruct
    CWsRedrawer();
    void ConstructL(CWsClient* aClient);
    ~CWsRedrawer();
    // drawing
    void IssueRequest();
    void DoCancel();
    void RunL();
protected:
    CWsClient* iClient;
    };


//////////////////////////////////////////////////////////////////////////////
//                          CWindow declaration
//////////////////////////////////////////////////////////////////////////////

class CWindow : public CBase
    {
protected:
    RWindow iWindow; // window server window
    TRect iRect; // window's extent
public:
    enum {KPointerMoveBufferSize=32};
    CWindow(CWsClient* aClient);
    void ConstructL (const TRect& aRect, const TRgb& aColor, CWindow* aParent=0);
    ~CWindow();
    // access
    RWindow& Window(); // our own window
    CWindowGc* SystemGc(); // system graphics context
    CWsScreenDevice* Screen();
    CFont* Font();
    // drawing
    virtual void Draw(const TRect& aRect) = 0;
    virtual void HandlePointerEvent (TPointerEvent& aPointerEvent) = 0;
private:
    CWsClient* iClient; // client including session and group
    CFont*  iFont;
    };

#endif
// BitmapSprite.H
//
// Copyright (c) 2005-2005 Symbian Software Ltd.  All rights reserved.
//


#if !defined(__WSPRIT21_H__)
#define __WSPRIT21_H__

#include "Base.h"

class CMainWindow : public CWindow
    {
public:
    CMainWindow (CWsClient* aClient);
    ~CMainWindow ();
    void Draw (const TRect& aRect);
    void HandlePointerEvent (TPointerEvent& aPointerEvent);
    void HandlePointerMoveBufferReady ();
    };

//////////////////////////////////////////////////////////////////////////
//                      Derived client class
//////////////////////////////////////////////////////////////////////////

class CSprite;
class CPointerCursor;
class CExampleWsClient : public CWsClient
    {
public:
    static CExampleWsClient* NewL(const TRect& aRect);
private:
    CExampleWsClient (const TRect& aRect);
    void ConstructMainWindowL();
    ~CExampleWsClient ();
    void RunL ();
    void HandleKeyEventL (TKeyEvent& aKeyEvent);
private:
    CMainWindow* iMainWindow;
    CSprite*    iSprite;
    const TRect& iRect;
    };


class CSprite : public CBase
    {
public:
    CSprite (CWsClient* aClient);
    ~CSprite ();
    void ConstructL(CWindow* aWindow);
    void UpdatePos(TPoint aAdjust);
private:
    CWsClient*  iClient;
    RWsSprite   iSprite;
    TPoint      iSpritePos;
    TSpriteMember   iSpriteMember[8];
    };

#endif
// BitmapSpritel.mmp
//
// Copyright (c) 2005 Symbian Softwares Ltd.  All rights reserved.
//

// From 9.1 builds supporting EKA2 with Winscw, os will treat all
// applications with the extension exe.
TARGET          BitmapSprite.exe      
TARGETTYPE      exe
UID             0x100098e8
VENDORID       0x70000001

SOURCEPATH      .
SOURCE          AppHolder.cpp Base.cpp BitmapSprite.cpp
USERINCLUDE     .
SYSTEMINCLUDE   \epoc32\include
SYSTEMINCLUDE   \epoc32\include\techview

// To support the new resource compilation practice from 9.1
// provide the following details to generate .rss files

START RESOURCE BitmapSprite.rss           
TARGET          BitmapSprite.rsc
TARGETPATH      \Resource\Apps
HEADER
LANG 01       // Build English language versions
END

// In v8.1, both aif files and registration files are supported,
// but from v9.0 onwards, only registration files are supported.
start resource    BitmapSprite_reg.rss         
targetpath         \private\10003a3f\apps
//lang          01
end

// To support localisation for the UI applicatons
start resource BitmapSprite_loc.rss           
//targetpath    \resource\apps
lang           01
end

LIBRARY         euser.lib
LIBRARY         apparc.lib
LIBRARY         cone.lib
LIBRARY         eikcore.lib 
LIBRARY         ws32.lib    
LIBRARY         bitgdi.lib
LIBRARY         gdi.lib

START BITMAP  BitmapSprite.mbm
    targetpath     \resource\apps
    header
    sourcepath .
    source 2 Windml1a.bmp Windml2a.bmp Windml1b.bmp Windml2b.bmp 
    source 2 Windml1c.bmp Windml2c.bmp Windml1d.bmp Windml2d.bmp 
    source 2 Mil1mask.bmp Mil2mask.bmp 
end 
// BitmapSprite.rss
//


NAME MEAD

#include <eikon.rh>
#include <eikcore.rsg>

RESOURCE RSS_SIGNATURE { }

RESOURCE TBUF
    {
    buf = "";
    }

RESOURCE EIK_APP_INFO
    {
    menubar = r_appholder_menubar;
    hotkeys = r_appholder_hotkeys;
    }

RESOURCE HOTKEYS r_appholder_hotkeys
    {
    control =
        {
        HOTKEY
            {
            command = EEikCmdExit;
            key = 'e';
            }
        };
    }

RESOURCE MENU_BAR r_appholder_menubar
    {
    titles =
        {
        MENU_TITLE
            {
            menu_pane = r_appholder_file_menu;
            txt = "File";
            }
    };
    }

RESOURCE MENU_PANE r_appholder_file_menu
    {
    items =
        {
        MENU_ITEM
            {
            command = EEikCmdExit;
            txt = "Close";
            }
        };
    }

 
#include <appinfo.rh>
   
RESOURCE LOCALISABLE_APP_INFO
{
short_caption = "BitmapSprite";
caption_and_icon =
    {
    CAPTION_AND_ICON_INFO
        {
        caption = "BitmapSprite";
        number_of_icons = 0; // each icon must be a bitmap/mask pair
        }
    };
}     
// BitmapSprite_reg.RSS
//
// Copyright (c) 2005 Symbian Software Ltd.  All rights reserved.
//

#include <appinfo.rh>

UID2 KUidAppRegistrationResourceFile
UID3 0x100098e8
RESOURCE APP_REGISTRATION_INFO
 { 
 app_file = BitmapSprite;
 localisable_resource_file="\\resource\\apps\\BitmapSprite_loc.rss";
 hidden=KAppNotHidden;
 embeddability=KAppNotEmbeddable;
 newfile=KAppDoesNotSupportNewFile;
 launch=KAppLaunchInForeground;
 }

[Top]


Description

The BitmapSprite example creates an animated sprite by loading a bitmap (.mbm) file. The sprite is a rotating windmill which can be moved around the screen using the arrow keys.

As in the previous example, the sprite is created by setting up the sprite members to contain bitmaps, then appending them to the sprite. In this example, however, the bitmaps are loaded from a file rather than created using off-screen bitmaps drawn to using a graphics context.

[Top]


Classes defined

CSprite: Uses class RWsSprite by setting up the sprite members to contain bitmaps then appending them to the sprite. In this example, the bitmaps are loaded from a file.

[Top]


Classes used