................... ...::: phearless zine #5 :::... ...............>---[ Writing Basic Symbian Application ]---<................ ...........................>---[ by argv ]---<.............................. argv.cpp[at]gmail[dot]com Sadrzaj: [1] Starting [2] Sources [3] Headers [4] Project Group [5] Compiled //////////////////////////////////////////////////////////////////////////// --==<[ 1. Starting \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ U ovom tutoru cu vam pokazati kako da napisete kostur za bilo koju aplikaciju. Ovaj kostur mozete koristiti za neke projekte koje cete kasnije raditi jer koristi sve potrebno za basic app. Sekcije sam podijelio po folderima koje projekt treba sadrzavati tako da se lako mozete snaci ako vam nesto kasnije zatreba. Ako ovaj app pisete rucno, morat cete staviti neke prefixe u sufixe u ime sourcea i headera, a ako koristite neko okruzje koje vec ima predefinirane, onda netrebate. Iako ta okruzja su uglavnom potpuno nepotrebna jer stvaraju dosta stvari koje uopce nisu potrebne i samo "zagusuju" foldere projekata. //////////////////////////////////////////////////////////////////////////// --==<[ 1. Sources \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Napravite folder "MyApp" i unutar tog foldera napravite slijedeca 4: src, inc, group i sis. Sve .cpp fajlove stavljate u src folder, headere u inc folder, compile info u group dok se compilani fajlovi buildaju u sis. Zapocet cemo sa osnovnim sourceom koji ce sluziti kao handle za pozivanje svih ostalih. Nazovimo ga MyApp.cpp i unutra stavimo: -- // MyApp.cpp #include "MyApp.h" // entry point za DLL GLDEF_C TInt E32Dll(TDllReason) { return KErrNone; } // napravi aplikaciju i pointaj EXPORT_C CApaApplication* NewApplication() { return (new CMyApp); } -- Ovaj kostur se koristi startanje 95% aplikacija, i uvijek ga mozete koristiti. Postoji jos nekoliko metoda, ali sve se svodi na isto, a ovaj je najjednostavniji. Sada moramo napraviti UID i pointer na "document" file od naseg projekta. UID ce se u vecini slucajeva sam generirati pa nije potrebno mozgati oko njega. Potrebno je staviti nesto samo pre-compile, a ostalo ce compiler sam napravit. Ovaj source ce se zvati "MyAppapplication.cpp". -- // MyApplication.cpp #include "MyAppDocument.h" #include "MyAppApplication.h" // UID za app static const TUid KUidMyApp = {0x1000000}; CApaDocument* CMyAppApplication::CreateDocumentL() { // stvaranje documenta i pointanje CApaDocument* document = CMyAppDocument::NewL(*this); return document; } TUid CMyAppApplication::AppDllUid() const { // vracanje UIDa za app return KUidMyApp; } -- Naravno, aplikacija mora imati i neki UI. Koristit cemo osnovni UI koji nam SDK pruza. Ako bas zelite neki fancy UI onda ce vam okruzja prilagodjena za to pomoci, ali kome to treba? :) Slijedeci source cemo nazvati "MyAppUi.cpp". Koristimo Avkon UI i Avkon wrappere. Source od menua koristi varijable iz resource fajlova, ali o tome nesto kasnije. -- // MyAppUi.cpp #include #include #include "MyApp.pan" #include "MyAppUi.h" #include "MyAppView.h" #include "MyApp.hrh" // ConstructL - pokretanje aplikacije (Avkon) void CMyAppAppUi::ConstructL() { BaseConstructL(); iAppView = CMyAppView::NewL(ClientRect()); AddToStackL(iAppView); } CMyAppUi::CMyAppUi() { // ne radimo nikakve fancy stvari pa nam ovo netreba } CMyAppUi::~CMyAppUi() { if (iAppView) { RemoveFromStack(iAppView); delete iAppView; iAppView = NULL; } } // nas menu void CMyAppAppUi::HandleCommandL(TInt aCommand) { switch(aCommand) { case EEikCmdExit: case EAknSoftkeyExit: Exit(); break; case EMyAppCommand1: { _LIT(message,"MyApp Message :)"); CAknInformationNote* informationNote = new (ELeave) CAknInformationNote; informationNote->ExecuteLD(message); } break; default: Panic(EMyAppBasicUi); break; } } -- Slijedece cemo pokazati nas interface. U proslom sourceu smo ga izgradili. Takodjer cemo koristiti Avkon, ali ovaj put moramo koristiti i interne kontrole iz coemain.h (ala buttoni i stuff u Win32). Nazovimo ovaj fajl "MyAppView.cpp". -- // MyAppView.cpp #include #include "MyAppView.h" // standardna izgradnja iz Avkona - uvijek ovo mozete koristiti CMyAppView* CMyAppView::NewL(const TRect& aRect) { CMyAppView* self = CMyAppView::NewLC(aRect); CleanupStack::Pop(self); return self; } CMyAppView* CMyAppView::NewLC(const TRect& aRect) { CMyAppView* self = new (ELeave) CMyAppView; CleanupStack::PushL(self); self->ConstructL(aRect); return self; } CMyAppView::CMyAppView() { // ovo je za fancy UI, nama netreba } CMyAppView::~CMyAppView() { // isto } void CMyAppView::ConstructL(const TRect& aRect) { // stvaranje prvog prozora CreateWindowL(); // velicina prozora (ovo se automatski generira) SetRect(aRect); // aktivacija prozora ActivateL(); } // pokazivanje naseg prozora na zaslonu void CMyAppView::Draw(const TRect&) const { // standardna grafika iz coe.h kontrola CWindowGc& gc = SystemGc(); TRect rect = Rect(); // clear za ciscenje messagea gc.Clear(rect); } -- I zadnje sto name je potrebno je dokument. Ovo je mandatorno jer koristi Symbianove construct metode i program se nece pokrenuti bez toga. Nazovimo fajl "MyAppDocument.cpp" -- // MyAppDocument.cpp #include "MyAppUi.h" #include "MyAppDocument.h" // pokretanje bilo koje Symbian aplikacije CMyAppDocument* CMyAppDocument::NewL(CEikApplication& aApp) { CMyAppDocument* self = NewLC(aApp); CleanupStack::Pop(self); return self; } CMyAppDocument* CMyAppDocument::NewLC(CEikApplication& aApp) { CMyAppDocument* self = new (ELeave) CMyAppDocument(aApp); CleanupStack::PushL(self); self->ConstructL(); return self; } void CMyAppDocument::ConstructL() } } CMyAppDocument::CMyAppDocument(CEikApplication& aApp) : CAknDocument(aApp) { } CMyAppDocument::~CMyAppDocument() { } CEikAppUi* CMyAppDocument::CreateAppUiL() { // stvaranje interfacea CEikAppUi* appUi = new (ELeave) CMyAppAppUi; return appUi; } -- //////////////////////////////////////////////////////////////////////////// --==<[ 3. Headers \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Headere stavljate u inc folder. Prvo cemo napraviti resource fajlove koje ce nas interface koristit. Napravite fajl "MyApp.hrh" i ubacite unutra: -- // MyApp.hrh #ifndef __MyApp_HRH__ #define __MyApp_HRH__ enum TMyAppIds { EMyAppCommand1 = 1 }; #endif -- Zatim napravite fajl "MyApp.pan" (panic modul) i ubacite: -- // MyApp.pan #ifndef __MyApp_PAN__ #define __MyApp_PAN__ enum TMyAppPanics { EMyAppBasicUi = 1 }; inline void Panic(TMyAppPanics aReason) { _LIT(applicationName,"MyApp Message :)"); User::Panic(applicationName, aReason); } #endif -- Sada krecemo sa headerima. Headeri nece koristi nista svemirsko =) nego najobicnije callove iz vec predefiniranih Symbianovih fajlova. Moramo napraviti header za svaki source u kojem smo ga zvali. Pocet cemo sa "MyAppApplication.h": -- // MyAppApplication.h #ifndef __MyApp_APPLICATION_H__ #define __MyApp_APPLICATION_H__ #include class CMyAppApplication : public CAknApplication { public: TUid AppDllUid() const; protected: CApaDocument* CreateDocumentL(); }; #endif -- Zatim idemo na "MyAppUi.h": -- // MyAppUi.h #ifndef __MyApp_UI_H__ #define __MyApp_UI_H__ #include class CMyAppAppView; class CMyAppAppUi : public CAknAppUi { public: void ConstructL(); CMyAppAppUi(); ~CMyAppAppUi(); public: void HandleCommandL(TInt aCommand); private: CMyAppAppView* iAppView; }; #endif -- Slijedece dolaze coe.h kontrole (iscrtavanje prozora). "MyAppView.h": -- // MyAppView.h #ifndef __MyApp_VIEW_H__ #define __MyApp_VIEW_H__ #include class CMyAppAppView : public CCoeControl { public: static CMyAppAppView* NewL(const TRect& aRect); static CMyAppAppView* NewLC(const TRect& aRect); ~CMyAppAppView(); public: void Draw(const TRect& aRect) const; private: void ConstructL(const TRect& aRect); CMyAppAppView(); }; #endif -- I zadnje nam je ostalo "MyAppDocument.h": -- // MyAppDocument.h #ifndef __MyApp_DOCUMENT_H__ #define __MyApp_DOCUMENT_H__ #include class CMyAppAppUi; class CEikApplication; class CMyAppDocument : public CAknDocument { public: static CMyAppDocument* NewL(CEikApplication& aApp); static CMyAppDocument* NewLC(CEikApplication& aApp); ~CMyAppDocument(); public: CEikAppUi* CreateAppUiL(); private: void ConstructL(); CMyAppDocument(CEikApplication& aApp); }; #endif //////////////////////////////////////////////////////////////////////////// --==<[ 4. Project Group \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Da bi uspjesno compilali program, potrebno je napraviti grupe koje ce compiler koristit da bi pronasao fajlove potrebne za compile. Prvo napravite fajl "bld.inf" i unutra ubacite: -- // bld.inf PRJ_MMPFILES MyApp.mmp -- Ovo nam sluzi kao pointer compileru da koristi informacije iz MyApp.mmp fajla. Zatim napravite "MyApp.mmp" file koji ce sadrzavati pathove do nasih fajlova i instrukcije gdje i sta da compiler napravit. -- // MyApp.mpp TARGET MyApp.app TARGETTYPE app UID 0x10000000 0x10000001 TARGETPATH \system\apps\myapp LANG SC SOURCEPATH ..\src SOURCE MyApp.cpp SOURCE MyAppApplication.cpp SOURCE MyAppAppView.cpp SOURCE MyAppAppUi.cpp SOURCE MyAppDocument.cpp SOURCEPATH ..\group RESOURCE MyApp.rss USERINCLUDE ..\inc SYSTEMINCLUDE \epoc32\include LIBRARY euser.lib LIBRARY apparc.lib LIBRARY cone.lib LIBRARY eikcore.lib LIBRARY avkon.lib -- Jos nam je samo potreban resource fajl. Nazovimo da "MyApp.rss": -- // MyApp.rss NAME MAPP #include #include #include #include #include "MyApp.hrh" RESOURCE RSS_SIGNATURE { } RESOURCE TBUF r_default_document_name { buf=""; } RESOURCE EIK_APP_INFO { menubar = r_MyApp_menubar; cba = R_AVKON_SOFTKEYS_OPTIONS_EXIT; } RESOURCE MENU_BAR r_MyApp_menubar { titles = { MENU_TITLE {menu_pane = r_MyApp_menu;} }; } RESOURCE MENU_PANE r_MyApp_menu { items = { MENU_ITEM {command = EMyAppCommand1; txt = "Start";}, MENU_ITEM {command = EAknSoftkeyExit; txt = "Exit";} }; } -- //////////////////////////////////////////////////////////////////////////// --==<[ 5. Compiled \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ U sis folderu napravite file "MyApp.pkg" koji ce posluziti kao pointer gdje se i koji fajlovi trebaju compilati: -- // MyApp.pkg &EN #{"MyApp"},(0x10000000),1,0,0 (0x101F6F88), 0, 0, 0, {"Series60ProductID"} "..\..\..\epoc32\release\thumb\urel\MyApp.APP"-"C:\system\apps\MyApp\MyApp.app" "..\..\..\epoc32\release\thumb\urel\MyApp.rsc"-"C:\system\apps\MyApp\MyApp.rsc" -- Nakon compilea dobit cete MyApp.app i MyApp.rsc. Napravite direktorij na telefonu na C:\system\apps\MyApp\ i kopirajte ta 2 filea unutra. U glavnom meniju ce se pokazati MyApp s ikonom puzzle i kad ga pokrenete dobit cete osnovni interface sa 2 opcije - Start i Exit. Start ispisuje message dok Exit izlazi (d0h=).