Symbian3/SDK/Source/GUID-0C814ED6-3F64-4E0E-9C47-654AEDADBA90.dita
changeset 7 51a74ef9ed63
child 8 ae94777fff8f
equal deleted inserted replaced
6:43e37759235e 7:51a74ef9ed63
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-0C814ED6-3F64-4E0E-9C47-654AEDADBA90" xml:lang="en"><title>Going
       
    13 Beyond Hello: A Tutorial for Symbian C++ Applications</title><shortdesc>This tutorial shows how you can extend that basic example to create
       
    14 a small paint application, along the way learning more about the application
       
    15 frameworks (e.g. defining menus, how to handle touch-screen events, drawing
       
    16 to the screen etc.).</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    17 <p>In the <xref href="GUID-301E5FAA-A1C3-4FD7-9D84-DAA61C66981B.dita">Symbian C++
       
    18 Quick Start</xref> you learned how to create a basic example application using
       
    19 Carbide.c++, and how to build and run it on the Windows emulator and on a
       
    20 device.  </p>
       
    21 <p><b>Comes with Code</b>: <xref href="http://developer.symbian.org/wiki/images/e/eb/HelloSymbianWorld_Example_Code.zip.dita">File:
       
    22 HelloSymbianWorld Example Code.zip</xref></p>
       
    23 <section id="GUID-14C6D367-D806-45F8-BC44-C5DBC78096D9">       <title> Application
       
    24 Structure</title>       <p>Carbide.c++ offers two ways of exploring your project.
       
    25 The traditional <b>Project Explorer</b> window, which can also be found in
       
    26 Eclipse, lists the files belonging to the project in the same directory structure
       
    27 as in the file system.  </p><p>The <b>Symbian Project Navigator</b> contains
       
    28 the same contents, but displays them in a logical hierarchy according to <xref href="http://developer.symbian.org/wiki/index.php/Coding_Standards_and_Conventions.dita">Symbian
       
    29 Conventions</xref>. </p><p> You might wonder why a basic "Hello World" application
       
    30 contains so many files. The answer is straightforward - a much simpler Hello
       
    31 World wouldn’t be a very good starting point for real-world applications.
       
    32  </p><p>Instead the wizard generates the project for a complete and readily
       
    33 extensible application. The project separates code and data, and uses a form
       
    34 of the <xref href="http://wiki.forum.nokia.com/index.php/Design_Patterns_in_Symbian.dita#http://wiki.forum.nokia.com/index.php/Design_Patterns_in_Symbian/Model-View-Control_Pattern">model
       
    35 view controller pattern</xref> for structuring your code. The application
       
    36 already reacts to system events and contains everything that is required for
       
    37 localization. </p><p/><p><b>What are the directories of a project?</b><fig id="GUID-898488F8-5CF9-4A01-95F8-45E2C5D2E501">
       
    38 <image href="GUID-FFC6F01E-15AB-43E6-90E8-0E42DA297AE9_d0e3849_href.png" placement="inline"/>
       
    39 </fig></p><p/><b>\group</b><ul>
       
    40 <li><p><b>bld.inf</b>: Component-definition file. This specifies the <codeph>mmp</codeph> files
       
    41 that belong to your component, any shared header files that it exports, and
       
    42 the default build targets (e.g. GCCE, WINSCW).</p><ul>
       
    43 <li><p><codeph>Bld.inf</codeph> is used to generate the makefiles and <codeph>abld.bat</codeph> used
       
    44 to build for the command-line (see <xref href="GUID-301E5FAA-A1C3-4FD7-9D84-DAA61C66981B.dita">Symbian
       
    45 C++ Quick Start</xref>). </p></li>
       
    46 <li><p>This file is the starting point when you want to import a Symbian C++
       
    47 project into Carbide.c++, because it contains references to all executables
       
    48 in your project (see the section on Importing Other Examples). </p></li>
       
    49 </ul></li>
       
    50 <li><p><b>HelloWorld.mmp</b>: Project-definition file. This specifies how
       
    51 to build an executable (in this case <codeph>HelloWorld.exe</codeph>) in a
       
    52 platform- and compiler-independent way. It contains information such as resource
       
    53 files to be compiled, source files to include when compiling, and the libraries
       
    54 to include when linking. </p></li>
       
    55 <li><p><b>Icons_aif_scalable_dc.mk</b>: Makefile used to create the application's
       
    56 icon from the <codeph>*.svg</codeph> file in the <codeph>/gfx</codeph> folder. </p></li>
       
    57 </ul><p> </p><p><b>\src</b></p><ul>
       
    58 <li><p> <b>HelloWorldApplication.cpp</b>: This file contains the entry point
       
    59 for the EXE file (<codeph>E32Main()</codeph>) as well as the implementation
       
    60 of the Application class (which provides some basic functionality for the
       
    61 GUI framework). Normally this is "boilerplate" code and you do not need to
       
    62 make any changes. </p></li>
       
    63 <li><p><b>HelloWorldDocument.cpp</b>: This class is supposed to take care
       
    64 of the persistent data model of your application and therefore provides some
       
    65 functions to load and save <codeph>.ini</codeph> files. This mechanism is
       
    66 disabled by default - for most applications you may treat this as "boilerplate"
       
    67 code. </p></li>
       
    68 <li><p><b>HelloWorldAppUi.cpp</b>: This is the main controller of your application.
       
    69 It contains the logic for handling application-wide events (so you don’t have
       
    70 to handle, for example, the exit event in every view). It owns all the views
       
    71 that you use. </p></li>
       
    72 <li><p><b>HelloWorldContainerView.cpp</b>: This is a kind of controller, which
       
    73 is responsible for handling events and the UI elements of the currently visible
       
    74 view. It’s not visible itself, but owns and manages the <i>Container</i> (below),
       
    75 which corresponds to the view in the traditional model view controller pattern.</p></li>
       
    76 <li><p><b>HelloWorldContainer.cpp</b>: Contains the UI elements that should
       
    77 be displayed by the view. Therefore, the ContainerView and the Container usually
       
    78 have a very strong relationship. </p></li>
       
    79 </ul><p>During start-up, one class instance creates the next:</p><fig id="GUID-2A3EE3C2-3515-4217-BCB3-182A01936898">
       
    80 <image href="GUID-AC3F5010-ECA6-4257-98B5-77FB26B4987F_d0e3955_href.png" placement="inline"/>
       
    81 </fig><p/><p><b>\inc</b></p><ul>
       
    82 <li><p><b>HelloWorldApplication.h</b>, <b>HelloWorldDocument.h</b>, <b>HelloWorldAppUi.h</b>, <b>HelloWorldContainerView.h</b>, <b>HelloWorldContainer.h</b>: Header files corresponding to each of the main source files above. </p></li>
       
    83 <li><p><b>HelloWorld.hrh</b>: UIDs/identifiers for UI elements including views.
       
    84 These are shared between the resource file definitions for UI elements and
       
    85 the source code command handlers.</p></li>
       
    86 <li><p><b>HelloWorld.pan</b>: Panic code and method definitions.</p></li>
       
    87 </ul><p/><p><b>\data</b></p><ul>
       
    88 <li><p><b>HelloWorld_reg.rss</b>: Contains registration information about
       
    89 the application, such as its title.</p></li>
       
    90 <li><p><b>HelloWorld.rss</b>: Main resource file. Contains additional information
       
    91 about the application, as well as user interface and text resource definitions.
       
    92      </p></li>
       
    93 <li><p><b>HelloWorld.loc</b>, <b>HelloWorld.l01</b>: Localization files. Strings
       
    94 used by UI are defined in separate localization resource files. Each file
       
    95 has the format <codeph>.lxx</codeph>, where <i>xx</i> is a language specific
       
    96 numeric file extension - e.g. UK English is ‘01’, French ‘02’ and German ‘03’.
       
    97 The <codeph>.loc</codeph> file is a kind of junction that <codeph>#includes</codeph> the
       
    98 language specific files. The languages are compiled into separate resource
       
    99 files (extension <codeph>.rxx</codeph>; the resource file for the current
       
   100 language is loaded by the UI framework at runtime</p></li>
       
   101 </ul><p/><p><b>\gfx</b></p><ul>
       
   102 <li><p><b>list_icon.bmp</b>, <b>list_icon_mask.bmp</b>, <b>mark_icon.bmp</b>, <b>mark_icon_mask.bmp</b>:
       
   103 Bitmap and bitmap masks. These are compiled into the MultiBitMap (<codeph>mbm</codeph>)
       
   104 format for display in the application.</p></li>
       
   105 <li><p> <b>qgn_menu_HelloWorld.svg</b>: SVG-T image that gets compiled into
       
   106 the <codeph>HelloWorld_aif.mif</codeph> MultiImageFile (<codeph>mif</codeph>)
       
   107 used for the application icon.</p></li>
       
   108 </ul><p/><p><b>\sis</b></p><ul>
       
   109 <li><p><b>HelloWorld.pkg</b>: Defines the contents that should be packaged
       
   110 into the installable <codeph>.sis</codeph> file for the device. This includes
       
   111 the executable as well as all resources required by the application (graphics
       
   112 and so on).</p></li>
       
   113 <li><p><b>HelloWorld.sis</b>: Compressed and self-contained installation file
       
   114 for the device. Compiled based on the package file.     </p></li>
       
   115 <li><p><b>HelloWorld.sisx</b>: <codeph>.sis</codeph> file which has been signed
       
   116 with a certificate (in this case self-signed).</p></li>
       
   117 </ul>     </section>
       
   118 <section id="GUID-65BEDD17-334B-4C42-8D89-DAB355F97F51"><title> Extending
       
   119 Hello World – Drawing</title><p>To make our application a little bit more
       
   120 interactive, we are going to implement a simple paint tool, allowing the user
       
   121 to draw lines by touching the screen.    </p><p>We could draw the lines directly
       
   122 on the screen, but then everything would get lost when something caused our
       
   123 application to redraw the screen – for example, a telephone call that came
       
   124 through while our application was running. Therefore, we have to draw the
       
   125 lines to a bitmap, which is simply copied to the screen whenever required.
       
   126   </p><p>Another solution (more difficult but also more flexible!) would be
       
   127 to store all lines in a list and to iterate over the list each time the application
       
   128 needs to draw the contents of the screen. </p></section>
       
   129 <section id="GUID-217EFA6E-9B5F-4B65-8B99-E056CC26156D"><title> Using the
       
   130 SDK Documentation</title><p>The class that can handle bitmap data is called <codeph>CFbsBitmap</codeph>.
       
   131 Let’s take a look at the documentation for this class to find out more about
       
   132 the required header files, libraries and available methods.    </p><p><xref href="http://developer.symbian.org/search/search_results.php?txtSearch=CFbsBitmap&amp;site=sdl_collection.dita">Search</xref> the
       
   133 online documentation for the class you're interested in, in this case <codeph>CFbsBitmap</codeph>. <xref href="http://developer.symbian.org/main/documentation/reference/s%5E2/doc_source/reference/tb91sf-PP/fontandbitmapserver/index.html.dita">CFbsBitmap
       
   134 in Os Font_and_Bitmap_Server</xref> should be (one of the) first topics you
       
   135 find. </p><p/><note>If you're working offline you can also search for documentation
       
   136 in the SDK. <b>Start</b> menu: <b>Start - S60 Developer Tools - 5th Edition
       
   137 SDK, v<i>1.0</i> - SDK Documentation</b></note><p>Right at the top of the
       
   138 reference page you will see that the header file we need to use is <codeph>FBS.H</codeph> and
       
   139 the library we need to link against is called <codeph>fbscli.lib</codeph>. </p><fig id="GUID-23B3B7CF-E676-4FBC-8B26-E7B88764781C">
       
   140 <image href="GUID-0B0EF90E-45A4-467F-8CD9-33FBC612B3BD_d0e4153_href.png" placement="inline"/>
       
   141 </fig><p>This class is capable of storing a bitmap. It's also possible to
       
   142 get direct access to the bitmap data. However for more convenient methods
       
   143 of drawing we will work through a drawing device and context.    </p><p>To
       
   144 find out more about bitmaps, contexts and drawing functions, <xref href="http://developer.symbian.org/search/search_results.php?txtSearch=bitmaps&amp;site=sdl_collection.dita">Search for ‘bitmaps’</xref> in the documentation, and go to the page <b>Bitmaps
       
   145 in Using Bitmaps</b>, or <b>Using Bitmaps in Using Graphics Device Interfaces</b>.
       
   146    Symbian provides several different device and context classes. For our
       
   147 application we’re going to use <codeph>CFbsBitmapDevice</codeph> (header file: <codeph>bitdev.h</codeph>,
       
   148 library: <codeph>bitgdi.lib</codeph>) and <codeph>CFbsBitGc</codeph> (header
       
   149 file: <codeph>bitstd.h</codeph>, library: <codeph>bitgdi.lib</codeph>). </p></section>
       
   150 <section id="GUID-D9C51891-11DE-4042-AE32-CC7EA362C32A"><title> Adding Libraries
       
   151 To a Project</title><p>In the previous step, we determined that we need two
       
   152 libraries in order to use all three bitmap-related classes: <codeph>fbscli.lib</codeph> and <codeph>bitgdi.lib</codeph>.
       
   153 To add them to our project, open the <codeph>HelloWorld.mmp</codeph> project
       
   154 file (in the <codeph>/group/</codeph> folder if you’re using the <b>Project
       
   155 Explorer</b> window). Switch to the <b>Libraries</b> tab.    At the top of
       
   156 this page, you will see a list of included libraries. <codeph>fbscli.lib</codeph> is
       
   157 already in the list, so we don’t need to add it. However <codeph>bitgdi.lib</codeph> is
       
   158 missing. </p><note>There are more libraries in the list than are used by our
       
   159 project (added by the wizard!). These cause no harm so we choose not to remove
       
   160 them.</note><p>Click on the <b>Add</b> button. Search for <codeph>bitgdi.lib</codeph> in
       
   161 the list and add it to the <b>Libraries</b> list. </p><fig id="GUID-7D1E15B4-5157-4F48-9084-6DDBD6EE0208">
       
   162 <image href="GUID-E5FB2D04-D57E-4EEA-850F-40F813C75D8C_d0e4231_href.png" placement="inline"/>
       
   163 </fig><p>When you’re finished, make sure that both libraries are in the <b>Libraries</b> list.
       
   164    </p><p>When you compile your application again, Carbide.c++ will detect
       
   165 the changes in the .mmp file and ask you what to do. Click on <b>Compile and
       
   166 Link</b> to update the project with the changes we have made to the <codeph>.mmp</codeph> file. <fig id="GUID-77F781CD-A2EF-4489-BAE2-EB283057670E">
       
   167 <image href="GUID-10540A35-7E8E-40F0-BF93-CBC01884550C_d0e4248_href.png" placement="inline"/>
       
   168 </fig></p></section>
       
   169 <section id="GUID-F2A4FC0F-8C67-4151-8BD2-808FCEDD121F"><title> Creating Bitmaps</title><p>Now
       
   170 the libraries have been added, we can use the bitmap classes in our project.
       
   171 Open the file <codeph>HelloWorldContainer.h</codeph> and add the following
       
   172 include statements: </p><codeblock xml:space="preserve">#include &lt;fbs.h&gt;
       
   173 #include &lt;bitdev.h&gt;
       
   174 #include &lt;bitstd.h&gt;
       
   175 </codeblock><p>We also need to store the bitmap objects as instance (member)
       
   176 variables. Add the following definitions to a private section of the <codeph>CHelloWorldContainer</codeph> class.
       
   177 Be careful not to write anything into areas managed by the UI designer, because
       
   178 your changes could be overwritten. These areas are marked by comments.   
       
   179  </p><codeblock xml:space="preserve">private:  
       
   180 CFbsBitmap* iBitmap;  
       
   181 CFbsBitmapDevice* iBmpDevice;  
       
   182 CFbsBitGc* iBmpGc;   </codeblock><p>Symbian C++ uses some <xref href="http://developer.symbian.org/wiki/index.php/Coding_Standards_and_Conventions.dita#http://developer.symbian.org/wiki/index.php/Coding_Standards_and_Conventions/Naming_Conventions">naming conventions</xref>. Instance variables should have a lowercase <codeph>i</codeph> at
       
   183 the beginning of the variable name (<codeph>iBitmap</codeph>). Arguments should
       
   184 be marked by an a (<codeph>aBitmap</codeph>). Normal local variables that
       
   185 you create inside a function do not need any prefix. That way, you instantly
       
   186 know where the variable is coming from – this is very important when deleting
       
   187 objects.    Next, we want to create the bitmap. Define and implement a new
       
   188 method: </p><codeph>void CHelloWorldContainer::CreateBitmapsL()</codeph><p>Let’s
       
   189 go line by line through the required code for this method:    First, we have
       
   190 to make sure that any previous objects are deleted if they already exist.
       
   191 This would be required (for example) if the running application needs to re-create
       
   192 the bitmap because the screen layout changes. You don’t need to add an if
       
   193 statement to check if the pointer is NULL beforehand – the C++ <codeph>delete</codeph> statement
       
   194 only deletes the object if the pointer is not NULL. You do however need to
       
   195 ensure that the objects are set to NULL after deletion to avoid possible "double
       
   196 deletion" in the destructor. </p><codeblock xml:space="preserve">delete iBitmap; iBitmap = NULL;  
       
   197 delete iBmpDevice; iBmpDevice = NULL;  
       
   198 delete iBmpGc; iBmpGc = NULL;</codeblock><p>This following line of code should
       
   199 look familiar – it simply creates an instance of the <codeph>CFbsBitmap</codeph> class:
       
   200      </p><p><codeph> iBitmap = new (ELeave) CFbsBitmap();</codeph>       </p><p>The
       
   201 (<codeph>ELeave</codeph>) parameter is Symbian C++ specific. This causes a <xref href="http://developer.symbian.org/wiki/index.php/Leaves_%26_The_Cleanup_Stack_(Fundamentals_of_Symbian_C%2B%2B).dita"> leave</xref> (the
       
   202 Symbian C++ equivalent of standard exceptions) if allocating the object fails
       
   203 – for example, because there is not enough free memory. With the (<codeph>ELeave</codeph>),
       
   204 you don’t have to manually check if the pointer is actually pointing to a
       
   205 valid object after creating the object instance. You can find out more about
       
   206 leaves in <xref href="http://developer.symbian.org/wiki/index.php/Fundamentals_of_Symbian_C%2B%2B.dita">Fundamentals
       
   207 of C++</xref>.    </p><p>We do not handle the potential leave here; that’s
       
   208 why the method name (<codeph>CreateBitmapL()</codeph>) has a trailing L to
       
   209 show that it can also leave. More on this topic in a moment.    </p><p>Now,
       
   210 it’s time to let the <codeph>CFbsBitmap</codeph> class allocate the memory
       
   211 for the bitmap it is going to manage. The available drawing size for our container
       
   212 can be queried by the method <codeph>Size()</codeph> from its base class. <codeph>EColor16MU</codeph> specifies
       
   213 the color depth – in this case, it’s a true color display mode with 32 bits
       
   214 per pixel; the top byte is unused. The color mode <codeph>EColor16MA</codeph> would
       
   215 use the top byte for the alpha channel, several other modes are available
       
   216 as well.   </p><p><codeph>iBitmap-&gt;Create(Size(), EColor16MU);</codeph>  
       
   217  </p><p>The next line creates a graphics device based on the bitmap. A graphics
       
   218 device represents the medium being drawn to and is needed to create a graphics
       
   219 context. The use of a <codeph>NewL()</codeph> method is common in Symbian
       
   220 C++; it is a static factory function which returns a fully constructed object
       
   221 of the desired type.   </p><p><codeph> iBmpDevice = CFbsBitmapDevice::NewL(iBitmap);</codeph> 
       
   222   </p><p>A graphics context provides a large number of drawing operations,
       
   223 along with state settings defining how the drawing is performed. The bitmap
       
   224 graphics context used here is a specialization of the generic graphics context
       
   225 and adds some methods that can be used for bitmaps only – such as clearing
       
   226 and copying rectangular areas.    </p><p><codeph>iBmpDevice-&gt;CreateContext(iBmpGc);</codeph> 
       
   227   </p><p>Whenever you create objects, it’s best to think about where and when
       
   228 they are going to be deleted right away. Memory leaks are a serious issue
       
   229 on a mobile device where no virtual memory is available and the main memory
       
   230 is limited to 30-80 MB. Therefore, go to the destructor of <codeph>CHelloWorldContainer</codeph> and
       
   231 add the required statements for deleting the three objects:      </p><p> <codeblock xml:space="preserve">delete iBmpGc;  
       
   232 delete iBmpDevice;  
       
   233 delete iBitmap;</codeblock>       </p><p>The next step addresses the remaining
       
   234 question: where to call the <codeph>CreateBitmapsL()</codeph> method. Of course,
       
   235 you could do this from the construction methods of the class. But what if,
       
   236 while your application is running, the user physically turns the phone, causing
       
   237 it to switch from portrait to landscape mode? Because the bitmap was created
       
   238 with the portrait size in mind, the user would no longer be able to use the
       
   239 full screen for drawing.    </p><p>Therefore, we have to react to events that
       
   240 inform us when the screen size is changed. In those situations, <codeph>SizeChanged()</codeph> is
       
   241 executed. When the container is first constructed, its size changes as well.
       
   242 Because of this, we can simply call our <codeph>CreateBitmapsL()</codeph> method
       
   243 from within <codeph>SizeChanged()</codeph>:       </p><p><codeblock xml:space="preserve">void CHelloWorldContainer::SizeChanged()  
       
   244 	{  
       
   245 	CCoeControl::SizeChanged();  
       
   246 	LayoutControls();     
       
   247 	// [[[ begin generated region: do not modify [Generated Contents]
       
   248 	// ]]] end generated region [Generated Contents]
       
   249 	if (!iBitmap || (iBitmap &amp;&amp; iBitmap-&gt;SizeInPixels() != Size()))
       
   250 		{
       
   251 		TRAPD(err, CreateBitmapsL());
       
   252 		}
       
   253 	}</codeblock>      </p><p>In the source code above, an additional check ensures
       
   254 that the bitmap is only re-created if the size available for the container
       
   255 is really different to the existing bitmap size – the <codeph>SizeChanged()</codeph> method
       
   256 is also called, for example, when the option menu obscures part of our view.
       
   257 This does not affect the available space for our drawing area and therefore
       
   258 should not lead to re-creating the bitmap.    </p><p>But what is the <codeph>TRAPD()</codeph> statement
       
   259 doing here? Let’s use this to take a closer look at the concept of leaves. </p><p/><p><b>Leaves</b></p><p>When
       
   260 programming using Symbian C++, an L is appended to the name of methods that
       
   261 can leave (usually because it contains other methods that can leave and does
       
   262 not choose to "TRAP" them). Note: this is a helpful convention, but is not
       
   263 checked or required by the compiler.    </p><p>Our <codeph>CreateBitmapsL()</codeph> method
       
   264 contains two methods that can leave: the (<codeph>ELeave</codeph>) parameter
       
   265 causes a leave if there is not enough memory to allocate the object. The <codeph>NewL()</codeph> method
       
   266 from the graphics device also has a trailing <codeph>L</codeph> – meaning
       
   267 that this method can also leave. We did not catch any (all) of those leaves
       
   268 in the <codeph>CreateBitmapsL()</codeph> method so it was named with a trailing <codeph>L</codeph>.
       
   269    </p><p>Any leaves are passed up in the call stack until caught by a <codeph>TRAPD</codeph> macro.
       
   270 The <codeph>SizeChanged()</codeph> method traps any leaves from <codeph>CreateBitmapsL()</codeph> and
       
   271 consequently does <b>not</b> need to have a trailing <codeph>L</codeph>. 
       
   272   </p><p>The error code of the leave is stored in the err variable, which
       
   273 is declared as a normal integer by this macro. It would be a good idea to
       
   274 take a look at the contents of this variable and to handle errors instead
       
   275 of ignoring them as we’re doing here. But for the sake of simplicity, we do
       
   276 not handle any errors that might occur in this situation. </p><p/><p><b>Tip</b></p><p>A
       
   277 good way to automatically check your code for potential problems is to use
       
   278 the <i>CodeScanner</i> tool that comes with Carbide.c++. It is a static code-analysis
       
   279 tool looking at Symbian coding rules and standards. Find out more at: <xref href="http://carbidehelp.nokia.com/help/topic/com.nokia.carbide.cpp.codescanner/html/codescanner.htm.dita">http://carbidehelp.nokia.com/help/topic/com.nokia.carbide.cpp.codescanner/html/codescanner.htm</xref></p></section>
       
   280 <section id="GUID-7E4A9491-8F22-4D68-9890-95332D31412B"><title> Handling Touch
       
   281 Events</title><p>Before we start handling the touch events, we need one more
       
   282 instance variable in our code. To draw a line from one touch position to the
       
   283 next, it’s necessary to save the first position. Therefore, add the following
       
   284 private instance variable to <codeph>CHelloWorldContainer</codeph>: <codeblock xml:space="preserve">TPoint iLastPos;</codeblock></p><p><codeph>TPoint</codeph> is
       
   285 a convenience class that stores two integers that can be used as co-ordinates.
       
   286 Additionally, it provides some methods to modify the point. We do not need
       
   287 to initialize the variable in the constructor of the <codeph>CHelloWorldContainer</codeph> class
       
   288 – the container class is indirectly derived from the class <codeph>CBase</codeph>,
       
   289 which automatically zero-initializes all member variables.    Touch events
       
   290 are delivered to the container class, which is responsible for managing the
       
   291 visible UI content in the main pane of your application. To handle the events
       
   292 ourselves, we have to override the following method in <codeph>CHelloWorldContainer</codeph>: </p><p><codeph>void
       
   293 CHelloWorldContainer::HandlePointerEventL(const TPointerEvent&amp; aPointerEvent)</codeph></p><p>Define
       
   294 this method in the header file (can be private or protected) and add its implementation
       
   295 in the <codeph>.cpp</codeph> file.    The information about the new event
       
   296 is sent through the argument <codeph>aPointerEvent</codeph>. We are interested
       
   297 in the up event for the first button (there is only one in current touch devices;
       
   298 you can’t click with a right button as you would with a mouse). Whenever the
       
   299 user releases the stylus or finger from the touch screen, we want to draw
       
   300 a line to this position. Put the following code into this if statement: <codeblock xml:space="preserve">if (aPointerEvent.iType == TPointerEvent::EButton1Up)
       
   301   {
       
   302   }</codeblock></p><p>Drawing the line itself is rather simple. First, define
       
   303 the color and style that should be used for drawing, then call the function
       
   304 for drawing the line. Note that the settings concerning the color and style
       
   305 stay active until they are changed again in this graphics context – you do
       
   306 not need to set them every time when executing consecutive drawing operations. </p><codeblock xml:space="preserve">iBmpGc-&gt;SetPenColor(KRgbRed);  
       
   307 iBmpGc-&gt;SetPenSize(TSize(2,2));  
       
   308 iBmpGc-&gt;DrawLine(iLastPos, aPointerEvent.iPosition);</codeblock><p>Next, we
       
   309 have to save the new position, because it will be required as the starting
       
   310 point for the next line. </p><codeph>iLastPos = aPointerEvent.iPosition;</codeph><p>Finally,
       
   311 issue a request to the framework to redraw the screen. Otherwise, the user
       
   312 won’t see the new line! </p><codeph>DrawDeferred();</codeph><p>At the end
       
   313 of the method, also call the <codeph>HandlePointerEventL()</codeph> method
       
   314 of the base class (the container is derived from <codeph>CCoeControl</codeph>,
       
   315 because it is a normal UI control by itself): </p><codeph>CCoeControl::HandlePointerEventL(aPointerEvent);</codeph><p>To
       
   316 sum it up, this is the final code for the <codeph>HandlePointerEvent()</codeph> method: </p><codeblock xml:space="preserve">void CHelloWorldContainer::HandlePointerEventL(const TPointerEvent&amp; aPointerEvent)
       
   317     {
       
   318     if (aPointerEvent.iType == TPointerEvent::EButton1Up)
       
   319       {
       
   320       iBmpGc-&gt;SetPenColor(KRgbRed);
       
   321       iBmpGc-&gt;SetPenSize(TSize(2,2));
       
   322       iBmpGc-&gt;DrawLine(iLastPos, aPointerEvent.iPosition);
       
   323       iLastPos = aPointerEvent.iPosition;
       
   324       DrawDeferred();
       
   325       }
       
   326     CCoeControl::HandlePointerEventL(aPointerEvent);
       
   327     }</codeblock><p>We’ve already added all the code required for drawing
       
   328 to the bitmap, but this bitmap still has to be transferred to the screen.
       
   329 The <codeph>CHelloWorldContainer::Draw()</codeph> method is called when the
       
   330 system wants the contents of the container to be redrawn. Therefore, we need
       
   331 to add the following line of code to the end of the <codeph>Draw()</codeph> method,
       
   332 which copies the bitmap to the top left of the graphics context of the screen: </p><codeph>gc.BitBlt(TPoint(0,
       
   333 0), iBitmap);</codeph><p>Now compile the project. It should already work –
       
   334 you can draw red lines by just clicking inside the main pane of the emulator! </p><fig id="GUID-CFD29EE4-464B-498C-80F5-493847DE0AEE">
       
   335 <image href="GUID-700CD2E2-DBB7-40BD-BC6D-9BC79C5A0BBF_d0e4528_href.png" placement="inline"/>
       
   336 </fig></section>
       
   337 <section id="GUID-8DC096A0-807D-437C-9A96-ABAFE2AF7F26"><title>  Defining
       
   338 a Menu </title><p>The application would be improved if the user could clear
       
   339 the drawing during use, rather than having to restart it. This section shows
       
   340 how you add and handle menu items to provide this functionality, and to exit
       
   341 the application    Open the <codeph>HelloWorldContainer.uidesign</codeph> document.
       
   342 You can find it in the root folder of your project in the <b>Project Explorer</b> or
       
   343 in the <b>UI Designs</b> folder of the Symbian Project Navigator.    </p><p>Click
       
   344 on the <b>Options</b> menu item below the UI design to reveal the menu. As
       
   345 indicated, you simply need to click on the empty menu item and start typing. </p><fig id="GUID-96D944A2-87C5-4530-AB0C-580C3277285D">
       
   346 <image href="GUID-20FEEF54-23CB-4D30-B846-11B4ACE8E772_d0e4552_href.png" placement="inline"/>
       
   347 </fig><p>Add two menu items – <b>Clear</b> (for clearing the image) and <b>Exit</b> (for
       
   348 closing the application).    </p><p>Then click once on the Exit menu item
       
   349 to select it. Go to the <b>Behavior</b> group of the <b>Properties</b> window
       
   350 and change the command ID to <codeph>EAknCmdExit</codeph> (this is available
       
   351 in the drop-down list). This command will also be sent to your application
       
   352 if the operating system wants to shut it down, for example, when the phone
       
   353 does not have enough memory left. Therefore, it is necessary that every application
       
   354 always responds to this event and instantly shuts the application down. It
       
   355 is already handled by the basic application that the Carbide.c++ wizard generated
       
   356 for you; you don’t need to implement the command handling for this event yourself. </p><fig id="GUID-8FD2973F-23FF-4734-AE16-CA39C02C7DE5">
       
   357 <image href="GUID-D7F000F0-019A-486E-BB0C-C0065D08C5F6_d0e4575_href.png" placement="inline"/>
       
   358 </fig><p>If you try your application now, you will see that the Exit menu
       
   359 item already works. </p><p/><p><b>Tip</b></p><p> When testing the application,
       
   360 always quit your application using the <b>Exit</b> command (rather than just
       
   361 closing the emulator). The application environment will then automatically
       
   362 check for memory leaks. If you just shut down the emulator you may not discover
       
   363 the leak until much later, making it a lot more difficult to find the cause.</p></section>
       
   364 <section id="GUID-0090F731-A243-44C7-96ED-1EC5DB172F8D"><title> Clearing the
       
   365 Drawing </title><p>Whenever the <b>Clear</b> menu item is selected the view
       
   366 class method <codeph>CHelloWorldContainerView::HandleCommandL()</codeph> is
       
   367 called with the command ID of the menu item as a parameter.   </p><p> If we
       
   368 want to handle the menu item, the UI designer can create the necessary code
       
   369 for us. Right-click on the menu item and choose <b>Handle ‘selected’ Event</b>.
       
   370 The UI designer will ask you to save the design – choose <b>Yes</b>. The code
       
   371 will then be generated and you will jump into the code view to a new method
       
   372 called <codeph>HandleClearMenuItemSelectedL()</codeph> – a more convenient
       
   373 place to put your command-handling code than directly in a big <codeph>HandleCommandL()</codeph> method
       
   374 that receives all commands. The auto-generated source code therefore calls
       
   375 the new extra method from within <codeph>HandleCommandL()</codeph> (take a
       
   376 look at that method to see what really happens). </p><fig id="GUID-8E944FEE-EFDF-4AFE-BEB8-F3B216B91A98">
       
   377 <image href="GUID-881C353C-6482-4DFE-9D43-CFB80DEB77A5_d0e4619_href.png" placement="inline"/>
       
   378 </fig><p>Now, we only need to tell the container that it should clear its
       
   379 bitmap buffer. To do this, create a new public method in the container: </p><codeblock xml:space="preserve">void CHelloWorldContainer::ClearDrawing()
       
   380   {
       
   381   iBmpGc-&gt;Clear();
       
   382   DrawDeferred();
       
   383   }</codeblock><p>Now, call this method from the menu item handler method.
       
   384 As explained in the section about the application architecture, the view class
       
   385 (<codeph>CHelloWorldContainerView</codeph>) is the controller and owner for/of
       
   386 the container class (<codeph>CHelloWorldContainer</codeph>). Therefore, this
       
   387 class has a pointer to the container as an instance variable, which you can
       
   388 use to clear the drawing. </p><codeblock xml:space="preserve">TBool CHelloWorldContainerView::HandleClearMenuItemSelectedL(TInt aCommand)
       
   389   {
       
   390   iHelloWorldContainer-&gt;ClearDrawing();
       
   391   return ETrue;
       
   392   }</codeblock><p>The menu command should now clear the image.    </p><p>Congratulations,
       
   393 you have completed the tutorial and have created your own small mobile painting
       
   394 application! </p></section>
       
   395 <section id="GUID-2BD775FF-BD36-4550-A388-48A3B1832D9E"><title> Further Exercises</title><p>As
       
   396 an exercise, it’s a good idea to extend the application by yourself – for
       
   397 example, you could add some menu items that allow the end user to change the
       
   398 color of the pen. </p><p/><p><b>Tip</b></p><p> It’s a good idea to learn
       
   399 keyboard shortcuts as early as possible, because they can significantly increase
       
   400 the efficiency of your work. For example, you can press <b>Ctrl + B</b> to
       
   401 build the project, instead of using the icon or the menu commands. Also very
       
   402 helpful: <b>Ctrl + Shift + F</b> automatically formats and indents your code.
       
   403 You can get a full list of commands by pressing <b>Ctrl + 3</b>. A hot keys
       
   404 list appears when you press <b>Ctrl + Shift + L</b>.</p><p/><p> <b>Importing
       
   405 Other Examples</b></p><p>The S60 SDK itself installs many examples; additional
       
   406 applications can be downloaded from the developer.symbian.org and Forum Nokia
       
   407 (see the Related Info section  for more information).    To import ready-made
       
   408 applications in Carbide.c++, go to <b>File | Import</b>. In the following
       
   409 dialog, select <b>Symbian OS Bld.inf file</b> and click <b>Next</b>. </p><fig id="GUID-8E8F4507-70E7-496C-AE4D-16DAD8146ABA">
       
   410 <image href="GUID-631E27DB-97A7-47E2-8FC1-856198435FFF_d0e4681_href.png" placement="inline"/>
       
   411 </fig><p/><p>Now, click <b>Browse</b> and navigate to the <codeph>bld.inf</codeph> file
       
   412 of the project you want to import. It’s usually stored in the <codeph>/group/</codeph> subfolder
       
   413 of the project. </p><fig id="GUID-B682943D-10EE-4DC8-B510-7C2D54C536EE">
       
   414 <image href="GUID-C588B869-6940-42B2-84F9-71467F6A4306_d0e4697_href.png" placement="inline"/>
       
   415 </fig><p>In the following step, select which SDKs you would like to use. The
       
   416 same considerations as those explained when creating your Hello World application
       
   417 apply. </p><fig id="GUID-5A381CA4-CCE0-4359-8F02-697AEDA72BDE">
       
   418 <image href="GUID-D492CF6C-F889-4299-AC75-951EF343AC9F_d0e4703_href.png" placement="inline"/>
       
   419 </fig><p>You can usually accept the default values for the next step and let
       
   420 the wizard import everything.    </p><p>In the last step, you have to define
       
   421 the <b>Project Properties</b>. In most cases, you can leave the default values. </p><fig id="GUID-1AB6D789-9407-4AB0-8F52-B1138DE063BD">
       
   422 <image href="GUID-F18A6C91-136D-450E-90F0-7C2B9263777C_d0e4714_href.png" placement="inline"/>
       
   423 </fig><p>Afterwards, the project is imported and you can start working. The
       
   424 project contents will not be copied to the current Carbide.c++ workspace,
       
   425 so you will work directly on the original directory and the original files.
       
   426 Copy the project to a different directory first if you want to keep the original
       
   427 project or example in its original state – for example, into the workspace
       
   428 directory.    </p><p><b>Troubleshooting</b>: If <keyword>importing</keyword> the
       
   429 project fails, take special care of the last step of the import process: the
       
   430 root directory should be set correctly to the root directory of the project
       
   431 and not one level above it. Also, the project name should be the same as the
       
   432 last part of the root directory. From time to time, the default values are
       
   433 not configured properly, causing problems in the import process. </p><p/><p><b>Warning</b>  </p><p>Do
       
   434 not use the standard (Eclipse) project import! The reason is that this import
       
   435 method would also import all build configuration settings, including references
       
   436 to installed SDKs and paths on the original system. Therefore, if you import
       
   437 a project from somebody else but don’t have the SDK installed in exactly the
       
   438 same directory, the build configurations will no longer work. The <codeph>bld.inf</codeph> import
       
   439 method recreates the SDK bindings and only imports the real contents of the
       
   440 project.</p></section>
       
   441 <section id="GUID-191D5D9D-00FB-47F0-B88B-8B87588A20C8"><title> Summary</title><p>This
       
   442 part of the tutorial has shown how we can extend the basic skeleton from the <xref href="GUID-301E5FAA-A1C3-4FD7-9D84-DAA61C66981B.dita">Symbian C++ Quick Start</xref> to
       
   443 create a small paint application. The tutorial explains the application framework,
       
   444 including how you define menus, how to handle touch-screen events, drawing
       
   445 to the screen etc. </p></section>
       
   446 <section id="GUID-8B6E602D-CA6B-41DD-B3DC-4C3BC9A04154"><title> Related Info</title><ul>
       
   447 <li><p><xref href="GUID-301E5FAA-A1C3-4FD7-9D84-DAA61C66981B.dita">Symbian C++
       
   448 Quick Start</xref></p></li>
       
   449 <li><p><xref href="http://developer.symbian.org/wiki/index.php/Getting_Started_with_Debugging_on_the_Device.dita">Getting
       
   450 Started with Debugging on the Device</xref></p></li>
       
   451 <li><p><xref href="http://developer.symbian.org/wiki/images/e/eb/HelloSymbianWorld_Example_Code.zip.dita">File:
       
   452 HelloSymbianWorld Example Code.zip</xref>  (code example associated with this
       
   453 article)</p></li>
       
   454 </ul></section>
       
   455 </conbody></concept>