Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 73 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
73
Dung lượng
678,12 KB
Nội dung
If the cardinality is not 1-to-1, then you need to indicate its value with UML adornments. You usually write the number of objects intended on one end of the UML connector. Common values are as follows: 0 1: the object is optional – perhaps a pointer is used to refer to it 1 n, 0 n or simply n: an arbitrary number of objects is intended – a list, array, or other collection class may be used to contain them 10: exactly 10 objects are intended. For instance, you can read Figure 3.5 as, 'The engine's iMyFleet fleet always has 10 ships. The engine's iOppFleet fleet may have anything from 0 to 10 ships.' Figure 3.5 3.10 Summy In this chapter, we've looked at the features of C++ that Symbian OS uses, those it avoids, and those it augments. We've also seen the coding standards that are used in Symbian OS. Specifically, we've seen the following: The use of Symbian OS fundamental types to guarantee consistent behavior between compilers and platforms. Naming conventions – the core ones help with cleanup. T, C, and R distinguish between different cleanup requirements for classes, i refers to member variables and L to leaving functions that may fail for reasons beyond the control of the programmer. M prefixes interfaces (consisting of pure virtual functions). Good design of function prototypes – how to code input and output parameters, and suggested use of references and pointers in Symbian OS. The difference between library and framework DLLs – the former provide functions that you call, the latter provide functions for you to implement that the framework will call. Exporting nonvirtual, noninline functions using the IMPORT_C and EXPORT_C macros. How to handle virtual functions. Symbian OS use of templates and the thin template pattern to keep code size to a minimum. The four relationships between classes and how to represent them in UML. The use of mixins to provide interfaces in the only use of multiple inheritance in Symbian OS. Chapter 4: A Simple Graphical Application Overview In Chapter 1, we built a text-mode version of the 'Hello World' program, and made the point that no one really wants to run text-mode programs on a user-friendly system like Symbian OS. Text-mode programming is useful for testing and for learning, but production programs use a GUI. We shall therefore now start looking at real graphics and GUI programming in Symbian OS. After a brief introduction to the Symbian OS graphics architecture, I'll spend the body of this chapter talking about hellogui, the graphical 'Hello world!' program. I'll start by walking through the code, explaining how its design fits in with the Uikon framework. Then, I'll take you through a session with the debugger, which will reinforce the code design and also introduce some ideas about controls, pointer, and key event handling, which we'll return to in Chapter 12. 4.1 What's in a Name? In Symbian OS v5, the graphics framework was known as Eikon. That version was originally intended to support both narrow (8-bit characters) and Unicode (16-bit characters) builds but, in the end, only the narrow build was supported. Version 5.1 contained the changes necessary to support Unicode builds and, from that version onwards, Unicode became the only supported build. To reflect this change, the name of the graphics framework was changed from Eikon to Uikon. All later versions of Symbian OS support customization of the user interface (UI), depending on the features of the target machine, such as the size and aspect ratio of the screen, whether it supports keyboard and/or pen-based input and the relative significance of voice- centric or data-centric applications. These differences are largely implemented by the creation of additional UI layers above Uikon. The Series 60 UI, based on Symbian OS v6.1, uses an additional layer known as Avkon to modify the behavior and/or appearance of the underlying Uikon framework. UIQ, based on Symbian OS v7.0, uses Qikon to perform a similar task. In this chapter we shall see only one or two consequences of these changes, mainly related to how a UIQ application is initialized and closed. Most of the code described in this chapter is applicable to any Symbian OS GUI application and I shall point out the cases in which it is specific to a particular UI. 4.2 Introduction to the Graphics Architecture The most important of the Symbian OS graphics and GUI components, and their main relationships, are shown in Figure 4.1: Figure 4.1 At the bottom is the GDI, which defines the drawing primitives and everything necessary to achieve device-independent drawing. The GDI is an entirely abstract component that has to be implemented in various contexts – for on-screen pixel graphics, for instance, or in a printer driver. I'll be covering the main drawing functions defined by the GDI in Chapter 11, and its support for device-independent drawing in Chapter 15. The BITGDI handles optimized rasterizing and bit blitting for on- screen windows and off- screen bitmaps. The font and bitmap server (FBS) manages fonts and bitmaps – potentially large graphics entities – for optimal space efficiency. Support for user interaction starts with the window server, which manages the screen, pointer or other navigation device, and any keypad or keyboard on behalf of all GUI programs within the system. It shares these devices according to windowing conventions that are easily understood by the average end user. A standard window is represented in the client application programming interface API by the RWindow class. The window server is a single server process that provides a basic API for client applications to use. CONE, the control environment, runs in each application process and works with the window server's client-side API, to allow different parts of an application to share windows, key and pointer events. A fundamental abstract class delivered by CONE is CCoeControl,a control, which is a unit of user interaction that uses any combination of screen, keyboard, and pointer. Many controls can share a single window. Concrete control types are derived from CCoeControl. CONE doesn't provide any concrete controls: that's the job of Uikon, the system GUI, and any UI-specific layer, such as Qikon. Together, they specify a standard look-and-feel, and provide reusable controls and other classes that implement that look-and-feel. 4.3 Application Structure By studying the code and the execution of the GUI version of 'Hello world!', we'll begin to understand how Symbian OS GUI applications fit together, using the frameworks provided by Uikon and the application architecture (APPARC). The source code in the three subdirectories of \scmp\hellogui\ consists of the definitions and implementations of four classes (and a resource file). You have to implement these four classes; anything less than this, and you don't have a Symbian OS GUI application. The classes are as follows: An application: the application class serves to define the properties of the application, and also to manufacture a new, blank, document. In the simplest case, as here, the only property that you have to define is the application's unique identifier, or UID. A document: a document represents the data model for the application. If the application is file-based, the document is responsible for storing and restoring the application's data. Even if the application is not file-based, it must have a document class, even though that class doesn't do much apart from creating the application user interface (app UI). An app UI: the app UI is entirely invisible. It creates an application view (app view) to handle drawing and screen-based interaction. In addition, it provides the means for processing commands that may be generated, for example, by menu items. An app view: this is, in fact, a concrete control, whose purpose is to display the application data on screen and allow you to interact with it. In the simplest case, an app view provides only the means of drawing to the screen, but most application views will also provide functions for handling input events. Figure 4.2 Three of the four classes in a UIQ application are derived from base classes in Qikon which themselves are derived from Uikon classes. In applications written for other target machines, these three classes may be derived directly from the Uikon classes or from an alternative layer that replaces Qikon. In turn, Uikon is based on two important frameworks: CONE, the control environment, is the framework for graphical interaction. I'll be describing CONE in detail in Chapters 11 and 12. APPARC, the application architecture, is the framework for applications and application data, which is described in Chapter 13. Uikon provides a library of useful functions in its environment class, CEikonEnv, which is in turn derived from CCoeEnv, the CONE environment, and I've shown these in the diagram as well. Fortunately, the application can use these functions without the need to write yet another derived class. Remember that this is a diagram for a minimal application. The application is free to use any other class it needs, and it can derive and implement more classes of its own, but no GUI application can get smaller than this. More realistic UIQ applications that have more than one view, and want to take advantage of the view architecture, must additionally derive their view classes from CONE's MCoeView interface class. I haven't shown this relationship in the diagram because it isn't essential for a simple application with only one view. You will find more information on the view architecture in Chapter 9. In addition to the four C++ classes, you have to define elements of your application's GUI – the menu, possibly some shortcut keys, and any string resources you might want to use when localizing the application – in a resource file. In this chapter we'll briefly describe the simple resource file used for hellogui: we'll take a closer look at resource files in Chapter 7. Note The stated design goal of Symbian OS is to make real, potentially large, programs easier to write and understand. Compared with this aim, programming a minimal application really isn't very important. As a consequence, the document class in nonfile-based applications doesn't do much, and the idea that the app UI is there to 'edit the document' is a bit overengineered. Let's have a look at how the classes in hellogui implement the requirements of APPARC, Uikon, and CONE, and how the resource file is used to define the main elements of the GUI. 4.4 A Graphical Hello World 4.4.1 The Program Our example program for this section is hellogui, a graphical version of 'Hello world!'. With the aid of this example, you'll learn how to build an application for the Uikon GUI. Since the application is intended to run on a P800 phone, I've used UIQ classes instead of Uikon ones, but I'll point out the differences as they arise. It will take more time to learn how a GUI program works and in this chapter we'll only briefly comment on the C++ code itself. There's nothing particularly difficult about it, but it will be easier to cover how such programs use C++ when we have seen more of how Symbian OS C++ works. It's still worth getting to grips with the tools and techniques though, because we'll be using GUI programs to show off some of the basics of Symbian OS in the next few chapters. Despite all the differences in the code, the build process is similar to that for hellotext: we start with a .mmp file, turn it into the relevant makefile or project file, open up the IDE, build the program for the emulator and check that it works. Then we rebuild for an ARM target, copy to the target machine and run it there instead. There are, however, some important differences: GUI programs must be built in such a way that Symbian OS can recognize them and launch them. To ensure this, a program called hellogui must be built into a path such as \system\apps\hellogui\ hellogui.app. GUI programs use the Symbian OS unique identifier (UID) scheme to verify that they are Symbian OS GUI applications, and also to associate them, if necessary, with file types identified by the same UID. GUI programs consist not only of the executable .app file, but also GUI data in a resource file. In this example, we'll start by looking at the project file for hellogui.app. We'll do a command-line build for the emulator, to generate hellogui.app together with its resource file, hellogui.rsc. Then we'll show how you can build the project from the IDE. Finally, we'll build for an ARM target and transfer both files to a target machine using Symbian OS Connect. 4.4.2 The Project Specification File The project specification file for hellogui is as follows: // HelloGui.mmp // // Copyright (c) 2002 Symbian Ltd. All rights reserved. // TARGET HelloGui.app TARGETTYPE app UID 0x100039ce 0x101f74a8 TARGETPATH \system\apps\HelloGui SOURCEPATH \group USERINCLUDE \inc RESOURCE HelloGui.rss SOURCEPATH \src SYSTEMINCLUDE \epoc32\include SOURCE HelloGui.cpp SOURCE HelloGui_Application.cpp SOURCE HelloGui_AppUi.cpp SOURCE HelloGui_AppView.cpp SOURCE HelloGui_Document.cpp LIBRARY euser.lib LIBRARY apparc.lib LIBRARY cone.lib LIBRARY eikcore.lib LIBRARY qikctl.lib Compared with the .mmp file for hellotext, whose listing appears in Chapter 1, there are some interesting differences here: The TARGET is HelloGui.app, and TARGETTYPE is app – that is, an application. The build tools know what to do to make the right kind of executable in the proper target directory. This time, the UIDs are nonzero. The first one you have to enter is 0x100039ce, and in fact this is the same for all GUI applications. The second should be obtained by you from Symbian- I'll show how to do that shortly. The TARGETPATH specifies where HelloGui.app will be generated. On the emulator, the emulated z: drive's path will be used as a prefix, so \epoc32\release\winscw\udeb\z\system\apps\ hellogui\hellogui.app will be the path used for the emulator debug build. As well as a number of source files, a resource file- hellogui.rss-is included in the project. Many more .lib files are involved this time. In addition, as indicated by the SOURCEPATH and USERINCLUDE statements, the source files are distributed in different subdirectories of \scmp\hellogui. The C++ source files are in a\scmp\hellogui\ src directory, whereas the header files are in \scmp\hellogui\inc. A third subdirectory, \scmp\hellogui\group, contains the bld.inf component definition file, the .mmp file and the resource file, hel logui.rss. This is probably an overkill for such a simple project but it becomes increasingly helpful for larger and more complex projects. 4.4.3 Getting a UID Every GUI application should have its own UID. This allows Symbian OS to distinguish files associated with that application from files associated with other applications. A UID is a 32- bit number, which you get as you need from Symbian. Note Microsoft uses 128-bit 'globally unique IDs', GUIDs. Programmers allocate their own, using a tool incorporating a random-number generator and distinguishing numbers (such as network card ID and current date and time) to ensure uniqueness. Symbian OS uses 32-bit UIDs for compactness, but this rules out the random- number generation approach. That's why you have to apply for UIDs from Symbian. Getting a UID is simple enough. Just send an e-mail to uid@symbiandevnet.com, titled 'UID request', and requesting clearly how many UIDs you want – ten is a reasonable first request. Assuming your e-mail includes your name and return e-mail address, that's all the information Symbian needs. Within 24 hours, you'll have your UIDs by return e-mail. If you're impatient, or you want to do some experimentation before using real UIDs, you can allocate your own UIDs from a range that Symbian has reserved for this purpose: 0x01000000-0x0fffffff. However, you should never release any programs with UIDs in this range. Don't build different Symbian OS applications with the same UID – even the same test UID – on your emulator or Symbian OS machine. If you do, the system will only recognize one of them, and you won't be able to launch any of the others. 4.4.4 Building the Application To build a debug application for the emulator from the command line, we follow the same steps as with hellotext; from the directory containing the bld.inf file, type bldmake bldfiles abld build winscw udeb The output from the command-line build is broadly similar to that for hellotext, showing the same six basic stages: make -r -f "\EPOC32\BUILD\SCMP\HELLOGUI\GROUP\EXPORT.make" EXPORT VERBOSE=-s Nothing to do make -r -f "\EPOC32\BUILD\SCMP\HELLOGUI\GROUP\WINSCW.make" MAKEFILE VERBOSE=-s perl -S makmake.pl -D \SCMP\HELLOGUI\GROUP\HELLOGUI WINSCW make -r -f "\EPOC32\BUILD\SCMP\HELLOGUI\GROUP\WINSCW.make" LIBRARY VERBOSE=-s make -s -r -f "\EPOC32\BUILD\SCMP\HELLOGUI\GROUP\HELLOGUI\WINSCW\HELLOGUI.WINSCW" LIBRARY make -r -f "\EPOC32\BUILD\SCMP\HELLOGUI\GROUP\WINSCW.make" RESOURCE CFG=UDEB VERBOSE=-s make -s -r -f "\EPOC32\BUILD\SCMP\HELLOGUI\GROUP\HELLOGUI\WINSCW\HELLOGUI.WINSCW" RESOURCEUDEB make -r -f "\EPOC32\BUILD\SCMP\HELLOGUI\GROUP\WINSCW.make" TARGET CFG=UDEB VERBOSE=-s make -s -r -f "\EPOC32\BUILD\SCMP\HELLOGUI\GROUP\HELLOGUI\WINSCW\HELLOGUI.WINSCW" UDEB make -r -f "\EPOC32\BUILD\SCMP\HELLOGUI\GROUP\WINSCW.make" FINAL CFG=UDEB VERBOSE=-s When building has finished, the application will be in \epoc32\ release\winscw\udeb\z\system\apps\hellogui\. In Windows Explorer, you'll see hellogui.app and hellogui.rsc, which are the real targets of the build. This time, unlike for hellotext, you can't launch the application directly by (say) double- clicking on hellogui.app from Windows Explorer. Instead, you have to launch the emulator using \epoc32\release\winscw\udeb\epoc.exe. You'll find that hellogui is displayed as an application, and you can launch it by clicking on its icon. This is what it looks like. You can see the world-famous text in the center of the screen, together with a menu that happened to be popped up when I did the screenshot. 4.4.5 Building in the CodeWarrior IDE The main phase of real application development is writing, building, and debugging from within the Metrowerks CodeWarrior IDE – not the command line. To see how to build a GUI program from the IDE, let's start with a clean sheet. If you tried out the command-line build above, from the command line type: abld reallyclean which will get rid of all files from the build. (It may also report errors and issue not-found messages as it tries to get rid of files that might have been produced, but weren't.) You can then launch the IDE and select File | Import Project From.mmp File to build the CodeWarrior project file. Select the appropriate Figure 4.3 SDK and then browse to the \scmp\hellogui directory and select hellogui.mmp. Click on Finish and, after a short time, the hellogui.mcpCodeWarrior project will have been created. Select Project | Set Default Target and make sure that the HELLOGUI WINSCW UDEB target is selected, then select Project | Make (or press F7) to build the project. You should then be able to start up the winscw udeb emulator and run the application in exactly the same way as you did after building from the command line. 4.4.6 The Source Code From within the CodeWarrior IDE project window, check the source files for the project, and you'll see there are seven files. The first two are hellogui.pref, the source file generated by the IDE from the.mmp file, containing the UID information, and hellogui.resources, another generated file that references the source text file for the application's resources. There are also five C++ source files. The C++ source file hellogui.cpp simply contains two nonclass functions and the remaining four C++ files contain the source for the four classes that make up the application. For each of the five C++ source files, there is a corresponding .hheader file (in the \scmp\hellogui\inc directory). Again, for a project of this size, it is somewhat excessive to have a separate header file for each class but it makes it clearer, for demonstration purposes, which source is related to which class. Such a division becomes increasingly helpful, if not essential, for more complex projects – although you need to make a compromise between this type of clarity and the confusion that arises from having too many source files and too many header file inclusions. In a real application, you may want to use source files that contain collections of closely related classes, but that is a decision you'll have to make for yourself. At this stage, I don't want to get too involved in the details of the code, so I'll just concentrate on the essentials of what is needed to start up an application. You'll see that the code obeys the class naming conventions described in Chapter 3 but, for the moment, you can ignore things like the precise way in which the classes are instantiated and constructed. For the sake of completeness, the descriptions include references to first-phase and second-phase construction; these terms are explained in Chapter 6 and you might want to review the descriptions given here after reading that chapter. With that in mind, I'll run through the content of each of the source files and explain what it's doing. Then I'll sum up some of APPARC's features, and give some pointers to more information in the book. DLL startup code When you launch an application, the file that is launched is not your application, but one with the name apprun.exe. The application name and the application's file name are passed as command line parameters to apprun.exe, which then uses the APPARC to load the correct application DLL. Important Every Symbian OS application is a DLL. After loading the DLL, the application architecture: checks that its second UID is 0x100039ce, runs the DLL's first ordinal exported function to create an application object – that is, an object of a class derived from CApaApplication. As we've already seen, the build tools support the generation of application DLLs. In order to understand those last two bullet points, let's take a closer look at the important features of a .mmp file. For our application, hellogui.mmp starts: TARGET HelloGui.app TARGETTYPE app UID 0x100039ce 0x101f74a8 The app target type causes the build tools to generate instructions that force NewApplication() to be exported as the first ordinal function from the hellogui.app DLL. All GUI applications specify a UID 0x100039ce, which identifies them as applications, while UID 0x101f74a8 identifies my particular application, hellogui.app. I allocated this UID from a block of 10 that were issued to me by Symbian DevNet, as I described earlier in this chapter. Note I said above that 0x100039ce was the second UID for this application. The build tools helpfully generate the first UID for you, a UID that indicates that the application is in fact a DLL. The main purpose of the DLL-related code in hellogui.cpp is to implement NewApplication(): // DLL interface code EXPORT_C CApaApplication* NewApplication() { return new CHelloGuiApplication; } GLDEF_C TInt E32Dll(TDllReason) { [...]... course, using 4 bits for a descriptor identifier leaves 'only' 28 bits for the length and descriptor data is therefore constrained to around 25 0 million characters rather than 4 billion This is not a serious restriction for Symbian OS Space efficiency matters in Symbian OS Descriptors are space efficient and they allow you to be 5 .2 Modifying Strings Having compared the way C and Symbian OS handle constant... C:\METROTRK.INI 4 .11 .1 Configuration The METROTRK.INI file contains a number of configuration settings that you should modify to match your target hardware If the installation was from a product SDK, then this will already have been done for you, and you can skip to the 'Launching MetroTRK' section The METROTRK.INI file has the following content: [SERIALCOMM] PDD EUART1 LDD ECOMM CSY ECUART PORT 2 RATE 11 520 0 You... \Codewarrior for Symbian Pro v2.0\Bin directory Select the Change button From the Symbian MetroTRK dialog you can set the appropriate protocol settings Change the connection type to Serial The settings will typically be 11 5 20 0 baud, 8 data bits, No parity, 1 stop bit You should also change the serial port number to match the physical serial connection to your device This completes configuration settings for. .. thought that would be useful for allocating DLL-specific data in the early days of Symbian OS development In practice, however, it isn't called symmetrically in Windows, so it doesn't work under the emulator, and therefore, is pretty useless for Symbian OS development Furthermore, different versions of Symbian OS call E32Dll() a differing number of times and in slightly different circumstances, which... here is that had I got my array size wrong (for helloworld-stack) or my heap cell size wrong (for helloworldheap), I might have overwritten the end of the string It's not simply the irritation of having to add or subtract 1 for the trailing NUL – the real problem is that the string data might not fit into the memory allocated for it 5 .2. 2 Modifying Symbian OS Strings The strings example shows how to... MetroTrk for Symbian OS Version 1. 7 Implementing MetroTrk API version 1. 7 Press "Q" to quit 4 .13 Setting up the CodeWarrior IDE Now we need to configure the Remote Connection Settings in CodeWarrior: Select the Edit | Preferences menu item to open the IDE preferences window Select Remote Connections in the IDE Preference Panel window Select Symbian MetroTRK in the Remote Connections list If the Symbian. .. intended application areas as it does for Symbian OS Symbian OS is a kind of halfway house: you have to do your own memory management, but you can't overwrite memory beyond the end of a string and, if you try to, you'll find out about it very early in your debugging cycle So descriptors contribute significantly to the compactness and robustness of Symbian OS 5 .2. 3 Modifying HBufCs You might have thought... commands All Symbian OS- defined command IDs are in the range 0x 010 0 to 0x01ff My command constants are defined in hellogui.hrh, as follows: enum THelloGuiMenuCommands { EHelloGuiCmd0 = 0x1000, EHelloGuiCmd1, EHelloGuiCmd2 }; It's clearly important that the constants I choose should be unique with respect to Uikon's, so I started numbering them at 0x1000 – you're safe if you do this too To handle these commands,... the support they provide for manipulating strings 5 .2 .1 Modifying C Strings When you add something to the end of a string, you have to have enough room for the new text Note Doing this in program binaries isn't an option: they can't be modified if they're in ROM or even in a RAM-loaded Symbian OS DLL You can allocate enough space on the stack by declaring an array big enough for both strings: you can... necessary – in other customized Symbian OS UIs, they should be avoided, or used sparingly, in UIQ applications, in which menu content should be kept as short and simple as possible Note that the text for the EEikCmdExit command is 'Close(debug)' A UIQ application, by convention, does not have a close option in its menus, but – as mentioned earlier – relies on the APPARC to close down the application (by . the features of C++ that Symbian OS uses, those it avoids, and those it augments. We've also seen the coding standards that are used in Symbian OS. Specifically, we've seen the following:. 'Shortcut keys' is the style-guide-approved language for what most programmers call 'hotkeys'. We decided that 'hotkeys' was too ambiguous or frightening for. of Symbian OS development. In practice, however, it isn't called symmetrically in Windows, so it doesn't work under the emulator, and therefore, is pretty useless for Symbian OS development.