diff -r 80ef3a206772 -r 48780e181b38 Symbian3/SDK/Source/GUID-0C814ED6-3F64-4E0E-9C47-654AEDADBA90.dita --- a/Symbian3/SDK/Source/GUID-0C814ED6-3F64-4E0E-9C47-654AEDADBA90.dita Fri Jul 16 17:23:46 2010 +0100 +++ b/Symbian3/SDK/Source/GUID-0C814ED6-3F64-4E0E-9C47-654AEDADBA90.dita Tue Jul 20 12:00:49 2010 +0100 @@ -9,238 +9,225 @@ --> -Going -Beyond Hello: A Tutorial for Symbian C++ ApplicationsThis tutorial shows how you can extend that basic example to create -a small paint application, along the way learning more about the application -frameworks (e.g. defining menus, how to handle touch-screen events, drawing -to the screen etc.). -

In the Symbian C++ -Quick Start you learned how to create a basic example application using -Carbide.c++, and how to build and run it on the Windows emulator and on a -device.

-

Comes with Code: File: -HelloSymbianWorld Example Code.zip

-
Application -Structure

Carbide.c++ offers two ways of exploring your project. -The traditional Project Explorer window, which can also be found in -Eclipse, lists the files belonging to the project in the same directory structure -as in the file system.

The Symbian Project Navigator contains -the same contents, but displays them in a logical hierarchy according to Symbian -Conventions.

You might wonder why a basic "Hello World" application -contains so many files. The answer is straightforward - a much simpler Hello -World wouldn’t be a very good starting point for real-world applications. -

Instead the wizard generates the project for a complete and readily -extensible application. The project separates code and data, and uses a form -of the model -view controller pattern for structuring your code. The application -already reacts to system events and contains everything that is required for -localization.

What are the directories of a project? - +Going Beyond Hello: A Tutorial for Symbian C++ ApplicationsThis tutorial shows how you can extend that basic example +to create a small paint application, along the way learning more about +the application frameworks (e.g. defining menus, how to handle touch-screen +events, drawing to the screen etc.). +

In the Symbian +C++ Quick Start you learned how to create a basic example application +using Carbide.c++, and how to build and run it on the Windows emulator +and on a device.

+

Comes with Code: File: HelloSymbianWorld Example Code.zip

+
Application Structure

Carbide.c++ offers two ways +of exploring your project. The traditional Project Explorer window, which can also be found in Eclipse, lists the files belonging +to the project in the same directory structure as in the file system. +

The Symbian Project Navigator contains the same contents, +but displays them in a logical hierarchy according to Symbian Conventions.

You might wonder +why a basic "Hello World" application contains so many files. The +answer is straightforward - a much simpler Hello World wouldn’t be +a very good starting point for real-world applications.

Instead +the wizard generates the project for a complete and readily extensible +application. The project separates code and data, and uses a form +of the model view controller pattern for structuring +your code. The application already reacts to system events and contains +everything that is required for localization.

What +are the directories of a project? +

\group

    -
  • bld.inf: Component-definition file. This specifies the mmp files -that belong to your component, any shared header files that it exports, and -the default build targets (e.g. GCCE, WINSCW).

      -
    • Bld.inf is used to generate the makefiles and abld.bat used -to build for the command-line (see Symbian -C++ Quick Start).

    • -
    • This file is the starting point when you want to import a Symbian C++ -project into Carbide.c++, because it contains references to all executables -in your project (see the section on Importing Other Examples).

    • +
    • bld.inf: Component-definition file. This specifies the mmp files that belong to your component, any shared header +files that it exports, and the default build targets (e.g. GCCE, WINSCW).

        +
      • Bld.inf is used to generate the makefiles +and abld.bat used to build for the command-line (see Symbian C++ Quick +Start).

      • +
      • This file is the starting point when you want to import a Symbian +C++ project into Carbide.c++, because it contains references to all +executables in your project (see the section on Importing Other Examples).

    • -
    • HelloWorld.mmp: Project-definition file. This specifies how -to build an executable (in this case HelloWorld.exe) in a -platform- and compiler-independent way. It contains information such as resource -files to be compiled, source files to include when compiling, and the libraries -to include when linking.

    • -
    • Icons_aif_scalable_dc.mk: Makefile used to create the application's -icon from the *.svg file in the /gfx folder.

    • +
    • HelloWorld.mmp: Project-definition file. This specifies +how to build an executable (in this case HelloWorld.exe) in a platform- and compiler-independent way. It contains information +such as resource files to be compiled, source files to include when +compiling, and the libraries to include when linking.

    • +
    • Icons_aif_scalable_dc.mk: Makefile used to create the +application's icon from the *.svg file in the /gfx folder.

    \src

      -
    • HelloWorldApplication.cpp: This file contains the entry point -for the EXE file (E32Main()) as well as the implementation -of the Application class (which provides some basic functionality for the -GUI framework). Normally this is "boilerplate" code and you do not need to -make any changes.

    • -
    • HelloWorldDocument.cpp: This class is supposed to take care -of the persistent data model of your application and therefore provides some -functions to load and save .ini files. This mechanism is -disabled by default - for most applications you may treat this as "boilerplate" -code.

    • -
    • HelloWorldAppUi.cpp: This is the main controller of your application. -It contains the logic for handling application-wide events (so you don’t have -to handle, for example, the exit event in every view). It owns all the views -that you use.

    • -
    • HelloWorldContainerView.cpp: This is a kind of controller, which -is responsible for handling events and the UI elements of the currently visible -view. It’s not visible itself, but owns and manages the Container (below), -which corresponds to the view in the traditional model view controller pattern.

    • -
    • HelloWorldContainer.cpp: Contains the UI elements that should -be displayed by the view. Therefore, the ContainerView and the Container usually -have a very strong relationship.

    • +
    • HelloWorldApplication.cpp: This file contains the entry +point for the EXE file (E32Main()) as well as the +implementation of the Application class (which provides some basic +functionality for the GUI framework). Normally this is "boilerplate" +code and you do not need to make any changes.

    • +
    • HelloWorldDocument.cpp: This class is supposed to take +care of the persistent data model of your application and therefore +provides some functions to load and save .ini files. +This mechanism is disabled by default - for most applications you +may treat this as "boilerplate" code.

    • +
    • HelloWorldAppUi.cpp: This is the main controller of +your application. It contains the logic for handling application-wide +events (so you don’t have to handle, for example, the exit event in +every view). It owns all the views that you use.

    • +
    • HelloWorldContainerView.cpp: This is a kind of controller, +which is responsible for handling events and the UI elements of the +currently visible view. It’s not visible itself, but owns and manages +the Container (below), which corresponds to the view in the +traditional model view controller pattern.

    • +
    • HelloWorldContainer.cpp: Contains the UI elements that +should be displayed by the view. Therefore, the ContainerView and +the Container usually have a very strong relationship.

    During start-up, one class instance creates the next:

    - +

    \inc

      -
    • HelloWorldApplication.h, HelloWorldDocument.h, HelloWorldAppUi.h, HelloWorldContainerView.h, HelloWorldContainer.h: Header files corresponding to each of the main source files above.

    • -
    • HelloWorld.hrh: UIDs/identifiers for UI elements including views. -These are shared between the resource file definitions for UI elements and -the source code command handlers.

    • +
    • HelloWorldApplication.h, HelloWorldDocument.h, HelloWorldAppUi.h, HelloWorldContainerView.h, HelloWorldContainer.h: Header files corresponding to each of +the main source files above.

    • +
    • HelloWorld.hrh: UIDs/identifiers for UI elements including +views. These are shared between the resource file definitions for +UI elements and the source code command handlers.

    • HelloWorld.pan: Panic code and method definitions.

    \data

      -
    • HelloWorld_reg.rss: Contains registration information about -the application, such as its title.

    • -
    • HelloWorld.rss: Main resource file. Contains additional information -about the application, as well as user interface and text resource definitions. -

    • -
    • HelloWorld.loc, HelloWorld.l01: Localization files. Strings -used by UI are defined in separate localization resource files. Each file -has the format .lxx, where xx is a language specific -numeric file extension - e.g. UK English is ‘01’, French ‘02’ and German ‘03’. -The .loc file is a kind of junction that #includes the -language specific files. The languages are compiled into separate resource -files (extension .rxx; the resource file for the current -language is loaded by the UI framework at runtime

    • +
    • HelloWorld_reg.rss: Contains registration information +about the application, such as its title.

    • +
    • HelloWorld.rss: Main resource file. Contains additional +information about the application, as well as user interface and text +resource definitions.

    • +
    • HelloWorld.loc, HelloWorld.l01: Localization +files. Strings used by UI are defined in separate localization resource +files. Each file has the format .lxx, where xx is a language specific numeric file extension - e.g. UK English +is ‘01’, French ‘02’ and German ‘03’. The .loc file +is a kind of junction that #includes the language +specific files. The languages are compiled into separate resource +files (extension .rxx; the resource file for the +current language is loaded by the UI framework at runtime

    \gfx

      -
    • list_icon.bmp, list_icon_mask.bmp, mark_icon.bmp, mark_icon_mask.bmp: -Bitmap and bitmap masks. These are compiled into the MultiBitMap (mbm) -format for display in the application.

    • -
    • qgn_menu_HelloWorld.svg: SVG-T image that gets compiled into -the HelloWorld_aif.mif MultiImageFile (mif) -used for the application icon.

    • +
    • list_icon.bmp, list_icon_mask.bmp, mark_icon.bmp, mark_icon_mask.bmp: Bitmap and bitmap masks. These are compiled +into the MultiBitMap (mbm) format for display in +the application.

    • +
    • qgn_menu_HelloWorld.svg: SVG-T image that gets compiled +into the HelloWorld_aif.mif MultiImageFile (mif) used for the application icon.

    \sis

      -
    • HelloWorld.pkg: Defines the contents that should be packaged -into the installable .sis file for the device. This includes -the executable as well as all resources required by the application (graphics -and so on).

    • -
    • HelloWorld.sis: Compressed and self-contained installation file -for the device. Compiled based on the package file.

    • -
    • HelloWorld.sisx: .sis file which has been signed -with a certificate (in this case self-signed).

    • +
    • HelloWorld.pkg: Defines the contents that should be +packaged into the installable .sis file for the device. +This includes the executable as well as all resources required by +the application (graphics and so on).

    • +
    • HelloWorld.sis: Compressed and self-contained installation +file for the device. Compiled based on the package file.

    • +
    • HelloWorld.sisx: .sis file which has +been signed with a certificate (in this case self-signed).

Extending -Hello World – Drawing

To make our application a little bit more -interactive, we are going to implement a simple paint tool, allowing the user -to draw lines by touching the screen.

We could draw the lines directly -on the screen, but then everything would get lost when something caused our -application to redraw the screen – for example, a telephone call that came -through while our application was running. Therefore, we have to draw the -lines to a bitmap, which is simply copied to the screen whenever required. -

Another solution (more difficult but also more flexible!) would be -to store all lines in a list and to iterate over the list each time the application +Hello World – Drawing

To make our application a little bit +more interactive, we are going to implement a simple paint tool, allowing +the user to draw lines by touching the screen.

We could +draw the lines directly on the screen, but then everything would get +lost when something caused our application to redraw the screen – +for example, a telephone call that came through while our application +was running. Therefore, we have to draw the lines to a bitmap, which +is simply copied to the screen whenever required.

Another +solution (more difficult but also more flexible!) would be to store +all lines in a list and to iterate over the list each time the application needs to draw the contents of the screen.

-
Using the -SDK Documentation

The class that can handle bitmap data is called CFbsBitmap. -Let’s take a look at the documentation for this class to find out more about -the required header files, libraries and available methods.

Search the -online documentation for the class you're interested in, in this case CFbsBitmap. CFbsBitmap -in Os Font_and_Bitmap_Server should be (one of the) first topics you -find.

If you're working offline you can also search for documentation -in the SDK. Start menu: Start - S60 Developer Tools - 5th Edition -SDK, v1.0 - SDK Documentation

Right at the top of the -reference page you will see that the header file we need to use is FBS.H and -the library we need to link against is called fbscli.lib.

- -

This class is capable of storing a bitmap. It's also possible to -get direct access to the bitmap data. However for more convenient methods -of drawing we will work through a drawing device and context.

To -find out more about bitmaps, contexts and drawing functions, Search for ‘bitmaps’ in the documentation, and go to the page Bitmaps -in Using Bitmaps, or Using Bitmaps in Using Graphics Device Interfaces. - Symbian provides several different device and context classes. For our -application we’re going to use CFbsBitmapDevice (header file: bitdev.h, -library: bitgdi.lib) and CFbsBitGc (header -file: bitstd.h, library: bitgdi.lib).

-
Adding Libraries -To a Project

In the previous step, we determined that we need two -libraries in order to use all three bitmap-related classes: fbscli.lib and bitgdi.lib. -To add them to our project, open the HelloWorld.mmp project -file (in the /group/ folder if you’re using the Project -Explorer window). Switch to the Libraries tab. At the top of -this page, you will see a list of included libraries. fbscli.lib is -already in the list, so we don’t need to add it. However bitgdi.lib is -missing.

There are more libraries in the list than are used by our -project (added by the wizard!). These cause no harm so we choose not to remove -them.

Click on the Add button. Search for bitgdi.lib in -the list and add it to the Libraries list.

- -

When you’re finished, make sure that both libraries are in the Libraries list. -

When you compile your application again, Carbide.c++ will detect -the changes in the .mmp file and ask you what to do. Click on Compile and -Link to update the project with the changes we have made to the .mmp file. - +

Using +the SDK Documentation

The class that can handle bitmap data +is called CFbsBitmap. Let’s take a look at the documentation +for this class to find out more about the required header files, libraries +and available methods.

Search the online documentation for the class you're interested +in, in this case CFbsBitmap. CFbsBitmap in Os Font_and_Bitmap_Server should +be (one of the) first topics you find.

If you're +working offline you can also search for documentation in the SDK. Start menu: Start - S60 Developer Tools - 5th Edition SDK, +v1.0 - SDK Documentation

Right at the top of the +reference page you will see that the header file we need to use is FBS.H and the library we need to link against is called fbscli.lib.

+ +

This class is capable of storing a bitmap. It's also possible +to get direct access to the bitmap data. However for more convenient +methods of drawing we will work through a drawing device and context. +

To find out more about bitmaps, contexts and drawing functions, Search for ‘bitmaps’ in the documentation, +and go to the page Bitmaps in Using Bitmaps, or Using Bitmaps +in Using Graphics Device Interfaces. Symbian provides several +different device and context classes. For our application we’re going +to use CFbsBitmapDevice (header file: bitdev.h, library: bitgdi.lib) and CFbsBitGc (header file: bitstd.h, library: bitgdi.lib).

+
Adding +Libraries To a Project

In the previous step, we determined +that we need two libraries in order to use all three bitmap-related +classes: fbscli.lib and bitgdi.lib. To add them to our project, open the HelloWorld.mmp project file (in the /group/ folder if you’re using +the Project Explorer window). Switch to the Libraries tab. At the top of this page, you will see a list of included +libraries. fbscli.lib is already in the list, so +we don’t need to add it. However bitgdi.lib is missing.

There are more libraries in the list than are used by our project +(added by the wizard!). These cause no harm so we choose not to remove +them.

Click on the Add button. Search for bitgdi.lib in the list and add it to the Libraries list.

+ +

When you’re finished, make sure that both libraries are in +the Libraries list.

When you compile your application +again, Carbide.c++ will detect the changes in the .mmp file and ask +you what to do. Click on Compile and Link to update the project +with the changes we have made to the .mmp file. +

-
Creating Bitmaps

Now -the libraries have been added, we can use the bitmap classes in our project. -Open the file HelloWorldContainer.h and add the following -include statements:

#include <fbs.h> +
Creating +Bitmaps

Now the libraries have been added, we can use the +bitmap classes in our project. Open the file HelloWorldContainer.h and add the following include statements:

#include <fbs.h> #include <bitdev.h> #include <bitstd.h> -

We also need to store the bitmap objects as instance (member) -variables. Add the following definitions to a private section of the CHelloWorldContainer class. -Be careful not to write anything into areas managed by the UI designer, because -your changes could be overwritten. These areas are marked by comments. -

private: +

We also need to store the bitmap objects as instance +(member) variables. Add the following definitions to a private section +of the CHelloWorldContainer class. Be careful not +to write anything into areas managed by the UI designer, because your +changes could be overwritten. These areas are marked by comments. +

private: CFbsBitmap* iBitmap; CFbsBitmapDevice* iBmpDevice; -CFbsBitGc* iBmpGc;

Symbian C++ uses some naming conventions. Instance variables should have a lowercase i at -the beginning of the variable name (iBitmap). Arguments should -be marked by an a (aBitmap). Normal local variables that -you create inside a function do not need any prefix. That way, you instantly -know where the variable is coming from – this is very important when deleting -objects. Next, we want to create the bitmap. Define and implement a new -method:

void CHelloWorldContainer::CreateBitmapsL()

Let’s -go line by line through the required code for this method: First, we have -to make sure that any previous objects are deleted if they already exist. -This would be required (for example) if the running application needs to re-create -the bitmap because the screen layout changes. You don’t need to add an if -statement to check if the pointer is NULL beforehand – the C++ delete statement -only deletes the object if the pointer is not NULL. You do however need to -ensure that the objects are set to NULL after deletion to avoid possible "double -deletion" in the destructor.

delete iBitmap; iBitmap = NULL; +CFbsBitGc* iBmpGc;

Symbian C++ uses some naming conventions. Instance variables should +have a lowercase i at the beginning of the variable +name (iBitmap). Arguments should be marked by an +a (aBitmap). Normal local variables that you create +inside a function do not need any prefix. That way, you instantly +know where the variable is coming from – this is very important when +deleting objects. Next, we want to create the bitmap. Define and +implement a new method:

void CHelloWorldContainer::CreateBitmapsL()

Let’s go line by line through the required code for this method: + First, we have to make sure that any previous objects are deleted +if they already exist. This would be required (for example) if the +running application needs to re-create the bitmap because the screen +layout changes. You don’t need to add an if statement to check if +the pointer is NULL beforehand – the C++ delete statement +only deletes the object if the pointer is not NULL. You do however +need to ensure that the objects are set to NULL after deletion to +avoid possible "double deletion" in the destructor.

delete iBitmap; iBitmap = NULL; delete iBmpDevice; iBmpDevice = NULL; -delete iBmpGc; iBmpGc = NULL;

This following line of code should -look familiar – it simply creates an instance of the CFbsBitmap class: -

iBitmap = new (ELeave) CFbsBitmap();

The -(ELeave) parameter is Symbian C++ specific. This causes a leave (the -Symbian C++ equivalent of standard exceptions) if allocating the object fails -– for example, because there is not enough free memory. With the (ELeave), -you don’t have to manually check if the pointer is actually pointing to a -valid object after creating the object instance. You can find out more about -leaves in Fundamentals -of C++.

We do not handle the potential leave here; that’s -why the method name (CreateBitmapL()) has a trailing L to -show that it can also leave. More on this topic in a moment.

Now, -it’s time to let the CFbsBitmap class allocate the memory -for the bitmap it is going to manage. The available drawing size for our container -can be queried by the method Size() from its base class. EColor16MU specifies -the color depth – in this case, it’s a true color display mode with 32 bits -per pixel; the top byte is unused. The color mode EColor16MA would -use the top byte for the alpha channel, several other modes are available -as well.

iBitmap->Create(Size(), EColor16MU); -

The next line creates a graphics device based on the bitmap. A graphics -device represents the medium being drawn to and is needed to create a graphics -context. The use of a NewL() method is common in Symbian -C++; it is a static factory function which returns a fully constructed object -of the desired type.

iBmpDevice = CFbsBitmapDevice::NewL(iBitmap); -

A graphics context provides a large number of drawing operations, -along with state settings defining how the drawing is performed. The bitmap -graphics context used here is a specialization of the generic graphics context -and adds some methods that can be used for bitmaps only – such as clearing -and copying rectangular areas.

iBmpDevice->CreateContext(iBmpGc); -

Whenever you create objects, it’s best to think about where and when -they are going to be deleted right away. Memory leaks are a serious issue -on a mobile device where no virtual memory is available and the main memory -is limited to 30-80 MB. Therefore, go to the destructor of CHelloWorldContainer and -add the required statements for deleting the three objects:

delete iBmpGc; +delete iBmpGc; iBmpGc = NULL;

This following line of +code should look familiar – it simply creates an instance of the CFbsBitmap class:

iBitmap = new (ELeave) +CFbsBitmap();

The (ELeave) +parameter is Symbian C++ specific. This causes a leave (the Symbian C++ equivalent of standard +exceptions) if allocating the object fails – for example, because +there is not enough free memory. With the (ELeave), you don’t have to manually check if the pointer is actually pointing +to a valid object after creating the object instance. You can find +out more about leaves in Fundamentals of C++.

We do not handle +the potential leave here; that’s why the method name (CreateBitmapL()) has a trailing L to show that it can also leave. More on this topic +in a moment.

Now, it’s time to let the CFbsBitmap class allocate the memory for the bitmap it is going to manage. +The available drawing size for our container can be queried by the +method Size() from its base class. EColor16MU specifies the color depth – in this case, it’s a true color display +mode with 32 bits per pixel; the top byte is unused. The color mode EColor16MA would use the top byte for the alpha channel, +several other modes are available as well.

iBitmap->Create(Size(), +EColor16MU);

The next line creates a graphics device +based on the bitmap. A graphics device represents the medium being +drawn to and is needed to create a graphics context. The use of a NewL() method is common in Symbian C++; it is a static factory +function which returns a fully constructed object of the desired type. +

iBmpDevice = CFbsBitmapDevice::NewL(iBitmap);

A graphics context provides a large number of drawing +operations, along with state settings defining how the drawing is +performed. The bitmap graphics context used here is a specialization +of the generic graphics context and adds some methods that can be +used for bitmaps only – such as clearing and copying rectangular areas. +

iBmpDevice->CreateContext(iBmpGc);

Whenever you create objects, it’s best to think about where and +when they are going to be deleted right away. Memory leaks are a serious +issue on a mobile device where no virtual memory is available and +the main memory is limited to 30-80 MB. Therefore, go to the destructor +of CHelloWorldContainer and add the required statements +for deleting the three objects:

delete iBmpGc; delete iBmpDevice; -delete iBitmap;

The next step addresses the remaining -question: where to call the CreateBitmapsL() method. Of course, -you could do this from the construction methods of the class. But what if, -while your application is running, the user physically turns the phone, causing -it to switch from portrait to landscape mode? Because the bitmap was created -with the portrait size in mind, the user would no longer be able to use the -full screen for drawing.

Therefore, we have to react to events that -inform us when the screen size is changed. In those situations, SizeChanged() is -executed. When the container is first constructed, its size changes as well. -Because of this, we can simply call our CreateBitmapsL() method -from within SizeChanged():

void CHelloWorldContainer::SizeChanged() +delete iBitmap;

The next step addresses the +remaining question: where to call the CreateBitmapsL() method. Of course, you could do this from the construction methods +of the class. But what if, while your application is running, the +user physically turns the phone, causing it to switch from portrait +to landscape mode? Because the bitmap was created with the portrait +size in mind, the user would no longer be able to use the full screen +for drawing.

Therefore, we have to react to events that +inform us when the screen size is changed. In those situations, SizeChanged() is executed. When the container is first constructed, +its size changes as well. Because of this, we can simply call our CreateBitmapsL() method from within SizeChanged():

void CHelloWorldContainer::SizeChanged() { CCoeControl::SizeChanged(); LayoutControls(); @@ -250,70 +237,62 @@ { TRAPD(err, CreateBitmapsL()); } - }

In the source code above, an additional check ensures -that the bitmap is only re-created if the size available for the container -is really different to the existing bitmap size – the SizeChanged() method -is also called, for example, when the option menu obscures part of our view. -This does not affect the available space for our drawing area and therefore -should not lead to re-creating the bitmap.

But what is the TRAPD() statement -doing here? Let’s use this to take a closer look at the concept of leaves.

Leaves

When -programming using Symbian C++, an L is appended to the name of methods that -can leave (usually because it contains other methods that can leave and does -not choose to "TRAP" them). Note: this is a helpful convention, but is not -checked or required by the compiler.

Our CreateBitmapsL() method -contains two methods that can leave: the (ELeave) parameter -causes a leave if there is not enough memory to allocate the object. The NewL() method -from the graphics device also has a trailing L – meaning -that this method can also leave. We did not catch any (all) of those leaves -in the CreateBitmapsL() method so it was named with a trailing L. -

Any leaves are passed up in the call stack until caught by a TRAPD macro. -The SizeChanged() method traps any leaves from CreateBitmapsL() and -consequently does not need to have a trailing L. -

The error code of the leave is stored in the err variable, which -is declared as a normal integer by this macro. It would be a good idea to -take a look at the contents of this variable and to handle errors instead -of ignoring them as we’re doing here. But for the sake of simplicity, we do -not handle any errors that might occur in this situation.

Tip

A -good way to automatically check your code for potential problems is to use -the CodeScanner tool that comes with Carbide.c++. It is a static code-analysis -tool looking at Symbian coding rules and standards. Find out more at: http://carbidehelp.nokia.com/help/topic/com.nokia.carbide.cpp.codescanner/html/codescanner.htm

-
Handling Touch -Events

Before we start handling the touch events, we need one more -instance variable in our code. To draw a line from one touch position to the -next, it’s necessary to save the first position. Therefore, add the following -private instance variable to CHelloWorldContainer: TPoint iLastPos;

TPoint is -a convenience class that stores two integers that can be used as co-ordinates. -Additionally, it provides some methods to modify the point. We do not need -to initialize the variable in the constructor of the CHelloWorldContainer class -– the container class is indirectly derived from the class CBase, -which automatically zero-initializes all member variables. Touch events -are delivered to the container class, which is responsible for managing the -visible UI content in the main pane of your application. To handle the events -ourselves, we have to override the following method in CHelloWorldContainer:

void -CHelloWorldContainer::HandlePointerEventL(const TPointerEvent& aPointerEvent)

Define -this method in the header file (can be private or protected) and add its implementation -in the .cpp file. The information about the new event -is sent through the argument aPointerEvent. We are interested -in the up event for the first button (there is only one in current touch devices; -you can’t click with a right button as you would with a mouse). Whenever the -user releases the stylus or finger from the touch screen, we want to draw -a line to this position. Put the following code into this if statement: if (aPointerEvent.iType == TPointerEvent::EButton1Up) + }

In the source code above, an additional +check ensures that the bitmap is only re-created if the size available +for the container is really different to the existing bitmap size +– the SizeChanged() method is also called, for example, +when the option menu obscures part of our view. This does not affect +the available space for our drawing area and therefore should not +lead to re-creating the bitmap.

But what is the TRAPD() statement doing here? Let’s use this to take a closer +look at the concept of leaves.

Leaves

When +programming using Symbian C++, an L is appended to the name of methods +that can leave (usually because it contains other methods that can +leave and does not choose to "TRAP" them). Note: this is a helpful +convention, but is not checked or required by the compiler.

Our CreateBitmapsL() method contains two methods +that can leave: the (ELeave) parameter causes a leave +if there is not enough memory to allocate the object. The NewL() method from the graphics device also has a trailing L – meaning that this method can also leave. We did not +catch any (all) of those leaves in the CreateBitmapsL() method so it was named with a trailing L.

Any leaves are passed up in the call stack until caught by a TRAPD macro. The SizeChanged() method traps +any leaves from CreateBitmapsL() and consequently +does not need to have a trailing L.

The error code of the leave is stored in the err variable, which +is declared as a normal integer by this macro. It would be a good +idea to take a look at the contents of this variable and to handle +errors instead of ignoring them as we’re doing here. But for the sake +of simplicity, we do not handle any errors that might occur in this +situation.

Tip

A good way to automatically +check your code for potential problems is to use the CodeScanner tool that comes with Carbide.c++. It is a static code-analysis tool +looking at Symbian coding rules and standards. Find out more at: http://carbidehelp.nokia.com/help/topic/com.nokia.carbide.cpp.codescanner/html/codescanner.htm

+
Handling +Touch Events

Before we start handling the touch events, +we need one more instance variable in our code. To draw a line from +one touch position to the next, it’s necessary to save the first position. +Therefore, add the following private instance variable to CHelloWorldContainer: TPoint iLastPos;

TPoint is a convenience class that stores +two integers that can be used as co-ordinates. Additionally, it provides +some methods to modify the point. We do not need to initialize the +variable in the constructor of the CHelloWorldContainer class – the container class is indirectly derived from the class CBase, which automatically zero-initializes all member variables. + Touch events are delivered to the container class, which is responsible +for managing the visible UI content in the main pane of your application. +To handle the events ourselves, we have to override the following +method in CHelloWorldContainer:

void +CHelloWorldContainer::HandlePointerEventL(const TPointerEvent& +aPointerEvent)

Define this method in the header file +(can be private or protected) and add its implementation in the .cpp file. The information about the new event is sent +through the argument aPointerEvent. We are interested +in the up event for the first button (there is only one in current +touch devices; you can’t click with a right button as you would with +a mouse). Whenever the user releases the stylus or finger from the +touch screen, we want to draw a line to this position. Put the following +code into this if statement: if (aPointerEvent.iType == TPointerEvent::EButton1Up) { - }

Drawing the line itself is rather simple. First, define -the color and style that should be used for drawing, then call the function -for drawing the line. Note that the settings concerning the color and style -stay active until they are changed again in this graphics context – you do -not need to set them every time when executing consecutive drawing operations.

iBmpGc->SetPenColor(KRgbRed); + }

Drawing the line itself is rather simple. First, +define the color and style that should be used for drawing, then call +the function for drawing the line. Note that the settings concerning +the color and style stay active until they are changed again in this +graphics context – you do not need to set them every time when executing +consecutive drawing operations.

iBmpGc->SetPenColor(KRgbRed); iBmpGc->SetPenSize(TSize(2,2)); -iBmpGc->DrawLine(iLastPos, aPointerEvent.iPosition);

Next, we -have to save the new position, because it will be required as the starting -point for the next line.

iLastPos = aPointerEvent.iPosition;

Finally, -issue a request to the framework to redraw the screen. Otherwise, the user -won’t see the new line!

DrawDeferred();

At the end -of the method, also call the HandlePointerEventL() method -of the base class (the container is derived from CCoeControl, -because it is a normal UI control by itself):

CCoeControl::HandlePointerEventL(aPointerEvent);

To -sum it up, this is the final code for the HandlePointerEvent() method:

void CHelloWorldContainer::HandlePointerEventL(const TPointerEvent& aPointerEvent) +iBmpGc->DrawLine(iLastPos, aPointerEvent.iPosition);

Next, we have to save the new position, because it will be required +as the starting point for the next line.

iLastPos = aPointerEvent.iPosition;

Finally, issue a request to the framework to redraw the screen. +Otherwise, the user won’t see the new line!

DrawDeferred();

At the end of the method, also call the HandlePointerEventL() method of the base class (the container is derived from CCoeControl, because it is a normal UI control by itself):

CCoeControl::HandlePointerEventL(aPointerEvent);

To sum it up, this is the final code for the HandlePointerEvent() method:

void CHelloWorldContainer::HandlePointerEventL(const TPointerEvent& aPointerEvent) { if (aPointerEvent.iType == TPointerEvent::EButton1Up) { @@ -324,132 +303,127 @@ DrawDeferred(); } CCoeControl::HandlePointerEventL(aPointerEvent); - }

We’ve already added all the code required for drawing -to the bitmap, but this bitmap still has to be transferred to the screen. -The CHelloWorldContainer::Draw() method is called when the -system wants the contents of the container to be redrawn. Therefore, we need -to add the following line of code to the end of the Draw() method, -which copies the bitmap to the top left of the graphics context of the screen:

gc.BitBlt(TPoint(0, -0), iBitmap);

Now compile the project. It should already work – -you can draw red lines by just clicking inside the main pane of the emulator!

- + }

We’ve already added all the code required for +drawing to the bitmap, but this bitmap still has to be transferred +to the screen. The CHelloWorldContainer::Draw() method +is called when the system wants the contents of the container to be +redrawn. Therefore, we need to add the following line of code to the +end of the Draw() method, which copies the bitmap +to the top left of the graphics context of the screen:

gc.BitBlt(TPoint(0, 0), iBitmap);

Now compile the project. +It should already work – you can draw red lines by just clicking inside +the main pane of the emulator!

+
Defining -a Menu

The application would be improved if the user could clear -the drawing during use, rather than having to restart it. This section shows -how you add and handle menu items to provide this functionality, and to exit -the application Open the HelloWorldContainer.uidesign document. -You can find it in the root folder of your project in the Project Explorer or -in the UI Designs folder of the Symbian Project Navigator.

Click -on the Options menu item below the UI design to reveal the menu. As -indicated, you simply need to click on the empty menu item and start typing.

- -

Add two menu items – Clear (for clearing the image) and Exit (for -closing the application).

Then click once on the Exit menu item -to select it. Go to the Behavior group of the Properties window -and change the command ID to EAknCmdExit (this is available -in the drop-down list). This command will also be sent to your application -if the operating system wants to shut it down, for example, when the phone -does not have enough memory left. Therefore, it is necessary that every application -always responds to this event and instantly shuts the application down. It -is already handled by the basic application that the Carbide.c++ wizard generated -for you; you don’t need to implement the command handling for this event yourself.

- -

If you try your application now, you will see that the Exit menu -item already works.

Tip

When testing the application, -always quit your application using the Exit command (rather than just -closing the emulator). The application environment will then automatically -check for memory leaks. If you just shut down the emulator you may not discover -the leak until much later, making it a lot more difficult to find the cause.

-
Clearing the -Drawing

Whenever the Clear menu item is selected the view -class method CHelloWorldContainerView::HandleCommandL() is -called with the command ID of the menu item as a parameter.

If we -want to handle the menu item, the UI designer can create the necessary code -for us. Right-click on the menu item and choose Handle ‘selected’ Event. -The UI designer will ask you to save the design – choose Yes. The code -will then be generated and you will jump into the code view to a new method -called HandleClearMenuItemSelectedL() – a more convenient -place to put your command-handling code than directly in a big HandleCommandL() method -that receives all commands. The auto-generated source code therefore calls -the new extra method from within HandleCommandL() (take a +a Menu

The application would be improved if the user could +clear the drawing during use, rather than having to restart it. This +section shows how you add and handle menu items to provide this functionality, +and to exit the application Open the HelloWorldContainer.uidesign document. You can find it in the root folder of your project in +the Project Explorer or in the UI Designs folder of +the Symbian Project Navigator.

Click on the Options menu item below the UI design to reveal the menu. As indicated, +you simply need to click on the empty menu item and start typing.

+ +

Add two menu items – Clear (for clearing the image) +and Exit (for closing the application).

Then click +once on the Exit menu item to select it. Go to the Behavior group of the Properties window and change the command ID +to EAknCmdExit (this is available in the drop-down +list). This command will also be sent to your application if the operating +system wants to shut it down, for example, when the phone does not +have enough memory left. Therefore, it is necessary that every application +always responds to this event and instantly shuts the application +down. It is already handled by the basic application that the Carbide.c++ +wizard generated for you; you don’t need to implement the command +handling for this event yourself.

+ +

If you try your application now, you will see that the Exit +menu item already works.

Tip

When testing +the application, always quit your application using the Exit command (rather than just closing the emulator). The application +environment will then automatically check for memory leaks. If you +just shut down the emulator you may not discover the leak until much +later, making it a lot more difficult to find the cause.

+
Clearing +the Drawing

Whenever the Clear menu item is selected +the view class method CHelloWorldContainerView::HandleCommandL() is called with the command ID of the menu item as a parameter. +

If we want to handle the menu item, the UI designer can create +the necessary code for us. Right-click on the menu item and choose Handle ‘selected’ Event. The UI designer will ask you to save +the design – choose Yes. The code will then be generated and +you will jump into the code view to a new method called HandleClearMenuItemSelectedL() – a more convenient place to put your command-handling code than +directly in a big HandleCommandL() method that receives +all commands. The auto-generated source code therefore calls the new +extra method from within HandleCommandL() (take a look at that method to see what really happens).

- -

Now, we only need to tell the container that it should clear its -bitmap buffer. To do this, create a new public method in the container:

void CHelloWorldContainer::ClearDrawing() + +

Now, we only need to tell the container that it should clear +its bitmap buffer. To do this, create a new public method in the container:

void CHelloWorldContainer::ClearDrawing() { iBmpGc->Clear(); DrawDeferred(); - }

Now, call this method from the menu item handler method. -As explained in the section about the application architecture, the view class -(CHelloWorldContainerView) is the controller and owner for/of -the container class (CHelloWorldContainer). Therefore, this -class has a pointer to the container as an instance variable, which you can -use to clear the drawing.

TBool CHelloWorldContainerView::HandleClearMenuItemSelectedL(TInt aCommand) + }

Now, call this method from the menu item handler +method. As explained in the section about the application architecture, +the view class (CHelloWorldContainerView) is the +controller and owner for/of the container class (CHelloWorldContainer). Therefore, this class has a pointer to the container as an instance +variable, which you can use to clear the drawing.

TBool CHelloWorldContainerView::HandleClearMenuItemSelectedL(TInt aCommand) { iHelloWorldContainer->ClearDrawing(); return ETrue; - }

The menu command should now clear the image.

Congratulations, -you have completed the tutorial and have created your own small mobile painting -application!

-
Further Exercises

As -an exercise, it’s a good idea to extend the application by yourself – for -example, you could add some menu items that allow the end user to change the -color of the pen.

Tip

It’s a good idea to learn -keyboard shortcuts as early as possible, because they can significantly increase -the efficiency of your work. For example, you can press Ctrl + B to -build the project, instead of using the icon or the menu commands. Also very -helpful: Ctrl + Shift + F automatically formats and indents your code. -You can get a full list of commands by pressing Ctrl + 3. A hot keys -list appears when you press Ctrl + Shift + L.

Importing -Other Examples

The S60 SDK itself installs many examples; additional -applications can be downloaded from the developer.symbian.org and Forum Nokia -(see the Related Info section for more information). To import ready-made + }

The menu command should now clear the image.

Congratulations, you have completed the tutorial and have created +your own small mobile painting application!

+
Further +Exercises

As an exercise, it’s a good idea to extend the +application by yourself – for example, you could add some menu items +that allow the end user to change the color of the pen.

Tip

It’s a good idea to learn keyboard shortcuts +as early as possible, because they can significantly increase the +efficiency of your work. For example, you can press Ctrl + B to build the project, instead of using the icon or the menu commands. +Also very helpful: Ctrl + Shift + F automatically formats and +indents your code. You can get a full list of commands by pressing Ctrl + 3. A hot keys list appears when you press Ctrl + Shift ++ L.

Importing Other Examples

The S60 +SDK itself installs many examples; additional applications can be +downloaded from the developer.symbian.org and Forum Nokia (see the +Related Info section for more information). To import ready-made applications in Carbide.c++, go to File | Import. In the following dialog, select Symbian OS Bld.inf file and click Next.

- -

Now, click Browse and navigate to the bld.inf file -of the project you want to import. It’s usually stored in the /group/ subfolder -of the project.

- -

In the following step, select which SDKs you would like to use. The -same considerations as those explained when creating your Hello World application -apply.

- -

You can usually accept the default values for the next step and let -the wizard import everything.

In the last step, you have to define -the Project Properties. In most cases, you can leave the default values.

- -

Afterwards, the project is imported and you can start working. The -project contents will not be copied to the current Carbide.c++ workspace, -so you will work directly on the original directory and the original files. -Copy the project to a different directory first if you want to keep the original -project or example in its original state – for example, into the workspace -directory.

Troubleshooting: If importing the -project fails, take special care of the last step of the import process: the -root directory should be set correctly to the root directory of the project -and not one level above it. Also, the project name should be the same as the -last part of the root directory. From time to time, the default values are -not configured properly, causing problems in the import process.

Warning

Do -not use the standard (Eclipse) project import! The reason is that this import -method would also import all build configuration settings, including references -to installed SDKs and paths on the original system. Therefore, if you import -a project from somebody else but don’t have the SDK installed in exactly the -same directory, the build configurations will no longer work. The bld.inf import -method recreates the SDK bindings and only imports the real contents of the -project.

-
Summary

This -part of the tutorial has shown how we can extend the basic skeleton from the Symbian C++ Quick Start to -create a small paint application. The tutorial explains the application framework, -including how you define menus, how to handle touch-screen events, drawing -to the screen etc.

-
Related Info
    -
  • Symbian C++ -Quick Start

  • -
  • Getting -Started with Debugging on the Device

  • -
  • File: -HelloSymbianWorld Example Code.zip (code example associated with this -article)

  • + +

    Now, click Browse and navigate to the bld.inf file of the project you want to import. It’s usually +stored in the /group/ subfolder of the project.

    + +

    In the following step, select which SDKs you would like to +use. The same considerations as those explained when creating your +Hello World application apply.

    + +

    You can usually accept the default values for the next step +and let the wizard import everything.

    In the last step, +you have to define the Project Properties. In most cases, you +can leave the default values.

    + +

    Afterwards, the project is imported and you can start working. +The project contents will not be copied to the current Carbide.c++ +workspace, so you will work directly on the original directory and +the original files. Copy the project to a different directory first +if you want to keep the original project or example in its original +state – for example, into the workspace directory.

    Troubleshooting: If importing the project fails, take special +care of the last step of the import process: the root directory should +be set correctly to the root directory of the project and not one +level above it. Also, the project name should be the same as the last +part of the root directory. From time to time, the default values +are not configured properly, causing problems in the import process.

    Warning

    Do not use the standard (Eclipse) +project import! The reason is that this import method would also import +all build configuration settings, including references to installed +SDKs and paths on the original system. Therefore, if you import a +project from somebody else but don’t have the SDK installed in exactly +the same directory, the build configurations will no longer work. +The bld.inf import method recreates the SDK bindings +and only imports the real contents of the project.

+
Summary

This part of the tutorial has shown how we can extend the basic +skeleton from the Symbian C++ Quick Start to create a small paint application. +The tutorial explains the application framework, including how you +define menus, how to handle touch-screen events, drawing to the screen +etc.

+
Related +Info
    +
  • Symbian +C++ Quick Start

  • +
  • Getting Started with Debugging on the Device

  • +
  • File: HelloSymbianWorld Example Code.zip +(code example associated with this article)

\ No newline at end of file