Symbian
Symbian OS Library

SYMBIAN OS V9.3

[Index] [Spacer] [Previous] [Next]



PtBuffer: the pointer move buffer


Example Code

Found in: examples\Graphics\WS\PtBuffer\

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.

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

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


#include "AppHolder.h"
#include "PointerMoveBuffer.h"
#include <EikStart.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
#if (defined __WINS__ && !defined EKA2)        //  E32Dll used only when WINS defined and EKA2 not defined
GLDEF_C TInt E32Dll(enum TDllReason)     
    {
    return KErrNone;
    }
#else                                       //   else E32Main is used
GLDEF_C TInt E32Main()        
    {
    return EikStart::RunApplication(NewApplication);
    }
#endif

////////////////////////////////////////////////////////////////
//
// 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 Symbian Softwares Ltd.  All rights reserved.
//

#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)
    {
    // 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 pointer grab to enable drag and drop
    iWindow.SetPointerGrab (ETrue);
    // Allocate pointer move buffer for freehand drawing
    iWindow.AllocPointerMoveBuffer(KPointerMoveBufferSize, 0);
    iWindow.DisablePointerMoveBuffer();
    // Tell the window server to deliver drag events
    iWindow.PointerFilter(EPointerFilterDrag, 0);
    // Activate the window
    iWindow.Activate();
    }

CWindow::~CWindow()
    {
    iWindow.FreePointerMoveBuffer();
    iWindow.Close();
    }

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

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

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

///////////////////////////////////////////////////////////////////////////////
//                          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 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();
    // 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()
    {
    }

// PointerMoveBuffer.CPP
//
// Copyright (c) 2005 Symbian Softwares Ltd.  All rights reserved.
//

// Hold down the SHIFT key and drag the mouse (with left mouse button down)
// for freehand drawing.

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



//////////////////////////////////////////////////////////////////////////////
//                   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)
    {
    CWindowGc* gc=SystemGc(); // get a gc
    gc->SetClippingRect(aRect); // clip outside this rect
    gc->Clear(aRect); // clear
}

/****************************************************************************\
|   Function:    CMainWindow::HandlePointerBufferReady
\****************************************************************************/

void CMainWindow::HandlePointerMoveBufferReady ()
    {       
    TPoint pnts[KPointerMoveBufferSize];
    TPtr8 ptr((TUint8 *)&pnts,sizeof(pnts));
    TInt numPnts=Window().RetrievePointerMoveBuffer(ptr);
    TSize size = Window().Size();
    TPoint position = Window().Position();
    TRect redrawRect (position, size);
    CWindowGc* gc=SystemGc();
    gc->Activate(Window());
    Window().Invalidate();
    Window().BeginRedraw(redrawRect); // N.B. Redrawer::RunL() gets called with this 
                                      // rectangle - must give it a non-zero value
    for(TInt index=0;index<numPnts;index++) gc->DrawLineTo(pnts[index]);
    Window().EndRedraw();
    gc->Deactivate();
    }

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

void CMainWindow::HandlePointerEvent (TPointerEvent& aPointerEvent)
    {   
    switch (aPointerEvent.iType)
        {
        case TPointerEvent::EButton1Down:
            {
            if (aPointerEvent.iModifiers&EModifierShift)
                {
                Window().EnablePointerMoveBuffer();
                CWindowGc* gc = SystemGc();
                gc->Activate(Window());
                gc->MoveTo(aPointerEvent.iPosition);
                gc->Deactivate();
                }
            break;
            }
        case TPointerEvent::EButton1Up:
            {
            Window().DisablePointerMoveBuffer();
            break;
            }
        default:
            break;
        }
}


//////////////////////////////////////////////////////////////////////////////
//                   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;
    }


/****************************************************************************\
|   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()
    {
    // Resources allocated in this function are freed in the CExampleWsClient destructor     
    iMainWindow=new (ELeave) CMainWindow(this);
    iMainWindow->ConstructL(iRect, TRgb (255,255,255));
    }

/****************************************************************************\
|   Function:    CExampleWsClient::HandleKeyEventL()
|   Purpose: Processes key events for CExampleWsClient
\****************************************************************************/
void CExampleWsClient::HandleKeyEventL (TKeyEvent& /*aKeyEvent*/)
    {
    }


/****************************************************************************\
|   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:
    case EEventKey:
    case EEventModifiersChanged:
    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:
        {
        CWindow* window=(CWindow*)(iWsEvent.Handle()); // get window
        window->HandlePointerMoveBufferReady ();
        break;
        }
    case EEventDragDrop:
        break;
    default:
        break;
        }
    IssueRequest(); // maintain outstanding request
    }

// AppHolder.h
//


#ifndef __APPHOLDER_H
#define __APPHOLDER_H

#include <coeccntx.h>

#include <eikenv.h>
#include <eikappui.h>
#include <eikapp.h>
#include <eikdoc.h>
#include <eikmenup.h>

#include <eikon.hrh>

const TUid KUidAppholder = { 0x100098e4 };

class CWsClient;

//
// CAppholderAppUi
//

class CAppholderAppUi : public CEikAppUi
    {
public:
    void ConstructL();
    ~CAppholderAppUi();
private: // from CEikAppUi
    void HandleCommandL(TInt aCommand);
private:
    CWsClient* iClient;
    };


//
// CAppholderDocument
//

class CAppholderDocument : public CEikDocument
    {
public:
    // construct/destruct
    CAppholderDocument(CEikApplication& aApp);
    ~CAppholderDocument();
private: // from CEikDocument
    CEikAppUi* CreateAppUiL();
    };


//
// CAppholderApplication
//

class CAppholderApplication : public CEikApplication
    {
private: // from CApaApplication
    CApaDocument* CreateDocumentL();
    TUid AppDllUid() const;
    };

#endif

// Base.H
//
// Copyright (c) 2005 Symbian Softwares Ltd.  All rights reserved.
//


#if !defined(__WINORD_H__)
#define __WINORD_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
    };



////////////////////////////////////////////////////////////////////////////
//                      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();
    // drawing
    virtual void Draw(const TRect& aRect) = 0;
    virtual void HandlePointerEvent (TPointerEvent& aPointerEvent) = 0;
    virtual void HandlePointerMoveBufferReady () = 0;
private:
    CWsClient* iClient; // client including session and group
    };


#endif

// PtBuffer.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          PtBuffer.exe  
TARGETTYPE      exe
UID             0x100098e4
VENDORID       0x70000001

SOURCEPATH      .
SOURCE          AppHolder.cpp Base.cpp PointerMoveBuffer.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 PtBuffer.rss       
TARGET          PtBuffer.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    PtBuffer_reg.rss 
targetpath         \private\10003a3f\apps
//lang          01
end

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

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

// PointerMoveBuffer.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 = "PtBuffer";
caption_and_icon =
    {
    CAPTION_AND_ICON_INFO
        {
        caption = "PtBuffer";
        number_of_icons = 0; // each icon must be a bitmap/mask pair
        }
    };
}     

// PtBuffer.RSS
//
// Copyright (c) 2005 Symbian Software Ltd.  All rights reserved.
//

#include <appinfo.rh>

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

[Top]


Description

This example implements simple freehand drawing. The example illustrates the use of RWindowBase's pointer move buffer functions: AllocPointerMoveBuffer(), EnablePointerMoveBuffer(), RetrievePointerMoveBuffer() and DisablePointerMoveBuffer().

[Top]


Running on the emulator

Hold down the shift key and drag the mouse (with left mouse button down) for freehand drawing.

[Top]


Running on the target phone

Hold down the shift key and draw using the pointer device.

[Top]


Classes used

The example demonstrates the pointer move buffer functions defined in class RWindowBase.