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