Sei sulla pagina 1di 110

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.

com

Page1of110

GettingStartedwithGambas Version2:ATutorial
Subject: Author: FileName: Version: LearningVisualBasicwithLinuxandGambas TimothyMarshalNichols GettingStartedwithGambasTutorial.odt 1.0(Revision:193) Sunday28May2006

Contents
1:Introduction.....................................................................................................................................2 1.1:GAMBasAlmostMeansBasic.................................................................................................2 1.2:Projects......................................................................................................................................4 1.3:GambasResources....................................................................................................................5 1.4:License......................................................................................................................................6 1.5:Acknowledgments.....................................................................................................................6 2:YourFirstGambasProject:SimpleEdit...........................................................................................7 2.1:Creatingtheproject...................................................................................................................7 2.2:Creatingtheuserinterface......................................................................................................13 2.3:Addingthecode......................................................................................................................18 2.4:Runningtheproject.................................................................................................................23 3:DrawingProject:ImageShow........................................................................................................28 3.1:Creatingtheproject.................................................................................................................28 3.2:Creatingtheuserinterface......................................................................................................29 3.3:AddingtheCode.....................................................................................................................37 3.4:Runningtheproject.................................................................................................................52 4:DatabaseProject:Notations..........................................................................................................56 4.1:Creatingtheproject.................................................................................................................59 4.2:Creatingtheuserinterface......................................................................................................64 4.3:CheckingouruserinterfaceforCRUD...................................................................................75 4.4:Addingthecode......................................................................................................................77 4.5:Runningtheproject.................................................................................................................99 4.6:SwitchingtoaMySQLorPostgreSQLDatabase.................................................................102 5:Appendix1:DatabaseCommandswithExecandSQL..............................................................104

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page2of110

1:

Introduction

ThisisasimpleGettingStartedwithGambasTutorial.Itisintendedforfirsttimeprogrammerswho wanttogainsomeideaofthecapabilitiesofGambas.Youcanthenseeifthisisthedevelopment environmentthattheywouldliketolearnmorefully.ItwillalsobeusefulforVisualBasic programmerswhoaremovingfromWindowstoLinux. TraditionallyonUnixbasedsystemslikeLinuxyouusedanumberoftoolstodevelopan application.Soyouusedacodeeditor,possiblyauserinterfacedesigner,acompilerandothertools. Youpreformedeachstageofthedevelopmentprocesswiththerelevanttool.Thisprocesscanwork, afterallmuchofLinuxwasbuiltthisway.Itdoeshavetheadvantagethatifyoudonotlikeonetool thenyoucanreplacejustthattoolwithsomethingyoudolike.Butitcanalsohavethedisadvantage ofcompatibilityissueswhentheoutputofonetooldoesnotfittherequiredinputforanothertool.It alsomakesitdifficultfornewdeveloperstolearntherequiredstepstoproduceprofessionallooking application.ToovercometheseproblemstherearenowanumberofIntegratedDevelopment Environment(IDE)forLinux.IDE'sincludeallthetoolsyouneedtodevelopapplicationswithin oneframework.Theyhavebeenverypopularonotheroperatingsystemsanddevelopersmovingto LinuxexpecttofindsimilarIDE's.TwoofthemostusedIDE'sonLinuxareKDevelopand MonoDevelop.KDevelopisanIDEforcreatingCandC++applicationsandforusingscripting languages.MonoDevelopisanIDEfordeveloping.NETapplicationusinglanguageslikeC#and VisualBasic.NETandothers. GambasisaIDEforVisualBasiconLinux.YoucanbuildmostkindsofLinuxapplicationwith Gambas.HoweverGambasisespeciallystrongatprovidingGraphicalUserInterfaces(GUI)types ofapplications.Theycanbestandaloneapplicationsorfrontendstoaserverordatabase.Gambas providesallthetoolsyouwouldnormallyexpectinaIDE.Ithasaformdesignerwhereyoucan dragcontrolsandcomponentsontoyourformstodevelopyouruserinterface.Italsohasaproject manager,acodeeditor,acodeexplorerandanintegratedhelpsystem.Youcanalsocompile,run anddebugyourapplicationsfromwithinGambas.ItisopensourceandsofitsinwiththeLinux philosophy. Gambasalsohasastrongusercommunity.Thereareanumberofusefulforumswherenewusers cangethelp.ThereisanactiveGambasmailinglist.IftherearebugswithGambasthen,inmy experience,theyarerapidlycorrected.SeetheGambasResourcessectionbelow. GambasisdefinitelyaVisualBasicforLinux.ItisnotsimplyaportofMicrosoftVisualBasicto Linux.HoweverWindowsusersofVisualBasic(atleastuptoversion6)willfindmuchinthis environmentthatisfamiliar.

1.1: GAMBasAlmostMeansBasic
BASICstandsforBeginner'sAllPurposeSymbolicInstructionCode.Thislanguagewasdeveloped byJ.KemenyandT.KurtzatDartmouthCollegetoteachbeginnerprogrammers.Eversinceithas

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page3of110

provedtoausefulfirstlanguageforbeginnerstolearn.BASICbecameverypopularwhenpersonal computers(PC's)firstappearedinthe1970's.Thesmalloverheadsofthelanguageandtheeaseof learningmadeitthelanguageofchoicefornewprogrammerswiththeirfirstPC.Microsoft understoodthisandshippedQuickBASICforMSDOS. AlanCooperiscreditedasthe'father'ofVisualBasicandsoldtheideatoMicrosoft.Microsoftalso learnedfromHyperCardontheMacandin1991launchedVisualBasic1.0.Butitwasnotuntil Windows3.0andVisualBasic3.0thatthisreallybecamepopular.Sincethenithasbecameoneof themostdominantdevelopmentenvironment,bothinthehomeandinindustry. TherehavebeenversionsoftheBASIClanguageforalmostalloperatingsystemsandLinuxisno exception.TherehavebeenQuickBASIClikeUnix/Linuxversions.Therearealsoversionsof VisualBasicforLinuxlikeHBasicandKBasic.Formoreinformationandexamplessee http://www.thefreecountry.com/compilers/basic.shtml.Arguablythemostdevelopedandusableof theVisualBasicsforLinuxisGambas. GambaistheSpanishforprawn.GambasisalsoanVisualBasicIDEdesignedbyBenoit Minisini.ThefirstpublicreleaseofGambaswasVersion0.20inFebruary2002.Therethen followedagreatdealofdevelopmentworkandreleases.ThefirststablereleaseofGambaswas Version1.0inJanuary2005.Sincethentherehavebeenanumberofbugfixestothestableversion. AlsoinJanuary2005camethereleaseofthenewdevelopmentversionofGambas(verion1.9.1). Thisversionwilleventuallybecomethestableversion2.0. AllversionofGambasareissuedundertheGNUGeneralPublicLicenseandarefreetouse.Italso meanstheGambasruntimeisfreetouseifyouneedtoinstallitonacustomersworkstation.As Gambasisopensourceyoucanobtain,lookatand,ifyouneedto,modifythesourcecode.Alsothe GambasIDEiswritteninGambas. InthistutorialweareusingthelatestdevelopmentversionofGambas.Atthetimeof writingthelateststableversionis1.0.16(2May2006)andthelatestdevelopment versionis1.9.28(29April2006). MostofwhatiswrittenhereshouldworkonthestableversionofGambas.Where changesareneededyoushallseeanotelikethis.Lookforthesymbolontheleft. AlsointheexampleprojectsthatarepartofthistutorialthereareversionsforGambas1 and2. AllofthescreenshotsinthistutorialarefromGambasversion2.Someofthescreens maylookslightlydifferentinGambasversion1ornewerinstallsofversion2. IhavebeenusingthedevelopmentversionofGambasforaboutsixmonthsatthetimeofwriting thistutorial.IwouldsaythatGambasismorestablethanMicrosoftVisualBasic6.Ihavehadfewer crasheswiththedevelopmentversionofGambasthanwithproductionreleaseofVB6.Itisproperly justasstableasMicrosoftVisualBasic.NET(boththe.NETruntimes1.0and1.1)whichIhave alsousedquiteextensively.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page4of110

1.2: Projects
Inthistutorialweshalldevelopthreeprojectsthatdemonstratesomeofthetypesofapplications thatcanbebuiltwithGambas.

SimpleEdit .Asimpletexteditor.Thisisasimplefirstapplicationtodemonstrateusingthe developmentenvironment.Itwillshowhowbyusingsomeofthecomponentsfromthetool boxandwithalittlecodingyoucanbuildausableapplication. ImageShow. Aimagedisplayprogramforplayingaslideshowofimagesfromaselected directory.ThisapplicationdemonstratssomeofthedrawingfunctionsinGambas. Notations. Aprojectforeditingandstoringusernotes.Thisprojectdemonstrateshowto createauserinterfacetoadatabase.Theapplicationwillalsocreatethedatabaseifitdoes notexist.Youcanthencreate,read,updateanddeleterecordsinthedatabase.

Thefollowingscreenshotshowsallthreeapplicationsinaction.

OneissueIamnotgoingtodealwithinthistutorialisinstallingGambasitself.Installing applicationsonLinuxcanbecomeheftychapterinitself.LookattheResourcessectionofthis introductionforlinkswereyoucanfindmorehelpandinformation.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page5of110

1.3: GambasResources
ThesearesomeofthewebsiteswhereyoucanfindmoreinformationaboutGambas.Youmayneed someoftheselinkstocompletethistutorialifyourLinuxdistributionhasnotincludedallthe requiredresources.NewsourcesofinformationaboutGambasarecomingonlineallthetime. IndeedIhavehadtoadditemstothislistanumberoftimeswhilewritingthistutorial.Ijustkeep discoveredmoreinformationaboutGambasontheweb.Asalwayswithweblinkstheycanbecome outofdatefastthesewerevalidinMay2006.

Gambas: TheGambasshrine SourceforgepageforGambasdownload TheGambashelpWiki GambasWikiBooktextbook GermanGambasWikiBook http://gambas.sourceforge.net/ http://gambas.sourceforge.net/download.html http://www.gambasdoc.org/ http://en.wikibooks.org/wiki/Gambas http://de.wikibooks.org/wiki/Gambas

YoucansubscribetotheGambasmailing https://lists.sourceforge.net/lists/listinfo/gambasuser listhere: ItalianGambassite GambasForums: LinuxBasic MyGambasCommunity GermanGambasClub SitiowebdeGambas(InSpanish) MoreLinks: SQLite MySQL PostgreSQL TangoDesktopProject GNULicenses MonoVisualBasic.NET FreeBASICCompilersandInterpreters http://www.sqlite.org/ http://www.mysql.org/ http://www.postgresql.org/ http://tangoproject.org/ http://www.gnu.org/licenses/ http://www.monoproject.com/Language_BASIC http://www.thefreecountry.com/compilers/basic.shtml http://www.linuxbasic.net/ http://forum.stormweb.no/ http://gambasclub.de/ http://gambas.gnulinex.org/ http://www.gambas.it/

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page6of110

1.4: License
Youarefreetousethecontentofthistutorialandexamplesourcecodeasyouwish.Alsoyoucan distributethistutorialtowhoeveryouwish.Iwouldrequestthatyouacknowledgetheauthorand alsomakesurethesourcecodeforexampleapplicationsisfreelyavailable(bothforVersions1and 2ofGambas).Butyouarenotforcedtothis.ThetextofthistutorialisissuedundertheTheGNU FreeDocumentLicense.Alloftheapplicationsandcodeexamplesfromthistutorialareissued undertheTheGNUGeneralPublicLicense2.Fordetailsseehttp://www.gnu.org/licenses/.

1.5: Acknowledgments
ManythankstoRohnnyStormoatMyGambasCommunityforcheckingoverthistutorial.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page7of110

2:

YourFirstGambasProject:SimpleEdit

Outfirstprojectisgoingtobeasimpletexteditor.Asastartingpointthismayseemalittle ambitiousforsomeonewhohasneverprogrammedinGambasbefore.Admittedlyourtexteditoris notgoingtobeasfullfeaturedassomeeditorsyoumayhaveused.Butstillitwillbeausabletext editor.Thisprojectshowsthepowerofamoderndevelopmentenvironment.Byusingthe functionalityofprebuiltcomponentsitiseasytobuildsomeusableapplicationsquickly. WithSimpleEdityoucandomanyofthethingsyoucandowithanyothertexteditor.Youcanopen andsavetextdocuments.Youwillhavetowriteabitofcodetoachievethis.ButtheTextArea componentwearegoingtousealsogivesusalotoffunctionality.Thisincludesbeingabletocut, copyandpastefromtheclipboard.Italsogivesusanundofacility.Andwedonothavetowriteany codetoincludethisfunctionalityinourapplication. InthisfirstprojectforGambaswearegoingtoprovidedetailedscreenshotsformostofthesteps. Inthelaterexampleprojectsweshallassumeyoudonotneedsomanyscreenshots.Youcanalways referbacktothisproject.

2.1: Creatingtheproject
ThefirststepistocreateanewGambasproject.SoopenGambasandandselectNewproject.... Thiswillstartthenewprojectwizard.Thefirstpageofthewizardsimplyshowsawelcomescreen withdetailsofhowtousethenewprojectwizard.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page8of110

ClicktheNext>>buttonforthenextpageofthewizard.Thisshowsapagewereyoucanselectthe typeofGambasprojectyouwanttobuild.Thetypesofprojectsinclude:

Agraphicalproject.Asthisisthemostoftenusedoptionanditisthedefaultoption.This typeofapplicationwouldhavewindowswithwhichtheuserinteracts.Itwouldbe controlledbythemouseand/orthekeyboard. Aterminalproject.Youwouldrunthistypeofprojectfromaterminalwindow.Youcan readandwritedatatostandardinput,errorandoutput.Itwillacceptparametersfromthe terminalandalltheotherthingyouwouldexpectfromacommandlineapplication. Copyanexistingproject.Youusedthisoptionifyouwanttocloneanexistingprojectto useasthestartingpointforanewGambasproject. ImportaVBproject.HereyoucanimportaprojectcreatedwithMicrosoftVisualBasic.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page9of110

Wearegoingtousethedefaultoptionofagraphicalproject.SoclicktheNext>>button.This showsapagewhenyouenterthenameandtitleforyourprojectwearegoingtocreate.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page10of110

EnterthenameofSimpleEditandthetitleofAsimpletexteditor.Leavetheother optionsunchecked.ClickontheNext>>button.Thisshowsapagewhereyouselectthedirectory whereyouwanttosavetheprojectfiles. Thefollowingscreenshotshowssavingyourprojecttothedocumentsdirectory.Thisis simplytoillustratethedialogue.Howeveritmightbeeasiertosetupadirectorywhere yousaveallyourGambasprojects.Youcouldthenstoreallyourprojectinonelocation. Thiswouldthenmakemanagingyourprojectseasier.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page11of110

Selectthelocationwhereyouwanttosavetheproject.ThenclicktheNext>>button.Thisfinal pageofthewizardliststheoptionsyouhaveselectedfortheproject.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page12of110

Checkthroughtheoptionsandthenclickthe OKbutton.WehavecreatedanewVisualBasic projectandGambaswillopenshowingthe Gambasprojectmanager. Gambaswillalsoopentwootherwindows.One isaToolbox.Thisshowssomeofthecontrols wecanuseinourprojects.Theotheristhe Propertieswindow.Thisiswheretheproperties ofcontrolsinyourprojectcanbeedited.Aswe havenotcreatedanycontrolsyetitwillbe blank.

IftheisthefirsttimeyouhaverunGambasyoumayseetwootheritems.Thefirstisa TipofthedaywindowandtheotheristheGambasmascot. OntheTipofthedaywindowthereisaClosebuttontohidethiswindow.Alsoifyou donotwanttoseethiswindoweachtimeyoustartGambasthenthereisacheckbox labelledShowtipsonstartupmakesureitisunchecked.IfyouwanttoseetheTipof

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page13of110

thedaywindowagaintheselectthe?(help)menuintheGambasprojectmanagerand thentheTipofthedayoption. TheotheritemyoumightseeistheGambasmascot.Somepeoplelikethisandothers donot.Youcanselectwhetherthisisshownornot.IntheGambasprojectmanager selecttheToolsmenuandthenthePreferences...option.Thiswillshowadialogue wheremanyofthesettingsfortheGambasuserinterfacecanbechanged.Selectthe Otherstab.IntheMiscellaneoussectionthereisacheckboxwhereyoucanselectif theMascotisshownornot.IfyouselectnottoshowtheMascotitwilllooksad.

2.2: Creatingtheuserinterface
NowwehaveaGambasproject.Thenextstepistoaddsomeelementstotheprojecttogiveusa userinterface.Thisprojectwillhaveonewindow.Mostofthiswindowwillbetakenupwitha TextAreacontrol.Byusingthiscontrolwegetmostofthefunctionsforourtexteditor.Thewindow willalsohavetwobuttonatthetopofit.Withthesebuttonsyouwillbeabletoopenandsave documentsfromtheTextArea. RightclickintheGambasproject manager.Thisbringsupapopup menu.FromthelistselectNew.This showsasubmenuwiththeitemswe canaddtoourproject.Weneedtoadd aFormtoactasthemainwindowto ourapplication.SoselectForm...from thismenu.

Thismenuoptionshowsadialoguewherewecandefinesomeofthepropertiesoftheformweare goingtocreate.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page14of110

GivetheformthenameofFormMain andaccepttheotherdefaultoptions. Thestartupclassistheclassthe Gambasruntimewillfirstloadwhen theapplicationisstarted.Therecan onlybeonestartupclassinyour project.Wewantthisformtobethe startupclasssomakesurethisoptionis checked.Leavealltheotheroptions unchecked.NowclicktheOKbutton tocreatetheform.TheGambasproject managershouldnowlooklikethe screenshotontheleft.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page15of110

Wenowneedtoaddsomecontrolsontotheformwehavejust created.Firstweshalladdtwobuttons.Makesuretheformwe havejustcreatedisvisible.Ifitisnotthendoubleclickontheform intheprojectmanager.AlsomakesuretheToolboxisvisible.Ifit isnotthenselecttheprojectmanagerViewmenthenToolboxsub menuorpresstheF6key. Thetoolboxhasseveraltabsthatgroupthekindsofcontrolswe canuse.MakesuretheFormtabisselected.Whenyoumovethe mouseoveritemsinthetoolboxthetooltipchangestoshowthe typeofobject.SelecttheButtoncontrolinthetoolbox. PlacetwoButtonsatthetopoftheformwindow.Youcandrag anddropitemsfromthetoolboxontoaformdesignerwindow.It ismucheasiertodothanitistodescribehowtodoit!

NowdothesamethingwithaTextArea.PlacetheTextArea undertheButtons. MakesuretheTextAreaispusedupunderthetwoButtonsandon thefarleftoftheform, InGambasversion1youwillseeonlyonetabforall thecontrols.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page16of110

YourFormMainshouldnow looksomethinglikethescreen shotoftheleft.Theexactsize oftheTextAreadoesnotmatter solongasthetop,leftposition iscorrect.Thisisbecausewe aregoingtoresizethis TextAreaatruntime. Thecontrolswillhavetheir defaultname.Howeverthese defaultnamesdonotgiveand informationabouthowwe intendtousethem.Itisgood programmingpracticeto changetheirnamesto somethingmeaningfulforour application.Thiswaywewill writeselfdocumentingcode.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page17of110

Wearenowgoingtochangesomeoftheproperties ofthesecontrols.Ifthepropertieswindowisnot visiblethenselecttheprojectmanageViewmenu thenthePropertiessubmenuorpresstheF4key. NowclickonButton1intheformdesigner.Thiswill showthepropertiesforthisbutton.Wearegoingto changetheNamepropertytoButtonOpenandthe TextpropertytoOpen... Nowweshallchangethesomepropertiesforthe othercontrolsontheform.ClickonButton2inthe formdesigner.Thiswillshowthepropertiesfor Button2.WearegoingtochangetheNameproperty toButtonSaveandtheTextpropertytoSave... FinallyclickonTextArea1intheformdesigner.We aregoingtochangetheNamepropertyto TextAreaEditandthendeletethetextintheText property.InotherwordsmaketheTextproperty empty.

FinallyweshallchangeonepropertyontheForm.ClickontheformthenchangetheBorder propertytoResizeable.Thefollowingtablelistthepropertieswehavechanged. DefaultName FormMain Button1 Button2 TextArea1 Property Border Name Text Name Text Name Text NewValue Resizeable ButtonOpen Open... ButtonSave Save... TextAreaEdit <none>

Ourformshouldnowlooklikethefollowingscreenshotwhenviewedintheformdesigner.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page18of110

Thatallweneedtodowiththeformdesigner.Inmanywaysitishardertodescribewhattodothan doit.WecanseehoweasyitistobuildauserinterfaceinGambas.

2.3: Addingthecode
Itisnowtimetoaddsomecode.Infactwewedonotneedtoaddverymuchcode.Allweneedto handleareresizingtheTextAreawhentheformisresized.Wealsoneedtohandleopeningand savingatextfilewhentheuserclicksononeofthebuttons. InVisualBasicyouwritecodetohandleevents.Eventsoccurwhensomethinghappenstoacontrol orobject.Thecontrolorobjectfirestheeventtoallowothercontrolsorobjectstorespondanddo somethingwhentheeventhappens.Foraformobjectpossibleeventsinclude:

Whentheformisopened Whenakeyispressed Whentheformgetclickedbytheuser Whentheformisclosed

Alongwithmanyotherevents.Forabuttonpossibleeventsincludewhenitisclickedbytheuser

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page19of110

andwhenitisdoubleclicked.InVisualBasicyouwritecodetohookuptheeventsfiredbycontrols orobjectstotheactionsyouwantyourapplicationtoperform. WhenyoudoubleclickonacontrolorformintheFormdesigneritshowsthedefaulteventhandler forthatobjectinthecodeeditor.Ifthecodedoesnotexistforthedefaulteventhandleritiscreated foryou.ForaformthedefaulteventisForm_Open.Forthisapplicationwedonotneedtodo anythingwhenthiseventisfired.Howeverwedoneedtoaddaneventhandlerforthe Form_Resizeevent. Toaddtheformresizingevent handlerrightclickontheform. (Makesureyourightclickon theform,notontheTextArea oroneoftheButtons.)This willshowapopupmenu.From thismenuselectEvent.This willshowasubmenuofallthe eventsyoucouldhandlethat aregeneratedbytheform. SelectResizefromthissub menu. Thiswilladdastubforthe Form_Resizeeventtothe codeintheformsclass.Now weshalladdtheeventhandlers forthebuttonclickevents.As theclickeventisthedefault eventforthebuttonitismuch simplertoadd.IntheGambas formdesignerDoubleclickon theButtonOpenbuttontoadd theButtonOpen_Click event.Finallydoubleclickon theButtonSavebuttontoadd theButtonSave_Click event. Thesearealltheeventswewanttohandleinthisapplication.Attheendofcreatingtheevent handlestheGambascodeeditorshouldlooksomethinglikethefollowingscreenshot.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page20of110

Nowweshalladdthecodefrom thefollowinglistingtotheseevent stubs.Notethat iconinthe followinglistingmeansthatthisis acontinuationofthepreviousline. HencefortheForm_Resize eventneedonlyaddonelineof code.Soenterthefollowingcode intothecodeeditor.

FormMain.class 'Gambasclassfile PUBLICSUBForm_Resize() TextAreaEdit.Resize(ME.ClientWidth,ME.ClientHeight TextAreaEdit.Top) END PUBLICSUBButtonOpen_Click() IFDialog.OpenFile()THENRETURN TextAreaEdit.Text=File.Load(Dialog.Path) CATCH Message.Error(Error.Text) END PUBLICSUBButtonSave_Click() IFDialog.SaveFile()THENRETURN

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com File.Save(Dialog.Path,TextAreaEdit.Text) CATCH Message.Error(Error.Text) END

Page21of110

Youmightbewonderingwhatsomeofthiscodedoes.Soletslookindetailatthiscode.Inthefirst procedureweresizetheTextAreawhenevertheformisresized.Thisresizeeventalsooccurswhen theformisfirstcreatedsowedonothavetoaddextracodetohandlethiscase. Thefirstlineofcodetellsuswearegoingtohandletheformresizeevent.Thenameforevent handlershavethefollowingformat:


Thenameoftheobjectthatfirestheevent Anunderscore Thenameoftheevent

SoherewearesayingwearegoingtohandletheResizeeventontheFormobject. PUBLICSUBForm_Resize() WethencalltheResizemethodontheTextArea.HerewetelltheTextAreawhatsizewewantitto be. TextAreaEdit.Resize(ME.ClientWidth,ME.ClientHeight TextAreaEdit.Top) TheResizemethodtakesparametersthatsetthewidthandheightoftheTextArea.Wecalculatethe sizebaseduponthesizeofthecurrentform.MEstandsforthecurrentobject,inthiscasethecurrent form.NotethatweuseClientWidthandClientHeightwhenwegetthesizeofthecurrent form.TheClientXXXpropertiesalwaysgivethecorrectsize.TheformalsohasWidthand Heightproperties.Butthevaluetheyreturndependsonwhethertheformismaximised.Sothey mightnotreturnthevalueyouexpect.Alsowewanttoleavespaceatthetopoftheformsothatour buttonsarevisible.SowehavetodeductthevalueforthetopoftheTextAreafromtheheightofthe form. Thefinallinefortheproceduresignalswherethecodefortheeventends. END Thenextlinetellsuswearehandlingtheclickeventfortheopenfilebutton. PUBLICSUBButtonOpen_Click() Thefirstthingweneedtodointhisprocedureisgetthepathofthefiletheuserwantstoopen.The GambasDialogobjecthasanumberofmethodswithwhichyoucandisplayanumberofcommon dialogs.Amongtheseisaopenfiledialogue.Alsoiftheusercancelsthedialogueweshouldexit ourprocedureandnonothingfurther.Givingtheuserthechancetocancelanactionisgood

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page22of110

programmingpractice.TheOpenFilemethodreturnsFALSEwhentheuserclicksontheOK buttonandTRUEotherwise.ByplacingthisstatementinsideanIFwecancheckthereturnvalueof theOpenFilemethod.TheRETURNstatementcausestheproceduretoquitimmediately.Soifthe userdoesnotclickontheOKbuttonafterselectingafilenamewethenweexitfromthis procedure.Atfirstthislinelookssomewhatcounterintuitive.Butthiswayofcallingthedialogdoes worksverywellwhenyougetusedtoit. IFDialog.OpenFile()THENRETURN WhenwereachthenextlineweknowtheuserhasclickedontheOKbuttonandselectedafile.The DialogobjecthasapropertycalledPathwhichwecanusetogetthefullpathtotheselectedfile. YouusetheFileobjectwhenperformingfileinputandoutput.TheFileobjectalsohasuseful methodsforquicklyreadingatextfile.HereweusetheFile.Load()method.Ittakesas parameterthepathtoourfileandthenreturnsthecontentofthefileasatextstring.Thisfunction handlesalltheopening,readingandclosingofthefileforus.Itiseasytousethisfunctionwhenwe wanttheentirecontentofaplaintextfile.WepassthecontentofthetextfileTextArea'sText property.ThisreplacestheentirecontentoftheTextAreawiththecontentofthefilewehave opened. TextAreaEdit.Text=File.Load(Dialog.Path) Wealsoneedtohandleanypossibleerrorsinourapplication.Thisisespeciallytruewhenyou communicatewithanythingoutsideyourapplication.Herewehaveadialoguewheretheuserenters input.Wealsohaveafilethatcouldcontainalmostanything.Withoutthefollowingerrorhandler ourprogramwouldcrashiftheuserselectedaninvalidfileorafilewheretheydidnothaveread permission.IfanyerroroccursthentheGambasruntimejumpstothisCATCHstatement.Herewe willjustdisplayamessagetotheuser.ByusingtheErrormethodontheMessageobjectwe displayaerroriconinthemessagebox.Herewehavekeptthemessageassimpleaspossible.We simplyshowthetextfromtheerrorthatwascreated. CATCH Message.Error(Error.Text) END CodeafteraCATCHstatementisnotexecutedwhennoerroroccurs.Sowithvalidfilestheuserwill neverseethemessagebox. Thecodeforthesavefilebuttonisverysimilartothatoftheopenfilebutton.Thefirstlinetellsus wearehandlingtheclickeventforthesavebutton. PUBLICSUBButtonSave_Click() Thistimewecallthesavefiledialogwhichisverysimilartotheopenfiledialogweusedabove. Butthisdialoghasfunctionalitymoreappropriatetosavingafile.AgainthisdialogreturnsFALSE whentheuserclicksontheOKbuttonandTRUEotherwise.SoiftheuserdoesnotclickontheOK buttonafterselectingafilenameweexitfromtheprocedure. IFDialog.SaveFile()THENRETURN

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page23of110

AgainweusetheFileobjectforsaving.Thisobjectalsohasausefulmethodforsavingtextfiles. Wesimplyneedtotellitwhatpathtousewhensavingthefileandwhatstringtosave.Here,of course,wearegoingtosavethecontentofourTextArea. File.Save(Dialog.Path,TextAreaEdit.Text) Hereagainwehavethesamekindoferrorhandlerasfortheopenfilebutton. CATCH Message.Error(Error.Text) END

2.4: Runningtheproject
That'severythingweneedforthisproject.So letsrunit.Youruntheprojectbyclickingon thegreenRunbuttonintheprojectmanager windoworbypressingtheF5key.

Iftheprojectdoesnotrunthemostlikelycauseisamisspellinginthecodeweentered. LookasthelinethatGambashighlightswhenfindinganerrorandcheckthenames matchthenamesofthecontrolsontheform.Alsocheckthesyntaxofthehighlighted linematchesthecodeexample. Hereisascreenshotofthefinalrunningapplicationafterwehaveopenedthecodefileforthis project.Asyoucanseethecodeisthesameasabove,butthereareextracommentsinthisfile. Thesecommentsareintheexamplesthatcomewiththistutorial.Thescreenshotalsoshowsapop upmenuwithoptionsforeditingthetext.ThismenuispartoftheTextAreacontrol.Yougetthis menuforfreebyusingthiscontrol.TryrightclickingontheTextAreainyourapplicationwhenitis running.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page24of110

Whenyoudevelopanykindofapplicationyouneedtotestitsfunctionality.Aboveallyoushould notbeabletocrashtheapplication.Itshouldbeabletohandleanyerrorsgracefullyandgivethe userausefulerrormessage.Evenforanapplicationassmallasthisyoushouldhaveatestplan. Butwhatshouldyoutest?Thesearethemostlikelyproblemareaswithanyapplication:

Yourcode.Yourtestsshouldcovereverylineofcodeintheapplication.Thisincludesall branchesisaselection.Alsoeveryloopshouldbetestedforzero,oneandmanyiterations. Interactionbetweenobjects.Itisoftenintheinteractionbetweenobjectswhereerrors occur.Thereshouldbeatestforeveryachievableinteractionbetweenobjects(interaction thatareonlytheoreticalneednotbetested). Interfacestotheworldoutsideyouapplication.Anyusefulapplicationhasto communicatewithsomethingoutsideofitself.Yourapplicationshouldnottrustanydata fromoutsideofitselfuntilithasbeenvalidatedinsidetheapplication.Thisincludesuser inputaswellandcommunicationstoanydevices.Youalsoneedtotestforanymixof otherwisevalidinputsthattogetherareinvalid.Alsoanyinvaliddatashouldbehandled appropriately.

Normallyyouwouldnottestthefollowingitems(exceptwhenbuildingacriticalsystemsuchas applicationforuseisahospital):

Operatingsystemfunctions.Thesecouldbesystemcallsorshellcommands.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page25of110

Inbuiltcontrolsforyourprogrammingenvironment. Anythirdpartycomponentsinyourapplication.

Theseareitemsyouhavelesscontrolover.Iftherearefaultswithanyoftheseitemsthenyouwould properlyhavetochangeyourapplicationtoworkaroundthefault. Agoodwaytototestyouapplicationistoproduceatableoftests.Ideallyyouwouldproducethis tablebeforeyoustartedcodingtheapplication.Ifnewfeaturesarelateraddedtotheapplication thenaddmoreteststothetable.Inthetableyouwouldwritedowneachofthetestandtheresult youexpectforthetesttopass.Youneedtostatetheexpectedresultsothereisnoambiguityifyour applicationdoessomethingdifferent.Thefinalcolumnisforyoutorecordtheresultsofthetesting process.Ourfirstsetoftestsdealwithresizingtheapplicationwindow. FormResizingTests Test Resizethewindowusingrightedge Resizethewindowusingbottomedge Resizethewindowusingleftedge Resizethewindowusingtopedge ExpectedResult Windowshouldberesizeandthetextarea resizedtofitinthewindow. Asabove. Asabove. Asabove. Pass/Fail

Resizethewindowusingnorth/westcorner Asabove. Resizethewindowusingsouth/westcorner Asabove. Resizethewindowusingsouth/eastcorner Asabove. Resizethewindowusingsouth/eastcorner Asabove. Minimizethewindowandrestoreit Maximisethewindowandrestoreit Thewindowshouldbecorrectlyresize whenrestored. Windowshouldresizeandthetextarea resizetofitinthemaximisedwindow. Thewindowshouldbecorrectlyresize whenrestored.

Makethewindowheightsmallerthenthe Youwillnotseethetextarea.Noerror toprowofbuttons shouldresult. Makethewindowwidthsmallerthanthe widthofbothbuttons Noerrorshouldresult.

Thenextsetoftestsareforthebuttonwhichopensatextfile.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com OpenFileTests Test Opentextfile Openanemptytextfile Openaverylargetextfile Openabinaryfile Trytoopenafilethatdoesnotexist Trytoopenafilewhereyoudonothave readpermission ExpectedResult Filedisplayedintextarea Textareaempty Filedisplayedintextarea. Filedisplayedintextarea.Contentis properlynotverymeaningful Errormessage Errormessage

Page26of110

Pass/Fail

Thefinalsetoftestsareforthebuttonwhichsavesatextfile.Whenpreformingthesavefiletests makesureyoudonotoverwriteanyfilesyouneedoranysystemfiles. SaveFileTests Test Entersometextinthetextareaandsavea Filesaved newtextfiletoyourHomedirectory Entersometextinthetextareaandsaveto Filesaved anexistingfileinyouHomedirectory. Withnotextinthetextareasaveanempty Filesaved filetoyourHomedirectory Openanbinaryfileandsavethisasanew Filesaved file Trytosavethefiletoadirectorywhere youdonothavewritepermission Errormessage ExpectedResult Pass/Fail

Trytosavethefiletoadirectorythatdoes Errormessage notexist Wehaveendedupwithmoreteststhanlinesofcodeinourapplication.Thismayseemoverkillfor yourfirstproject.Butthemorethoroughyouareattestingthemoreusefulyourapplicationswillbe tootherusers.Gettingusedtoatoughtestingregimefromthestartwillpaydividendsinthelong run.Therealproblemisbeingasmeticulousasyoucaninyourtests.Youneedtocoveranymany optionsaspossibleandmakesureallcodeiscovered.Onehundredpercentcoverageisnotpossible, butyoushouldaimforthis. Soworkthroughthelistoftextandmakesureyourecordiftheypassorfail.Ifanytestfailsyou willneedtodebugthecodetofindthefault.Alsoarethereanyteststhatshouldbeaddedtothe

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com list? OneofthebestpiecesofadviceIcangiveyouis: Usetheapplicationsyoubuildyourself.

Page27of110

Ifyoubuildapaintprogramthenuseitforallyourdrawingtasks.Thatwayyoufind whatfeaturesyouneedtoadd.(Andalsowhatfeaturesseemedagoodideaat developmenttime,butarelittleused.)Alsoafterafewweeksmakesureyouthinkagain abouthoweasyitisforanewusertolearnyourapplication. Thatwasnottohard.Wehavecreatedabasicbutperfectlyfunctionaltexteditor.Wehaveachieved thisbyusingthepowerofexistingcomponents.Thecorefunctionalityforourtexteditorwas alreadycontainedintheTextAreacontrol. Youcouldgoonaddingfeaturestothisprojectanddevelopitasyourowntexteditor.Forexample youcouldaddsomebuttonstocut,copyandpastetext.Thenhooktheseuptothemethodsonthe TextAreacontroltohandlethisfunctionality.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page28of110

3:

DrawingProject:ImageShow

Withthisprojectwearegoingtocreateasimpleslideshowapplication.Wewanttheprojecttohave thefollowingfunctionality:

Theapplicationshoulddisplayimagesfromaselecteddirectory. Thedisplayshouldbefullscreen. Imagesshouldbedisplayedfullsizeandcentredonthescreen. Ifanimageislargerthenthescreenthenitshouldbescaledtofitonthescreenkeepingthe aspectratiooftheimage. Onceadirectoryisselectedtheapplicationwillscrollthroughtheimagesdisplayingone every15seconds. PressingtheEscapekeywillquittheapplication. PressingF1willdisplayabriefhelpscreen. Pressingspacebarorrightarrowwillscrolltothenextimage. Pressingthebackspacekeyorleftarrowwilldisplaythepreviousimage. Pressingthe'D'keywillallowtheusertochangetheimagedirectory. Pressingthe'S'willstartorpausetheslideshow Pressingthe'I'keywilldisplayinformationabouttheimage/show. Themouseshouldbehiddenwhenimagesaredisplayed.

Thislookslikealonglistbutasweshallseethefinalapplicationisnotthatcomplex.

3.1: Creatingtheproject
ThefirststepistocreateanewGambasproject.SoopenGambasandandselectNewproject.... Thiswillstartthenewprojectwizard.Thefirstpageofthewizardsimplyshowsawelcomescreen withdetailsofhowtousethenewprojectwizard.ClicktheNext>>buttontoforthenextpageof thewizard.ThisshowsapagewerewecanselectthetypeofGambasprojectwewanttobuild.We aregoingtousethedefaultoptionofagraphicalproject.SoclicktheNext>>button.Thisshowsa pagewhenyouenterthenameandtitleforyourprojectwearegoingtocreate.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page29of110

EnterthenameofImageShowandthetitleofAsimpleimageslideshow.Leavethe otheroptionsunchecked.ClickontheNext>>button.Thisshowsapagewhereyouselectthe directorywhereyouyouwanttosavetheprojectfiles. Selectthelocationwhereyouwanttosavetheproject.ThenclicktheNext>>button.Thisfinal pageliststheoptionsyouhaveselectedfortheproject.Checkthroughtheoptionsandthenclickthe OKbutton.WehavecreatedanewVisualBasicprojectandGambaswillopenshowingtheGambas projectmanager.

3.2: Creatingtheuserinterface
NowwehaveaGambasproject.Thenextstepistoaddsomeelementstotheprojecttogiveusa userinterface.Thisprojectwillhaveonewindowthatwillbedisplayedfullscreen.Allofthis windowwillbetakenupwithaDrawingAreacontrol.Wecoulddrawtheimagedirectlyontheform butusingaDrawingAreagivesussomeextrafunctionality.Wewillalsoputatimerontheform. Thisissowecanfireeventstochangeimagesassetintervals.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page30of110

RightclickintheGambasprojectmanager. Thisbringsupapopupmenu.Fromthelist selectNew.Thisshowsasubmenuwiththe itemswecanaddtoourproject.Weneedto addaFormtoactasthemainwindowtoour application.SoselectForm...fromthis menu. Thismenuoptionshowsadialoguewherewe candefinesomeofthepropertiesoftheform wearegoingtocreate.

GivetheformthenameofFormImageShowandaccepttheotherdefaultoptions.Thestartup classistheclasstheGambasruntimewillfirstloadwhentheapplicationisstarted.Therecanonly beonestartupclassinyourproject.Wewantthisformtobethestartupclasssomakesurethis optionischecked.NowclicktheOKbuttontocreatetheform.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page31of110

Wenowneedtoaddsomecontrolsontotheformwehavejust created.FirstweshalladdaTimer.Makesuretheformwehave justcreatedisvisible.Ifitisnotthendoubleclickontheformin theprojectmanager.AlsomakesuretheToolboxisvisible.Ifitis notthenselecttheprojectmanagerViewmenuthenToolboxsub menuorpresstheF6key. Thetoolboxhasseveraltabsthatgroupthekindsofcontrolswe canuse.MakesuretheSpecialtabisselected.Whenyoumove themouseoveritemsinthetoolboxthetooltipchangestoshow thetypeofobject.SelecttheTimercontrolthethetoolbox. PlaceaTimerontheformwindow.Youcandraganddropitems fromthetoolboxontoaformdesignerwindow.Itdoesnotmatter whereyouputthetimerasitwillnotbevisiblewhentheprogram isrun.

NowmakesuretheContainertabisselected.Selectthe DrawingAreacontrolinthetoolboxandplacethisontheform.It doesmatterwhereyouplacetheDrawingAreaasitwillberesized atruntime. ForGambasversion1thesetwocontrolsareonthe Formtab. AtthispointourFormImageShowshouldlooklikethefollowing screenshot.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page32of110

Thecontrolswillhavetheirdefaultname.Howeverthesedefaultnamesdonotgiveanyinformation abouthowweintendtousethem.Itisgoodprogrammingpracticetochangethenamesto somethingmeaningfulforourapplication.Thiswaywewillwriteselfdocumentingcode. Wearenowgoingtochangesomeofthepropertiesofthese controls.Ifthepropertieswindowisnotvisiblethenselectthe projectmanageViewmenuthenPropertiessubmenuorpressthe F4key.NowclickonTimer1intheformdesigner.Thiswillshow thepropertiesforthisobject.WearegoingtochangetheName propertytoTimerShow.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page33of110

ClickontheDrawingAreaobjectandchangetheName propertytoDrawingAreaImage. Thatallofthepropertieswearegoingtochangeinthe Formdesigner.Someotherpropertiesoftheseobjectswill bechangedinthecode. Wewanttoshowsomehelpinformationstotheuserwhen theypresstheF1key.Themethodwearegoingtouseis suitablewhentherequiredamountofhelpissmallandwill fitononepage.TheGambasMessageboxisquitea flexibleclassandwilltakeaHTMLformattedmessage. Sowiththesinglelineofcode: Message.Info(File.Load("help.htm")) wecandisplayaHTMLfile.

SoletcreatetheHTMLfileinGambas.Right clickintheGambasprojectmanager.This bringsupapopupmenu.Fromthelistselect New.Thisshowsasubmenuwiththeitems wecanaddtoourproject.Weneedtoadda TextfilesoselectTextfile...fromthismenu.

Thisshowsadialoguewherewegivethetextfileaname.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page34of110

Givethefilethename help.htmandpressthe OKbuttontosaveit.This willaddthefiletothe datasectionofyour projectandwillopenthe newtextfileinthe Gambastexteditor window.Thescreenshot ontheleftshowsthe Gambastexteditor windowafterwehave enteredsomeHTMLinto it.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page35of110

ThisisnotatutorialaboutHTMLthereareplentyofthoseontheinternet.Sowearenotgoingto saymuchaboutthisfile.JustenterthefollowingHTMLintothetexteditor.Notethat,asbefore,the iconinthefollowinglistingmeansthislineisacontinuationofthepreviousline. help.htm <html> <head> <title>ImageShowHelp</title> </head> <body> <h2><fontcolor='Blue'>ImageShowHelp</font></h2> <hr> <p>ImageShowpresentsaslideshowofimagesfromadirectory youselect. </p> <p>Thefollowingkeyscanbeusedwhileviewingimages: </p> <p>The<b><fontcolor='Blue'>Spacebar</font></b>or<b><font color='Blue'>RightArrow</font></b>keystoshowthenextimage <br>The<b><fontcolor='Blue'>Backspace</font></b>or<b><font color='Blue'>LeftArrow</font></b>keystoshowtheprevious image <br>The<b><fontcolor='Blue'>D</font></b>keytoselectanew picturedirectory <br>The<b><fontcolor='Blue'>I</font></b>keytoshow informationabouttheimage <br>The<b><fontcolor='Blue'>S</font></b>keytoggles startingandpausingtheshow <br>The<b><fontcolor='Blue'>Esc</font></b>keytoquit <br>The<b><fontcolor='Blue'>F1</font></b>keyforhelp </p> <hr> <p>ImageShowv.0.0.1wasdevelopedbyTimothyMarshalNichols inMay2006.Itisissuedunderthe<b>TheGNUGeneralPublic License2</b>.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com </p> <hr> </body> </html>

Page36of110

TheGambascontrolsthatacceptHTMLformattingonlytakeasubsetofHTMLtags.Soitis sometimestrialanderrortofindoutwhatworks.ThefollowingscreenshotshowswhatthisHTML lookslikeinamessageboxwhentheapplicationisrunandtheuserpressestheF1key.

Thatalloftheelementsweneedfortheuserinterface.Alltherestoftheapplicationsfunctionality isgoingtobedoneincode.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page37of110

3.3: AddingtheCode
Therearethreeeventweneedtohandleinthisapplication.Weneedsomesetupcodewhenthe applicationopens.Whentheuserpressesakeyonthekeyboardweneedtocheckthekeypressand, ifrequired,respond.Wealsoneedtoupdatethescreenimageevery15secondswhentheslideshow isrunning. Soletsaddtheseeventstoourapplication.Thefirsteventiseasydoubleclickonthe FormImageShowintheformdesigner.ThiswilladdtheeventForm_OpentotheFormImageShow class. Nextweshalladdtheeventforauserkeypress.RightclickontheontheFormImageShowinthe formdesigner.Thiswillshowapopupmenu.SelecttheEventsoptionandthenfromthesubmenu selectKeyPress.ThiswilladdtheeventForm_KeyPresstotheFormImageShowclass.Finally doubleclickontheTimerShowobjectontheFormImageShow.Thiswilladdtheevent TimerShow_TimereventtoFormImageShowclass. Whenyouhaveaddedtheseevents theFormImageShowclassshould looklikethisscreenshot.

NowweshalladdcodetotheFormImageShowclass.Inthistutorialchapterweshallsplitthecode intochuckssothatwecandescribeeachsection.Weneedtwovariablestostoreinformationabout

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page38of110

ourslideshow.ThefirstvariableisaarrayofstringscalledpictureFiles.Hereweshallstore thefilepathstoallinimagesinourslideshow.ThenextvariableispictureNumberwhichwill holdtheindexnumberofthecurrentlydisplayedimage. FormImageShow.class PRIVATEpictureFilesASNEWString[] PRIVATEpictureNumberASInteger ContinuedBelow NoticethatwedeclarethesevariablesasPRIVATE.Lateronyouwillseethatvariablesdeclared insideaprocedureorfunctionaredeclaredusingtheDIMstatement.HoweverinGambaswhen declaringvariablesatmoduleorclasslevelyouneedtousethePUBLICorPRIVATEkeywords. WeshalladdcodetotheForm_Openeventwecreatedearlier.Thiseventfireswhentheformis firstshownandonlyfiresonce.Itisausefulplacetoputanysetupcodeyouneedforaform.We startbysettingtheformsbackgroundtoblackandmakingtheformfullscreen.(Gambasversion1 usersseethenotebelow.) WethensetthechangesweneedtotheDrawingArea.WeresizetheDrawingAreawiththemove statement.NormallywewouldusetheME.ClientWidthandME.ClientHeightproperties togetthesizeofthecurrentform.Inmostcasesthesearethepropertiesyoushoulduse.Buthere theyarestillsettotheoldformsize.Theydonotappeartobecomesettothevalueswewantuntil theformresizeeventiscalled.AswewanttheformtobefullscreenwecanusetheDesktopobject togetthevaluesweneed.TheDesktopobjectgivesussomeusefulinformationaboutthescreen. AlsofortheDrawingAreawesettheCashedpropertytoTRUE.Whenthispropertyissetthe DrawingAreawillautomaticallyhandlerefreshingofitselfifthecurrentpictureneedstobe redrawn.ThismeanswelettheDrawingArearedrawthecurrentpicturewhenneeded.Weonlyneed tothinkaboutdrawingwhenwewanttochangethepicture. Wethencalltwofunctions.Thefirstallowstheusertoselectadirectoryfromwhichtobuildalist ofimages.Thenextfunctionwilldisplayanimage.Thecodeforthesefunctionsisdescribedlater on.Aftercallingthesefunctionswehidethemousesoitdoesnotdetractfromtheimage. Finallywesetuptheshowtimer.Wesetthedelaytimebetweenimagesto15seconds.Butweonly starttheshowtimerifwehavesomeimages. FormImageShow.classContinued

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page39of110

PUBLICSUBForm_Open() 'Setformproperties ME.BackColor=Color.Black ME.FullScreen=TRUE 'Setdrawingareaproperties DrawingAreaImage.Move(0,0,Desktop.Width,Desktop.Height) DrawingAreaImage.Cached=TRUE 'Selectimagedirectory Dialog.Path=User.Home SelectImages() NextPicture() 'Hidemouse DrawingAreaImage.Mouse=Mouse.Blank 'Startshowtimer TimerShow.Delay=15000'15seconds TimerShow.Enabled=(pictureFiles.Count>0) END ContinuedBelow InGambasversion1youuseaslightlydifferentmethodofdisplaystheformfullscreen. TheME.FullScreen=TRUElineintheabovelistingneedstobechangedtothe following: ME.State=Window.Fullscreen AlsotoselecttheusershomedirectoryyouusetheSystemobject. Dialog.Path=System.Home

Thisnexteventhandlesanykeypressourapplicationreceives.Whenevertheuserpressesakeywe selecttheoptiontheuserwants.WeusetheTimerShow.Enabledpropertyasaflagtoindicate iftheimageshowisrunningorpaused.Forsomeofthekeypressoptionswewanttorestorethe imageshowtoitspreviousstate.SowestorethecurrentstateinthevariabletimerState. TheKeyobjectgivesusinformationaboutthelastkeypress.TheKey.Codepropertygivesusthe

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page40of110

keyboardcodeandwecancomparethiswithconstantsintheKeyobjectinourSELECTstatement. WhentheEscapekeyispressedweuseME.Close()toendtheapplication.IftheF1keyis pressedweholdtheimageshowandthendisplayourHTMLhelpfileinamessagebox.Whenthe userclosesthemessageboxtheimageshowstateissettothesavedstate. InGambasversion1themessageboxgetslostbehindtheformwhentheformisfull screen.SoamendthecodefortheF1buttontothefollowing: TimerShow.Enabled=FALSE DrawingAreaImage.Mouse=Mouse.Default ME.State=Window.Normal ME.Border=Window.Resizable Message.Info(File.Load("help.htm")) ME.State=Window.FullScreen DrawingAreaImage.Mouse=Mouse.Blank TimerShow.Enabled=timerState Thehelpmessagedoesnotlookasgoodasinversion2ofGambas.Butatleastitdoes notgetlost. Thenexttwocaseshandletheusermanuallyadvancingthecurrentimage.Whentheuserpresses theRightArroworBackspacekeywedecrementthecurrentimagecounterandthencallour proceduretodrawtheimage.SimilarlyiftheuserpressestheLeftArroworSpacebarkeywe incrementthecurrentimagecounterandthencallourproceduretodrawtheimage. WhentheDkeyispressedwehandletheuserchangingtheselecteddirectoryforimages.Firstwe pausetheslideshow.Thenweshowthemousebysettingittoitsdefaultcursor.Itcouldbe confusingtotheusertokeepthemousehidden.Wethencalltwofunctionsthatweusedinthe Form_Openevent.Thefirstallowstheusertoselectadirectoryfromwhichtobuildalistofimages. Thenextfunctionwilldrawanimage.Wehidethemouseagainandstarttheshowtimerifwehave someimages. TheSkeytogglespausingtheslideshoworstartingitrunningagain.Whenpausingtheslideshow wesimplydisabletheslideshowtimer.Weonlyallowtheslideshowtostartiftherearesome imagestodisplay.Iftherearesomeimagesweincrementthecurrentimagecounteranddisplaythe nextimage.Thisgivesavisualconfirmationtotheuserthattheslideshowhasstartedrunning again.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page41of110

WhentheIispressedwecallaprocedurethatdrawssomeinformationonthescreenaboutthe currentstateoftheslideshowandthecurrentimage.Thisprocedureisdescribedlater. FormImageShow.classContinued PUBLICSUBForm_Press() DIMtimerStateASBoolean timerState=TimerShow.Enabled SELECTCASEKey.Code CASEKey.Esc 'Closetheslideshow ME.Close() CASEKey.F1 'ShowHTMLhelp TimerShow.Enabled=FALSE DrawingAreaImage.Mouse=Mouse.Default Message.Info(File.Load("help.htm")) DrawingAreaImage.Mouse=Mouse.Blank TimerShow.Enabled=timerState CASEKey.BackSpace,Key.Left 'Showpreviouspicture TimerShow.Enabled=FALSE DECpictureNumber NextPicture() TimerShow.Enabled=timerState CASEKey.Space,Key.Right 'Shownextpicture TimerShow.Enabled=FALSE INCpictureNumber NextPicture() TimerShow.Enabled=timerState CASEKey["D"] 'Getanewslideshowfromadirectory TimerShow.Enabled=FALSE DrawingAreaImage.Mouse=Mouse.Default SelectImages()

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com NextPicture() DrawingAreaImage.Mouse=Mouse.Blank TimerShow.Enabled=(pictureFiles.Count>0) CASEKey["S"] IFTimerShow.EnabledTHEN 'Iftheshowisrunningthenstopit TimerShow.Enabled=FALSE ELSEIFpictureFiles.Count>0THEN 'Iftheshowisnotrunningandwehavepictures 'thenstarttheshowwiththenextpicture INCpictureNumber NextPicture() TimerShow.Enabled=TRUE ENDIF CASEKey["I"] 'Showsomeinformationabouttheshow ShowMessage() DEFAULT 'Nothing ENDSELECT END ContinuedBelow

Page42of110

Whentheimageshowisrunningatimereventwillbefired.Hereweincrementthecounterwehave fortheimagenumberby1andthencallourfunctiontodrawtheimage.Wewrapthedrawingcall withEnablingandDisablingatimer.Thisisproperlynotneededandisahangoverfromcodingin anotherVisualBasic.Ihaveputthisinsoweresetthetimerafterhavingcompleteddrawingthe image. FormImageShow.classContinued PUBLICSUBTimerShow_Timer() TimerShow.Enabled=FALSE 'Gotothenextimage INCpictureNumber

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com 'Drawthenextimage NextPicture() TimerShow.Enabled=TRUE END ContinuedBelow

Page43of110

Wehavecalledthisnextprocedureseveraltimesabove.Itallowstheusertoselectanewimage directoryandloadsthepathsoftheimagefilesintopictureFilesarray.Firstwecallastandard dialoguethatallowstheusertoselectadirectory.Callingthisdialogueissimilarthewayweopened andsavedfilesintheSimpleEditprojectabove.IftheuserdoesnotselectatheOKbuttonanda directorywereturnfromtheprocedure.TheDialog.Pathpropertyreturnsthenameandpathof theselecteddirectory.Iftheuserselectsadirectorywecleartheoldlistofimagefiles. UsingtheDirfunctionwecanobtainalistofallfilesinadirectory.Asthislistisnotsortedwe usetheSort()methodonastringarraytosortthefilelist.WethenuseaFORNEXTconstructto loopthrougheachofthefiles.TheFileclassprovidessomeusefulmethodforextractingelements fromafilepath.HerewewanttotestthefileextensionforeachfilesoweusetheFile.Ext method.Inordertoprovideacaseinsensitivesearchforimagesweconverttheextensiontolower case.WethentestthefileextensionfortheimagefiletypessupportedbyGambas.Ifwehavefound aavalidimagefilenamethenweaddthefullfilenameandpathtoourimagefilelist. Whenwehavecompletedtheloopwechecktoseeifwehavefoundanyimagefilesinthedirectory. Ifwehavenotwedisplayamessagetotheuser.Wethensetthecurrentimageindextothefirst image.WehaveaCATCHherebecauseweareinterfacingwiththefilesystemandthereisthe possibilityoffileI/Oerrors.Hopefullytheuserwillneverseethiserrormessage. Wehavebuiltalistofimagesbasedupontheextensionofthefile.Inmostcasesthiswillproducea validlist.Howeverjustbecauseafilehasanextensionofjpgdoesnotmeanitisavalidjpgimage file.Ausercangiveafileanynametheywant.Hencewhenwedisplaytheimagesweshallstill needsomeerrorcheckingcode. FormImageShow.classContinued PRIVATESUBSelectImages() DIMfileNameASString DIMfileListASString[] DIMfileExtensionASString 'Getthedirectorynamefromtheuse

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com IFDialog.SelectDirectory()THENRETURN pictureFiles.Clear() fileList=Dir(Dialog.Path) fileList.Sort() FOREACHfileNameINfileList fileExtension=Lower(File.Ext(fileName)) 'Onlyselectimagefiles IFfileExtension="png"ORfileExtension="jpeg"OR fileExtension="jpg"ORfileExtension="bmp"OR fileExtension="gif"OR fileExtension="xpm"THEN 'Thisisaimagesoaddtoimagelist pictureFiles.Add(Dialog.Path&/fileName) ENDIF NEXT IFpictureFiles.Count=0THEN

Page44of110

Message.Info("Noimagesfoundinthedirectory:\n\n"& Dialog.Path) ENDIF pictureNumber=0 CATCH Message.Warning("Errorselectingimagesfrom:\n\n\t"& Dialog.Path&"\n\n"&ERROR.Text) END ContinuedBelow AlthoughwecalltheNextPictureprocedureseveraltimeitisnotwherewedotherealworkof drawingthecurrentimageisdone.Ratherthisprocedurecheckswehavevalidinputforthe DisplayImageprocedure.Firstwemakesurewehavesomeimagestodisplay.The pictureFilesarrayholdsthepathstotheimagesfilesinourshow.BymakingsuretheCount propertyisgreaterthanzeroweensurethereissomethingtodisplay.Wethenmakesureourindex forthecurrentpictureiswithinavalidrange.Ifourindexisgreaterthannumberofimages availablethenwesetittothestartoftheshow.Similarlyifourindexislessthanzerothenwesetit totheendoftheshow.ThiswaywecansafelyincrementanddecrementthepictureNumber indexintheproceduresabove.Weknowthathereweshallwraptheindexaroundtheendsofthe array.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page45of110

Rememberthattheindexinaarraystartsatzeroandthefinalelementofanarrayisonelessthen theCountproperty.WhenwehaveavalidindexwecalltheDisplayImageprocedurethatdoes alltheactualdrawingwork. FormImageShow.classContinued PRIVATESUBNextPicture() 'Checkwehavesomeimagefilepaths IFpictureFiles.Count>0THEN 'Limittheimagenumbertothenumberof 'filesinourarrayoffilepaths IFpictureNumber>=pictureFiles.CountTHEN pictureNumber=0 ELSEIFpictureNumber<0THEN pictureNumber=pictureFiles.Count1 ENDIF 'Nowdrawtheimage DisplayImage(pictureFiles[pictureNumber]) ENDIF END ContinuedBelow DrawingtheimageontheDrawingAreaisveryeasy.Threeobjectsareinvolvedinthisprocess.The Imageobject,theDrawobjectandtheDrawingAreacontrol.

Image:Thisclassstoresabitmaptypeofimagesuchasajpgorpngformatimage.The mostimportantmethodforusisthestretchmethodwhichallowsustoresizetheimageif required.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page46of110

Draw:Youdrawonadevice.Thedevicecanbeaanyof thefollowingobjects:Picture,Window(i.e.aForm),the Printer,aDrawing,oraDrawingArea.Youstartdrawing byinitializingthedeviceyouwanttodrawon.Thisis donepassingthedrawingdevicetotheBeginmethod. Youthensetthepropertiesrequiredforthenextdrawing action.Thisincludespropertieslikeselectingcolors, fontsorlinestyles.Youthencallthemethodtoperform thedrawingaction.Thedrawingmethodsinclude drawinglines,rectangles,textandimages.Theprocess ofsettingdrawingpropertiesandcallingdrawing methodsiscontinueduntilthedrawingisfinished. FinallyyoucalltheEndmethodtocompletethe drawing.

Begin(Device)

Setdrawing properties

Calldrawing method More?

End

DrawingArea:Thiscontrolactslikevisualdevicethatwecandrawon.IftheCashed propertyissettoTRUEthenredrawingthecurrentimageishandledautomaticallywhenthe controlneedstoberefreshed.ThisisthemainreasonweuseaDrawingArea.Youcandraw directlyonaform,butthenyouneedtohandlerefreshingthecurrentimagewhenrequired.

Thisdiagramshowstherelationshipbetweenthedrawingobjectsinourapplication.

ImageFile
jpg,png, bmporgif

LoadImage fromdisk

Image

Callmethod onDrawclass usingImage object DrawingArea


Adrawingdevice

Draw Imagedrawn onscreen

Whenwefirstloadtheimagefromfile.Weneedtoputsomeerrorhandlingonthis.Theload

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page47of110

methodusesthefileextensiontodeterminewhatkindofimagetoload.Ifthefilecontentdoesnot matchthefileextensionthenwehaveanderror.Eveniftheuserselectedsomevalidimagesitis possiblewemaynothavereadpermissiononthefile.Thisagaincouldgiveuseanerror.Ifweget anerrorwesimplyreturnfromtheprocedure. Wethencheckthesizeoftheimage.Iftheimageislargerthenthesizeofthescreenthenwewant toscaleittofitonthescreen.Whenscalingwewanttoscaleisotropicallywhichmeansscalingthe imagebythesamefactorinbothdirections.Thiswillkeeptheaspectratiooftheimage.Thereare twopossiblescalingfactorswecoulduse.Scalingtomakethewidthfitonthescreenorscalingto maketheheightfitonthescreen.Wetakethesmallestoftheseandapplythemtoboththewidth andtheheightoftheimage. Amoreinterestingproblemismakingsurethepreviousimageiscleared.Whenanewimageis drawnitmaynotbethesamesizeasthepreviousimage.Eitherinthewidthdirectionoftheheight direction.Ifallwedoisdrawthenewimagewecouldleavebitsoftheoldimageonthescreen. Thiswouldnotlookverygood. ThefirstsolutionItriedwassimplytousetheClearmethodontheDrawingAreaandthendrawthe image.Inmanycasesthisworksfine.TheClearmethodclearstheDrawingAreausingthe Backgroundcolor.Theproblemwasfordrawinglargeimagesthescreenproducedanoticeable 'flash'eachtimeanimagechanged.Yousawthebackgroundcolorflashovertheentirescreenfora fractionofasecond.ThisdidnotlookverygoodsotheClearmethodhadtogo. ThenextsolutionItriedwastodrawasolidrectangleovertheentireDrawingAreausingthe backgroundcolor.ThenIwoulddrawtheimagecentredonthescreen.Thisworkedbetter.Butyou stillsawanoticeable'flash'whenalargeimagewasdrawn. ThenextsolutionItriedwastodrawthenewimagefirst.Thentodrawovertherestofthescreen withthebackgroundcolortoclearanypartsoftheoldimageleftbehind.Todothisweneedto draw4solidrectanglesinthebackgroundcoloroneachedgeoftheimage.Thefollowingdiagram willhelpuscalculatethesizeoftherectanglesweneedtodraw.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page48of110

x1

x2

x3

y1 Image y2
Height

y3

Width

Usingthisthiswecanseetherectanglesweneedtodrawtoclearanypossiblefragmentsofthe previousimage. Rectangle Top Bottom Left Right StartPoint 0,0 0,y2 0,0 x2,0 x3 x3 x1 x3x2 Width y1 y3y2 y3 y3 Height DrawRectangle Rect(0,0,x3,y1) Rect(0,y2,x3,y1) Notethat:y1=y3y2 Rect(0,0,x1,y3) Rect(x2,0,x1,y3) Notethat:x1=x3x2

(Ourrectanglesoverlapinthecorners.Youcouldmaketheapplicationmoreefficientbyreducing thesizeofsomeoftherectangle.ButIdonotthinkitisworthit.Idoubttheuserwouldevernotice aspeeddifference.Comparedwiththetimetakentoload,scaleanddrawtheimage,drawingthe rectanglesisveryfast.Alsoyouruntheriskofleavinglinesthathavenotbeenclearedacrossthe screenatthejoinsofrectangles.Thiscouldoccureifthereareanyroundingerrorsinyour calculations.) ThefinalmethodthatmightbetriedistouseaPictureobjectasadrawingbuffer.Withthismethod youwouldcreateaPictureobjectthesizeoftheDrawingArea.SetthePictureobjectsbackgroundto theDrawingAreasbackgroundcolor.ThendrawtheimagecentredonthePictureobject.Thefinal stepwouldbetodrawthePictureobjectontotheDrawingArea.Againthisworks.Butitdidnot provideasolutionanybetterthanthepreviousmethodwelookedat.Soforthefinalversionofthe

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page49of110

codewehaveusedthatmethodofclearinganypreviousimage.Thecodelistingfordrawingand imagefollows. SomeversionofGambasmayrequirethetheline: TRYcurrentImage.Load(ImagePath) tobe: TRYcurrentImage=Image.Load(ImagePath) asthesyntaxoftheloadfunctionhaschanged. FormImageShow.classContinued PRIVATESUBDisplayImage(ImagePathASString) DIMcurrentImageASNEWImage DIMscaleASFloat DIMx1ASInteger DIMx2ASInteger DIMx3ASInteger DIMy1ASInteger DIMy2ASInteger DIMy3ASInteger 'Loadtheimage 'SomeversionofGambasmayrequirethislinetoread 'TRYcurrentImage=Image.Load(ImagePath) TRYcurrentImage.Load(ImagePath) IFERRORTHENRETURN'Ifwecannotloadtheimagethengiveup 'Checkiftheimageislargerthanthescreen IF(currentImage.Width>DrawingAreaImage.ClientWidth)OR (currentImage.Height>DrawingAreaImage.ClientHeight)THEN 'Scaleimagetofitonthescreen scale=Min(DrawingAreaImage.ClientWidth/currentImage.Width, DrawingAreaImage.ClientHeight/currentImage.Height) currentImage=currentImage.Stretch(currentImage.Width* scale,currentImage.Height*scale) ENDIF 'Calcrectanglespoints x1=(DrawingAreaImage.ClientWidthcurrentImage.Width)/2

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com x2=x1+currentImage.Width x3=DrawingAreaImage.ClientWidth

Page50of110

y1=(DrawingAreaImage.ClientHeightcurrentImage.Height)/2 y2=y1+currentImage.Height y3=DrawingAreaImage.ClientHeight 'Drawimage Draw.Begin(DrawingAreaImage) Draw.Image(currentImage,x1,y1) 'Drawrectanglesovertheareanotcoveredbythenewimage Draw.BackColor=DrawingAreaImage.BackColor Draw.ForeColor=DrawingAreaImage.BackColor Draw.FillColor=DrawingAreaImage.BackColor Draw.FillStyle=Fill.Solid 'Drawtoprectangle Draw.Rect(0,0,x3,y1) 'Drawbottomrectangle Draw.Rect(0,y2,x3,y1) 'Drawleftrectangle Draw.Rect(0,0,x1,y3) 'Drawrightrectangle Draw.Rect(x2,0,x1,y3) Draw.End END ContinuedBelow Thefinalprocedurewehavedrawsaninformationmessageabouttheslideshow.Thisiscalled whentheuserpressestheIkey.Firstwebuildthestringforthemessage.Weaddsomeinformation aboutiftheshowisrunningorpaused.Ifitisrunningweaddinformationaboutthetimeinterval betweenimages.Wethenshowsomeinformationaboutthecurrentimage.Weshowthecurrent picturenumberandthetotalnumberofimagesaswellastheimagepath.Notethatweaddoneto thecurrentimageindexbecausethestringarrayindexfortheimagepathsstartsatzero. Nextwecalculatethescreenpositionforthemessage.Wewanttoplacethemessageatthebottom ofthescreenandinthecentre.Wewilldrawthismessageusingthedefaultfont.Weusethe TextWidthandTextHeighmethodsontheDrawobjecttogetthesizeofthetext.Wecanthen calculatethepositionforthetext.Theleftpositionforthetextwillbehalfthewidthofthescreen

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page51of110

minusthewidthofthetextmessage.Thetoppositionforthetextwillbetheheightofthescreen minustheheightofthetext. Wewanttomakesurethetextisvisible.Ifwesimplydrewthetextitcouldbeoveranycolorthat formsthebackground.Sofirstwedrawafilledrectangleasthebackground.Thenwedrawthetext ontopofthisrectangleatthepositionwehavecalculated. FormImageShow.classContinued PRIVATESUBShowMessage() DIMmessageASString DIMx1ASInteger DIMy1ASInteger DIMmessageWidthASInteger DIMmessageHeightASInteger 'Gettheinformationmessage IFTimerShow.EnabledTHEN message="ShowRunning(Every"&CInt(TimerShow.Delay/ 1000)&"seconds)" ELSE message="ShowPaused:" ENDIF IFpictureFiles.Count>0THEN message&="Picture:("&(pictureNumber+1)&"/"& pictureFiles.Count&")"&pictureFiles[pictureNumber] ELSE message&="Nopictures" ENDIF 'Drawtheinformationmessage Draw.Begin(DrawingAreaImage) 'Calcmessageposition messageWidth=Draw.TextWidth(message) messageHeight=Draw.TextHeight(message) x1=(DrawingAreaImage.ClientWidthmessageWidth)/2'Center ofscreen y1=DrawingAreaImage.ClientHeightmessageHeight'Bottomof

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com screen 'Drawthemessagebackground Draw.ForeColor=Color.LightGray Draw.FillColor=Color.LightGray Draw.FillStyle=Fill.Solid Draw.Rect(x1,y1,messageWidth,messageHeight) 'Drawthemessagetext Draw.ForeColor=Color.Black Draw.Text(message,x1,y1) Draw.End END

Page52of110

3.4: Runningtheproject
Theprojectisnowcompletesoletsrunit.YouruntheprojectbyclickingonthegreenRunbutton intheprojectmanagerwindoworbypressingtheF5key.Adialogueshouldopenaskingyouto selectadirectory.Selectadirectorywithsomeimagesinpngorjpgformat.Watchtheshow! Wenowneedtotesttheapplicationworksasexpected.Soruntheapplicationandselectaimage directory.ThenpresstheDkeytochangetheimageshowdirectory.Testtheapplicationwiththe followingkindsofdirectories: OpenImageDirectoryTests Test Openadirectorywithimagesinit. Tryanemptydirectory. Tryadirectorywithnoimagesbutsome otherfiletypes. Adirectorywithsomejpgimagefiles. Adirectorywithsomejpegimagefiles. Adirectorywithsomepngimagefiles. Adirectorywithsomegifimagefiles. Adirectorywithsomebmpimagefiles. ExpectedResult Imageshowdisplayed. Anoimagesfoundmessage. Anoimagesfoundmessage. Imageshowdisplayed. Imageshowdisplayed. Imageshowdisplayed. Imageshowdisplayed. Imageshowdisplayed. Pass/Fail

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com OpenImageDirectoryTests Test Adirectorywithsomexpmimagefiles. ExpectedResult Imageshowdisplayed.

Page53of110

Pass/Fail

Makesureinalloftheaboveteststhattheapplicationdoesnottrytoopenanyfilesthatarenot imagesandthatalltheimagesareshown.Theapplicationshouldnotcrashandyoushouldbeable toselectanotherdirectory.Wenowwilltestalltheotherkeysperformthecorrectaction. KeyPressTests Test Withanimageshowpressthespacebar. Withanimageshowpressthebackspace key. Withanimageshowpresstheleftarrow. WiththeshowrunningpresstheSkey. WiththeshowpausedpresstheSkey. WiththeshowrunningpresstheIkey. ExpectedResult Nextimageshouldbedisplayed. Previousimageshouldbedisplayed. Previousimageshouldbedisplayed. Theshowshouldpause.(Waitmorethan 15secondstomakesure.) Thenextimageshouldbedisplayedand theshowstartrunning. Aninformationlineshouldbeshown.It shouldsaytheshowisrunningandgive thecurrentimagename. Aninformationlineshouldbeshown.It shouldsaytheshowispausedandgivethe currentimagename. Ahelpmessageshouldbedisplayedand alsothemouse.Whenthemessageis clearedthemouseshouldbehidden. Theapplicationshouldclose. Pass/Fail

Withanimageshowpresstherightarrow. Nextimageshouldbedisplayed.

WiththeshowpausedpresstheIkey.

WiththeshowrunningpresstheF1key.

PresstheEsckey.

Finallyforthisprojectweagoingtocreateaexecutableversionoftheapplication.Thiswayyou canrunImageShowoutsidetheGambasdevelopmentenvironment.Firstmakesureyouhave completedallthetestingdescribedabove.ThenintheGambasprojectmanagerselecttheProject menuandthentheMakeexecutable...submenu.Thiswillshowastandarddialogueaskingforthe nameofafile.AcceptthedefaultsandclicktheOKbutton.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page54of110

Thiswillcreatean executableversionofyour applicationinyourproject directorycalled ImageShow.gambas.

InUnix/Linuxtheyourhomebindirectoryisagoodplacetostoreyourpersonalapplicationsand scripts.OnmostsystemthisdirectoryisinyourPATHsoitwillbesearchedwhenyouenter commandsfromaterminal.MovethefileImageShow.gambasthatwehavejustcreatedinyour projectdirectorytoyour$HOME/bindirectory. Nowopenaterminalwindowandtype ImageShow.gambas&andour applicationshouldstart.The&afterthe commandissotheterminaldoesnot waitfortheImageShowprocesstoend. ItisnotrequiredtostartImageShow.

NotallLinuxdistributionhavea$HOME/bindirectory. Onsomedistributionsyoucancdtothedirectorywheretheexecutablecontained.Then type./ImageShow.gambasandtheexecutableshouldrun. Onsomedistributionsyouneedtogivethefullpathtotheexecutable.Iftheexecutable wasinadirectorycallImagesinourhomedirectorythentry: $HOME/Images/ImageShow.gambas

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page55of110

OnereasonIwantedtocreateaexecutableforthisapplicationwastodemonstratethatfilesinthe datasectionofaGambasprojectareincludedinthefinalexecutable.Andthattheyusetherelative pathwithintheapplicationfortheirfilelocation.ToprovethisworkspresstheF1keyandviewthe help.ThisshouldcorrectlyloadtheHTMLhelpfilewecreatedandloaditintothemessageboxfor display. Youcouldalsoaddalinktothisexecutableonyourdesktop.Thiswouldallowyoutorunour applicationbyclickingonanicon.Howyoudothisisdependentonthewindowmanageryouare using.Seethehelpforyourwindowmanager.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page56of110

4:

DatabaseProject:Notations

MicrosoftVisualBasicbecameverypopularontheWindowsplatform.Onereasonforthissuccess isthatMicrosoftVisualBasicwasagoodfrontendfordatabaseapplications.Manyusers,like myself,comingfromtheWindowsworldtoLinuxwillhaveexperienceofdevelopingapplications withVisualBasictoactasauserinterfacetoadatabase.Theywillwanttotransfertheseskillsto Linux.Inthisexamplewearegoingtogetyoustartedwithasmallprojecttocommunicatewithan SQLite2database.WithGambasyoucanusealmostthesamecodetocommunicatewithaMySQL orPostgreSQLdatabase.WithlaterversionsofGambasyoucanalsoconnecttoaSQLite3,ODBC orFirebirddatabase. AswithinstallingGambasthistutorial willnotcoverinstallingSQLite.SQLite shouldbeinstalledwithmostLinux distributions.Inordertocheckyouhave SQLiteinstalledonyourworkstation openaterminalandtypesqlite version.Ifaversionnumberis returnedthenSQLiteisinstalled.

Notethatthiswillcheckifversion2ofSQLiteisinstalled.Weareusingversion2becauseitis supportedbymoreversionsofGambas.NewerversionofGambasalsoworkwithSQLiteversion3. YoucancheckforSQLiteversion3withsqlite3version. IfSQLiteisnotinstalledthenyoushouldbeabletoinstallitthroughyoupackagemanagerorvisit theSQLitewebsiteathttp://www.sqlite.org/.IfyouarenewtoSQLiteitisalsoworthlookingat thedocumentationonthiswebsite. TherearetwopossibleapproachesyoucouldtaketointerfacingwithadatabaseinGambas.The firstistousetheGambasdatabaseobjects.Withthismethodyourcodewouldperformthe followingactions:


CreatethedatabaseinGambasusingtheconnectionobject. Buildthedatabasetables,indexes,etc.usingtheGambasdatabaseobjects. ReaddatafromthedatabaseusingtheResultobject.YouwouldcreatetheResultobject usingtheFindorEditmethodonthedatabaseconnection. UpdateandDeleteactionsonrecordswouldbethroughtheResultobject.Youwouldcreate

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com theResultobjectusingtheEditmethodontheconnection.

Page57of110

AddingrecordswouldbethroughtheResultobject.YouwouldcreatetheResultobject usingtheCreatemethodonaconnection. Youareabstractedfromthedatabaselayer. YoudonotneedtoknowmuchSQL(StructuredQueryLanguage). YourcodeisportablebetweenthedatabasessupportedbyGambas.Youshouldonlyneedto changetheconnectionparameterstoswitchdatabasetypes. Searchandfilteringdataismoreawkwardandislesswellsupportedthandirectlyusing SQL. Viewsanddatabasequeriesrequiringmorethanonetablearenotaswellsupportedasin directlyusingSQL. Therearesomefeaturesoftheunderlyingdatabasethatyoucannotaccess.

Thisapproachhasthefollowingadvantages:

Italsohasafewdisadvantages:

Formostkindsofdatabaseapplicationtheabovemethodisthebest.Howeverthereisasecond methodyoucoulduse.WiththismethodyouwouldbetousetheExecmethodontheconnection objecttosendSQLstatementstothedatabase.Withthismethodyourcodewouldperformthe followingactions:

Therearetwopossiblemethodyoucouldusetocreatethedatabase.

Createthedatabaseusingtoolsprovidedbythedatabasevendororathirdparty. CreatethedatabaseinGambasandbuildthetables,indexesetc.usingaSQLscript. SendthisscripttotheconnectionExecmethod.

YouwouldreaddatafromthedatabaseusingtheExecconnectionmethodusingaSQL queryandreturnthisdatatoareadonlyResultobject. Update,InsertandDeleteshouldalsobepreformedusingtheSQLstatementssenttothe Execconnectionmethod. Yougainfinegrainedcontroloverthedatabase.YoucontrolthedetailofeachSQLqueryor command. MostdatabasessupportmorefieldtypesfortablesthanaresupportedbyGambas. FeaturesinthedatabasenotsupportedinGambasareeasilyaccessible. Itiseasytoaccessdatabaseviewsandmultitablequeries. YouneedagoodknowledgeofSQLforyourtargetdatabase.

Theadvantagesare:

Possibledisadvantagesare:

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page58of110

Youneedtoformatthedatayourselfwhensendingorreceivingitfromthedatabase.For exampleyouneedtomakesuredatesareinaformatunderstoodbythedatabase. YouneedmorecarefulerrorhandlingtocatchSQLerrors.DebuggingtheSQLisalsomore complex. Yourapplicationisproperlynotportableifyouneedtoswitchdatabasetypes.

Whichmethodshouldyouchose?Mygeneraladvicewouldbe:

Ifyouonlyrequireasmalldatabaseoryouneedportabilitybetweendatabasesthenstickto thefirstmethod.InthiscasetrytoavoidusingtheExecmethodofobtainingdataorpassing SQLqueriestothedatabase. Ifyouhavealargedatabaseandthedatabasetypeisnotlikelytochangethenconsiderthe secondmethod.Alsoconsiderthesecondmethodifyourdatabasequeriesaregoingtobe largeorcomplex.IfyouselectthesecondmethodonlyusetheConnectionandResult objectsandonlyusetheExecmethodtoperformqueries.

Iwouldnotmixthetwoapproaches.Ofcoursethereisnothingtostopyouifyoureallywantto.But youcouldendupwithnoneoftheadvantagesofeithermethodandallofthedisadvantages. Inthistutorialwearegoingtodemonstratethefirstofthesemethods.Thisisafterallatutorial aboutGambasandnotSQL.AlsowecanthendemonstratemoreoftheGambasdatabaseobjects youmightwanttouse. InaAppendixtothistutorialweshalllookathowtoconvertthisNotationsexampleto thesecondapproachusingExecandSQLstatements. AcommonformofinterfacedesignforadatabaseistheMaster/Detaildesign.Hereyouhavealist ofrecordsinawindow.Thereissomefieldfromthedatabasethatsummarisesthedatabaserecords andthisisusedtocreatealist.Whenarecordfromthelistisselecteditsdetailsaredisplayedinthe restofthewindow.Ifrequiredthedetailscanbeupdatedandsavedtothedatabase.Therewillalso besomemechanismforaddinganddeletingrecords.ThisNotationsexamplewillfollowthisbasic interfacedesigntoadatabaseapplication. Withthisexamplewearegoingtocreateanotetakingapplication.Weshallstorethenotesina SQLitedatabase.Theusershouldbeableto:

Addnotes. Viewnotes. Updatenotes. DeleteNotes. Cut,CopyandPastetextfromtheClipboardtoandfromnotes.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page59of110

Viewalistofnotetitles.Youcanthenclickonanotetitletoviewthecompletenote. Searchthetextinnotetitlesandnotesforagivensearchtext.

Weshallkeepourdatabaseverysimple.Thedatabasenameisgoingtobethesameasthe applicationname.WeshallonlyneedonetableandthiswillbecalledNotes.Thefollowingentry liststhefieldsinthetable. FieldName CreateDate LastModified Type DATETIME DATETIME Comment PrimaryKey.Whenanewnoteisfirstcreatedthiswillbe settothecurrentdateandtime. Whenanoteisfirstcreatedthiswillhavethesamevalue aretheCreateDatefield.Eachtimeanoteisupdatedthis fieldwillbesettothecurrenttime. Length0foraunlimitedstring Length0foraunlimitedstring Priorityencodedasaninteger.0islow,1ismediumand3 ishighpriority.

Title Note Priority

STRING STRING INTEGER

NotationsisnamedafterapieceofmusicbytheFrenchcomposerPierreBoulez originallywrittenin1945.Thisearlyworkwasasetof12shortpiecesforpiano.Later, in1978,Boulezorchestratedfourofthepiecesforlargeorchestra.Herevisedthem againin1984.Thenaddedanadditionalorchestrationin1997.Giventhename,the historyofthemusicandthefactthatBoulezisFrenchandsoisthemaindeveloperof Gambas,BenoitMinisini,thisseemedagoodnameforanotetakingapplication.

4.1: Creatingtheproject
ThefirststepistocreateanewGambasproject.SoopenGambasandandselectNewproject.... Thiswillstartthenewprojectwizard.Thefirstpageofthewizardsimplyshowsawelcomescreen withdetailsofhowtousethenewprojectwizard.ClicktheNext>>buttontoforthenextpageof thewizard.ThisshowsapagewerewecanselectthetypeofGambasprojectwewanttobuild.We aregoingtousethedefaultoptionofagraphicalproject.SoclicktheNext>>button.Thisshowsa pagewhenyouenterthenameandtitleforyourprojectwearegoingtocreate.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page60of110

GivetheprojectthenameNotationsandthetitleNotationsanotetaking application.Leavetheotheroptionsblank.ClickontheNext>>button.Selectthelocation whereyouwanttosavetheproject.ThenclicktheNext>>button.Thisfinalpageliststheoptions youhaveselectedfortheproject.CheckthroughtheoptionsandthenclicktheOKbutton.Wehave createdanewVisualBasicprojectandGambaswillopenshowingtheGambasprojectmanager. Withthisprojectwearegoingtouseatoolbartodisplaysomebuttons.Toolbarscanprovideanice lookinginterfacetotheuserandtakeuplittlespace.Soweshallneedsomeiconsforthesebuttons. TheTangoprojectaimstoprovideacommonlookandfeeltothedesktop.Italsoprovideagood iconsetforuseinyourapplications.Youcangettherequirediconsfromtheexampleapplications thatcomewiththistutorialortheTangowebsitehttp://tangoproject.org/.Thissitealsoprovides usefulinformationaboutdesigningandusingicons. GototheprojectdirectoryandcreateasubdirectorycalledImages.Inthisdirectoryplacethe followingiconsfromtheTangoiconset.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page61of110

Thetangoiconsaregroupedintosizeandthencategory,Selectthe iconsshowninthefollowingtableandplacethemintheImages directory. IconSize 16x16 16x16 22x22 IconCategory actions status actions IconName dialog.information.png mediarecord.png documentnew.png documentsave.png editfind.png viewrefresh.png accessoriestexteditor.png helpbrowser.png xdirectorytrash.png

22x22 22x22

apps mimetypes

ThefollowingscreenshotshowshowtheImagesdirectoryshould lookaftercopyingtheseicons.

FromtheprojectmanagerwindowopentheProjectmenuandthentheProperties...submenu.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page62of110

Thisshowstheprojectpropertiesdialog.SelecttheGambasiconandthenselectthe Images/accessoriestexteditor.pngiconfromtheImagesdirectorywecreated above.

ClickontheOKbutton.TheProjectPropertiesshouldnowshowtheaccessoriestext editor.pngicon.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page63of110

IntheprevioustwoapplicationsweonlyusedthestandardGambascomponents.Howeverthereare manymorecontrolsandcomponentsavailable.Wearegoingtoaddthegb.dbDatabaseaccess componenttotheproject.ThesewillgiveusaccesstotheGambasdatabaseobjectsandprovidethe interfacetothedatabase.SelecttheComponentstabonthepreviousdialog.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page64of110

Makesurethegb.dbDatabaseaccesscomponentanditemischecked.ThenclicktheOKbutton toacceptthisdialog.

4.2: Creatingtheuserinterface
Thisapplicationisonlygoingtohaveonewindowastheinterface.Thisinterfaceisgoingtobe slightlymorecomplexthantheprevioustwoexamples.Inordertogiveussomeideaofwhatweare workingtowardshereisascreenshotofthelookoftheformwhenwehaveaddedallthecontrols anditisindesignmode.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page65of110

Clickintheprojectmanagerwindowandcreateanewform.CalltheformFormNotationsand accepttheoptionforthistobeastartupclass.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page66of110

Wearefirstgoingtocreatesomebuttonsinatoolbartogoacrossthetopoftheform.Soselectthe ContainertabintheGambastoolbox.FromthisselecttheHPanelandaddthistothetopofthe form.Resizethiscontrolsoitis42pixelsheighandthewidthisabitlessthanthewidthofthe form.Theexactwidthdoesnotmatterasthiswillbecontrolledatruntime. Toresizecontrolsfirstclickontherequiredcontrol.Thiswillshoweightresizingboxes.Thenclick anddragoneoftheseresizingboxeswiththemouse.IfyouhavetheGambaspropertieswindow openyouwillseetheHeightandWidthpropertieschange.Youcanalsoedittheseproperties directlyinthiswindow. Inthisprojectwearegoingtoaddquiteafewcontrolsthatneedtobeplaceinsidea parentcontrol.Italltoeasytoplacethenewcontrolabovetheparentcontainerrather thaninsidetheparentcontainer.Theformwillstilllookcorrectindesignmodebut unfortunatelythecontrolswillnotresizecorrectlyatruntime.Trytofollowthislittle sequenceeachtimeyouaddachildcontroltoaparentcontainercontrol: Clickontheparentcontrol.Makesureitishighlightedanditseightresizing boxesasvisible. Thenclickonthetoolboxcontrolyouaregoingtoadd. Whenyouclickanddragthemousetoaddthecontrolmakesureyouareinside therequiredparentcontrol.Alsomakesuretheeightresizingboxesarestill

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page67of110

visible. Itisagoodideaeverysooftentomovetheparentcontrolyouareaddingchildcontrols to.Thenmoveitbacktoitsdesiredpositionontheform.Whenyoudothischeckall childcontrolsmovewiththeparent.Ifanychildcontroldoesnotmovewithitsparent thenitisproperlynotplacedcorrectlyinsidetheparentcontrol.Tryaddingthethe misplacedchildcontrolagain. Thenextstepistoaddthebuttonswewantinourtoolbar.SelecttheFormtabintheGambas toolbox.Thefirstbuttonisgoingtobeournewnotebutton.NowclickontheToolButtonandadd thistotheHPanelwehavejustadded.MakesurethisbuttonisinsidetheHPanelandnotabovethe HPanel.MovethisbuttonsoitisatthefarleftoftheHPanelandis42pixelsheighand42pixels wide.NowaddtwomoreToolButtontotheHPanelthesearegoingtobeourDeletebuttonandour Refreshbutton.Moveeachbuttonsoitis42pixelsheighand42pixelswideandplacednexttothe previouslyaddedbutton.WeshouldnowhavethreebuttonsintheHPanel. ThenextbuttontoaddistheSearchbutton.WearealsogoingtoaddaTextBoxnexttothisbutton inwhichtoplacethenotessearchtext.WhentheHPanelisresizedatruntimeitwillmovecontrols ontoanadditionallineiftheydonotfitonthewidthofthecontrol.Thisisnicebehaviourand meanswecankeepallofourbuttonsvisiblenomatterhowwidetheuserresizesourformwindow. WhatwouldalsobeniceisiftheSearchbuttonandTextBoxwerealwaysnexttoeachotherwhen thisresizingtakesplaceatruntime.Wecanachievethisbyplacingthesetwocontrolsinsidea PanelwhichisinsideourHPanel.Thissearchpanelwillnotbevisibleatruntime. SoletsaddtheseSearchcontrols.SelecttheContainerstabintheGambastoolbox.Fromthis selectthePanelandaddthistotheHPanel.MovethisPanelnexttoourRefreshbuttonandsetits heightto42pixelsanditswidthtoabout224pixels.SelecttheFormtabintheGambastoolbox. AddaToolButtoninsidethissearchPanel.MoveittotheleftofthesearchPanelandresizethe buttonsoitis42pixelsheighand42pixelswide.NowaddaTextBoxtothesearchPanel.Resize thistextboxsoitisheightis21anditswidthis168.AlsomakesureitsXvalueis42anditsY valueis14.YoumayneedtousetheGambaspropertieswindowtochangesomeofthesevalues. Thefinalpartofourtoolbaristwomorebuttons.Thesewillbeforupdatinganoteandahelp dialogbutton.SelecttheFormtabintheGambastoolbox.PlacetwoToolButtonsinsidethe HPanelnexttothesearchPanel.Resizeeachbuttonsoitis42pixelsheighand42pixelswide. Thathasaddedallthecontrolsweneedforourtoolbar.Nowweshalladdthecontrolsthatformthe mainpartofourwindowanddisplayournotes.Ontheleftsideoftheformwindowwearegoingto havealistofnotes.Ontherightsidewearegoingtohavethedetailsofthecurrentlyselectednote inthelist.InorderfortheusertoresizeeachhalfofourformwindowwearegoingtouseaHSplit control.SelecttheContainerstabintheGambastoolbox.AddaHSplittotheformunderthe HPanel.WeshallbeaddingmorecontrolstotheHSplitsomakeitlargeenoughforthis.Itsexact sizedoesnotmatterasitwillberesizedatruntime.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page68of110

InGambasversion1theHSplitcontrolisnotavailablesoweshallhavetomissitout. Thismeanstheuserwillnotbeabletoresizethetwohalf'softhewindowwiththe centralbar.PlacetheColumnViewweaddnextdirectlyontheform.Alsowedirectly placesecondpanelweaddlaterdirectlyontotheform. WearegoingtouseaColumnViewtoprovidethelistofnotes.Atruntimeweshallsetthecolumn titlesandcontentforthislist.SoselecttheFormtabintheGambastoolbox.Thenadda ColumnViewtotheHSplitandmakesureitisinsidetheHSplit.PushtheColumnViewtothetop leftcorneroftheHSplitandmakeitswidthaboutaquarteroftheHSplit.Oneofthenicethings aboutusingtheHSplitcontrolisthattheresizingoftheColumnViewwillbehandledbytheHSplit controlwhenitisresized.Weshallnothavetoaddandcodeforthis. Thisnextgroupofcontrolsiswhereweshalldisplayaparticularnote.Wefirstneedtoaddanother PanelsotheHSplitgroupsthesecontrolstogetheratruntime.SelecttheContainerstabinthe Gambastoolbox.ThenaddaPaneltotheHSplit.PushthepaneltothetopoftheHSplitandnextto theColumnView.MakethesizeofthePanelcoversmostoftheareaoftheHSplitnotoccupiedby theColumnView. Thefinalsetofcontrolstoaddwillshowthedetailsforaparticularnote.Allthesecontrolsgo insidethePanelwehavejustadded.SelecttheFormtabintheGambastoolbox.Nowaddthese controlstoourPanel. Thesenextcontrolsareforthetitleofthenote.AddaLabeltothetopofthePanel.Underthe LabelplaceaTextBox. Nowaddsomecontrolswheretheusercanselectthepriorityofanote.AddanotherLabelunder theTextBoxandthenalongsidethisaddthreeRadioButtons. Thesenextcontrolsareforthecontentofthenote.AddanotherLabelunderthePriorityLabeland thenaTextAreaunderthisLabel. Wearenotdonewiththesecontrolsyet.Weneedtochangesomeoftheirproperties.Somakesure theGambaspropertieswindowisdisplayed.Clickoneachcontrolinturnandchangetherequired properties.Thisisalistofallthepropertiesweneedtochange.(Gambas1usersshouldskipthe HSplit1control.)

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com DefaultName FormNotation Property Icon Border HPanel1 ToolButton1 Name Name ToolTip Picture ToolButton2 Name ToolTip Picture ToolButton3 Name ToolTip Picture Panel1 ToolButton4 Name Name ToolTip Picture TextBox1 ToolButton5 Name Text Name ToolTip Picture ToolButton6 Name ToolTip Picture HSplit1 ColumnView1 Panel2 Label1 TextBox2 Name Name Sorted Name Name Text Name Text NewValue

Page69of110

Images/accessoriestext editor.png Resizeable HPanelTools ToolButtonNew Createanewnote Images/documentnew.png ToolButtonDelete Deletetheselectednote Images/xdirectorytrash.png ToolButtonRefresh Refreshthenoteslist Images/viewrefresh.png PanelSearch ToolButtonSearch Searchnotesfortext Images/editfind.png TextBoxSearch <blank> ToolButtonUpdate Updatecurrentnote Images/documentsave.png ToolButtonHelp Displayhelp Images/editundo.png HSplitWindow ColumnViewNotes True PanelNote LabelNoteTitle Title: TextBoxTitle <blank>

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com DefaultName Label2 RadioButton1 Property Name Text Name Group Text RadioButton2 Name Group Text RadioButton3 Name Group Text Value Label3 TextArea1 Name Text Name Text NewValue LabelNotePriority Priority: RadioButtonHigh

Page70of110

RadioButtonPriority High RadioButtonMedium RadioButtonPriority Medium RadioButtonLow RadioButtonPriority Low True LabelNoteText Note: TextAreaNote <blank>

Inordertotestourworksofarletsaddasmallamountofresizingcodecodetotheproject.Right clickontheformandaddaForm_Resizeevent.NowrightclickontheHSplitWindowobject andaddaHSplitWindow_Resizeevent.Inthesetwoeventhandlersaddthefollowingcode. Gambasversion1userswouldonlyaddtheForm_Resizeevent.Alsotheresizing codeisalittledifferentseebelow. FormNotations.class PUBLICSUBForm_Resize() HPanelTools.Width=ME.ClientWidth HSplitWindow.Move(0,HPanelTools.Height,ME.ClientWidth, ME.ClientHeightHPanelTools.Height) END PUBLICSUBHSplitWindow_Resize() TextBoxTitle.Width=PanelNote.ClientWidth

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com TextAreaNote.Resize(PanelNote.ClientWidth, PanelNote.ClientHeightTextAreaNote.Top) END

Page71of110

OurresizingcodeisslightlydifferentforGambasversion1.Thisisbecausewehadto omittheHSplitcontrol. FormNotations.class PUBLICSUBForm_Resize() HPanelTools.Width=ME.ClientWidth ColumnViewNotes.Top=HPanelTools.Height ColumnViewNotes.Height=ME.ClientHeight ColumnViewNotes.Top PanelNote.Top=ColumnViewNotes.Top PanelNote.Width=ME.ClientWidthPanelNote.Left PanelNote.Height=ColumnViewNotes.Height TextBoxTitle.Width=PanelNote.ClientWidth TextAreaNote.Resize(PanelNote.ClientWidth, PanelNote.ClientHeightTextAreaNote.Top) END

Nowitistimetotesttheworkwehavedonesofar.Hitthegreenrunbuttonintheprojectmanager orpresstheF5key.Theapplicationwilldoverylittle.Butyoushouldbeabletograbthecentral barbetweentheColumnViewandtheTextAreapanelandthecontrolswillresizethemselves correctly.(AtleastforGambas2users.)

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com Youshouldalsobeabletoresizetheformwindow andthecontrolswillresizethemselves.Iftheydonot thenthemostlikelyreasonisthatsomecontrolsare notcorrectlyinsidetheircontainers. YoucancheckthisusingtheGambasHierarchytool. Indesignmodeselecttheform.Nowfromthe GambasprojectmanagerselecttheViewmenuand thentheHierarchyoptionorpressCtrl+H.Check thecontrolshierarchyonyourformmatchesthe screenshotontheright. Ifacontrolisnotattherightlevelinthehierarchy thenclickontheoffendingcontrol.PressCtrl+Xto cutthecontrol.Thenselectthecorrectparentcontrol andpressCtrl+Vtopastethecontrolintoitscorrect container.

Page72of110

Ifacontrolisattherightlevelinthe hierarchybutnotintherightorderthen Rightclickontheparentcontroland thiswillshowapopupmenu.Selectthe Arrangementoptionandthiswillshow asubmenu.InthismenuselectLeftto right.Thiswillreorderthechildcontrol intheordertheyareontheform. Wewanttoshowsomehelpinformationstotheuserwhentheyclickonthehelpbutton.Weare goingtousethesamemethodasthepreviousproject.Thismethodissuitablewhentherequired amountofhelpissmallandwillfitononepage.TheGambasmessageboxisquiteaflexibleclass andwilltakeaHTMLformattedmessage.Sowiththesinglelineofcode: Message.Info(File.Load("help.htm")) wecandisplayaHTMLfile. SoletcreatetheHTMLfileinGambas.RightclickintheGambasprojectmanager.Thisbringsup apopupmenu.FromthelistselectNew.Thisshowsasubmenuwiththeitemswecanaddtoour project.WeneedtoaddaTextfilesoselectTextfile...fromthismenu.Givethefilethename help.htmandpresstheOKbuttontosaveit.Thiswilladdthefiletothedatasectionofyour projectandwillopenthenewtextfileintheGambastexteditorwindow.EnterthefollowingHTML

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page73of110

intothetexteditorandsaveit.Notethat,asbefore,the iconinthefollowinglistingmeansthis lineisacontinuationofthepreviousline. help.htm <html> <head> <title>NotationsHelp</title> </head> <body> <h2><fontcolor='Blue'>NotationsHelp</font></h2> <hr> <p>Notationsisasimplenotetakingapplication.The followingbuttonsareinthetoolbar: </p> <p>The<b><fontcolor='Blue'>New</font></b>buttonwillcreate anewnote <br>The<b><fontcolor='Blue'>Delete</font></b>buttonwill deletethecurrentlyselectednote <br>The<b><fontcolor='Blue'>Refresh</font></b>buttonwill showallavailablenoteinthenoteslist <br>The<b><fontcolor='Blue'>Search</font></b>buttonwill findallnoteswiththesearchtextinanoteornotetitle <br>The<b><fontcolor='Blue'>Save</font></b>buttonwill updatethecurrentnote <br>The<b><fontcolor='Blue'>Help</font></b>buttonwillshow thishelp </p> <hr> <p>Notationsv.0.0.1wasdevelopedbyTimothyMarshalNichols inMay2006.Itisissuedunderthe<b>TheGNUGeneralPublic License2</b>. </p> <hr> </body> </html>

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page74of110

ThefollowingscreenshotshowswhatthisHTMLlookslikeinamessageboxwhentheapplication isrunandtheuserpressesthehelpbutton.

Thereisonefinalfileweneed.Whenwecreatethenotesdatabaseweshallalsoaddafirstnote. Thiswillbeawelcomenotegivingtheusersomehelpinformation.Asthetextforthisnoteisgoing tobemorethanafewlinewearegoingtoloadthetextfromafile.Thismethodofloadingthetext fromafilewillbeverysimilartothatusedforthehelp.Thisalsogivesusagreatdealofflexibility ifweneedtochangethisapplicationinthefuture.Wecaneasilyincorporatetextchangestothe welcomehelptext. RightclickintheGambasprojectmanagerandselectthemenutoaddanewtextfile.Thistimegive thefilethenameWelcome.txtandpresstheOKbuttontosaveit.Thiswilladdthefiletothe datasectionofyourprojectandwillopenthenewtextfileintheGambastexteditorwindow.Enter thefollowingtextandsavethefile.Asyouwillnoticeitisverysimilartothehelptext. Welcome.txt

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com WelcometoNotations.Asimplenotetakingapplication Thefollowingbuttonsareinthetoolbar: TheNewbuttonwillcreateanewnote TheDeletewilldeletethecurrentlyselectednote

Page75of110

TheRefreshwillshowallavailablenoteinthenoteslist TheSearchwillfindallnoteswiththesearchtextinanoteor notetitle TheUpdatewillsavethecurrentnote TheHelpbuttonwillshowhelp Notationsv.0.0.1wasdevelopedbyTimothyMarshalNicholsin May2006. ItisissuedundertheTheGNUGeneralPublicLicense2.

Sowecreatedalltheitemweneedfortheuserinterfacetothisapplication.Wehaveonlyneeded7 lineofcode(and4ofthembeginningandend'stoprocedures)togetadecentinterface.Itshows thatwithalittleknowledgeofhowcontainersandcontroloperatewithinGambasyoucancreate somegooduserinterfaces.

4.3: CheckingouruserinterfaceforCRUD
Manyapplicationdeveloperswouldalreadyhaveleaptintothecodingstagebynow.Butitisworth standingbackandcheckingthedesignofourapplicationforfunctionality.Onecheckingmethod oftenusedwithdatabaseapplicationsisCRUD.CRUDstandsforCREATE,READ,UPDATE, DELETE.Itisachecklisttoapplytorecordsorentitiesindatabasetablesagainstoperations performedbyusers. TheCRUDchecklistisoftensetoutasamatrix.Alongonesidearelistedthetablesorentitiesin thedatabase.Alongtheothersidearelistedtheuserrolesforthedatabase.Insideeachcellyoulist theCRUDactionsthateachuserrolecanperformoneachtableorentity.Thefollowingdiagram demonstratesanimaginaryCRUDmatrix.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com User User1 User2 Administrator R,U C,R,U,D C,R,U,D Table1 R,U C,R,U C,R,U Table2 R,U C,R,U,D

Page76of110

Table3

FromthismatrixwecanseethatUser1canonlyreadandupdatetables1and2.User2has differentlevelsofaccesstoeachtable.TheAdministratorhasfullaccesstoalltablesapartfrom table2.Alsofortable2wehavenowayofdeletingarecord.Theseobservationsmightbecorrect forourimaginaryapplication.ButwithaCRUDmatrixlikethisweneedtochecktherequirements forourapplicationagaintofindout. CRUDisachecklist.Itisachecklistthathelpsyouspotanymissingoperationsinyour application.Thisdoesnotmeanthateveryusershouldbeabletoperformalltheseoperations.In manycasesthereareoperationsyouwouldnotwantperformedbyallusers.Forexampleina bankingdatabaseyouwouldnotwantalluserstobeabletodeletedetailsoffinicaltransactions. RatherwithCRUDyouarecheckingthefunctionalityofyourdatabaseapplication.Youthenhave tothinkaboutwhysomeusershouldhaveornothavesomeparticularfunctionality.Itisthe thinkingprocessthatisimportant. OftenanadditionaloperationisaddedtotheCRUDchecklist.ThisisLforLIST.Canauserlist databaserecords?IwouldalsoaddSforSEARCH.Canausersearchdatabaserecordsusingsome searchcriteria? TherearelotsofdescriptionsofCRUDontheinternet.SearchforCRUD+databases. Youcouldtry:http://en.wikipedia.org/wiki/CRUD_(acronym) IfindCRUDisausefulchecklistevenwhenyouarenotdealingwithadatabase.Anyplaceina applicationwhereyouareaddingorremovingdatafromcontrolsatruntimeisworthputting throughtheCRUDchecklist.Thiscouldbeagrid,atextarea,acomboboxormanyothercontrols. CRUDismostoftenpresentedasamatrix.InourNotationsapplicationweonlyhaveoneuserand onetable.Sothematrixlooksabitsilly.InsteadletsusetheCRUDLSchecklisttothinkaboutthe actionsperformedbyouruseronthedatabaserecords.

Create:Theusercancreatenotesusingtheaddbutton.Thiswilladdthecurrentcontentof theNoteTitletextbox,PriorityselectionandNotetextareatothedatabase. Read:ClickingonanoteinthecolumnviewwillplacethatrecordintheNotetextbox, PriorityRadioButtonsandNotetextareasoitcanberead. Update:Clickingontheupdatebuttonwillsaveanychangestothecurrentnotetothe database.Alsoifanychangesaremadetoanoteandanactionisattemptedwhichcouldlose

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page77of110

thechangesawarningmessageisdisplayed.Youcanthenchoosetocontinueandlosethe changesorcanceltheaction.

Delete:Byselectingarecordinthecolumnviewandthenclickingthedeletebuttonthe currentlyselectedrecordwillbedeleted. List:Alistofdatabaserecordsisshowninthecolumnview.ClickingontheRefreshbutton willloadallnotetitlesintothecolumnview. Search:Inthetoolboxwehaveatextboxwhereyoucanenterasearchstring.Clickingon thesearchbuttonnexttothistextboxwilllistalldatabaserecordsthatcontainthistextina NoteTitleorNote.Ifyouwanttogetthecompletelistofnotesbackagainthenyouwould clicktherefreshbutton.

4.4: Addingthecode
Thisisthesectionwherewegetourapplicationtodoit'srealwork.Thecodeforthisapplicationsis splitintotwosections.Thefirstistheformwindowthathandlestheuserinterface.Wehavejust createdthecontrolsweneedforthisandtheresizingcode.Laterweshalladdcodetohandle operationscreatedwhentheusereditsnotes.Thesecondcodesectionisgoingtobetheinterfaceto thedatabase.Creatingthismoduleiswhatwearegoingtodonext. OurcodetocommunicatewiththedatabaseisgoingtobeplacedinaGambasmodule.Havingthis databasecodeinonemodulemakesiteasiertoseparatethedatabasespecificcodefromtheuser interfacecode.RightclickintheGambasprojectmanagerandselectNewfromthepopupmenu. ThenselectModule...fromthesubmenu.InthedialogcallthemoduleModuleDatabaseand leavethecheckboxesinthedefaultstateofunchecked.ClickontheOKbuttontocreatethe module. Wefirstneedtwovariablesthatareusedbyanumberofprocedures.Thefirstisadatabase connectionobject.ThisisonlyusedinsidethisproceduresoitismadePRIVATE.Thesecond variableisaResultobject.ThisholdsourNotesdataaswellasbeingusedtoupdateanddelete notes.AsitisalsousedbytheFormNotationsclassitismadePUBLIC. ModuleDatabase.module PRIVATEdatabaseConnectionASNEWConnection PUBLICNotesASResult ContinuedBelow

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com Ourfirstprocedureopensadatabaseconnection.Itperformsthefollowingactions:


Page78of110

Openaconnection(tothedatabaseserveronly). Checkiftheserverconnectionhasadatabasewiththerequireddatabasename. Ifthereisnodatabasewiththerequireddatabasenamethencreateanewdatabase. Closetheserverconnection. Openaconnectiontothedatabase. CheckifthedatabasehasaNotestable. IfthereisnoNotestableinthedatabasethenaddthistable.Alsoaddadefaultwelcome notewithsomeinformationabouthowtousethisapplication.

Firstwesetuptheinformationfortheconnectiontothedatabaseserver.Weusetheinformation passedtotheprocedurefordatabasetype,hostname,usernameandpassword.Noticewesetthe databasenamepropertytoablankstring.Thisisbecausewewanttoopenaconnectiontotheserver firstandcheckthatthedatabaseexists.Havingsetuptheconnectionwetrytoopenit.Thisisone ofthekeypointstheprocedurecouldproduceanderror.Wethentestifthedatabasenamewe requirealreadyexists.Ifitdoesnotexistthenweaddthisdatabasetotheserver. ForaSQLitedatabaseIfoundyouneededtogivethesystemashortdelaytowritethenewly createddatabasetodiskbeforeattemptingtoopenit.Thisisnotrequiredforclient/servertypesof databaseslikeMySQLorPostgreSQL.Asitdoesnotdoanyharmweincludeitforalltypesof databases. Ifwereachthispointthenweknowtheseexistsadatabasewiththerequiredname.Sowesetthe databasenameontheconnection.(Wealsosetthehostnameagain,thisisnotstrictlynecessary,but Ithinkitmakesthecodeabitmorereadable.)Thenweopenthedatabaseconnection.Thisisthe secondkeypointwherewecouldproduceanderror. Wethentestifthenotestableexistsinthedatabase.Ifthetabledoesnotexistthenweneedtoadd it.Wedothisbycreatinganewtableobjectusingourdatabaseconnection.Wethenaddthe requiredfieldstothistableandstatewhichfieldistheprimarykeyforthetable.Inordertowrite thenewtableintothedatabasewecalltheupdatemethodonthetableobject. ThefollowingtableshowssomeinformationaboutthefieldsforourNotestable.Theinformationin thefirstthreecolumnsisrequiredbyGambas.ThefinalcolumnsshowwhattheGambasdatatypes maptoforsomedatabasetypes. FieldName CreateDate LastModified GambasType gb.Date gb.Date Comment PrimaryKey SQLite2Type DATETIME DATETIME MySQLType datetime datetime

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com FieldName Title Note Priority GambasType gb.String gb.String gb.Integer Comment Length0fora unlimitedstring Length0fora unlimitedstring SQLite2Type TEXT TEXT INT4

Page79of110

MySQLType text text int(11)

Wearegoingtowriteaproceduretoaddrecordstoourdatabase.Sowemayaswellusethisto createafirstrecordinourdatabase.Thecontentofthenoteistakenfromthewelcometextfilewe createdabove.Asthisisarelativefilepathitwouldbeincludedintheapplicationwhenitis compiled. Gambasversion1doesnotunderstandtheDconvfunction.Solinesthatincludeit: ...Dconv(Error.Text)... shouldjustomitthefunctioncall: ...Error.Text... ThisalsoappliestomostoftheproceduresinModuleDatabasethatfollow. ModuleDatabase.module PUBLICSUBOpenDatabase(DBTypeASString,DBHostASString,DBName ASString,UserNameASString,UserPasswordASString) DIMnotesTableASTable DIMerrorMessageHeaderASString 'Openaconnection(tothedatabaseserveronly) databaseConnection.Type=Lower(DBType) databaseConnection.Host=DBHost databaseConnection.Name="" databaseConnection.Login=UserName databaseConnection.Password=UserPassword databaseConnection.Port="" 'Opentheconnection TRYdatabaseConnection.Open() IFERRORTHEN errorMessageHeader="Couldnotopendatabaseconnection"& DBHost Error.Raise(Error.Text)

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com ENDIF

Page80of110

'Checkiftheserverconnectionhasadatabasewiththe 'requireddatabasename. IFNOTdatabaseConnection.Databases.Exist(DBName)THEN PRINT"Databasenotfound.Creatingnewdatabase" 'Createnewdatabase databaseConnection.Databases.Add(DBName) 'IfoundIneededthiswithaSQLitedatabase '(butnotwithaMySQLdatabase) WAIT0.5 ENDIF 'Closetheserverconnection databaseConnection.Close() 'Openaconnectiontothedatabase databaseConnection.Host=DBHost databaseConnection.Name=DBName TRYdatabaseConnection.Open() IFERRORTHEN errorMessageHeader="Couldnotopendatabase"&DBName& "on"&DBHost Error.Raise(Error.Text) ENDIF 'CheckifthedatabasehasaNotestable IFNOTdatabaseConnection.Tables.Exist("Notes")THEN PRINT"Databasetablesnotfound.Creatingnewnotestable" 'AddaNotestabletothedatabase notesTable=databaseConnection.Tables.Add("Notes") notesTable.Fields.Add("CreateDate",gb.Date) notesTable.Fields.Add("LastModified",gb.Date) notesTable.Fields.Add("Title",gb.String,0) notesTable.Fields.Add("Note",gb.String,0) notesTable.Fields.Add("Priority",gb.Integer,,0) notesTable.PrimaryKey=["CreateDate"] notesTable.Update() 'Addadefaultwelcomerecord AddData("Welcome",File.Load("Welcome.txt"),0)

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com ENDIF CATCH IFerrorMessageHeader=""THEN

Page81of110

errorMessageHeader="Databaseconnectionerror:"&DBName& "on"&DBHost ENDIF Error.Raise("<b>"&errorMessageHeader&"</b><hr>Error:<br>"& DConv(Error.Text)) END ContinuedBelow Asyoucanseemostoftheaboveproceduredealswithcheckingwehaveavaliddatabaseand tables.Thecodetocreatetheconnectionisrelativelysmall.Ifyouknewyouhadavaliddatabase thenyoucouldcutthisproceduredowntothefollowingcode: databaseConnection.Type=Lower(DBType) databaseConnection.Host=DBHost databaseConnection.Name=DBName databaseConnection.Login=UserName databaseConnection.Password=UserPassword databaseConnection.Port="" databaseConnection.Open() Alsoyouwouldneedsomeerrorcheckingwhenyouopenedthedatabaseconnection. Whencommunicatingwithadatabaseitisimportanttohandleanypossibleerrors.Butwhereisthe bestplaceinyourapplicationforsuchcode?Wewantthismoduletobegeneralandflexible.So herewejustformattheerrormessage.TheGambasmessageboxcanuseHTMLformattingsowe addsomeinformationandHTMLformattingandpassontheerrorusingtheError.Raise method.ThismeansthatinthecodeintheFormclassweneedtocatchtheseerrorsanddisplaythe errormessage.Therearethreepossibleerrorswecouldhaveinthisprocedure:

Whenweopenaconnection(tothedatabaseserveronly). Whenweopenadatabaseconnection. Anyothertypeoferror.Forexampleifwedonothavepermissionstocreatethedatabaseor table.

Thismodulewillgiveaslightlydifferenterrormessageineachcase.Intheproceduresbelowwe adoptasimilarapproachtohandlingerrors.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page82of110

Thefollowingprocedurewillclosetheconnectiontothedatabase.Thisprocedureiscalledwhenwe closeourapplication.WeplaceaTRYbeforetheclosemethodaswedonotwantanyerrors displayedtotheuserifthedatabaseisalreadyclosed.Ifthereisaerrorclosingthedatabasewe PRINTasmessage.Thisissoyoucanseeerrorswhendevelopingtheapplication.Howeverthe usershouldnotseethismessage. ModuleDatabase.moduleContinued PUBLICSUBCloseDatabase() TRYdatabaseConnection.Close() IFERRORTHENPRINT"Errorclosingdatabase" END ContinuedBelow ThisnextfunctionaddsarecordtoourNotesdatabasetable.Thevaluespassedtothefunctionare theNoteTitle,theNoteitselfanditsPriority.Forthecreationandlastmodifiedtimeweusethe currenttime. UsingtheCreatemethodontheconnectionobjectwecreateaResultobjectthatisdesignedto addrecordstoadatabasetable.WepassthenameofthetabletotheCreatemethod.Thisreturns aResultobjectthathasoneemptyrecordinit.ThefieldsinthisResultobjectarethefieldsinour table.Wethenfillthefieldswiththerequiredvaluesforthenewrecord.ThenwecalltheUpdate methodwhichwilladdournewrecordtothedatabasetable. Ifthereareanyerrorsincreatingthedatabaserecordtheweformattheerrormessageandpassitup tothecallingprocedure.Thefunctionreturnsathedateandtimethatthenotewascreated.This dateandtimeisthevalueofthekeyfieldofthenewlycreatednote.Itallowsthecallingprocedure tofindthenewnoteusingthiskey. ModuleDatabase.moduleContinued 'Createarecord PUBLICFUNCTIONAddData(TitleASString,NoteASString,Priority ASInteger)ASString DIMnewNoteASResult DIMcreateTimeASDate createTime=Now

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com newNote=databaseConnection.Create("Notes") newNote["CreateDate"]=createTime newNote["LastModified"]=createTime newNote["Title"]=Conv(Title,Desktop.Charset, databaseConnection.Charset) newNote["Note"]=Conv(Note,Desktop.Charset, databaseConnection.Charset) newNote["Priority"]=Priority newNote.Update() RETURNFormatDate(createTime) CATCH

Page83of110

Error.Raise("<b>Adddatabaserecorderror</b><hr>Error:<br>"& DConv(Error.Text)) END ContinuedBelow AResultobjectisastructurethatcanstoretheresultofadatabasequery.Therearethreekindsof ResultobjectsCreate,ReadandWrite.TherearefourmethodwecanusedtocreateaResult object.ThefunctionalityofthereturnedResultobjectdependsonthemethodusedtocreateit. Thesemethodsaresummarisedinthefollowingtable.WehavealreadyusedtheCreatemethodto addadatabaserecordseeabove.Butwealsopresentitheretobecomplete. Method ResultType Comment CreatesaResultobjectwithonerecordthat canbeusedforaddingrecordstoatable. Thismethodreturnsdatafromasingletable. Tableisthe(caseinsensitive)nameofthe databasetable.RequestisaoptionalSQL typeWHEREclauseusedtofilterthetable rows.Argumentsisaoptionallistof parameterstobesubstitutedintheRequest clause.ThereturnedResultobjectcannotbe updated.

Create(TableASString) Create ASResult Find(TableASString[, ReadOnly RequestASString, Arguments...])ASResult

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com Method ResultType Comment

Page84of110

Edit(TableASString[, Read/Write RequestASString, Arguments...])ASResult

Thismethodreturnsdatafromasingletable. Tableisthe(caseinsensitive)nameofthe databasetable.RequestisaoptionalSQL typeWHEREclauseusedtofilterthetable rows.Argumentsisaoptionallistof parameterstobesubstitutedintheRequest clause.ThereturnedResultobjectis updateable. InthereturnedResultobjectrecordscanbe updatedbymovingtoarowchangingthe fieldvaluesandcallingtheUpdatemethod. Recordscanbedeletedbymovingtoarow andcallingtheDeletemethod.Therecord isthendeletedfromtheunderlyingdatabase table. YoucannotaddrecordtothiskindofResult object.SeetheCreatemethodabove. HereRequestisanySQLquery. Argumentsisaoptionallistofparameters thatareusedinthequery.ThereturnedResult objectcannotbeupdated. ThismethodcanbeussendanySQLqueryto thedatabase.Seeabove

Exec(RequestASString [,Arguments...])AS Result

ReadOnly

WewanttobeabletoeditdatabaserecordssoweusetheEditmethodtoreturnaResultobject. Usingthenameofournotestableasaparametertoselectallthedatabasenotesrecords.Ifthereare anyerrorsinselectingthedatabaserecordsthenweformattheerrormessageandpassituptothe callingprocedure. ModuleDatabase.moduleContinued 'Readatable PUBLICSUBSelectData() Notes=databaseConnection.Edit("Notes") CATCH Error.Raise("<b>Selectdatabaserecordserror</b><hr>Error:<br>" &DConv(Error.Text)) END ContinuedBelow

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page85of110

WeopenedtheNotesResultobjectwiththeEditmethodontheConnectionobject.Wepassed theEditmethodthenameourNotesdatabasetable.ThismeanswehaveaResultobjectthatcan beedited.Herewewanttoupdatearecord.Thefirstvaluespassedtothefunctionistheindexinthe Resultobjectoftherecordwewanttoupdate.Thefirstthingthisproceduredoesistomovetothis record. TheothervaluespassedtothefunctionarethenewvaluesfortheNoteTitle,theNoteitselfandits Priority.ThesevaluesarecopiedtotheResultobject.WealsosettheLastModifiedfieldtothe currentdateandtime.WedonotchangetheCreateDateasthisisthekeyfield.Whenwehave settherequiredvaluesforthetablesfieldstheUpdatemethodisthencalledtoupdatethe databasetable.Ifthereareanyerrorsinupdatingthedatabaserecordthenweformattheerror messageandpassituptothecallingprocedure. ModuleDatabase.moduleContinued 'Updatearecord PUBLICSUBUpdateData(RowASInteger,TitleASString,NoteAS String,PriorityASInteger) Notes.MoveTo(Row) Notes["LastModified"]=Now Notes["Title"]=Conv(Title,Desktop.Charset, databaseConnection.Charset) Notes["Note"]=Conv(Note,Desktop.Charset, databaseConnection.Charset) Notes["Priority"]=Priority Notes.Update() CATCH Error.Raise("<b>Updatedatabaserecorderror</b><hr>Error:<br>" &Dconv(Error.Text)) END ContinuedBelow InordertodeleteanotesrecordallweneedistheindextothenotesrecordrowintheResultobject. Thisispassedasaparametertothedeletefunction.Wemakesureweareonthisrowandcallthe ResultobjectsDeletemethod.Thisdeletestherecordfromthedatabasetable.Ifthereareany errorsindeletingthedatabaserecordthenweformattheerrormessageandpassituptothecalling

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com procedure. ModuleDatabase.moduleContinued 'Deletearecord PUBLICSUBDeleteData(RowASInteger) Notes.MoveTo(Row) Notes.Delete() CATCH

Page86of110

Error.Raise("<b>Deletedatabaserecorderror</b><hr>Error:<br>" &DConv(Error.Text)) END ContinuedBelow Inthedatabasemoduleweprovideamethodthatconvertsadateobjecttoaformatteddatestring. Wedothissowecanhaveacommonformatforthedate/timeinourapplication.Wealwaysusethis methodcalltoformatthedate.Thenifweeverneedtochangethedateformatweonlyhavetodo thisinoneplace. ModuleDatabase.moduleContinued PUBLICFUNCTIONFormatDate(dASDate)ASString RETURNFormat(d,"ddmmmyyyyhh:nn:ss") END

Sofarwehavecreatedauserinterfaceandwehavejustcreatedainterfacetothedatabase.Nowwe needtobringthesetwosectionstogether.Weneedtoaddthecodesothatwhentheusereditsanote intheuserinterfaceitconnectstoandupdatesthedatabase. ThefirstprocedurehandlestheFormopenevent.Thisisrunthefirsttimetheformisloadedandso isagoodplaceforoursetupcode.Wesetthetitletotheformwindowtoincludetheapplication nameandversion.WehaveaColumnViewontheleftoftheformwhichwillshowalistofthe availablenotesinthedatabase.HereweconfigurethisColumnViewandsetthenumberofcolumns andthetextforthecolumnheadings.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page87of110

Wethencallsomefunctionstotodisplayinformationfromthedatabase.Firstwecallthefunction wecreatedabovetocreateadatabaseconnection.Wethencallfunctionstorefreshthenoteslistin theColumnViewandtodisplaythecurrentlyselectednote.Ourdatabaseprocedurescanthrow errorssoweneedtocatchtheseanddisplaytheerrormessage. Whencallingaproceduresorfunctioninamodulewehavetousetheformat: ModuleName.ProcedureName(...) or object=ModuleName.FunctionName(...) withoutprefixingtheproceduresorfunctionwiththemodulenameiswillnotbevisiblewithinthe callingobject.AlsoonlyPUBLICproceduresorfunctioninamodulecanbeaccessed. SomeolderversionsofGambasuseSystem.HometoreturntheusersHome directory.Sothelinethatcallsouropendatabasemethodshouldbechangedtothe following: ModuleDatabase.OpenDatabase("sqlite",System.Home, Application.Name,"","") FormNotations.class PRIVATEchangesMadeASBoolean PUBLICSUBForm_Open() ME.Title=Application.Name&"Version:"& Application.Version 'ColumnViewproperties ColumnViewNotes.Columns.Count=3 ColumnViewNotes.Columns[0].Text="P" ColumnViewNotes.Columns[0].Width=20 ColumnViewNotes.Columns[1].Text="Title" ColumnViewNotes.Columns[1].Width=150 ColumnViewNotes.Columns[2].Text="LastModified" ColumnViewNotes.Columns[2].Width=150 'UsethisconnectionforaSQLitedatabase ModuleDatabase.OpenDatabase("sqlite",User.Home, Application.Name,"","")

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com RefreshNotes() IFColumnViewNotes.Current<>NULLTHEN DisplayNote(ColumnViewNotes.Current.Key) ENDIF CATCH Message.Warning(ERROR.Text) END ContinuedBelow

Page88of110

Whentheformisabouttocloseweneedtocheckiftheuserhasmadeanychangestothecurrent notethathavenotbeensavedyet.Aswearegoingtohavetoperformthistestinanumberofplaces wehavewrittenasmallfunctionforthis.Itwillshowamessageboxwarningofanyunsaved changes.ThisfunctionreturnsTRUEiftheuserwantstocanceltheselectedaction.Tocancelthe closeeventontheformweusetheSTOPEVENTstatement.STOPEVENTonlycancelstheevent andpreventsanyothereventshandlersfortheeventbeingcalled.Itdoesnotexitthecurrentevent handler.SoweneedtheRETURNstatementtodothis. IftherewerenochangestothedatabaseortheuserclickedtheContinuebuttonwhenprompted aboutunsavedchangesthenweclosethedatabaseconnectionandquittheapplication. FormNotations.classContinued PUBLICSUBForm_Close() IFTestChangesMade()THEN STOPEVENT RETURN ENDIF ModuleDatabase.CloseDatabase() END ContinuedBelow Thisisourformresizingcodeagain.Wehaverepeateditheretoshowitspositioninthecode listing.(IfyouareusingGambasversion1yourcodemaylookdifferent.Seeabove.) FormNotations.classContinued

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page89of110

PUBLICSUBForm_Resize() HPanelTools.Width=ME.ClientWidth HSplitWindow.Move(0,HPanelTools.Height,ME.ClientWidth, ME.ClientHeightHPanelTools.Height) END PUBLICSUBHSplitWindow_Resize() TextBoxTitle.Width=PanelNote.ClientWidth TextAreaNote.Resize(PanelNote.ClientWidth, PanelNote.ClientHeightTextAreaNote.Top) END ContinuedBelow Thenextgroupofprocedureshandleeventswhentheuserclicksonabuttoninourtoolbar.This procedurehandlestheclickeventwhentheuserselectsthenewnotebutton. Firstwecheckwhichofthenotepriorityradiobuttonsisselectedandsetaintegerbaseduponthe selection.Thepriorityvalue0isforlowpriority,thevalue1isformediumpriorityandthevalue2 isforhighpriority.Wethensendthisvaluealongwiththetitletextandnotetexttotheaddnote functionwecreatedearlier. Addingthenotetothedatabaseisveryeasy.Themainproblemisfindingitagain!Whentheuser addsanewnotewewantthenewnotetobehighlightedintheColumnViewandtobethecurrently selectednote.OurAddDatafunctionreturnsthekeyofthenewlycreatednote.Wethencallour refreshnotemethodtoupdatetheColumnView.Thisshouldincludethenewnote.Wethensearch thetextintheColumnViewLastModifiedcolumnforthekeyandmakethisthecurrentnote. FormNotations.classContinued PUBLICSUBToolButtonNew_Click() DIMkeyASString DIMpriorityASInteger IFRadioButtonHigh.ValueTHEN priority=2 ELSEIFRadioButtonMedium.ValueTHEN

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com priority=1 ELSE priority=0 ENDIF key=ModuleDatabase.AddData(TextBoxTitle.Text, TextAreaNote.Text,priority) RefreshNotes() 'Findthenotewejustcreated IFColumnViewNotes.MoveFirst()THENRETURN REPEAT IFkey=ColumnViewNotes.Item[2]THEN

Page90of110

ColumnViewNotes[ColumnViewNotes.Item.Key].Selected=TRUE BREAK ENDIF UNTILColumnViewNotes.MoveNext() 'Makethenotewecreatedthecurrentnote IFColumnViewNotes.Current<>NULLTHEN DisplayNote(ColumnViewNotes.Current.Key) ENDIF CATCH Message.Warning(ERROR.Text) END ContinuedBelow ThisprocedureistohandlewhentheuserclicksontheDeleteNotetoolbarbutton.Wefirstcheck thatanotehasbeenselectedintheColumnViewtodelete.Ifanoteisselectedwedisplayawarning messagethatallowstheusertocanceltheaction.IftheyselectYestothispromptwecallthedelete methodwecreatedearlier.WethencallourrefreshnotemethodtoupdatetheColumnViewand thencallourdisplaymethodtoshowthedefaultnote. FormNotations.classContinued PUBLICSUBToolButtonDelete_Click() IFColumnViewNotes.Current<>NULLTHEN IFMessage.Warning("Areyousureyouwanttodeletethe

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page91of110

note?\n\n"&ModuleDatabase.Notes["Title"],"Yes","Cancel")=1 THEN ModuleDatabase.DeleteData(ColumnViewNotes.Current.Key) RefreshNotes() IFColumnViewNotes.Current<>NULLTHEN DisplayNote(ColumnViewNotes.Current.Key) ENDIF ENDIF ELSE Message.Info("Nonotehasbeenselectedtodelete") ENDIF CATCH Message.Warning(ERROR.Text) END ContinuedBelow WenowhandletheeventwhentheRefreshtoolbarbuttonisclicked.Wewantarefreshbutton because,asweshallseeinthenextprocedure,theusercanselectjustthenotesthatcontaina specificsearchtext.ThiswillrefreshtheColumnViewanddisplayallnotes. Beforewerefreshthelistwecheckthattherearenounsavedchangedtothecurrentnoteusingthe functionwearegoingtocreatebelow.Wethenusecodesimilartothatintheformopeneventto displaytheColumnViewlistanddisplaythedefaultnote. FormNotations.classContinued PUBLICSUBToolButtonRefresh_Click() IFTestChangesMade()THENRETURN RefreshNotes() IFColumnViewNotes.Current<>NULLTHEN DisplayNote(ColumnViewNotes.Current.Key) ENDIF CATCH Message.Warning(ERROR.Text) END

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page92of110

ContinuedBelow ThisprocedurehandlestheeventoftheuserclickingontheSearchbutton.Theuserwillhave enteredsometextintheTextBoxSearchnexttothesearchbutton.Theobjectiveofthis procedureisthentosearchthroughallnotetitlesandthenotecontentsforthesearchtext.Andto placeallthenotesthatcontainthesearchtextintheColumnView. Westartthisprocedurebycallingourfunctiontotestifthecurrentnotehaschangesthathavenot beensaved.Wearegoingtocreatethisfunctionbelow.Nextwetestiftheuserhasenteredsome texttosearchforintheTextBoxSearchcontrol.Ifthereisnotexttherewedisplayamessageto theuser. ToperformthesearchwecalltheRefreshNotesproceduresendingitthesearchtextasaparameter. Wethentestifthisprocedurefoundanynoteswiththerequiredsearchtext.Ifsomenoteshavebeen foundthentheColumnView'scurrentvaluewillbeset.Ifitissetthenwecallourprocedureto displaythecurrentnote.Ifnonoteshavebeenfoundthenweclearthecontrolsontherighthalfof theformwindowthatdisplaythecurrentnoteandalsodisplayamessagetotheuserinformingthem thatthesearchtexthasnotbeenfound. FormNotations.classContinued PUBLICSUBToolButtonSearch_Click() IFTestChangesMade()THENRETURN IFTextBoxSearch.TextTHEN RefreshNotes(TextBoxSearch.Text) IFColumnViewNotes.Current<>NULLTHEN DisplayNote(ColumnViewNotes.Current.Key) ELSE TextBoxTitle.Text="" RadioButtonMedium.Value=FALSE RadioButtonHigh.Value=FALSE RadioButtonLow.Value=FALSE TextAreaNote.Text="" changesMade=FALSE Message.Info("Thesearchtext\""&TextBoxSearch.Text& "\"hasnotbeenfoundinanynote") ENDIF

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com ELSE

Page93of110

Message.Info("Thereisnosearchtexttofindinnotes") ENDIF CATCH Message.Warning(ERROR.Text) END ContinuedBelow Thisprocedurehandlestheeventwhenthebuttontoupdatethecurrentlyselectednoteisclicked. Wefirsttestifthereisacurrentlyselectednoteanddisplayamessageifnonoteisselected. Nextwefindthevaluetosendtothedatabaseforthepriorityfromthepriorityradiobuttons.We thensavetheindexkeytothecurrentnotesowecanfinditagainafterwerefreshthenoteslist.We thencallourdatabaseproceduretoupdateanote.Thisprocedurerequirestheindexkeyforthenote toupdatealongwiththeinformationforthenote. WecallourproceduretorefreshthenoteslistintheColumnViewwiththenewdata.Thisprocedure willsetthecurrentnotetoadefaultnote.Buthereisyourbemoreusefultotheusertodisplaythe notetheyhavejustupdated.Soweusetheindexkeywehavesavedtosetthecurrentiteminthe ColumnView.Wethencallthedisplaynoteprocedurepassingittheindexkeytodisplaythe updatednotecontent. FormNotations.classContinued PUBLICSUBToolButtonUpdate_Click() DIMpriorityASInteger DIMnoteNumberASInteger IFColumnViewNotes.Current=NULLTHEN Message.Info("Nonotehasbeenselectedtoupdate") RETURN ENDIF 'Getvaluefromradiobuttonsforpriority IFRadioButtonHigh.ValueTHEN priority=2 ELSEIFRadioButtonMedium.ValueTHEN priority=1

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com ELSE priority=0 ENDIF noteNumber=ColumnViewNotes.Current.Key 'Updatechangedrecord

Page94of110

ModuleDatabase.UpdateData(noteNumber,TextBoxTitle.Text, TextAreaNote.Text,priority) 'Refreshthenoteslist RefreshNotes() 'Displaythisnote ColumnViewNotes[noteNumber].Selected=TRUE DisplayNote(noteNumber) CATCH Message.Warning(ERROR.Text) END ContinuedBelow Thehelpbuttonisverysimple.WeloadtheHTMLhelpfilewecreatedearlierintoamessagebox todisplaythehelp. FormNotations.classContinued PUBLICSUBToolButtonHelp_Click() Message.Info(File.Load("help.htm")) END ContinuedBelow ThiseventhandlerisforwhentheuserclicksonarowintheColumnView.Wethenwantthenote theuserclickedontobedisplayed.Weknowtheusermusthaveclickedonavalidnoteasclick eventisonlyfirediftheColumnViewhassomeitemstoselect.Wecheckiftherehavebeenchanges madetothepreviousnotethathavenotbeensaved.Wearegoingtocreatethisfunctionbelow.If theuserselecttocanceltheactionwehighlightthepreviousnoteintheColumnView.Ifthereare nounsavedchangesortheuserhasselectedtocontinuethenwecallourdisplaynotesmethodto showtheselectednote.ThekeyoftheColumnViewviewitemwehavedesignedtomatchtheindex forthenote.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page95of110

FormNotations.classContinued PUBLICSUBColumnViewNotes_Click() 'Checkifchangeshavebeenmadetothepreviousnote IFTestChangesMade()THEN 'Userselectedtocancelchangeofnote 'Displaythepreviousnote ColumnViewNotes[ModuleDatabase.Notes.Index].Selected=TRUE ELSE 'Displaythenewnote DisplayNote(ColumnViewNotes.Current.Key) ENDIF END ContinuedBelow Thisgroupofeventhandlersareusedtodetectiftheuserhasmadeanychangestothecurrentnote. IfthetextinaTextBoxorTextAreaismodifiedtheChangeeventiscalled.AlsotheClickeventon theRadioButtonisusedtodetectifaRadioButtonhasbeenselected.Notethattheclickeventon theRadioButtonisalsocallediftheuserchangedthecurrentRadioButtonusingthekeyboard. FormNotations.classContinued PUBLICSUBTextBoxTitle_Change() changesMade=TRUE END PUBLICSUBTextAreaNote_Change() changesMade=TRUE END PUBLICSUBRadioButtonPriority_Click() changesMade=TRUE END

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com ContinuedBelow

Page96of110

WenowcometotheprocedureswehaveintheFormNotationsclass.Wehavecalledallofthese proceduresinthecodeabove.Thisfirstprocedurewehavecalledmanytimesabove.Itisused refreshtheColumnViewwiththecurrentnotesfromthedatabase. MyfirstintentionwastowriteseparateproceduresforrefreshingtheColumnViewnoteslistandfor searchingnotesforsomesearchtext.Insomewaysthisisthemoreobviousdesignchoice.Butifwe hadusedtwoproceduresmostofthecodeineachprocedurewouldhavebeenthesame.Soitseems bettertouseaOPTIONALparametertotheRefreshNotesprocedureasthesearchtext.Ifthis parameterissetthenfilteroutthenotesthatdonotcontainthistext. Wecallourdatabaseproceduretoselectallthenotesinthedatabase.Wewantthedefaultnotetobe thefirstnotewefindwiththehighestpriority.WeusethefirstItemvariabletokeeptrackofthe priorityofthenotewehaveselected.SoweneedtoinitialisefirstItemtoavaluelowerthenany possiblepriorityvalueinthedatabase.WethenconverttheSearchTextvariabletolowercaseso wecanperformacaseinsensitivesearchforthesearchtext.NextwecleartheColumnViewofany itemsthatitcurrentlymaycontain. Nowwecometothemainloopofthisprocedure.Hereweloopthroughalltherecordthathave beenreturnedfromthedatabase.Wedecideifwewanttotestforthesearchtextbycheckingifthe variableSearchTexthasavalue.IfSearchTexthasavaluethenwecheckifthesearchtext canbefoundinthenotesTitlefieldorinthenotesNotefield.Ifitcannotbefoundweusethe CONTINUEstatementtoskipprocessingthecurrentrecord. WeaddeachitemtotheColumnViewandselecttheimagefortheitembaseduponthepriority field.ThisplacestheimageinthefirstcolumnoftheColumnView.WeusethetextvaluesH, Mand(aslow)forthepriorityvaluessotheitemscanbesortedbypriority.(IfweusedLfor thelowpriorityitemsthelistwouldhavethelowpriorityitemsbetweenthehighandmedium priorityitems.Thiswouldnotlookverygood.) OneimportantpointisusingtheindexfromtheResultobjectasthekeytotheColumnViewitems. ThisenablesustoeasilyfindarecordintheResultobjectwhenweneedtoupdateordeleteanotes recordinthedatabase. WetheaddthetitleofthenotetothesecondcolumnoftheColumnView.Thenweaddthenotes lastmodifieddateandtimetothethirdcolumn.Hereweformatthedataandtimeusingthefunction inourdatabasemodule.Thefinalcheckintheloopistomakethedefaultselecteditemthefirst itemwefindwiththehighestpriority.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com FormNotations.classContinued PRIVATESUBRefreshNotes(OPTIONALSearchTextASString) DIMfirstItemASInteger ModuleDatabase.SelectData() firstItem=1 SearchText=Lower(SearchText) ColumnViewNotes.Clear FOREACHModuleDatabase.Notes IFSearchTextTHEN

Page97of110

IFNOT((InStr(Lower(ModuleDatabase.Notes["Title"]), SearchText)>0)OR (InStr(Lower(ModuleDatabase.Notes["Note"]),SearchText)> 0))THEN 'Ifthesearchtextisnotfoundthengoontothenext record CONTINUE ENDIF ENDIF IFCInt(ModuleDatabase.Notes["Priority"])=1THEN ColumnViewNotes.Add(ModuleDatabase.Notes.Index,"M", Picture["Images/dialoginformation.png"]) ELSEIFCInt(ModuleDatabase.Notes["Priority"])>1THEN ColumnViewNotes.Add(ModuleDatabase.Notes.Index,"H", Picture["Images/mediarecord.png"]) ELSE ColumnViewNotes.Add(ModuleDatabase.Notes.Index,"") ENDIF ColumnViewNotes[ModuleDatabase.Notes.Index][1]= ModuleDatabase.Notes["Title"] ColumnViewNotes[ModuleDatabase.Notes.Index][2]= ModuleDatabase.FormatDate(ModuleDatabase.Notes["LastModified"]) 'Selectfirstitemwithhighestpriority IFCInt(ModuleDatabase.Notes["Priority"])>firstItemTHEN ColumnViewNotes[ModuleDatabase.Notes.Index].Selected=TRUE firstItem=CInt(ModuleDatabase.Notes["Priority"])

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com ENDIF NEXT END ContinuedBelow

Page98of110

Thisprocedurewilldisplayaselectednoteinthedetailssectionoftheformwindowontheright sideoftheform.TheprocedureexpectstheindextoarowintheNotesResultobjecttoselectwhat's displayed.ThiswhyweusedthisindexasthekeyforitemsintheColumnView.Wesimplyneedto movetothedesiredrowtogettherecordweneed. Wecopythenotetitletothetitletextbox.Thenwesettheselectedradiobuttonforthenotepriority basedupontheintegerinthePriorityfield.Thenotecontentiscopiedtothenotetextarea.We placethecursorinthetextareaattheendofthetextandsetthefocustothetextarea.Thisseemsto bethemostreasonablepositionfortheusertostartfromaftertheyhavejustselectedanote. FinallywesetthechangesMadevariabletoFALSE.Tostatetheobvious:thismustbedoneafter wehavecompletedallthechangesweneedtomaketothenotescontrols.Thisisbecausethese controlsfirechangesmadeeventsthatsetthisvariabletoTRUE. FormNotations.classContinued PRIVATESUBDisplayNote(RowASInteger) ModuleDatabase.Notes.MoveTo(Row) TextBoxTitle.Text=ModuleDatabase.Notes["Title"] IFCInt(ModuleDatabase.Notes["Priority"])=1THEN RadioButtonMedium.Value=TRUE ELSEIFCInt(ModuleDatabase.Notes["Priority"])>1THEN RadioButtonHigh.Value=TRUE ELSE RadioButtonLow.Value=TRUE ENDIF TextAreaNote.Text=ModuleDatabase.Notes["Note"] TextAreaNote.Pos=String.Index(TextAreaNote.Text, Len(TextAreaNote.Text)) TextAreaNote.SetFocus() changesMade=FALSE

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com END ContinuedBelow

Page99of110

Ourfinalfunctiontestsiftheuserhasmadeanychangestothecurrentnote.Whendevelopingthe applicationIfoundIwaswritingthiskindoflogicinanumberofplaces.Soitlookedlikeagood ideatowriteafunctionforthis.Thisalsoensuresourapplicationhasacommonformatforhandling changesthathavenotbeensaved. WecheckforchangestothecurrentnotebylookingatthevalueofthechangesMadevariable.If therearechangesthathavenotbeensavedthenwedisplayamessagebox.Iftheuserhasclickedthe ContinuebuttonthenwereturnFALSEotherwisewereturnTRUE.Wehaveputthefunctionreturn logicthiswayroundsoourmessageboxfunctionbehavesthesamewayasthemethodsinthe Dialogclassforgettingafilenameandpath. FormNotations.classContinued PRIVATEFUNCTIONTestChangesMade()ASBoolean DIMmessASString IFchangesMadeTHEN mess="Changesmadetothenote\n\n\t"&TextBoxTitle.Text& "\n\nhavenotbeensaved.Doyouwanttocontinue?" IFMessage.Warning(mess,"Continue","Cancel")<>1THEN RETURNTRUE ENDIF RETURNFALSE END

4.5: Runningtheproject
Wehavenowcompletedtheprojectsoletsrunit.YouruntheprojectbyclickingonthegreenRun buttonintheprojectmanagerwindoworbypressingtheF5key.ASQLitedatabasewillbecreated inyouruserhomedirectoryandatableaddedtothedatabase.Thenthewelcomenoteisaddedto thetable.Wecannowtestourapplicationworkscorrectly.Therefollowssomeofthetestswemight perform.Thisfirstsetofteststesthowweconnecttothedatabase.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page100of110

DatabaseConnectionTests Test ExpectedResult Pass/Fail Runtheapplicationwithavalid Anewdatabaseandtableshouldbe connectionandwhenthedatabasedoesnot created.Thewelcomenoteshouldbe exist. displayed. Runtheapplicationagainwiththevalid connectionanddatabase. Callthedatabasewithaninvalid connection. Nochangesshouldbemadetothe database.Thefirstnotefoundwiththe highestpriorityshouldbedisplayed. Anerrormessageshouldbedisplayed.

Afteropeningtheapplicationinthe Anerrormessageshouldbedisplayed, previousstepclickonallthebuttonsinthe toolbarinturn. Thereisaforthpossibletestyoucouldadd.Thisiswherewehaveavalidconnectionanddatabase butthedatabasetabledoesnotexist.Foraproductionapplicationyouwouldwanttoperformthis test.AsitisabitofacomplextestnewGambasusersmightwanttoskipit. Thenextsetoftestchecktheadding,reading,updatinganddeletingofnotes.Agoodwayof developingthistestlististouserourCRUDLSchecklistasastartingpoint.Lookateachitemin theCRUDLSlistanddeveloptestsforwhentheactionsucceeds.Wealsoneedtestsfortheallthe possiblewayseachactioncouldfail.Thefollowingtestsassumeweareconnectedtothedatabase. DatabaseCreate,Read,UpdateandDeleteTests.PlusListandSearchTests Test ChangethecurrentnoteclicktheAdd button. ExpectedResult Anewnoteisaddedtothedatabaseand thisbecomesthecurrentnote. Pass/Fail

Changethecurrentnotebutmakesurethe Anewnoteisaddedtothedatabasewith notehasthesametitleasanexistingnote. theduplicatenotetitleandthisbecomes thecurrentnote. ThenclicktheAddbutton. ClickontheRefreshbutton.(Makesure Thenoteslistisrefreshedfromthe anychangestothecurrentnotehavebeen database.Thefirsthighestprioritynote becomesthecurrentnote. savedbeforeyoudothis.) ClickontheRefreshbuttonafterchanges Thenoteslistisrefreshedfromthe havebeenmadetoanotebuthavenotbeen database.Thefirsthighestprioritynote saved.Inthemessageboxthatisdisplayed becomesthecurrentnote.Changestothe previousnotearelost. clickontheContinuebutton.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com DatabaseCreate,Read,UpdateandDeleteTests.PlusListandSearchTests Test ExpectedResult

Page101of110

Pass/Fail

ClickontheRefreshbuttonafterchanges Therefreshactioniscancelled. havebeenmadetoanotebuthavenotbeen saved.Inthemessageboxthatisdisplayed clickontheCancelbutton. Clearthesearchtextboxofanytext.Click Amessageisdisplayedstatingthereisno searchtext. ontheSearchbutton. Entersomesearchtextinthesearchtext Onlythosenotesthatcontainthesearch box.Verifythistextcanbefoundinsome textinthenotetitleorcontentareshown. notes.ClickontheSearchbutton.(Make sureanychangestothecurrentnotehave beensavedbeforeyoudothis.) Entersomesearchtextinthesearchtext Amessageisdisplayedstatingthatthe box.Verifythistextcannotbefoundin searchtextwasnotfound.Nonotesare somenotes.ClickontheSearchbutton. displayed. (Makesureanychangestothecurrentnote havebeensavedbeforeyoudothis.) ClickontheSearchbuttonafterchanges Onlythosenotesthatcontainthesearch havebeenmadetoanotebuthavenotbeen textinthenotetitleorcontentareshown. saved.Inthemessageboxthatisdisplayed Changestothepreviousnotearelost. clickontheContinuebutton. ClickontheSearchbuttonafterchanges Thesearchactioniscancelled. havebeenmadetoanotebuthavenotbeen saved.Inthemessageboxthatisdisplayed clickontheCancelbutton. Makesomechangestoanoteandthen clickontheUpdatebutton.Testinturn changestothetitle,noteandpriority. Thecurrentnoteisupdatedandthenotes listisupdated.Theupdatednoteremains thecurrentnote.

Thecurrentnoteisdeletedandthenotes WithanoteselectedclickontheDelete button.Theninthewarningmessageclick listisrefreshed. ontheContinuebutton. Thedeleteactioniscancelled. WithanoteselectedclickontheDelete button.Theninthewarningmessageclick ontheCancelbutton. ClickontheDeletebuttonwheneitherno Amessageisdisplaysstatingthereisno noteisselectedortherearenonotesinthe currentnotetodelete. databasetable. Ourfinalbatchoftestscovertheuserinterfacetoourapplication.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page102of110

OtherTests Test Clickonthehelpbutton. ExpectedResult Thehelpmessageshouldbedisplayed. Pass/Fail

Clickontheheadinginthecolumnviewof Thenotessortorderchangeshouldchange notes. totherelevantcolumn. Testtheresizingofthewindowfromeach Theformscontrolsshouldberesizedtofit sideofthewindow. thewindow. Testtheresizingofthewindowfromeach Theformscontrolsshouldberesizedtofit cornerofthewindow. thewindow. Resizethewindowsoitswidthislessthan Iconsthatdonotfitwithinthewidthofthe widthofalltheiconsinthetoolbar. toolbarmoveontoasecondline.Therest oftheformscontrolsareresized appropriately. Usethebarbetweenthetwohalf'softhe Thecontrolsinthetwohalf'softhe formwindowtoresizeeachsectionofthe windowshouldberesizedcorrectly. window.(Thistestdoesnotapplyto GambasVersion1)

4.6: SwitchingtoaMySQLorPostgreSQLDatabase
WearenotgoingtodealwithinstallingorsettingupaMySQLorPostgreSQLdatabase.For informationonthisyoushouldlookathttp://www.mysql.org/orhttp://www.postgresql.org/. PreformingainternetsearchforInstalling+MySQL+Linuxfindsalargeamoutof help.AlsotryInstalling+MySQL+YourLinuxdirstibutionname.Similarresults canbeobtainedforPostgreSQLwithInstalling+PostgreSQL+Linux. Swappingtoaoneofthesedatabasesisverysimple.FindthelineForm_Openeventinthe FormNotationsclassthatlookslikethis: ModuleDatabase.OpenDatabase("sqlite",User.Home, Application.Name,"","") andchangeittosomethinglikethisforaMySQLdatabase: ModuleDatabase.OpenDatabase("mysql","localhost", Application.Name,"mysql","password") MakesuretheMySQLuseraccountyouselecthaspermissionstocreatethedatabaseandtablesthe firsttimethisprocedureisrun.CheckonyourMySQLinstallationorwithyourdatabase

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page103of110

administratorfortheMySQLuseraccountdetails.Thatallweneedtochange.Solongasyouhavea validconnectiondetailstheprogramshouldrunandcreatethedatabaseforyou. ForaPostgreSQLdatabasewewouldchangethecalltosomethinglikethis: ModuleDatabase.OpenDatabase("postgresql","localhost", Application.Name,"postgres","password") Alsothecommentaboveaboutaccountdetailsappliestothistypeofdatabase. Thisexampledemonstratesthechangesrequiredtoswitchdatabasetypes.Wecanseehoweasythis was.Buttherearesomeissuesyoushouldconsiderfromadatabaseadministratorperspective:

Itisprobablynotagoodideatohardcodethepassword.Itwouldbebettertohavea connectiondialogueandatleasthavethepasswordenteredbytheuser.Thisdialoguewould besimpletoaddinGambas. Youneedthedatabaseusertohavepermissionstocreatethedatabaseandtableswhenthe programisfirstrun.Howeverisnotgoodpractisealeaveanormaluserwiththese permissions.Thiscouldbeasecurityissue.

ThisisnotreallyaproblemwiththeSQLitedatabasewefirstused.SQLiteisintendedtobea singleuserdatabase.Butasyoucanseetheissuesinvolvedwhenswappingdatabasetypeshave moretodowithbeingagooddatabaseadministratorthanwithGambasrelatedissues. AfterchangingthedatabasetypeitwouldbeprudenttorerunthetestsintheRunning theprojectsectiontoensureyourapplicationstillworkswiththenewdatabasetype.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page104of110

5:

Appendix1:DatabaseCommandswithExecandSQL

InthisappendixweshalllookatconvertingtheNotationsapplicationtodirectlyusingStructured QueryLanguage(SQL)tocommunicatewithadatabase.Inthemainsectionofthistutorialwe avoidedusingSQLinordertodemonstratemoreoftheGambasdatabaseclasses.Wealsomadethe designdecisiontoplaceallthecodetocommunicatewiththedatabaseinsideonemodulecalled ModuleDatabase.Thisdecisionhaspaidbenefitsnowasallthechangesweneedtomakeare confinedtothisonemodule. IntheexampleNotationsprojectthatshipswiththistutorialtherearetwoextra directoriesintheproject.ThesubdirectorycalledModuleDatabaseSQLcontainsa versionofthefileModuleDatabase.modulethatfollowsthecodeexamplesinthis appendix.Simplycopythisfileintothemainprojectdirectoryandoverwritetheone thatalreadyexiststhere. Inordertotestthisfileyouwillneedtocompiletheprojectagain.Gambasbydefault onlycompilesfilesthathavechangedusingaprojecteditor.SelectProjectmenuinthe Gambasprojectmanager.ThenselectthesubmenuoptionCompileAll.Thiswill ensureallfilesarenewlycompiledandyouarerunningthelatestversionoftheproject. YoucanalsoclickontheCompilealltoolbarbuttonintheprojectmanagertoachieve thesameresult. ThesubdirectorycalledModuleDatabaseGambascontainsabackupcopyofthe originalfileModuleDatabase.module.Youcanusethisfiletorestoretheprojecttoits originalformat. Thestructureofthecommandsweneedisfairlystraightforward.WeonlyneedtwoGambas databaseobjects,aconnectionobjectandaresultobject.TheExecmethodontheconnection objectreturnsareadonlyresultobject.SotogetrecordsfromthedatabaseweconstructourSQL statement,passthistotheExecmethod,andthenwecanreadthereturneddatafromtheresult object: sql=SQLselectstatement result=connection.Exec(sql) YoualsocanusetheExecmethodtosendanyvalidSQLstatementstoyourtargetdatabase.So thismethodcanalsobeusedwhenweadd,updateordeleterecordsfromthedatabase. sql=CreateSQLupdate,insertordeletestatement(s) connection.Exec(sql) Ofcoursewiththesemethodyoustillneedtocatchanyerrorsreturned.Wearenotgoingtodeal withhowtouseSQLinthistutorial.IfyouneedinformationonSQLagoodplacetostartisthe websitesforthedatabasevendorslistedintheGambasResourcessection.

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page105of110

TherearetwoimportantissuestoconsiderwhenconstructingthestringfortheSQLstatement.The firstisweneedtoformatthedate/timeinawaythatisunambiguousandunderstoodbythe database.Thisfragmentshowshowweformatthecurrentdate/time: '&Format(Now,"yyyymmddhh:nn:ss")&' Thiswillproduceastringsomethinglike'2006051319:38:34'atthetimeofwritingthis sentence(on13May2006at19:38:34). InourSQLstatementswehaveusedtextstringsthataresurroundedbysinglequotes.Thismeans thatiftheuserentersasinglequoteintheirtitleornoteentrythentheINSERTorUPDATESQL statementwouldfail.ThiswouldbeconfusingtotheuserastheywouldjustseeanbadSQLquery errormessageandnotknowhowtocorrecttheproblem.Hencewehaveadoptedthe(admittedly crude)approachofreplacinganysinglequoteswithdoublequoteswhenconstructingourSQL query.(Youcanincludesinglequoteswithinatextstringintheversionofthisapplicationusing Gambasobjectstoaddandupdaterecords.) ThisisalistingofthechangesweneedtomaketotheModuleDatabasecodetousetheSQL methodforcommunicationstothedatabase. AfterenteringthislistingyoushouldreruntheallthetestsintheRunningtheproject sectiontoensureyourapplicationstillworkswiththisdifferentmethodof communicatingwiththedatabase. Alsoifyouchangethedatabasetype,asdescribedin,SwitchingtoaMySQLor PostgreSQLDatabaseyoushouldbeverythoroughinrerunninganytesting.Youneed torepeatallyourtestingforeachtypeofdatabaseyouintendtosupport.Youneedtodo moreretestingthanityouusedtheGambasmethodofcommunicatingwiththe database. InthefollowinglistingyouneedtomakeafewsmallchangesforGambasversion1. Thelinesthathavetheformat: sql&=xxx needtobechangedto: sql=sql&xxx asGambasversion1doesnotunderstandthe&=operator.AlsoGambasversion1does notunderstandtheDconvfunction.Solinesthatincludeit: ...Dconv(Error.Text)... shouldjustomitthefunctioncall: ...Error.Text...

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com ModuleDatabase.module PRIVATEdatabaseConnectionASNEWConnection PUBLICNotesASResult 'ThisprocedurewillopenaSQLitedatabaseconnection. 'Ifthedatabasedoesnotexistitwillbecreated. 'Ifthetablesdonotexisttheywillbecreated.

Page106of110

PUBLICSUBOpenDatabase(DBTypeASString,DBHostASString,DBName ASString,UserNameASString,UserPasswordASString) DIMsqlASString DIMerrorMessageHeaderASString 'Openaconnection(tothedatabaseserveronly) databaseConnection.Type=Lower(DBType) databaseConnection.Host=DBHost databaseConnection.Name="" databaseConnection.Login=UserName databaseConnection.Password=UserPassword databaseConnection.Port="" 'Opentheconnection TRYdatabaseConnection.Open() IFERRORTHEN errorMessageHeader="Couldnotopendatabaseconnection"& DBHost Error.Raise(Error.Text) ENDIF 'Checkiftheserverconnectionhasadatabasewiththe 'requireddatabasename. IFNOTdatabaseConnection.Databases.Exist(DBName)THEN PRINT"Databasenotfound.Creatingnewdatabase" 'Createanewdatabase databaseConnection.Databases.Add(DBName) 'IfoundIneededthiswithaSQLitedatabase '(butnotwithaMySQLdatabase) WAIT0.5 ENDIF

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com 'Closetheserverconnection databaseConnection.Close() 'Openaconnectiontothedatabase databaseConnection.Host=DBHost databaseConnection.Name=DBName TRYdatabaseConnection.Open() IFERRORTHEN

Page107of110

errorMessageHeader="Couldnotopendatabase"&DBName& "on"&DBHost Error.Raise(Error.Text) ENDIF 'CheckifthedatabasehasaNotestable IFNOTdatabaseConnection.Tables.Exist("Notes")THEN PRINT"Databasetablesnotfound.Creatingnewnotestable" 'AddaNotestabletothedatabase sql="CREATETABLE'Notes'(" sql&="CreateDateDATETIMENOTNULL," sql&="LastModifiedDATETIME,titleTEXT," sql&="NoteTEXT," sql&="PriorityINTEGERNOTNULLDEFAULT0," sql&="PRIMARYKEY(CreateDate));" databaseConnection.Exec(sql) 'Addadefaultwelcomerecord AddData("Welcome",File.Load("Welcome.txt"),0) ENDIF CATCH IFerrorMessageHeader=""THEN errorMessageHeader="Databaseconnectionerror:"&DBName& "on"&DBHost ENDIF Error.Raise("<b>"&errorMessageHeader&"</b><hr>Error:<br>"& DConv(Error.Text)) END PUBLICSUBCloseDatabase() TRYdatabaseConnection.Close()

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com IFERRORTHENPRINT"Errorclosingdatabase" END 'Createarecord

Page108of110

PUBLICFUNCTIONAddData(TitleASString,NoteASString,Priority ASInteger)ASString DIMsqlASString DIMcreateTimeASDate createTime=Now Title=Replace(Title,"'","\"") Note=Replace(Note,"'","\"") sql="INSERTINTONotes" sql&="(CreateDate,LastModified,Title,Note,Priority)" sql&="VALUES(" sql&="'"&Format(createTime,"yyyymmddhh:nn:ss")&"'," 'CreateDate sql&="'"&Format(createTime,"yyyymmddhh:nn:ss")&"'," 'LastModified sql&="'"&Conv(Title,Desktop.Charset, databaseConnection.Charset)&"'," sql&="'"&Conv(Note,Desktop.Charset, databaseConnection.Charset)&"'," sql&=Priority&");" databaseConnection.Exec(sql) RETURNFormatDate(createTime) CATCH Error.Raise("<b>Adddatabaserecorderror</b><hr>Error:<br>"& DConv(Error.Text)) END 'Readatable PUBLICSUBSelectData() DIMsqlASString sql="SELECT*FROMNotes;" Notes=databaseConnection.Exec(sql) CATCH

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com

Page109of110

Error.Raise("<b>Selectdatabaserecordserror</b><hr>Error:<br>" &DConv(Error.Text)) END 'Updatearecord PUBLICSUBUpdateData(RowASInteger,TitleASString,NoteAS String,PriorityASInteger) DIMsqlASString DIMcreateDateASDate Title=Replace(Title,"'","\"") Note=Replace(Note,"'","\"") Notes.MoveTo(Row) sql="UPDATENotes" sql&="SETLastModified='"&Format(Now, "yyyymmddhh:nn:ss")&"'," sql&="Title='"&Conv(Title,Desktop.Charset, databaseConnection.Charset)&"'," sql&="Note='"&Conv(Note,Desktop.Charset, databaseConnection.Charset)&"'," sql&="Priority="&Priority&"" createDate=Notes["CreateDate"] sql&="WHERECreateDate='"&Format(createDate, "yyyymmddhh:nn:ss")&"';" databaseConnection.Exec(sql) CATCH Error.Raise("<b>Updatedatabaserecorderror</b><hr>Error:<br>" &DConv(Error.Text)) END 'Deletearecord PUBLICSUBDeleteData(RowASInteger) DIMsqlASString DIMcreateDateASDate Notes.MoveTo(Row) createDate=Notes["CreateDate"] sql="DELETEFROMNotes"

GettingStartedwithGambasVersion2:ATutorial timothy.marshalnichols@ntlworld.com sql&="WHERECreateDate='"&Format(createDate, "yyyymmddhh:nn:ss")&"';" databaseConnection.Exec(sql) CATCH

Page110of110

Error.Raise("<b>Deletedatabaserecorderror</b><hr>Error:<br>" &DConv(Error.Text)) END PUBLICFUNCTIONFormatDate(dASDate)ASString RETURNFormat(d,"ddmmmyyyyhh:nn:ss") END

Potrebbero piacerti anche