Symbian
Symbian Developer Library

SYMBIAN OS V9.4

Feedback

[Index] [Previous] [Next]


CustomControls: custom control example

Note: This example only works properly with Techview and there is no guarantee that it will work with other interfaces.

[Top]


Example code

These files are found in: examples\AppFramework\UIControls\CustomControls

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

Custom.h

// CUSTOM.H
//
// 
// Copyright (c) 2000 Symbian Ltd.  All rights reserved.
//
// 
// UI Control Framework example application
//

#if !defined(__COSMILEY_H__)
#define __COSMILEY_H__

//////////////////////////////////////////////////////////////////////////////
//
// Include files containing:
//
// 1. Symbol definitions used by C++ code and resource scripts (the *.hrh)
// 2. Resource ids generated by resource compilation of 
//    resource scripts (the *.rsg)
// 3. Class definitions required by this app (the *.h)
//    
//////////////////////////////////////////////////////////////////////////////

// 1.
#include <eikon.hrh>
#include "custom.hrh"
// 2.
#include <eikon.rsg>
#include <custom.rsg>
// 3.
#include <eikenv.h>
#include <eikappui.h>
#include <eikproc.h>
#include <eikdialg.h>
#include <eikmenub.h>
#include <eikapp.h>
#include <eikdoc.h>
#include <coeutils.h>
#include <barsread.h>
#include <eikfctry.h>

  // The unique identifier for this application.
  // NOTE that the number has been arbitrarily chosen for the purpose of
  // of the example.
const TUid KUidExampleApp={0x01000d00};


//////////////////////////////////////////////////////////////////////////////
//
// -----> CSmileyDialog(definition)
//
//////////////////////////////////////////////////////////////////////////////
class CSmileyDialog : public CEikDialog
    {
public:
    // Construct and run
    static TBool RunDlgLD();
private:
    SEikControlInfo CreateCustomControlL(TInt aControlType);
    };  

//////////////////////////////////////////////////////////////////////////////
//
// -----> CSmiley (definition)
//
//////////////////////////////////////////////////////////////////////////////
class CSmiley : public CCoeControl
    {
public:
    CSmiley(TBool aSmiling);
    ~CSmiley();
public:
    TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
    TBool IsSmiling();
private:
    void Draw(const TRect& aRect) const;
    void SizeChanged();
protected:
    void HandlePointerEventL(const TPointerEvent& aPointerEvent);
    void FocusChanged(TDrawNow aDrawNow);
private:
    TBool   iSmiling;
    TRect   iSmileyRect;
    TInt    iSmileyWidth;
    TInt    iSmileyHeight;
    TRect   iSmileRect;
    TRect   iFrownRect;
    };

//////////////////////////////////////////////////////////////////////////////
//
// -----> CSmileyContainer(definition)
//
//////////////////////////////////////////////////////////////////////////////
class CSmileyContainer : public CCoeControl, 
                         public MCoeControlObserver
    {
public:
      // Construction
    CSmileyContainer();
    void ConstructL(const TRect& aRect);
      // Destruction
    ~CSmileyContainer();
    void ConstructFromResourceL(TResourceReader& aReader);
    void PrepareForFocusLossL();
    TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
protected:
    void FocusChanged(TDrawNow aDrawNow);
private:
      // Virtual, defined by CCoeControl; replaces the default implementation
      // provided by CCoeControl.
    void         Draw(const TRect& aRect) const;
    
      // Virtual, defined by CCoeControl; replaces the default implementation
      // provided by CCoeControl. 
    TInt         CountComponentControls() const;

      // Virtual, defined by CCoeControl; replaces the default implementation
      // provided by CCoeControl.
    CCoeControl* ComponentControl(TInt aIndex) const;

      // Virtual, defined by CCoeControl; empty implementation provided by
      // CCoeControl; full implementation provided by this class
    void         SizeChanged();
    
      // Defined as pure virtual by the mixin class MCoeControlObserver 
      // inherited by CCoeControl. An empty implementation provided by 
      // this class (its containees do not report events).
    void         HandleControlEventL(CCoeControl* aControl,
                                     TCoeEvent aEventType);
private:
      // Member functions defined and used by this class
    void        SwapFocus(CCoeControl* aControl);
private:
      // Data members defined and used by this class.
    CSmiley*    iSmiley1;
    CSmiley*    iSmiley2;
    };



//////////////////////////////////////////////////////////////////////////////
//
// -----> CMainWinControl (definition)
//
//////////////////////////////////////////////////////////////////////////////
class CMainWinControl : public CCoeControl
{
public:
    CMainWinControl();
    ~CMainWinControl();
    void ConstructL(const TRect& rect);
    TInt CountComponentControls() const;
    CCoeControl* ComponentControl(TInt aIndex) const;
    TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType);
private:
    void Draw(const TRect& aRect) const;
private:
    CSmileyContainer*   iContainer;
};

//////////////////////////////////////////////////////////////////////////////
//
// -----> CExampleAppUi (definition)
//
//////////////////////////////////////////////////////////////////////////////
class CExampleAppUi : public CEikAppUi
    {
public:
      // Destruction.
    ~CExampleAppUi();

public:
      // Virtual, defined by CEikAppUi; replaces the implementation 
      // provided by CEikAppUi.
    void ConstructL();
    
private:
      // Virtual, defined by CEikAppUi; empty implementation
      // provided by CEikAppUi; full implementation provided
      // by this class. 
    void  HandleCommandL(TInt aCommand);
    
      // Virtual, defined by CEikAppUi; empty implementation
      // provided by CEikAppUi; full implementation provided
      // by this class. 
    void  HandleModelChangeL();
    
private:
    void         OnCmdExit();
private:
    // Data members defined by this class.
    CMainWinControl* iMainWinControl;
    };

//////////////////////////////////////////////////////////////////////////////
//
// -----> CExampleDocument (definition)
//
//////////////////////////////////////////////////////////////////////////////
class CExampleDocument : public CEikDocument
    {
public:
      // Construction.
    static CExampleDocument* NewL(CEikApplication& aApp);
    CExampleDocument(CEikApplication& aApp);
      // Destruction.
    ~CExampleDocument();

private:
      // Defined as pure virtual by CEikDocument; full implementation
      // provided by this class
    CEikAppUi* CreateAppUiL();     // Construct an app.user interface

      // Defined as pure virtual by CApaDocument; empty implementation 
      // provided by CEikDocument; full implementation provided
      // by this class.
    void       NewDocumentL();    // Build a new document

      // Defined as pure virtual by CApaDocument; empty implementation
      // provided by CEikDocument; full implementation provided
      // by this class.
    void       StoreL(CStreamStore& aStore,
                      CStreamDictionary& aStreamDic
                     ) const;
    void       RestoreL(const CStreamStore& aStore,
                        const CStreamDictionary& aStreamDic
                       );

public:
      // Member functions defined by this class
    void       DoNewFileL(const TFileName& aFileName);
    void       DoOpenFileL(const TFileName& aFileName);
    void       DoSaveToNewFileL(const TFileName& aNewFileName);
    TBool      FileNameExists(const TFileName& aFileName) const;

private:
      // Member functions defined by this class
    void       CreateModelL();
    void       ResetModelL();
    };

//////////////////////////////////////////////////////////////////////////////
//
// -----> CExampleApplication (definition)
//
//////////////////////////////////////////////////////////////////////////////
class CExampleApplication : public CEikApplication
    {
private:        
      // Defined as pure virtual by CApaApplication; implementation
      // provided by this class 
    TUid          AppDllUid() const; // Returns Uid associated with app

      // Defined as pure virtual by CEikApplication; implementation
      // provided by this class.
    CApaDocument* CreateDocumentL(); // Construct new document
    };



#endif

Custom.cpp

// CUSTOM.CPP
//
// Copyright (c) 2000 Symbian Ltd.  All rights reserved.
//


//
// UI Control Framework example program
//
// This example demonstrates how to write new control classes.
//
// The example creates three new control classes:
//      1. CSmiley              - a simple control which displays a 
//                              smiley face that can have two moods,
//                              happy and sad. The user can change
//                              the smiley's mood by pressing the
//                              space bar.
//      2. CSmileyContainer     - a compound control which contains
//                              two CSmiley controls, side by side.
//                              The user can move the keyboard focus
//                              from one CSmiley to the other using
//                              the arrow keys, or the pointer.
//      3. CMainWinControl      - a compound control which does nothing
//                              except act as a background window and a 
//                              container for other controls in the 
//                              application.
//
//
// When the application starts up, it creates a CMainWinControl to cover
// the entire screen, and a CSmileyContainer inside this main window.
// The application's menu contains just two options. One of them closes 
// the application; the other creates a dialog which contains a 
// CSmileyContainer. CSmileyContainer therefore illustrates how to write 
// a control that can be created both in a dialog and within the
// application's main view.
//

#include "custom.h"
#include <eikstart.h>


//////////////////////////////////////////////////////////////////////////////
//
// -----> CMainWinControl(implementation)
//
//////////////////////////////////////////////////////////////////////////////
CMainWinControl::CMainWinControl()
    {
    }

CMainWinControl::~CMainWinControl()
    {
    delete iContainer;
    }

// CMainWinControl needs a ConstructL(), because it is a compound control
// (and a window-owning control).
void CMainWinControl::ConstructL(const TRect& rect)
    {
    // Make this a window-owning control.
    CreateWindowL();
    SetRect(rect);

    // Create its only component, a CSmileyContainer
    iContainer = new(ELeave) CSmileyContainer;
    iContainer->SetContainerWindowL(*this);
    TRect containerRect=Rect();
    iContainer->ConstructL(containerRect);
    // Activate the main window control - this will also activate the 
    // CSmileyContainer and its components.
    ActivateL();
    DrawNow();
    }

// The following two functions have to be implemented for all compound controls.
TInt CMainWinControl::CountComponentControls() const
    {
    return 1;
    }

CCoeControl* CMainWinControl::ComponentControl(TInt /*aIndex*/) const
    {
    return iContainer;
    }

// Draw the main window.
void CMainWinControl::Draw(const TRect& /*aRect*/) const
    {
    CWindowGc& gc=SystemGc();
    gc.SetBrushColor(KRgbWhite);
    gc.Clear(Rect());
    }

// CSmileyContainer can't be put on the control stack, because it's a component of this 
// control. The main window control goes on the stack and passes on any key events it gets
// to the CSmileyContainer.
TKeyResponse CMainWinControl::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
    {
    return (iContainer->OfferKeyEventL(aKeyEvent, aType));
    }

//////////////////////////////////////////////////////////////////////////////
//
// -----> CSmileyContainer (implementation)
//
//////////////////////////////////////////////////////////////////////////////
CSmileyContainer::CSmileyContainer()
    {}

    
CSmileyContainer::~CSmileyContainer()
    {
      // Delete all the contained controls 
    delete iSmiley1;
    delete iSmiley2;
    }


// Because CSmileyContainer is a compound control, it needs a
// ConstructL() for when it's created outside a dialog, and a
// ConstructFromResourceL() for when it's created inside a dialog.
void CSmileyContainer::ConstructL(const TRect& aRect)
    {
    TBool isSmiling=ETrue;

    // Create the two CSmileys. Their size and position is 
    // set in CSmileyContainer::SizeChangedL().
    iSmiley1 = new(ELeave) CSmiley(isSmiling);
    iSmiley1->SetContainerWindowL(*this);

    isSmiling=EFalse;

    iSmiley2 = new(ELeave) CSmiley(isSmiling);
    iSmiley2->SetContainerWindowL(*this);

    iSmiley1->SetFocus(ETrue);

    // Set the container as the observer of the two CSmileys. This 
    // is for handling keyboard focus. When an arrow key is pressed 
    // or the pointer is clicked on one of the CSmileys, an 
    // EEventRequestFocus event is sent to the container, and the
    // container changes the focus if applicable.
    iSmiley1->SetObserver(this);
    iSmiley2->SetObserver(this);

    // Set the bounding rectangle of this control (this will result in 
    // a call to SizeChangedL(). The component controls must be 
    // created before calling this, because SizeChangedL() sets their
    // sizes.
    SetRect(aRect);
    }


// This function is used when the CSmileyContainer is created inside a dialog.
void CSmileyContainer::ConstructFromResourceL(TResourceReader& aReader)
    {
    // Read the smiley mood from the resource file
    TBool isSmiling=(TBool)aReader.ReadInt8();
    // Read the width of the smiley container from the resource file.
    TInt width=aReader.ReadInt16();
    // Set the height of the container to be half its width
    TSize containerSize (width, width/2);

    iSmiley1 = new(ELeave) CSmiley(isSmiling);
    iSmiley1->SetContainerWindowL(*this);

    iSmiley2 = new(ELeave) CSmiley(isSmiling);
    iSmiley2->SetContainerWindowL(*this);

    iSmiley1->SetFocus(ETrue);

    iSmiley1->SetObserver(this);
    iSmiley2->SetObserver(this);

    SetSize(containerSize);

    ActivateL();    
    }

// The following two functions have to be implemented for all compound controls.
TInt CSmileyContainer::CountComponentControls() const
    {
    return 2;
    }

CCoeControl* CSmileyContainer::ComponentControl(TInt aIndex) const
    {
    if (aIndex==0)
        return iSmiley1;
    else
        return iSmiley2;
    }

// This function gets called whenever one of the size-setting functions is called.
// As this is a compound control, this function calculates and sets the size and  
// position for its components, based on its own size.
void CSmileyContainer::SizeChanged()
    {
    TInt containerWidth=Size().iWidth;
    TInt containerHeight=Size().iHeight;
    // Find half of the greater - width or height
    TInt length=containerHeight>containerWidth ? containerWidth/4 : containerHeight/4; 
    TSize smileySize(length,length);

    // Do some preliminary calculations so that Draw() is as short
    // as possible.
    TInt xOffset=smileySize.iWidth/4; // x offset from the center
    TInt yOffset=(containerHeight - smileySize.iHeight) / 2;
    iSmiley1->SetPosition(Position() +
        TPoint(containerWidth/2 - smileySize.iWidth - xOffset, yOffset));
    iSmiley2->SetPosition(Position() + 
        TPoint(containerWidth/2 + xOffset, yOffset));
    // Calling SetSizeL() causes the components' SizeChanged() to be called.
    iSmiley1->SetSize(smileySize);
    iSmiley2->SetSize(smileySize);
    }
    
void CSmileyContainer::Draw(const TRect& aRect) const
    {
    // Just draw a rectangle round the edge of the control.
    CWindowGc& gc=SystemGc();
    gc.Clear(aRect);
    gc.SetClippingRect(aRect);
    gc.DrawRect(Rect());
    }

// This function is defined by MCoeControlObserver. It gets called whenever
// a control that this control is observing calls ReportEventL().
// In this example, the CSmileyContainer is the observer for both of the 
// CSmileys.  CCoeControl::ProcessPointerEventL() calls ReportEvent(), 
// sending an event of type EEventRequestFocus, whenever an EButton1Down event
// occurs in the CSmiley that doesn't currently have focus.
void CSmileyContainer::HandleControlEventL(CCoeControl* aControl,
                                        TCoeEvent aEventType)
    {
    switch (aEventType)
        {
        case EEventRequestFocus:
            {
            if (aControl->IsFocused())
                return;
            SwapFocus(aControl);
            }
            break;
        default:
            break;
        }
    }

// This function is called by the framework whenever a component in a dialog is 
// about to lose focus. It checks that the data in ithe component is valid. In
// this example, there's a "rule" that both the CSmileys in the container can't
// be miserable! If they are, the function leaves. The framework issues the message 
// we give it, and doesn't move focus away from the CSmileyContainer.
void CSmileyContainer::PrepareForFocusLossL()  
    {
    if (!iSmiley1->IsSmiling() && !iSmiley2->IsSmiling())
        {
        CEikonEnv::Static()->LeaveWithInfoMsg(R_EXAMPLE_TEXT_VALIDATE);
        }
    }

// This function gets called whenever the application calls SetFocus().
// It redraws the CSmileyContainer, so that they are updated to show 
// which one now has focus.
void CSmileyContainer::FocusChanged(TDrawNow aDrawNow)
    {
    if (IsFocused())
        {
        iSmiley1->SetFocus(ETrue, EDrawNow);
        }
    else
        {
            if (iSmiley1->IsFocused())
            iSmiley1->SetFocus(EFalse, EDrawNow);
            else
            iSmiley2->SetFocus(EFalse, EDrawNow);
        }
    if (aDrawNow)
        DrawNow();
    }


void CSmileyContainer::SwapFocus(CCoeControl* aControl)
    {
    if (aControl==iSmiley1)
        {
        iSmiley2->SetFocus(EFalse, EDrawNow);
        iSmiley1->SetFocus(ETrue, EDrawNow);
        }
    else
        {
        iSmiley1->SetFocus(EFalse, EDrawNow);
        iSmiley2->SetFocus(ETrue, EDrawNow);
        }
    }

TKeyResponse CSmileyContainer::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
    {
    // Use the arrow keys to move focus between the two CSmileys.
    switch (aKeyEvent.iScanCode)
        {
        case EStdKeySpace:
            if (iSmiley1->IsFocused())
                return iSmiley1->OfferKeyEventL(aKeyEvent, aType);
            else if (iSmiley2->IsFocused())
                return iSmiley2->OfferKeyEventL(aKeyEvent, aType);
            break;
        case EStdKeyRightArrow:
            if (iSmiley1->IsFocused())
                SwapFocus(iSmiley2);
            return EKeyWasConsumed;
            break;
        case EStdKeyLeftArrow:
            if (iSmiley2->IsFocused())
                SwapFocus(iSmiley1);
            return EKeyWasConsumed;
            break;
        default:
            break;
        }
    // If the CSmileyContainer didn't use the key event, it must return EKeyWasNotConsumed,
    // so that the key event is passed to other controls on the stack.
    return EKeyWasNotConsumed;
    }




//////////////////////////////////////////////////////////////////////////////
//
// -----> CSmiley (implementation)
//
//////////////////////////////////////////////////////////////////////////////

// CSmiley doesn't need a ConstructL() because it's a simple control.

CSmiley::CSmiley(TBool aSmiling) : iSmiling(aSmiling)
    {
    }

CSmiley::~CSmiley()
    {
    }

TBool CSmiley::IsSmiling()
    {
    return iSmiling;
    }

void CSmiley::Draw(const TRect& aRect) const
    {
    CWindowGc& gc=SystemGc();
    if (IsFocused())
        {
        gc.SetPenColor(KRgbBlack);
        }
    else
        {
        gc.SetPenColor(KRgbWhite);
        }
    gc.SetBrushColor(KRgbWhite);
    gc.Clear(Rect());
    gc.DrawRect(Rect());

    gc.SetClippingRect(aRect);

    // Draw the smiley face, smiling or looking sad
    gc.SetPenColor(KRgbBlack);
    // Draw a circle for the face
    gc.DrawEllipse(iSmileyRect);
    // Draw the eyes
    TPoint leftEye(iSmileyWidth/3, iSmileyHeight/3);
    TPoint rightEye(iSmileyWidth*2/3, iSmileyHeight/3);
    gc.SetPenSize(TSize(5,5));
    gc.Plot(iSmileyRect.iTl+leftEye);
    gc.Plot(iSmileyRect.iTl+rightEye);
    //Draw the mouth, smiling or looking sad.
    gc.SetPenSize(TSize(1,1));
    gc.SetPenColor(KRgbWhite);
    if (iSmiling)
        gc.DrawArc(iFrownRect, iFrownRect.iTl+TPoint(iSmileyWidth/2,iFrownRect.Height()/2), 
                              iFrownRect.iTl+TPoint(0,iFrownRect.Height()/2));
    else
        gc.DrawArc(iSmileRect, iSmileRect.iTl+TPoint(0,iSmileRect.Height()/2), 
                              iSmileRect.iTl+TPoint(iSmileyWidth/2,iSmileRect.Height()/2));
    gc.SetPenColor(KRgbBlack);
    if (iSmiling)
        gc.DrawArc(iSmileRect, iSmileRect.iTl+TPoint(0,iSmileRect.Height()/2), 
                              iSmileRect.iTl+TPoint(iSmileyWidth/2,iSmileRect.Height()/2));
    else
        gc.DrawArc(iFrownRect, iFrownRect.iTl+TPoint(iSmileyWidth/2,iFrownRect.Height()/2), 
                              iFrownRect.iTl+TPoint(0,iFrownRect.Height()/2));
    }

void CSmiley::SizeChanged()
    {
    // Calculate sizes of rectangles for drawing face and mouth
    iSmileyRect=Rect();
    // Allow room for the focus rectangle round the outside
    iSmileyRect.Shrink(3,3);
    iSmileyWidth=iSmileyRect.Width();
    iSmileyHeight=iSmileyRect.Height();
    iSmileRect.SetRect(iSmileyRect.iTl+TPoint(iSmileyWidth/4, iSmileyHeight/2),
                    TSize(iSmileyWidth/2, iSmileyHeight/3));
    iFrownRect.SetRect(iSmileyRect.iTl+TPoint(iSmileyWidth/4, iSmileyHeight*2/3),
                    TSize(iSmileyWidth/2, iSmileyHeight/3));
    }

void CSmiley::FocusChanged(TDrawNow aDrawNow)
    {
    if (aDrawNow)
        DrawNow();
    }

void CSmiley::HandlePointerEventL(const TPointerEvent& aPointerEvent)
    {
    if (aPointerEvent.iType==TPointerEvent::EButton1Down)
        {
        iSmiling = !iSmiling;
        DrawNow();
        }
    }

TKeyResponse CSmiley::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
    {
    // The space bar changes the "mood" of the CSmiley.
    if (aType==EEventKey && aKeyEvent.iScanCode==EStdKeySpace)
        {
        iSmiling = !iSmiling;
        DrawNow();
        return EKeyWasConsumed;
        }
    else
        {
        return EKeyWasNotConsumed;
        }
    }

//////////////////////////////////////////////////////////////////////////////
//
// -----> CSmileyDialog(implementation)
//
//////////////////////////////////////////////////////////////////////////////
TBool CSmileyDialog::RunDlgLD()
    {
    CEikDialog* dialog = new (ELeave) CSmileyDialog();
    return (dialog->ExecuteLD(R_SMILEY_DIALOG));
    }

// This function is used by CEikForm::ConstructByTypeL() to create the custom 
// control within the dialog.
SEikControlInfo CSmileyDialog::CreateCustomControlL(TInt aControlType)
    {
    SEikControlInfo controlInfo;
    controlInfo.iControl = NULL;
    controlInfo.iTrailerTextId = 0;
    controlInfo.iFlags = 0;

    switch (aControlType)
        {
    case ESmileyControl:
        controlInfo.iControl = new(ELeave) CSmileyContainer;
        break;
    default:
        break;
        }
    return controlInfo;
    }

//////////////////////////////////////////////////////////////////////////////
//
// -----> CExampleAppUi (implementation)
//
//////////////////////////////////////////////////////////////////////////////
void CExampleAppUi::ConstructL()
    {
      // Allow base class (CEikAppUi) to perform necessary construction
    BaseConstructL();
    // Construct the CMainWinControl which forms the main view
    // for this application.
    iMainWinControl=new(ELeave) CMainWinControl;
    iMainWinControl->ConstructL(ClientRect());
    // The main window is added to the control stack (for key event
    // handling).  
    AddToStackL(iMainWinControl);
    }
    

CExampleAppUi::~CExampleAppUi()
    {
    RemoveFromStack(iMainWinControl);
      // Delete the main window
    delete iMainWinControl;
    }

void CExampleAppUi::HandleCommandL(TInt aCommand)
    {
      // Handle the command generated by:
      //   1. menu item selection
      //   2. short-cut key press
    switch (aCommand)
        {
    // EXIT comand
    case EEikCmdExit:
        OnCmdExit();
        break;
    case ECreateSmileyDialog:
        CSmileyDialog::RunDlgLD();
        break;
    default :
        break;
        }
    }

void CExampleAppUi::OnCmdExit()
    {
    CBaActiveScheduler::Exit();
    }

void CExampleAppUi::HandleModelChangeL()
    {
    }

/////////////////////////////////////////////////////////////////////////////
//
// -----> CExampleDocument (implementation)
//
/////////////////////////////////////////////////////////////////////////////

CExampleDocument::CExampleDocument(CEikApplication& aApp)
     : CEikDocument(aApp)
    {}

CExampleDocument::~CExampleDocument()
    {
    }

CExampleDocument* CExampleDocument::NewL(CEikApplication& aApp)
    {
    CExampleDocument* self=new(ELeave) CExampleDocument(aApp);
    CleanupStack::PushL(self);
    self->CreateModelL();
    CleanupStack::Pop();
    return self;
    }

void CExampleDocument::ResetModelL()
    {
    CreateModelL();
    }

void CExampleDocument::CreateModelL()
    {
    }

CEikAppUi* CExampleDocument::CreateAppUiL()
    {
    return(new(ELeave) CExampleAppUi);
    }

void CExampleDocument::NewDocumentL()
    {
    ResetModelL();
    }

void CExampleDocument::StoreL(CStreamStore& /*aStore*/,CStreamDictionary& /*aStreamDic*/) const
    {
    }

void CExampleDocument::RestoreL(const CStreamStore& /*aStore*/,const CStreamDictionary& /*aStreamDic*/)
    {
    }


//////////////////////////////////////////////////////////////////////////////
//
// -----> CExampleApplication (implementation)
//
//////////////////////////////////////////////////////////////////////////////
TUid CExampleApplication::AppDllUid() const
    {
    return(KUidExampleApp);
    }


CApaDocument* CExampleApplication::CreateDocumentL()
    {
    return CExampleDocument::NewL(*this);
    }


//
// EXPORTed functions
//


LOCAL_C CApaApplication* NewApplication()
    {
    return new CExampleApplication;
    }
    
GLDEF_C TInt E32Main()
    {
    return EikStart::RunApplication(NewApplication);
    }

#if defined(__WINS__) && !defined(EKA2)
GLDEF_C TInt E32Dll(TDllReason)
    {
    return KErrNone;
    }
EXPORT_C TInt WinsMain(TDesC* aCmdLine)
    {
    return EikStart::RunApplication(NewApplication, aCmdLine);
    }
#endif

Custom.hrh

// Custom.HRH
//
// Copyright (c) 2000 Symbian Ltd.  All rights reserved.
//

//////////////////////////////////////////////////////////////////////////////      
//
// Definitions
//
// Maximum length of text item on the application data dialog
//
//////////////////////////////////////////////////////////////////////////////
#define KExampleMaxlenTextData 16 


//////////////////////////////////////////////////////////////////////////////      
//
// Command ids
// Identify all commands defined by this application.
//
//
//////////////////////////////////////////////////////////////////////////////

#define ECreateSmileyDialog    0x800

//////////////////////////////////////////////////////////////////////////////      
//
// Control ids
// Identify all controls defined and used by this application.
//
//////////////////////////////////////////////////////////////////////////////   
enum {ESmileyControlIdData};


//////////////////////////////////////////////////////////////////////////////      
//
// Define the CSmileyContainer control so it can be created as a component in a dialog           
//
//////////////////////////////////////////////////////////////////////////////   
// Assume there are less than 1000 framework controls, and they can't be defined anywhere else.      
enum {ESmileyControl=1000};

//////////////////////////////////////////////////////////////////////////////      
//
// Define the values for the "mood" resource.          
//
//////////////////////////////////////////////////////////////////////////////   
enum TSmileyMood {ESad, EHappy};

Custom.rss

// COSMILEY.RSS
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//


NAME COSM
        // Include definitions of resource STRUCTS used by this
        // resource script 
#include <eikon.rh>

        // Include the standard resource ids 
#include <eikon.rsg>

        // Include the symbol definitions used by C++ code and
        // this resource script.
#include <eikon.hrh>

#include "custom.hrh"
#include "custom.rh"

RESOURCE RSS_SIGNATURE
    {
    }
    
RESOURCE TBUF { buf=""; } // default document name


RESOURCE EIK_APP_INFO
    {   
    hotkeys=r_example_hotkeys; 
    menubar=r_example_main_menubar; 
    }


//////////////////////////////////////////////////////////////////////////////
//
// Dialog containing smileys
//
//////////////////////////////////////////////////////////////////////////////


RESOURCE DIALOG r_smiley_dialog
    {
    title="Smileys";
    buttons=R_EIK_BUTTONS_CANCEL_OK;
    items=
        {
        DLG_LINE
            {
            type=ESmileyControl;
            id=ESmileyControlIdData;
            control=SMILEYCONTROL
                {
                mood=EHappy;
                width=200;
                };
            }
        };
    }



//////////////////////////////////////////////////////////////////////////////
//
// Short cut keys
//
//////////////////////////////////////////////////////////////////////////////
RESOURCE HOTKEYS r_example_hotkeys
  {
    control=
            {
            HOTKEY {command=EEikCmdExit;                 key='e';},
            HOTKEY {command=ECreateSmileyDialog;        key='d';}
            };
  }

//////////////////////////////////////////////////////////////////////////////
//
// The menu bar
//
//////////////////////////////////////////////////////////////////////////////
RESOURCE MENU_BAR r_example_main_menubar
    {
    titles=
        {
        MENU_TITLE { menu_pane=r_example_file_menu;   txt="File"; }
        };
    }

//////////////////////////////////////////////////////////////////////////////
//
// The "file" menu pane hung directly from the menu bar
//
//////////////////////////////////////////////////////////////////////////////
RESOURCE MENU_PANE r_example_file_menu
    {
    items=
        {
        MENU_ITEM
            {
            command=ECreateSmileyDialog;
            txt="Create Smiley Dialog";
            },
        MENU_ITEM 
            { 
            command=EEikCmdExit; 
            txt="Exit";
            }
        };
    }

//////////////////////////////////////////////////////////////////////////////
//
// Text resources for info messages
//
//////////////////////////////////////////////////////////////////////////////

RESOURCE TBUF r_example_text_validate             { buf="They can't both be miserable!";}

Custom.rh

// COSMILEY.RH
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

STRUCT SMILEYCONTROL
    {
    BYTE mood=EHappy;
    WORD width=300;
    }

Custom_reg.rss

#include <appinfo.rh>

UID2 KUidAppRegistrationResourceFile
UID3 0x01000d00 // application UID
RESOURCE APP_REGISTRATION_INFO
    {
    app_file = "Custom";
    }

Bld.inf

// BLD.INF
// Component description file 
//
// Copyright (c) 2000 Symbian Ltd.  All rights reserved.

PRJ_MMPFILES

Custom.MMP

Custom.mmp

// Custom.MMP
//
// Copyright (c) 2000 Symbian Ltd.  All rights reserved.
//
TARGET        Custom.exe
TARGETTYPE    exe
UID           0x100039ce 0x01000d00
VENDORID 0x70000001
EPOCSTACKSIZE 0x5000

SOURCEPATH    .
SOURCE        Custom.cpp

START RESOURCE Custom.rss
TARGETPATH      \Resource\Apps
HEADER
END

START RESOURCE Custom_reg.rss
TARGETPATH      \private\10003a3f\apps
END

USERINCLUDE   .
SYSTEMINCLUDE \epoc32\include
SYSTEMINCLUDE \epoc32\include\techview
LIBRARY       euser.lib cone.lib  apparc.lib bafl.lib
LIBRARY       eikcore.lib eikcoctl.lib eikdlg.lib

[Top]


Description

CustomControls demonstrates customised simple and compound UI Control Framework control classes. Compound controls are used as on-screen containers for other controls, either simple or compound. The custom controls are subclasses of the class CCoeControl, with implementations of its virtual functions for construction, drawing, and accepting user input.

Note that the CustomControls example has dependencies on GUI components that may not be present on all Symbian OS licensee SDKs.

[Top]


Usage

When the application starts, it displays two smiling faces (smiley) controls. The mood of the smileys can be changed by selecting a smiley using the left/right keys or pointer, and pressing space/clicking. A dialog containing the smiley controls can be started from the application’s menu.

[Top]


Class summary

All of the examples use the following classes: