Symbian OS programming


This example builds around a simple ?HelloWorld? application to illustrate the key classes and frameworks used to create applications for the Nokia 9200 Series. The HelloWorld program will demonstrate how you can code applications, which offer standard 9200 Series functionality, i.e.: The code for HelloWorld is broken down into several .CPP files, each designed to represent a segment of the above application launching process. These files are: In addition the following files make up the rest of the source for the project: Finally, the following files make up the build files used by the SDK tools to create the project. We will now examine in detail each of the files listed above. Below shows the source code for HelloSp.

The Build Files
These files are used by the tool chain to construct your project files and build the application from source.

 BLD.INF 

// BLD.INF
//
// Copyright (c) 2000-2001 Symbian Ltd. All rights reserved.
PRJ_MMPFILES
HelloWorld.mmp
       

 HelloWorld.mmp 

// HelloWorld.mmp
//
// Copyright (c) 2000-2001 Symbian Ltd. All rights reserved.
TARGET HelloWorld.app
TARGETTYPE app
UID 0x100039CE 0x101F43AB
TARGETPATH \System\Apps\HelloWorld
SOURCE HelloWorld_Main.cpp
SOURCE HelloWorld_Application.cpp
SOURCE HelloWorld_Document.cpp
SOURCE HelloWorld_AppUi.cpp
SOURCE HelloWorld_AppView.cpp
SOURCE HelloWorld_Dialogs.cpp
USERINCLUDE .
SYSTEMINCLUDE \epoc32\include
RESOURCE HelloWorld.rss
LIBRARY euser.lib apparc.lib cone.lib eikcore.lib
LIBRARY linkui.lib linkmdl.lib eikdlg.lib eikcoctl.lib
       

The Resource File
A resource file is used in Symbian OS to define the way your application looks on screen. Everything from the status pane, the menu and hotkeys through to individual dialog boxes can be defined in the resource file. Resources initially look rather complex, but when taken step-by-step they are quite straightforward. The resource file for HelloWorld looks like this:

 HelloWorld.rss 

// HelloWorld.rss
//
// Copyright (c) 2000-2001 Symbian Ltd. All rights reserved.
NAME HEWO

// Core resource file includes
#include <eikon.rh>
#include <eikcore.rsg>
#include <indicato.rsg> // Status Pane definitions
#include "HelloWorld.hrh"  // Our application-specific definitions

//
// Some application information
//
#define KApplicationName "HelloWorld"
#define KApplicationLongName "Nokia 9200 Series C++ HelloWorld Application"
#define KCopyrightYear "2000-2001"
RESOURCE RSS_SIGNATURE { }
RESOURCE TBUF { buf = ""; }

//
// Application framework controls definition
//
RESOURCE EIK_APP_INFO
{
  hotkeys     = r_example_hotkeys;    // Hotkeys e.g. Ctrl+A
  menubar     = r_example_menubar;    // Menu bar contents
  cba         = r_example_cba;        // Command Button Array contents
  status_pane = r_example_indic_pane; // Status pane settings
}

RESOURCE STATUS_PANE_APP_MODEL r_example_indic_pane
{
  layout = R_INDICATOR_LAYOUT_NARROW; // Defined in INDICATO.RSG
}

//
// Command Button Array definition - 4 buttons, the middle two are blank here
//
RESOURCE CBA r_example_cba
{
  buttons=
  {
    CBA_BUTTON { id = EExampleCmd0; txt = "Option\nzero"; },
    CBA_BUTTON { id = EEikBidBlank; txt = ""; },
    CBA_BUTTON { id = EEikBidBlank; txt = ""; },
    CBA_BUTTON { id = EEikCmdExit;  txt = "Close"; }
  };
}

//
// Application hotkey definitions, with support for both
// Ctrl+? and Shift+Ctrl+? hotkey combinations
//
RESOURCE HOTKEYS r_example_hotkeys
{
  control =
  {
    HOTKEY { command = EExampleCmd0; key = 'a'; },
    HOTKEY { command = EExampleCmd1; key = 'b'; }
  };
  shift_control =
  {
    HOTKEY { command = EExampleCmd2;     key = 'c'; },
    HOTKEY { command = EExampleCmdAbout; key = 'a'; }
  };
}

//
// Top-level application menu bar menu contents
//
RESOURCE MENU_BAR r_example_menubar
{
  titles =
  {
    MENU_TITLE { menu_pane = r_example_file_menu;  txt = "File"; },
    MENU_TITLE { menu_pane = r_example_tools_menu; txt = "Tools"; }
  };
}

//
// Contents of the top-level "File" menu on the menu bar
//
RESOURCE MENU_PANE r_example_file_menu
{
  items =
  {
    MENU_ITEM { command = EExampleCmd0; txt = "Option 0";
    flags = EEikMenuItemSeparatorAfter; }
  };
}

//
// Contents of the top-level "Tools" menu on the menu bar
//
RESOURCE MENU_PANE r_example_tools_menu
{
  items =
  {
    MENU_ITEM { command = EExampleCmd1; txt = "Option 1"; },
    MENU_ITEM { command = EExampleCmd2; txt = "Option 2"; },
    MENU_ITEM { command = EExampleCmd3; txt = "Option 3";
    flags = EEikMenuItemSeparatorAfter; },
    MENU_ITEM { command=EExampleCmdAbout; txt="About
      "KApplicationName; }
  };
}

//
// Resource buffers for text to be displayed at various points in our application
//
RESOURCE TBUF r_example_text_Hello
  { buf = "Hello World from the Nokia 9200 Series Communicator!";}
RESOURCE TBUF r_example_text_Item0 { buf = "Option 0 selected"; }
RESOURCE TBUF r_example_text_Item1 { buf = "Option 1 selected"; }
RESOURCE TBUF r_example_text_Item2 { buf = "Option 2 selected"; }
RESOURCE TBUF r_example_text_Item3 { buf = "Option 3 selected"; }

//
// About dialog box resources
//
RESOURCE TBUF80 r_example_about_dialog_version_label
{ buf = KApplicationName" program - Version %d.%02d(%03d)"; }
 
RESOURCE DIALOG r_example_about_dialog
{
  flags   = EEikDialogFlagWait|EEikDialogFlagButtonsRight;
  title   = "About "KApplicationName;
  buttons = R_EIK_BUTTONS_CONTINUE;
  items   =
  {
    DLG_LINE { type = EEikCtLabel; control = LABEL
      {txt = KApplicationLongName;};},
    DLG_LINE { type = EEikCtLabel; control = LABEL
      {txt = "Copyright "" Symbian Ltd "KCopyrightYear;};},
    DLG_LINE { type = EEikCtLabel; control = LABEL{ txt = "All rights reserved.";};},
    DLG_LINE
    {
      id      = EDialogAboutVersionLine;
      type    = EEikCtLabel;
      control = LABEL
        {
          txt = r_about_dialog_version_label;
        };
    }
  };
}
       

The Source Files
The following files make up the body of the application source. There are two header/include files and several CPP files.

The header files

 HelloWorld.hrh 

// HelloWorld.hrh
//
// Copyright (c) 2000-2001 Symbian Ltd. All rights reserved.

//
// Command IDs specific to our application for key handling, 0x1000 is a sensible
// start point to ensure no clashes with standard system command IDs
//
enum TExampleMenuCommands
{
  EExampleCmd0 = 0x1000,
  EExampleCmd1,
  EExampleCmd2,
  EExampleCmd3,
  EExampleCmdAbout,

  EExampleCmdAddToDesk
};

//
// Control IDs specific to our application for use in dialogs, 0x1000 is a sensible
// start point to ensure no clashes with standard system control IDs
//
enum TExampleDialogIdentifiers
{
  EDialogAboutVersionLine = 0x1000
};
       

 HelloWorld.h 

// HelloWorld.h
//
// Copyright (c) 2000-2001 Symbian Ltd. All rights reserved.
#ifndef __HELLOWORLD_H__
#define __HELLOWORLD_H__

// Standard includes
#include <eikenv.h> // CEikonEnv
#include <eikapp.h> // CEikApplication
#include <eikdoc.h> // CEikDocument
#include <eikappui.h> // CEikAppUi
#include <coecntrl.h> // CCoeControl
#include <uikon.hrh> // Standard control and command ID definitions

// For "Add to Desk" functionality
#include <eikproc.h> // CEikProcess
#include <eikmenub.h> // CEikMenuBar
#include <linkbase.h> // CLinkBase and useful constants
#include <linkdocument.h> // CLinkDocument
#include <linkutils.h> // LinkUtils (static interface to Link functionality)

// For dialog functionality
#include <eikdialg.h> // CEikDialog
#include <eiklabel.h> // CEikLabel

/// Our application-specific definitions
#include <helloworld.rsg>
#include "helloworld.hrh"
const TUid KUidHelloWorldNokia9200Series = { 0x101F43AB };
const TInt KVersionMajor = 1;
const TInt KVersionMinor = 0;
const TInt KVersionBuild = 3;

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

///////////////////////////////////////////////////////////////
//
// CHelloDocument
//
///////////////////////////////////////////////////////////////
class CHelloDocument : public CEikDocument
{
  public:
  static CHelloDocument* NewL(CEikApplication& aApp);
  CHelloDocument(CEikApplication& aApp);
  void ConstructL();
  private: // from CEikDocument
  CEikAppUi* CreateAppUiL();
};

///////////////////////////////////////////////////////////////
//
// CHelloAppUi
//
///////////////////////////////////////////////////////////////
class CHelloAppView;
class CHelloAppUi : public CEikAppUi
{
  public:
  void ConstructL( );
  ~CHelloAppUi( );
  void AddToDeskL( ) const;
  private: // from CEikAppUi
  void HandleCommandL(TInt aCommand);
  void DynInitMenuPaneL(TInt aResourceId,CEikMenuPane* aMenuPane);
  private:
  CHelloAppView* iAppView;
};

///////////////////////////////////////////////////////////////
//
// CHelloAppView
//
///////////////////////////////////////////////////////////////
class CHelloAppView : public CCoeControl
{
  public:
  ~CHelloAppView( );
  void ConstructL(const TRect& aRect);
  private:         // from CCoeControl
  void Draw(const TRect& /*aRect*/) const;
  private:
  HBufC* iHelloText;
};

///////////////////////////////////////////////////////////////
//
// CHelloAboutDialog
//
//////////////////////////////////////////////////////////////
class CHelloAboutDialog : public CEikDialog
{
  public:
  CHelloAboutDialog(const TVersion& aVersionInfo);
  private: // from CEikDialog
  void PreLayoutDynInitL();
  private:
  TVersion iVersionInfo;
};
#endif // __HELLOWORLD_H_
       

The source files
The following cpp files constitute the various aspects of the application:

 HelloWorld_Main.cpp 

// HelloWorld_Main.cpp
//
// Copyright (c) 2000-2001 Symbian Ltd. All rights reserved.

/////////////////////////////////////////////////////////////////////////
//
// This example is a simple Nokia 9200 Series Communicator application
// containing a single view with sample "Hello World" text drawn on it.
// 
/////////////////////////////////////////////////////////////////////////

#include "HelloWorld.h"

//
// The entry point for the application code. It creates an instance of the
// CApaApplication derived class, CHelloApplication.
//
EXPORT_C CApaApplication* NewApplication()
{
  return new CHelloApplication;
}

//
// This function is required by all Symbian OS DLLs. In this example (and
// most standard applications) it does nothing.
//
GLDEF_C TInt E32Dll(TDllReason)
{
  return KErrNone;
}
       

 HelloWorld_Application.cpp 

// HelloWorld_Application.cpp
//
// Copyright (c) 2000-2001 Symbian Ltd. All rights reserved.

#include "HelloWorld.h"

//
// This function is called by the UI framework to ask for the application's UID.
// The returned value is defined by the constant KUidHelloWorldNokia9200Series in
// HelloWorld.h
//
// This constant must match the second value defined in the project definition
// (.MMP) file.
// 
TUid CHelloApplication::AppDllUid() const
{
  return KUidHelloWorldNokia9200Series;
}

//
// This function is called by the UI framework at application start-up. It creates
// an instance of our application's CEikDocument-derived document class.
//
CApaDocument* CHelloApplication::CreateDocumentL()
{
  return new (ELeave) CHelloDocument(*this);
}
       

 HelloWorld_Document.cpp 

// HelloWorld_Document.cpp
//
// Copyright (c) 2000-2001 Symbian Ltd. All rights reserved.

#include "HelloWorld.h"

//
// The constructor of the document class just passes the supplied reference to the
// constructor initialisation list. The document has no real work to
// do in this application
//
CHelloDocument::CHelloDocument(CEikApplication& aApp)
  :CEikDocument(aApp)
{ }

//
// This is called by the UI framework as soon as the document has been created. It creates
// an instance of the Application UI. The Application UI class is an instance of a
// CEikAppUi derived class
//
CEikAppUi* CHelloDocument::CreateAppUiL()
{
  return new(ELeave) CHelloAppUi;
}
       

 HelloWorld_AppUi.cpp 

// HelloWorld_AppUi.cpp
//
// Copyright (c) 2000-2001 Symbian Ltd. All rights reserved.

#include "HelloWorld.h"

//
// This is the second phase constructor of the application UI class. The application
// UI creates and owns the one and only view of this application.
//
void CHelloAppUi::ConstructL()
{
  // BaseConstructL() completes the UI framework's construction of the App UI.
  BaseConstructL();

// Create the single application view in which to draw the text our
// "Hello World" text, passing into it the rectangle available to it.
iAppView = new(ELeave) CHelloAppView();
iAppView->ConstructL(ClientRect());

// This call will allow us to support "Add to Desk" functionality which is
// a standard part of most Nokia 9200 Series Communicator applications
LinkUtils::AddLinkHotKeyL(
  *iEikonEnv->AppUiFactory()->MenuBar()->HotKeyTable(),EExampleCmdAddToDesk);
}

//
// The application UI owns the only view and is, therefore, responsible
// for destroying it in its destructor
//
CHelloAppUi::~CHelloAppUi()
{
  delete iAppView;
}

//
// This method is called by the UI framework when a command has been issued.
// In our application, a command can originate through a hot-key being pressed,
// the selection of a menu item or the selection of a CBA button.
//
// The various command IDs are defined in the .HRH file and are 'connected'
// to the hot-key, menu and CBA items in the application resource file.
//
// Note that EEikCmdExit is defined by the UI framework in uikon.hrh. This
// is the standard value passed by the framework when your application
// should close down (for example, for a system backup)
//
void CHelloAppUi::HandleCommandL(TInt aCommand)
{
  switch (aCommand)
  {
    case EExampleCmd0:
      iEikonEnv->InfoMsg(R_EXAMPLE_TEXT_ITEM0);
      break;
    case EExampleCmd1:
      iEikonEnv->InfoMsg(R_EXAMPLE_TEXT_ITEM1);
      break;
    case EExampleCmd2:
      iEikonEnv->InfoMsg(R_EXAMPLE_TEXT_ITEM2);
      break;
    case EExampleCmd3:
      iEikonEnv->InfoMsg(R_EXAMPLE_TEXT_ITEM3);
      break;
    case EExampleCmdAbout:
    {
      CEikDialog* dialog = new(ELeave)
      CHelloAboutDialog(TVersion(KVersionMajor,KVersionMinor,KVersionBuild));
      dialog->ExecuteLD(R_EXAMPLE_ABOUT_DIALOG);// Execute the dialog using our

      // R_EXAMPLE_ABOUT_DIALOG resource
      // definition to govern how the dialog appears
      // on screen
    }
      break;
    case EExampleCmdAddToDesk:
      AddToDeskL( );
      break;
    case EEikCmdExit: 
      // Exit the application. The Exit() method is
      // implemented by the UI framework.
      Exit( );
      break;
  }
}

//
// This function is called just before a menu bar is displayed. It allows
// us to manipulate the menu by for example adding or removing items or
// marking them as dimmed. In this case we need to add the standard
// "Add to Desk" menu item to the file menu pane.
//
void CHelloAppUi::DynInitMenuPaneL(TInt aResourceId,CEikMenuPane* aMenuPane)
{
  if (aResourceId==R_EXAMPLE_FILE_MENU)
  LinkUtils::AddLinkMenuItemL(*aMenuPane,EExampleCmdAddToDesk);
}

//
// This function adds a shortcut to our application on to
// the Desk main screen
//
void CHelloAppUi::AddToDeskL() const
{
  CLinkDocument* link = CLinkDocument::NewL();
  CleanupStack::PushL(link);// Push our new variable pointer onto the "CleanupStack", a

  // key feature of the OS framework. This ensures memory
  // is cleaned up properly in the event of an error or
  // out-of-memory condition later on in our code. See
  // the SDK for extensive information and examples

  // If this application has a document, create a link to that. Otherwise
  // create a link directly to the application itself
  TPtrC currentDocument = iEikonEnv->Process( )->MainDocFileName( );
  if (currentDocument.Length( ) == 0)
    link->SetDocumentL(Application( )->DllName( ));
  else
    link->SetDocumentL(currentDocument);

  LinkUtils::CreateLinkDocumentL(*link);
  CleanupStack::PopAndDestroy( ); // Remove "link" from the CleanupStack
}
       

 HelloWorld_AppView.cpp 

// HelloWorld_AppView.cpp
//
// Copyright (c) 2000-2001 Symbian Ltd. All rights reserved.

#include "HelloWorld.h"

//
// Destructor for the view
//
CHelloAppView::~CHelloAppView( )
{
  delete iHelloText;
}

//
// Second phase constructor for this class
//
void CHelloAppView::ConstructL(const TRect& aRect)
{
  // Fetch the text from the resource file.
  iHelloText = iEikonEnv->AllocReadResourceL(R_EXAMPLE_TEXT_HELLO);

  // Control is a window owning control
  CreateWindowL( );

  // Set the extent of the control using aRect. In our application
  // this is the whole screen rectangle available, minus any standard
  // controls such as the CBA and status pane. This value is calculated
  // and passed to this function by CHelloAppUi::ConstructL()
  SetRect(aRect);

  // At this stage, the control is ready to draw so we tell
  // the UI framework by activating it.
  ActivateL( );
}

//
// Drawing the view - in this example, this consists of drawing a simple
// outline rectangle and then drawing the text in the middle using the
// default font supplied by the UI.
//
// In this example, we don't use the redraw region because it's easier
// to redraw to the whole client area.
//
void CHelloAppView::Draw(const TRect& /*aRect*/) const
{
  // Window graphics context
  CWindowGc& gc = SystemGc();

  // Area in which we shall draw
  TRect drawRect = Rect( );

  // Font used for drawing text is the title font supplied by the UI
  const CFont* fontUsed = iEikonEnv->TitleFont( );
  gc.UseFont(fontUsed);

  // Start with a clear screen
  gc.Clear( );

  // Draw an outline rectangle (the default pen and brush styles
  // ensure this) slightly smaller than the drawing area.
  gc.DrawRect(drawRect);
  drawRect.Shrink(10,10);

  // Draw the text in the middle of the rectangle.
  TInt baselineOffset = (drawRect.Height() - fontUsed->HeightInPixels())/2; 
  gc.DrawText(*iHelloText,drawRect,baselineOffset,CGraphicsContext::ECenter, 0);

  // We have finished using the font so discard it.
  gc.DiscardFont( );
}
       

 HelloWorld_Dialogs.cpp 

// HelloWorld_Dialogs.cpp
//
// Copyright (c) 2000-2001 Symbian Ltd. All rights reserved.

#include "HelloWorld.h"

//
// Class CHelloAboutDialog
//
CHelloAboutDialog::CHelloAboutDialog(const TVersion& aVersionInfo)
  :iVersionInfo(aVersionInfo)
{ }

//
// This is a class in the CEikDialog framework called before the dialog is shown on
// screen. It allows us to, for example, manipulate the contents of controls on the
// dialog at runtime before the user sees them. In this case, we set one of the
// labels to show our application version information.
//
void CHelloAboutDialog::PreLayoutDynInitL()
{
  TBuf<80> versionText1;
  TBuf<80> versionText2;
  iEikonEnv->ReadResource(versionText1,R_EXAMPLE_ABOUT_DIALOG_VERSION_LABEL);
  versionText2.Format(versionText1,iVersionInfo.iMajor,
    iVersionInfo.iMinor,iVersionInfo.iBuild);

  CEikLabel* versionLabel = (CEikLabel*)Control(EDialogAboutVersionLine);
  versionLabel->SetTextL(versionText2);
}