You are on page 1of 364

A Beginner's Guide to Gambas

CoverdesignbyFabienBodard
ForewordbyFabienBodardandBenotMinisini

1
A Beginner's Guide to Gambas

Copyright Notice for the printed version of this work:

A Beginner's Guide to Gambas (this work) is copyright 2005 by John W.


Rittinghouse, all rights are reserved. Personal use of this material is permitted.
However, permission to reprint/republish this material for advertising or promotional
purposes or for creating new collective works for resale or redistribution to servers or
lists, or to reuse any copyrighted component of this work in other works must be
obtained from the the author, John W. Rittinghouse. The author grants a perpetual
license to the Gambas user-community for use of the electronic version of this printed
work under the terms and conditions of the OpenContent License printed on the
following page.

2
A Beginner's Guide to Gambas

Copyright Notice for the electronic (online) version of this work, based on the OpenContent License
(OPL), Version 1.0, July 14, 1998.

This document outlines the principles underlying the OpenContent (OC) movement and may be redistributed provided it remains
unaltered. For legal purposes, this document is the license under which OpenContent is made available for use. The original
version of this document may be found at http://opencontent.org/opl.shtml .

LICENSE

Terms and Conditions for Copying, Distributing, and Modifying

Items other than copying, distributing, and modifying the Content with which this license was distributed (such as using, etc.)
are outside the scope of this license.

1. You may copy and distribute exact replicas of the OpenContent (OC) as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the OC a copy of
this License along with the OC. You may at your option charge a fee for the media and/or handling involved in creating a unique
copy of the OC for use offline, you may at your option offer instructional support for the OC in exchange for a fee, or you may at
your option offer warranty in exchange for a fee. You may not charge a fee for the OC itself. You may not charge a fee for the
sole service of providing access to and/or use of the OC via a network (e.g. the Internet), whether it be via the world wide web,
FTP, or any other method.

2. You may modify your copy or copies of the OpenContent or any portion of it, thus forming works based on the Content, and
distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:

a) You must cause the modified content to carry prominent notices stating that you changed it, the exact nature and content of
the changes, and the date of any change.

b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the OC or any
part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License, unless otherwise
permitted under applicable Fair Use law.

These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the OC, and
can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to
those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is
a work based on the OC, the distribution of the whole must be on the terms of this License, whose permissions for other licensees
extend to the entire whole, and thus to each and every part regardless of who wrote it. Exceptions are made to this requirement
to release modified works free of charge under this license only in compliance with Fair Use law where applicable.

3. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to
copy, distribute or modify the OC. These actions are prohibited by law if you do not accept this License. Therefore, by
distributing or translating the OC, or by deriving works herefrom, you indicate your acceptance of this License to do so, and all
its terms and conditions for copying, distributing or translating the OC.

NO WARRANTY

4. BECAUSE THE OPENCONTENT (OC) IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE OC, TO
THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE OC "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK OF USE OF THE OC IS WITH
YOU. SHOULD THE OC PROVE FAULTY, INACCURATE, OR OTHERWISE UNACCEPTABLE YOU ASSUME THE COST OF
ALL NECESSARY REPAIR OR CORRECTION.

5. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT
HOLDER, OR ANY OTHER PARTY WHO MAY MIRROR AND/OR REDISTRIBUTE THE OC AS PERMITTED ABOVE, BE
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE OC, EVEN IF SUCH HOLDER OR OTHER PARTY
HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

3
A Beginner's Guide to Gambas

Table of Contents
Acknowledgments........................................................................16

Foreword.......................................................................................17

Chapter1IntroducingGambas.................................................19
GambasArchitecture......................................................19
TheGambasProgrammingEnvironment......................22
GambasIDEComponents.................................................25

Chapter2GambasLanguageConcepts.................................30
GambasVariables,DatatypesandConstants.............30
VariableAssignment..........................................................35
AssignmentUsingTheWITHStatement...........................35
OperatorsandExpressions............................................36
Comparisonoperators......................................................36
ArithmeticOperators..........................................................36
Let'sStartCodingGambas................................................37
END,RETURNandQUITStatements.......................................37
StringOperators................................................................44

Chapter3KeywordsandProgramFlowControl....................46
ThePRINTStatement.......................................................46
TheIFStatement...............................................................47
TheSELECT/CASEStatement.......................................48
GOTOandLABELS..........................................................49
TheFOR/NEXTStatement..............................................49
DO[WHILE]LOOP............................................................51
WHILE[Expression]WENDLoops...................................52
TheREPEATUNTILloop.................................................53
DefiningandUsingArraysinGambas..........................53
Collections.......................................................................55
TheFOREACHStatement...............................................55

Chapter4IntroducingtheGambasToolBox..........................57
TheButtonControl..........................................................61
CommonControlProperties..............................................62
ButtonMethods.................................................................70

4
A Beginner's Guide to Gambas

ButtonEvents....................................................................78
ThePictureClass............................................................78

Chapter5ControlsforGatheringInput...................................80
TextLabel..........................................................................82
TextBox............................................................................83
ComboBox........................................................................85
ListBox.............................................................................89
Frame................................................................................92
ToggleButton...................................................................93
Checkbox.........................................................................93
Panel.................................................................................95
RadioButton.....................................................................95

Chapter6Menus,Modules,DialogsandMessageBoxes.....97
TheGambasMenuEditor...............................................98
BuildingMenus..............................................................101
Dialogs............................................................................103
Modules..........................................................................105
MessageBoxes...............................................................112
InformationMessages.....................................................112
Query/ConfirmMessages................................................114
ErrorMessages...............................................................115
WarningorAlertMessages.............................................115
DeleteMessages.............................................................116
DialogClassFilerelatedFunctions.............................117
DialogOpenFileFunction................................................117
DialogSaveFileFunction.................................................118
DialogSelectDirectoryFunction......................................119
CompleteExampleListing............................................120
Module1.modulelisting.................................................123

Chapter7HandlingStringsandConvertingDatatypes.....125
StringFunctions............................................................125
Len...................................................................................126

5
A Beginner's Guide to Gambas

Upper$/Ucase$/UcaseandLower$/Lcase$/Lcase........126
Trim$,LTrim$,andRTrim$..............................................127
Left$,Mid$,andRight$..................................................128
Space$............................................................................130
Replace$........................................................................130
String$............................................................................131
Subst$............................................................................131
InStr.................................................................................132
RInStr..............................................................................134
Split..................................................................................134
ConvertingDatatypes..................................................135
AscandChr$..................................................................135
Bin$.................................................................................136
CBool..............................................................................137
CByte...............................................................................138
CDate..............................................................................138
CFloat..............................................................................139
CInt/CintegerandCShort.............................................140
CStr/CString.................................................................140
Hex$................................................................................141
Conv$.............................................................................141
ValandStr$....................................................................142
Str$.................................................................................142
Format$...........................................................................145
Datatypemanagement.................................................147
TypeOf.............................................................................148

Chapter8UsingAdvancedControls.....................................149
IconViewControl...........................................................149
ListViewControl............................................................158
UsingtheGambasIconEditTool................................162
TheTreeViewControl....................................................163
TheGridViewControl....................................................171
TheColumnViewControl..............................................175
LayoutControlsHBox,VBox,HPanelandVpanel. .177
HBoxandVBox...............................................................177
HPanelandVpanel..........................................................177

6
A Beginner's Guide to Gambas

TheTabStripControl.....................................................182

Chapter9WorkingwithFiles.................................................188
Access............................................................................188
Dir....................................................................................189
Eof...................................................................................190
Exist................................................................................190
IsDir/Dir?.....................................................................191
Stat.................................................................................191
Temp/Temp$...............................................................192
OPENandCLOSE..........................................................192
LINEINPUT.....................................................................193
READ,SEEK,WRITEandFLUSH.................................194
COPY,KILLandRENAME.............................................195
MKDIR,RMDIR...............................................................196

Chapter10MathOperations..................................................215
PrecedenceofOperations............................................215
Abs..................................................................................216
Acs/ACos......................................................................216
Acsh/ACosh.................................................................217
Asn/ASin.......................................................................217
Asnh/ASinh..................................................................218
Atn/ATan.......................................................................218
Atnh/ATanh..................................................................219
Cos..................................................................................219
Cosh................................................................................220
DegandRad...................................................................221
Exp..................................................................................221
FixandFrac...................................................................222
Int....................................................................................223
Log..................................................................................223
Log10..............................................................................224

7
A Beginner's Guide to Gambas

MaxandMin...................................................................224
Pi.....................................................................................225
RandomizeandRnd......................................................225
Round.............................................................................227
Sgn..................................................................................227
Sin...................................................................................228
Sinh.................................................................................229
Sqr...................................................................................229
Tan..................................................................................230
Tanh................................................................................231
DerivedMathFunctions................................................231

Chapter11ObjectOrientedConcepts..................................237
FundamentalsofObjectOrientedProgramming........238
Objects............................................................................239
DataAbstraction..............................................................239
Encapsulation..................................................................240
Polymorphism..................................................................240
Inheritance.......................................................................240
TheGambasApproachtoOOP....................................241
GambasClasses.............................................................241
Sampleprogram:Contacts...........................................242
TheContactclass............................................................242
Contact.GetDataMethod.................................................243
Contact.PutDataMethod.................................................246
Form1.classfile...............................................................247
Form1Constructor...........................................................248
Form_OpenSubroutine...................................................250
AddingControlstoForm1.Form......................................250
TheToolButtons.......................................................................251
TheQuitButton.........................................................................251
AddingtheLabelsandTextBoxes............................................252
UpdateForm()Subroutine................................................253
CodingToolbuttons:First,Prev,Next,andLast.......................254
CodingToolButtons:Addingarecord.......................................256
CodingToolButtons:Clearingdata...........................................258
ValidatingUserInput.......................................................258

8
A Beginner's Guide to Gambas

AddingaSearchFeature.................................................260
TheDoFindSubroutine.............................................................262
ToolButtonsagain:UpdatingaRecord............................263
Toolbuttonsagain:DeletingaRecord.............................264
ToolButtonsagain:SavingData......................................265
CreatingaStandaloneExecutable..............................266

Chapter12LearningtoDraw.................................................267
DrawProperties.............................................................267
BackColor/BackgroundandForeColor/Foreground........267
Clip..................................................................................268
FillColor,FillStyle,FillX,FillY..............................................268
Font.................................................................................269
Invert................................................................................269
LineStyle/LineWidth.........................................................270
Transparent.....................................................................270
DrawMethods................................................................270
Text/TextHeight/TextWidth..............................................272
DrawPrimitives:Point/Rect/Ellipse/Line..........................274
DrawPrimitives:PolygonandPolyline............................280
Image/Picture/Tile............................................................284
DrawingwithaDrawingobject........................................292

Chapter13ErrorManagement...............................................298
GeneralConceptsofErrorManagement.....................298
ErrorHandling.................................................................298
BoundaryRelatedErrors.................................................299
CalculationErrors............................................................299
InitialandLaterStates.....................................................300
ControlFlowErrors..........................................................300
ErrorsinHandlingorInterpretingData............................301
RaceandLoadConditions..............................................301
PlatformandHardwareIssues........................................302
Source,Version,andIDControlErrors...........................303
TestingErrors..................................................................303
TestPlanReviews...........................................................303
GambasErrormanagement.........................................304
TRYstatement...IFERROR...........................................304

9
A Beginner's Guide to Gambas

CatchandFinallyStatements..........................................306
GambasEventmanagement........................................309

Chapter14Mouse,KeyboardandBitOperations................312
MouseOperations.........................................................312
KeyboardOperations....................................................316
BitOperations................................................................318

Chapter15GambasandDatabases......................................326
ConnectionClass..........................................................327
ConnectionProperties.....................................................328
Charset.....................................................................................328
Databases.................................................................................328
Host...........................................................................................329
Login.........................................................................................329
Name........................................................................................329
Password..................................................................................330
Port...........................................................................................330
Tables.......................................................................................330
Type..........................................................................................330
Users.........................................................................................330
Version......................................................................................330
TheConceptofaTransaction.........................................331
ConnectionClassMethods..............................................332
Open/Close...............................................................................332
Begin/Commit/Rollback............................................................333
Find...........................................................................................333
Create.......................................................................................334
Edit............................................................................................334
Exec..........................................................................................334
Quote........................................................................................335
ResultObjects.................................................................335
DBClass.........................................................................336
Database.........................................................................337
Field................................................................................337
Index...............................................................................337
Table...............................................................................337
User.................................................................................338

10
A Beginner's Guide to Gambas

TheDatabaseExampleProgram..................................338

Chapter16GlobalGambas....................................................351
Internationalization........................................................351
Localization....................................................................351
UniversalCharacterSet(UCS).....................................352
Unicode..........................................................................352
UTF8..............................................................................353
HowtotranslateinGambas.........................................355

11
A Beginner's Guide to Gambas

Table of Figures
Figure1GeneraloverviewofGambasarchitecture...........................................20
Figure2theGambasOpeningScreen..............................................................21
Figure3TheGambasProjectCreationWizard.................................................22
Figure4AdialogtoselectthetypeofGambasprojectyouwishtocreate.......23
Figure5ProjectNameSelectionDialog............................................................24
Figure6ProjectDirectorySelectionDialog........................................................24
Figure7NewProjectconfirmationdialog...........................................................25
Figure8TheGambasIDE.................................................................................26
Figure9ProjectExplorerFileMenu...................................................................27
Figure10ProjectMenu......................................................................................27
Figure11ProjectExplorerViewMenu...............................................................27
Figure12ProjectExplorerToolsMenu..............................................................27
Figure13ProjectExplorerMenuandToolbar...................................................28
Figure14ADivisionbyZeroErrorDialog..........................................................40
Figure15TheGambasToolBox........................................................................58
Figure16AdditionalcontrolsforQT...................................................................60
Figure17FirstButtoncoderesults....................................................................65
Figure18Demonstratingfontcapabilities..........................................................67
Figure19Thedottedlineindicatesfocusforacontrol......................................72
Figure20ThelayoutforSecondProjectForm1.form.........................................72
Figure21Apartiallyconstructedformwithourfirstfourcontrols.......................73
Figure22Eventmenu........................................................................................74
Figure23AddingtheFunBtntoourform...........................................................76
Figure24Whatourformlookslikewhenamouseisdetectedovertheform.
Notethetextisblankedout...............................................................................77
Figure25TheprogressbarwhentheFunBtnisclickedthreetimes.................77
Figure26ThirdProject(almost)finalresult........................................................80
Figure27UsingHTMLtoformatTextLabeloutput............................................82
Figure28ModifiedTextLabeloutputusingHTMLformatting............................83
Figure29AddingaToolTiptoinformtheuserhowtoshow/hideacontrol.......85
Figure30OurComboBox..................................................................................86
Figure31TheEditlistpropertyeditor................................................................87
Figure32FormattingaTextLabelwithHTML....................................................88
Figure33PlusandminusbuttonstoaltertheComboBoxlist............................88
Figure34WhatourListBoxwilllooklike............................................................90
Figure35ListBoxEditlistpropertyeditor...........................................................90
Figure36Whattheexampleframewebuildwilllooklike..................................92

12
A Beginner's Guide to Gambas

Figure37APanelwithRadioButtons................................................................95
Figure38MenuProjectFinalresults..................................................................97
Figure39TheGambasMenuEditorwhenitfirststarts.....................................98
Figure40EditfieldsfortheMenuEditor............................................................99
Figure41Buildingourprojectmenu................................................................101
Figure42Aformattedtextlabeldisplayingthecolorvalue..............................104
Figure43Selectingcolorsandfonts................................................................111
Figure44MakinganewdefaultfontfortheTextLabel1control......................112
Figure45AnInformationMessageBox............................................................113
Figure46Acheckedmenuitem.......................................................................113
Figure47AQuestionMessageBox.................................................................115
Figure48AnErrorMessage............................................................................115
Figure49AWarningmessage.........................................................................116
Figure50Deletemessagewiththreebuttons..................................................117
Figure51TheOpenFileDialog.......................................................................118
Figure52SaveFileDialog...............................................................................119
Figure53TheSelectDirectoryDialog.............................................................119
Figure54ChoosingtheExplorerexample.......................................................149
Figure55LayoutforourListViewexample......................................................159
Figure56CreatinganewIconimageinGambas............................................163
Figure57Oursquareiconimage.....................................................................163
Figure58IconEditorToolBox.........................................................................163
Figure59Ourcircleiconimage.......................................................................163
Figure60TheTreeViewProjectwindow..........................................................164
Figure61WhatourGridViewwilllooklike.......................................................172
Figure62OurColumnViewexample...............................................................175
Figure63Layoutprojecticons.........................................................................178
Figure64Form1designmodeshowinglayoutofourcontrols.........................179
Figure65Layoutprogramwhenitstartsup.....................................................182
Figure66ATabStripcontrol............................................................................183
Figure67TabProjectForm1.formDesign.......................................................183
Figure68Tab0layout......................................................................................184
Figure69Tab1layout......................................................................................184
Figure70Tab2ToolButtonlayoutwithicons...................................................185
Figure71Tab3layoutwithaComboBox.........................................................186
Figure72TheFileOpsprogramatruntime......................................................196
Figure73Form2.formdesignmode................................................................210
Figure74FinishedContactsprogram..............................................................248
Figure75Form1seenindesignmode.............................................................253

13
A Beginner's Guide to Gambas

Figure76ContactsManagerrunningstandaloneonmydesktop....................266
Figure77gfxDemoForm1layout.....................................................................271
Figure78ResultsofclickingtheTextButton...................................................274
Figure79ResultsofInvRectbuttonclick.Notethetinyblackcrosshaircenter
screen................................................................................................................275
Figure80Ellipsesdemonstratesdrawinglinesandellipses............................278
Figure81OutputafterclickingtheFillRectbutton...........................................280
Figure82UsingDraw.Polygontodrawatriangle............................................282
Figure83UsingDraw.Polylinetodrawlines....................................................284
Figure84UsingtiledimageswiththeTileImgbuttonofourdemoprogram....292
Figure85LoadinganSVGfileinGambas.......................................................295
Figure86ErrorresultscaughtwithTRY..........................................................305
Figure87CATCHtestprogramopeningscreen..............................................307
Figure88DivbyZeroerrorcaughtbyCATCH................................................307
Figure89TheTextLabelupdatedwitherrorinfo.............................................308
Figure90Infomessagethattheerroriscleared..............................................308
Figure91Mainscreenaftererrorhasbeencleared........................................308
Figure92DefaultGambaserrordialog............................................................309
Figure93Oureventwasraised.......................................................................311
Figure94MouseOpsprogramrunning............................................................315
Figure95KbdOpsprogramrunning.................................................................318
Figure96TheBitOpsprogramindesignmode...............................................320
Figure97OurbitOpsprogramrunning............................................................325
Figure98TheFMainformindesignmode......................................................339
Figure99FRequestFormindesignmode.......................................................339
Figure100ChoosingtheTranslateoptioninGambas.....................................356
Figure101TheTranslateDialoginGambas...................................................356

14
A Beginner's Guide to Gambas

Thispageisintentionallyblank.

15
A Beginner's Guide to Gambas

Acknowledgments
Firstofall,averyspecialthankstoBenotMinisini forthecreationofGambas
andforhissupportofthisefforttofurtherdocumentthiswonderfullanguage.Without
Benot'sinitiative,wewouldallbestrugglingtofindabettertoolthanwhatexiststoday
onLinuxplatforms.MuchoftheinitialdocumentationoftheGambaslanguagewasput
ontheGambasWikibyBenotandhedeservesspecialcreditformakingthisinformation
available. Asitwasthe onlyknownpublishedsourceofdefinitivedocumentationin
existencepriortothiswriting,muchofthereferencematerialhereinwasgleanedfrom
thatinitialsetofdocumentation. Aswithanywrittenmaterial,thereisnoguarantee
thatthisdocumentationisasaccurateaswhatyoumayfindinthelatestreleaseofthe
Gambasproduct.

TheauthorwouldliketoextendaspecialthankstoFabienBodardforhishelpin
makingthisworkbecomeareality. Fabientirelesslyeditedcode,reviewedthesample
projectspresentedherein,andprovidedgreatinsightintotheinnerworkingsofGambas
allatthetimeofharvestforhisvineyard.LaurentCarlierandSteveStarrbothalso
deservemygratitudefortheirmeticulousworkeditingthecodeandensuringeverything
worked as advertised. Their feedback, suggestions and corrections were greatly
appreciated.IwouldalsoliketothankDanielCamposwhowasagreatassetinhelping
metounderstandsomeofthefinerpointsofGambas.NigelGerrardalsocontributedto
thesuccessofthisprojectbyprovidingafinalreviewandeditofthedatabasematerial.
FromamongtheseGambasHallofFamecoders,whoelsecouldhavedoneitbetter?

CountlessemailswerereceivedfrommanymembersoftheGambascommunity,
all of which provided ongoing encouragement and support which motivated me to
completethiseffortandmakeitavailabletoeveryone.Giventhedifficultiesofwritinga
bookinthefirstplace,itwasagreatfeelingofsatisfactiontoreceivesuchsupportfrom
completestrangerswhoallsharethesinglevisionofmakingGambasasuccess. Ican
onlyhopethatthisbookwilldojusticetothateffortandwelcomeanysuggestionsfor
change,aswellasanycomplimentsorconstructivecriticism.Ithasbeenalotoffunto
learnthiswonderfulnewlanguageandtoexplorethepossibilitiesitoffers.Idedicate
thisbooktoallofthoseGambasusersanddeveloperswhohavereliedoneachotherin
the Gambasuser/developercommunitytomake this productbecomereality. Shared
vision,commongoals,andopensoftwarearepowerfulforcesthatshouldnoteverbe
underestimated.Suchforceshavebeenknowntochangetheworldandwillcontinueto
dosolongafterthisbookhasbeenreadandforgotten.

JohnW.Rittinghouse,Ph.D.,CISM
October,2005

16
A Beginner's Guide to Gambas

Foreword
For the last three years, I have plunged headfirst into the Linux
programmingenvironment.ConsideringmyfirstinstallationofLinuxwasbackin
1996, it shouldnotbeconsidered agoodfirststart. Asan enthusiastic Basic
developer,theLinuxenvironmentlackedatoolthatwould allowmetoeasily
programintheLinuxenvironment.Bychance,Istumbleduponasmallproject,
thefruitofmorethantwoyearsofworkfromamannamedBenoitMinisini.After
figuringouthowtogetpasttheidiosyncrasiesofcompilation,Idiscoveredwhat
wastobetheembryonicstagesofoneofthemostfabulousprojectsicouldhave
imagined,Gambas!Atthattime,Gambaswasalreadyimplementedwithit'sown
IntegratedDevelopmentEnvironment(IDE)andasyntaxhighlighter.Theability
ofGambastodynamicallyloadcomponentsandremainfairlytruetotheBasic
languageasusedunderWindowswasanaddedbenefit.

Today,Gambashasarrivedasamatureproductthat,init'sfirstversion,
allowsausertoconstructgraphicalapplicationsorconsolebasedapplications,
supportsdatabasemanagement,connectiontotheInternetortosocketservers,
utilizesdatacompression,supportsDCOPwithKDEapplications,andmuchmore.
AGambasapplicationcanbetranslateddirectlyfromtheIDEandpackagedin
binaryformfordifferentLinux distributions.Whatwasinitiallyalluringtome
still is Gambas has gone beyond being just another programming language
becauseitsupportsallofthefeaturesofa"professional"productwhileretaining
itssimplicity. Gambasprovidesarealtoolforthebeginningprogrammerand
makesitpossibleforanoviceprogrammertodevelophighqualityapplications.
Here,inthisbook,youwillfindthefirstcomprehensivetreatmentofGambas.It
makes approaching the Gambas language simple and the reader can easily
progressfromthebeginner'sleveltopicstothemoreadvancedtopicsprofessional
programmersusedaily.

Gambashasandwillcontinuetoevolve.GambasVersion1.0(discussedin
thisbook)isthefoundationofalanguagewhichwillevolvetobeevenmore
powerful.Forexample,GambasVersion2willmakeitpossibletomakeAPIcalls
toa native library. Itwillallowprogrammers to manageevenmore typesof
database servers and will work equally well with either Qt or GTK graphics
libraries. Gambas2willallowprogrammerstodeveloptheirowncomponents
fromwithintheGambasenvironment. Developerswillbeabletocreategames
usingSDLandOpenGL.ThescopeoftheGambaslanguageisgrowinglargerand
andthesyntaxisbecomingmorecompact. Alloftheseideasforimprovement

17
A Beginner's Guide to Gambas

and change do not rest solely in the heads of a stable of chosen developers
workingontheGambas2project.TheycomefromallGambasuserswhoprovide
theideasthatmakeGambas2evenbetterthanbefore.Alreadyitcandosomuch
morethanversion1.0.Istronglyrecommendthatwhileyouarewaitingforthe
stablereleaseofGambas2,youbeginyourGambastrainingwithyourmachine
and what you will find in this book. It will prepare you for a wonderful
programmingexperienceintheLinuxenvironment.

FabienBodardandBenoitMinisini

18
A Beginner's Guide to Gambas

Chapter 1 - Introducing Gambas


GambaswasinitiallycreatedbyBenotMinisini,aresidentofthesuburbs
ofParis.AccordingtoBenot,GambasisaBasiclanguagewithobjectextensions.
The name itself is a play on the words "Gambas almost means Basic" and,
accordingtotheauthor,Gambasevolvedbecauseofhispersonalprogramming
experiences with the Microsoft Visual Basic software product1. Rather than
contend withthehorrendousnumberofbugsand idiosyncrasiesfound inthat
product,hedecidedtocreateGambas.

GambasislicensedundertheGNUPublicLicense2andhastakenonalife
ofit'sownduetoitsimmensepopularity. Gambasrunsonmostofthemajor
Linux platforms and the current (at the timeof this writing) stable version is
Release1.0.9. MinisinimakesitveryclearthatGambasisnotcompatiblewith
Visual Basic and itwill never bemade compatible. The syntax and internal
workingsofGambasarefarbetterandmoreuserfriendly. Minisinistated[sic]
that he took from Visual Basic what he found useful: the Basic language, the
developmentenvironment,andtheabilitytoquickly[andeasily]makeprograms
with[graphical]userinterfaces.3

Minisini disliked the overall poor level ofprogramming that iscommon


amongmanyVisualBasicprograms.Manybelievethatthisproblemmaybedue
totheenforceduseofquirkyprogrammingpracticesimposedondevelopersasa
resultofthewiderangeofbugsandthestrangeidiosyncrasiesoftheproprietary
VBlanguage.Gambashasbeendevelopedtobeascoherent,logicalandreliable
aspossible. Becauseitwasdevelopedwithanapproachdesigned toenhance
programmingstyleandcapturethebesttheBasicprogramminglanguagehasto
offer,theadditionofobjectbasedprogramminghasallowedGambastobecomea
popular,modern,stable,usableprogrammingenvironmentforLinuxdevelopers.

GambasArchitecture

EveryprogramwrittenwithGambasBasiciscomprisedofasetofproject
files. Each file within a project describes a class. The class files areinitially
compiled and subsequently executed by the Gambas Interpreter. This is very
similartohowJavaworks.Gambasismadeupofthefollowingprograms:

1 Thereaderisencouragedtovisithttp://gambas.sourceforge.net/index.htmltolearnmoreabouttheGambasproject.
2 Forinformationaboutthelicense,visithttp://www.gnu.org/licenses/licenses.html#GPL.
3 SeetheGambasWikiWebSiteIntroductionathttp://gambas.sourceforge.net/index.htmlformoredetails.

19
A Beginner's Guide to Gambas

Acompiler
Aninterpreter
Anarchiver
Agraphicaluserinterfacecomponent
Adevelopmentenvironment

Figure1below4isanillustrationoftheoverallarchitectureofGambas.In
Gambas,aprojectcontainsclassfiles,forms,modules,anddatafiles.AGambas
projectisstoredinasingledirectory.Compilingaprojectuses inincremental
compilemethodthatonlyrequiresrecompilationofthemodifiedclasses.Every
external reference of a class is solved dynamically at runtime. The Gambas
archiver transforms the entire project directory structure into a standalone
executable.TheGambasdevelopmentenvironmentwaswrittenwithGambasto
demonstratethefantasticcapabilitiesofthelanguage.

Figure1GeneraloverviewofGambasarchitecture.

SomeotherfeaturesthatsetGambasapartfromotherlanguagesinclude
the fact that Gambas has an extensible component architecture that allows
programmerstoextendthelanguage.Anyonecanwritecomponentsasshared
libraries that dynamically add new native classes to the interpreter. The
componentarchitectureisdocumentedonlineintheGambasWikiencyclopedia5.
4 See URL http://gambas.sourceforge.net/architecture.html, for the original graphic.
5 Copyright (c) 1999-2005 by contributing authors. All material on the Gambas Wiki is the property of the contributing

20
A Beginner's Guide to Gambas

WewillcoverGambascomponentsingreaterdetaillaterinthisbook.Bydefault,
the GambasInterpreter isatextonly(consolebased)program. Thecomponent
architectureisusedforthegraphicaluserinterface(GUI)partofthelanguage.
BecausetheGUIisimplementedasaGambascomponent,ithastheabilitytobe
independentofanyspecificGUItoolkit.WithGambas,youcanwriteaprogram
and choosewhichtoolkit,suchas GTK+6, Qt7,etc., touselater. Thecurrent
releaseofGambasimplementsthegraphicaluserinterfacewiththe Qt toolkit.
TheGUIcomponentsarederiveddirectlyfromtheQTlibrary.Itisrecommended
thatthereaderalsoconsultwiththeQTdocumentation8tobetterunderstandthe
GUIcontrols.AccordingtoMinisini,a GTK+ componentwithanearlyidentical
interfaceastheQtcomponentisplanned.

Figure2theGambasOpeningScreen.

authors.
6 FormoreinfoaboutGTK+,visithttp://www.gtk.org/.
7 FormoreinfoaboutQt,visithttp://www.trolltech.com/products/qt/.
8 http://doc.trolltech.com/3.3/index.html

21
A Beginner's Guide to Gambas

Another feature of Gambas that sets it apart from other programming


languagesisthecapabilityofanywindowordialogboxtobeusedlikeacontrol.
This feature is not directly supported in other programming languages. Also,
Gambasprojectsareeasilytranslatable,intoalmostanyotherlanguage.Wewill
demonstrate this feature later in the book when we cover Internationalization
(i18n).

TheGambasProgrammingEnvironment

For now, let's take a quick tour of Gambas and introduce you to the
Gambasprogrammingenvironment.Alloftheexamplesandcodewrittenforthis
book were developed using Gambas version 1.0.9 running on Linspire 5.09.
TheyshouldworkonanyplatformthatyoucaninstallGambasonsuccessfully.
ForLinspireusers,itisassimpleastheclickofabuttonusingtheClickNRun
warehousefeatureofthatproduct.Whenyoufirstclickthedesktopicontostart
theGambasprogram,youwillbepresentedwithanopeningscreensimilartothat
foundinFigure2above.Thewelcomescreenallowsyoutocreateanewproject,
openanexistingproject,viewandselectfromrecentprojects,lookatexamples,
orquit. ForourquicktourofGambas,wearegoingtoselecttheNewProject
optionandcreateourfirstGambasproject.YouwillseeadialogsimilartoFigure
3belowappear.

Figure3TheGambasProjectCreationWizard.

9 FormoreinfoaboutLinspire,visithttp://www.linspire.com.

22
A Beginner's Guide to Gambas

Simplyclickthe Next>> buttonandyouwillbepresentedwithanother


dialogthatrequiresyoutochoosethetypeofprojectyouwanttocreate(see
Figure4,below). ThisdialogrequiresyoutopickbetweenaGUIprojectora
consoleproject.

Figure4AdialogtoselectthetypeofGambasprojectyouwish
tocreate.

Forourexample,choosethefirstselection,Createagraphicalprojectand
clicktheNext>>buttonatthebottomofthedialog. The next dialog that you
willseerequiresyoutonameyourprojectandchoosewhereitwillbelocatedon
yourlocalfilesystem.ItisshowninFigure5below.

Thissectionofthewizardhasyoutospecifythenameoftheprojectasit
willbestoredondisk.Remember,inGambasaprojectisentirelyselfcontained
inadirectoryorfolder.Thefoldernameyouchooseasthenamefortheproject
iswhatwillbecreatedonyoursystem.

Thetitleoftheprojectwillbewhatyouspecifyinthesecondtextinput
field of the dialog. Additionally, the Options section allows you to choose
whetherornotyourprojectwillbetranslatableandifthecontrolsusedonyour
formsaregoingtobemadepubliclyaccessible.Wewilldiscusstheseoptionin
moredetaillaterinthisbook.Fornow,justfilloutthedialogasshowninFigure
5andclickNext>>.

23
A Beginner's Guide to Gambas

Figure5ProjectNameSelectionDialog.

Chooseadirectoryappropriateforyourfilesystemandclickthe Next>>
button to proceed to the final dialog screen of the wizard, as shown on the
followingpageinFigure7. Thisdialogissimplyaconfirmationscreenofthe
choicesyouhavemade.Themostimportantthingtorememberaboutthisscreen
isthatitisthelastchanceyouhavetobackupandmakechangesbeforeyour
newprojectiscreated.

Figure6ProjectDirectorySelectionDialog.

24
A Beginner's Guide to Gambas

Figure7NewProjectconfirmationdialog.

OnceyouhaveclickedontheOKbuttontofinishthiswizard,Gambas
will present you with the Gambas integrated development environment (IDE).
TheIDEconsistsofseveralcomponentsthatareshowninFigure8onthenext
page.

GambasIDEComponents

TheProjectExploreristhemainGambaswindow.ItshowyouaTreeView
ofthetypesoffilesfoundwithinyourproject(i.e.,classfiles,forms,modules,and
othertypesoffilessuchasdataandpictureoriconfiles)andtheProjectExplorer
allows you to perform most Gambas project management operations, such as
opening and saving projects, building executables, running your program or
debuggingit,showingorhidingvariousGambasdialogs,etc.FromtheTreeView
intheProjectExplorer,youwillseetheitemslistedasfollows:

Classes
Forms
Modules
Data

Classes lists the class files you've created for your project. Classes are
basicallytemplatesthatcanbeusedtomakeobjectsoutofatruntime,withcode
todefineproperties,methodsandeventhandlersforeachobjectyoucreate.

25
A Beginner's Guide to Gambas

Figure8TheGambasIDE.

Forms liststhevariousformsyoucreateforyourproject. Formsarethe


windowstheuseractuallyinteractswith.

Modulesdisplaythemodulesyou'vewrittenforyourproject.Modulesare
simplysetsofsubroutinesandfunctionstobeusedanywhereinyourprogram.
Unlikeclasses,youcan'tmakeobjectsoutofthematruntimeandtheyhaveno
eventhandlers.

Dataliststheotherfilesinyourproject.Thesecanincludeanyotherkind
offileused tobuildyourproject,suchasgraphicfiles,icons,bitmaps,textor
HTMLfiles,andevenmediafiles.AtthebottomoftheProjectExploreryouwill
findtheStatusBarwhichisusedtoindicatewhatGambasiscurrentlydoing.

WhenyoustarttodevelopaprojectinGambas,youwillusuallywantto
begin with a main form. The main form is where the program startup and
initializationwilloccuranditisusuallythefirstthingyouruserwillseewhen
theyexecute(orrun)theapplicationyouhavebuilt.Thisistheformyouwilladd
controlstoandspecifywhatactionsaretobetakenwhentheuserinteractswith

26
A Beginner's Guide to Gambas

thosecontrols. SuchinteractionbetweentheuserandtheGUIisreferredtoas
events. The controls are found in the ToolBox window. You can change the
appearanceandbehaviorofthecontrolsbysettingthepropertiesforeachcontrol.
Propertiescanbeseeninthepropertieswindow.

Now,letstakealookatthemenusandbuttonsfoundatthetopofthe
ProjectExplorer.Themenus(seeFigures9through12below)controlallthemain
Gambasmanagementtasks.TheFilemenuwillallowyoutoopenaproject,save
aproject,createanewproject, opensomeGambasexampleprojects,orquit
usingGambas.TheProjectMenuiswhereprogramcompilationoccurs.Youcan
also create the program executable, make a source archive, or create an
installation package. This menu offers you the option of translating your
programintoanotherlanguage.Finally,youcansetGambasIDEpropertiesfrom
thismenu.

Figure9ProjectExplorerFileMenu.

Figure10ProjectMenu.

Figure12ProjectExplorerToolsMenu.

Figure11ProjectExplorerViewMenu.

27
A Beginner's Guide to Gambas

TheViewmenuwillallowyoutobringupthepropertieswindoworthe
ToolBox window. You can open a console or use the Icon Editor to create
programicons. TheHierarchyoptionwillopenawindowandshowyouyour
project'sclasshierarchy.Finally,fromthismenu,youcancloseallofthewindows
thatarecurrentlyopenintheIDE. The ToolBar buttons (seeFigure13below)
providesingleclickaccesstothemostcommonmenuitems.Hoveringyourmouse
cursoroveroneofthebuttonswilldisplayaToolTipthatwilltellyouwhatmenu
actionthatparticularbuttonwillperform.

Figure13belowshowsyoutheFilemenuandToolBar.FromtheProject
ExplorerTreeView youcandoubleclickonaformanditwillpopupforyouto
edit.Editingformsissimplyamatterofselectingwhattypeofcontrolyou'dlike
toplaceontheformandthenusingthemousetoresize(draw)itonyourform.

Figure13ProjectExplorerMenuandToolbar.

Rightclickingontheformoranyofitschildren(controls)willshowyoua
popupmenuthatwillallowyoutoperformoperationsonthecontrol,editits
propertiesordeleteit.Thecurrentlyselectedcontrolisindicatedbyfourblack
squarescalledhandles. Clickingonahandleandusingthemousetodragthe
controlwhereyouwantitwillallowyoutomoveorresizethecontrol.Double
clicking on a control will bring up the code editor window and display any
existingeventhandlerforthecontrolordisplayadefaulteventhandlerifthere
havebeennonespecified.

TheGambasCodeEditorenablesyoutowritecodetohandleeventsforthe
controlsyou'veplacedonyourform.IntheToolBoxwindow,theSelectionTool
istheonlyitemintheToolBoxthatisn'tactuallyacontrol. TheSelectionTool
simplygivesyoucontrolofthedefaultmousepointer. Youusethispointerto
selectcontrolsandperformpositioningandresizingoperationsonformsandtheir
associatedcontrols.

FromtheProjectExplorerFileMenu,choosetheQuitoptionandsaveyour
project.Whenwereopenit,allyourworkwillbesaved.Inthenextsection,we
willbegintocovertheessentialsyouneedtounderstandinordertoprogramwith

28
A Beginner's Guide to Gambas

Gambas. Wewillcomebacktothisprojecttodevelopaprogramthatusesthe
GUIafterwelearnabitmoreabouttheGambascodingenvironment,theprimary
languageconceptsthatarerequiredtouseGambas,andsomebasicsaboutdata
typesandvariables. Thatisallcoveredinthenextsectionandconstitutesthe
remainderofthisintroductiontoGambasprogramming.Fornow,takeashort
breakandwewillcontinuewhenyoucomeback.

29
A Beginner's Guide to Gambas

Chapter 2 Gambas Language


Concepts
Inthischapter,wewillbegintolearnthebasicconceptsneededtomaster
the Gambas programming language. The topics we will cover in this chapter
includelearningabout Gambasdatatypes,constants,andvariablesandhowto
declareandassignvaluestothoseconstantsandvariables.Wewilllearnabout
thebasicarithmeticoperators,comparisonoperators,andstringoperators.

GambasVariables,DatatypesandConstants

Variablesmustbedefinedatthebeginningofaclass,methodorfunction.
Variabledeclarationscaneitherbelocaltoaprocedureorfunctionortheycanbe
declaredglobaltoaclass.Aglobalvariableisaccessibleeverywhereintheclass
itisdeclared.TheformatofaglobalvariabledeclarationinGambastakesthe
followinggeneralform:

[STATIC](PUBLIC|PRIVATE)Identifier[Arraydeclaration]AS[NEW]Datatype

IfthePUBLICkeywordisspecified,itisalsoaccessibletotheotherclasses
thathaveanyreferencetoanobjectofthatclass.Ifthe PRIVATE keyword is
specified,itisnotaccessibleoutsidetheclass inwhichitwasdefined. Ifthe
STATICkeywordisspecified,thesamevariablewillbesharedwitheveryobject
oftheclasswhereitisdeclared.IftheNEWkeywordisspecified,thevariableis
initializedwith(i.e.,instantiatedwith)anewinstanceoftheclassusingthedata
typespecified.Forlocalvariabledeclarations,theformatislikethis:

[DIM]IdentifierASDatatype

Thiswilldeclarealocalvariableinaprocedureorfunction.Thisvariableis
onlyaccessibletotheprocedureorfunctionwhereitisdeclared.Anexampleof
severallocaldeclarationsisshownbelow:

DIMiValueASINTEGER
DIMstMyNameASSTRING
DIMfMyMatrix[3,3]ASFLOAT
DIMoMyObjectASOBJECT

30
A Beginner's Guide to Gambas

Therearecurrentlyninebasicdatatypesaprogrammercanusetowrite
programcodeinGambas10.Thesedatatypesincludethefollowing:

Boolean Byte Short


Integer Float Date
String Variant Object

Boolean datatypes can contain only a single value, either TRUE or


FALSE. TRUEisdefinedas1andFALSEisdefinedas0. Thedeclarationofa
Booleanvariableoccupies1byteofmemoryandthedefaultvalueisFALSE.An
exampleofavariabledeclarationforaBooleanvariablelookslikethis:

STATICPRIVATEbGridASBoolean

Typically, a programmer would use a Boolean datatype when the only


valuesforthevariablewouldbeyes/no,TRUE/FALSE,1/0,etc. Ifthevalues
usedinyourprogramcouldbeanythingelse,Booleanwouldbeaninappropriate
selection for the variable datatype. Another thing to note in the variable
declaration above is the placement of the lowercase letter b in from of the
variablename.

Good programming convention encourages this practice, known as the


HungarianNotation11,asitallowstheprogrammerstoknowwhatdatatypethe
variableisbysimplyknowingthatthe'b'standsforBoolean.Whathappenswhen
a programmer wants to use a Byte datatype instead of a Boolean datatype?
Typically,asecondletterisaddedtothevariabledeclarationsoratherthanusing
'b'infrontofthevariablenametheprogrammerwoulduse'by'asbelow:

STATICPRIVATEbySomethingASByte

Theletters'ar' 's', 'i', 'f', 'd', 'st', 'v' and 'o' arecommonlyusednotations
whendeclaringvariableswhileprogramminginGambas.Itisgoodprogramming
practicetoforceyourselftoadheretothistechniquesothatotherscanpickup
yourcodeanduseitwithouthavingtosearcharoundtofindthedatatypefor
eachvariableencountered.Someprogrammersevenusemorethanthefirstletter
(s) to name their variables. For example, they would code IntMyNumber or
ByteSomething.

10 In the second release of Gambas (Gambas2) "Long" and "Single" data types are planned. These data-types are like the C
LONG LONG and FLOAT data types. This is a significant improvement because Gambas2 will provide direct programming
access to the C API and will also support 64 bit platforms.
11 Hungarian Notation (HN) is a naming convention originated by Charles Simonyi of Microsoft. It was first presented in his
thesis and is widely used throughout the source code of the Windows operating system, among other places.

31
A Beginner's Guide to Gambas

The Bytedatatype cancontainvaluesfrom0to255andoccupiesone


byte of memory when declared. The default value when a Byte datatype is
declaredis0.Ifyouarecertainyourvalueswillnotexceed255thenthisdata
type is appropriate for use. If it is possible that the values assigned to this
variablewouldexceed255,thenthelikelyresultwouldbeaprogramcrashatrun
time. Itisbettertousethe Shortdatatype oran Integerdatatype forsuch
situations. For a Short datatype, values can range from 32768 to +32767.
Shortdatatypesoccupytwobytesofmemoryanddefaulttoazerovaluewhen
declared.Integerdatatypesoccupytwiceasmuchmemory,takingupfourbytes.
The range of values you can use with the Integer datatype is from
2,147,483,684to+2,147,483,647.ThisissimilartotheLONGdatatypeusedin
VB.ExamplesofShortandIntegerdatatypevariabledeclarationsare:

STATICPUBLICsSomeShortASShort
STATICPUBLICiSomeIntegerASInteger

Whenintegerswillnotworkforyourpurposes,Gambasprovidesyouwith
theFloatdatatype.Thisdatatypeallowsyoutousefloatingpointnumbersfor
yourprogram.FloatdatatypesarelikeDoubledatatypesusedinCandVB.The
rangeofvaluesfor floatdatatype variablesisfrom1.79769313486232E308to
4.94065645841247E324fornegativevaluesandfrom4.94065645841247E324
to1.79769313486232E308forpositivevalues.Floatvariablesoccupyeightbytes
ofmemoryanddefaulttoazerovaluewhendeclared.Asampledeclarationfora
floatwouldbeasfollows:

DIMfRadiusASFloat

ThelastnumericdatatypewehaveinGambasistheDatedatatype.Date
variablesalsotakeupeightbytesofmemory. Thedateportionofthedateis
storedinafourbyteintegerandthetimeportionisstoredinafourbyteinteger.
Itisstoredas [Year,Month,Day][,Hours,Minutes,Seconds] andisusually
usedwiththeGambasbuiltinDateandTimefunctions,whichwewillexplain
about later in this book. The date datatype defaults to a NULL value when
initialized.HereishowtodeclareaDatedatatype:

DIMddateASDate
DIMdtimeASDate

Strings,VariantsandObjectsarethenonnumericdatatypessupportedin
Gambas. A String datatype is a series of zero or more characters that are
treatedasasingleentity.Stringscancontainalphanumericdata.Alphanumeric

32
A Beginner's Guide to Gambas

meansthatthedatacancontainanycombinationoflettersandintegersorspecial
characterssuchas$%^&*.Strings,whendeclaredtakefourbytesofmemory.
Thismeansthemaximumsizeforastringis4bytes*8bitsperbyte,or32bits
squared(1,024bytes).StringvariablesdefaulttoaNULLvaluewhendeclared.
Declareastringvariablejustlikeyouwouldanyothervariable:

STATICPUBLICstSomeStringASString

TheVariantdatatypeisusedwhenyoudonotknowwhatkindofdata
typethevariablewillbereceiving.Forexample,ifreadingdatafromafile,you
couldreadaninteger,astring,asinglecharacter,floatingpointnumbers,etc.To
ensure the data is placed in a variable without causing a program crash, the
variantdatatypeisused.Youcanthentestthevariantdatausingsomebuiltin
functionsofGambastodeterminethedatatypeoryoucanjustconvertthedata
tothedatatypeyouneedusingaconversionfunction.Wewilldemonstratethis
laterinthebook.Fornow,itisonlyimportantthatyouunderstandthatvariant
datatypesexistandthattheyareusedwhenyouarenotsureofthetypeofdata
thevariablewillhold.

The Object datatype is a special datatype that holds and references


objects such as controls and forms. Later, when we begin to discuss OO
programming,wewillcovertheuseof objectdatatypesingreaterdetail. The
tableshownbelowispresentedasaconvenientreference:

Gambas data-types
Name Description Memorysize Default
Boolean TrueorFalse 1byte FALSE
Byte 0...255 1byte 0
Short 32768...+32767 2bytes 0
Integer 2147483648...+2147483647 4bytes 0
Float SimilartothedoubledatatypeinC 8bytes 0
Date Date/time,eachstoredina4byteinteger. 8bytes NULL
String Areferencetoavariablelengthstring. 4bytes NULL
Variant Canconsistofanydatatype. 12bytes NULL
Object Anindirectreferencetoanobject. 4bytes Null

Now that you know about all the different types of data that Gambas
supports,wewillstarttolookatwhatyoucandowiththosedatatypes.When
usingyourvariablesinGambasprograms,theycanberepresentedbydatathat
changes (e.g.,itisavariable) ortheycanberepresentedbydatathatremains

33
A Beginner's Guide to Gambas

constantthroughouttheprogram. Thistypeofdataisknownasa Constant in


Gambas. GambasconstantsisusedtorepresentaNULLobjectreference,azero
lengthstring,aNULLdate,oranuninitializedvariant. Examplesofconstants
includethevaluesNULL,TRUEandFALSE.TodeclareaconstantinGambasuse
thefollowingformat:

(PUBLIC|PRIVATE)CONSTIdentifierASDatatype=value

This declares a class global constant. This constant is accessible


everywhereintheclassitisdeclared. Ifthe PUBLIC keyword isspecified,itis
alsoaccessibletotheotherclasseshavingareferencetoanobjectofthisclass.
Constant values must be Boolean, integers, floating point or string datatypes.
Herearesomeexamplesofconstantdeclarations:

PUBLICCONSTMAX_FILEASInteger=30
PRIVATECONSTMAGIC_HEADERASString="#Gambasformfile"

ThebuiltinconstantsyouwoulduseinGambasarelistedinthetablebelow:

Gambas Constants
Constant Example
TheTRUEvalue. TRUE
TheFALSEvalue. FALSE
Integernumbers. 0,562,17,32769
Hexadecimalshortsignedintegers. &H100F3,&HF0FF,&FFFF
Hexadecimalsignedintegers. &H1ABF332E,&1CBF302E
Hexadecimalunsignedintegers. &H80A0&,&HFCFF&
Binaryintegers. &X1010111101,%101000011
Floatingpointnumbers. 1.1110,5.3419E+4
Stringconstants. "Hello,GambasWorld!"
Stringconstantstobetranslated. ("Thisisvery,verycool")
NULLconstant/voidstring. NULL

34
A Beginner's Guide to Gambas

Stringconstantscanalsocontainthefollowingescapecharacters:

Escapecharacter ASCIIequivalent
\n CHR$(13)
\r CHR$(10)
\t CHR$(9)
\ Doublequote
\\ Backslash
\xx CHR$(&Hxx)

Youcanwriteastringconstantinseveralsuccessiveparts.Forexample,
"Myson""is""sixteen"isseenbyGambasas"Mysonissixteen".

VariableAssignment

AprogrammercanassignanyvaluetoavariableinGambasbyusingthe
followinggeneralformat:

Variable=Expression

This assignment statement assigns the value of an expression to one of the


followingelements:

Alocalvariable
Afunctionparameter
Aglobal(class)variable
Anarrayelement
Apublicobjectvariableorproperty

Herearesomeexampleofvariableassignments:

iMyVal=1984
stMyName="Orwell"
fMyNum=123.45

AssignmentUsingTheWITHStatement

Thisstatementismostcommonlyusedtosetpropertiesforcontrols.The
expressionthatexistsbetweentheWITHkeywordandtheENDWITHinstruction

35
A Beginner's Guide to Gambas

isused. Theexpressionwillbeginwith dotnotation,i.e.,.Textcouldbeused.


WITHassignsthedottedexpressionontheleftoftheequalsignthevaluefound
ontherightsideoftheequalsign. Expression mustbeanobject. Hereisa
sampleofhowtheWITHstructurelooks:

WITHExpression
.object=something;.
ENDWITH

Asanexample,thecodebelowiscodeequivalenttohButton.Text="Exit"

WITHhButton
.Text="Exit"
ENDWITH

OperatorsandExpressions

Now thatwe know howto declare variables and constantsand how to


assignvaluestothesevariablesandconstants,letstakealookattheoperations
thatcanbeperformedwiththem.Wewillbeginwithcomparisonoperatorsthen
takealookatarithmeticoperatorsandstringoperators.

Comparisonoperators

Comparison of two variables requires finding answers to questions like


doesxequalyorisalessthanb.Thefollowingcomparisonsaresupportedin
Gambas:

Operator Meaning Example


= Isequalto IFa=bTHEN...
<> Isnotequal IFa<>cTHEN...
< Islessthan IFa<dTHEN...
> Isgreaterthan IFa>eTHEN...
<= Islessthanorequalto IFa<=fTHEN...
>= Isgreaterthanorequalto IFa>=gTHEN...

ArithmeticOperators

All of the basic arithmetic operations are supported in Gambas. These

36
A Beginner's Guide to Gambas

operators include addition, subtraction, multiplication, and division. The


standard symbols for these operations are '+', '', '*', and '/'. For example,
Number+Numberwilladdtwonumbers.Whenavalueorvariableispreceded
byaminussign, 222, forexample,Gambascomputestheoppositesignofthat
number.ThevalueZeroistheoppositeofitself.Now,wewillstarttowritesome
Gambas code using the Gambas terminal application feature. The console
window will display our output so lets use Gambas to experiment with the
operatorsaswelearnaboutthem.

Let'sStartCodingGambas

Nowthatweknowaboutdatatypesandvariableassignments,letsgetour
feetwetwithGambas. StartGambasandfromthe ProjectExplorer FileMenu
selectNewProject.AsyougothroughtheNewProjectWizard,selectaTerminal
ProjectandclickNext.NamethisprojectTerminalTestandplaceitinadirectory
called TerminalTest. Don't worry about any of the other options. Just click
Next>>untilthewizardcompletes.OncetheIDEappearswithyournewproject
wewillneedtocreateastartupclassinordertorunourcode.FromtheProject
ExplorerfindtheTreeViewitemcalledClassesandrightclickthemouse.Choose
the New... option and take the default name Class1. The code window will
appearandinsidethewindowitshouldlooksomethinglikethis:

'Gambasclassfile
STATICPUBLICSUBMain()

END

Let'stakealookatsomeGambaskeywordsyoushouldknowabitmoreabout
beforeweproceed.

END,RETURNandQUITStatements

The END keyword indicatestheendofaprocedureorafunction. There


aredifferencesfrom VB whenusing END. In VB,the End commandclosesall
formsandfilesandterminatestheprogram.InGambas,theENDcommandworks
morelikeVB'sEndFunctioncombinedwithVB'sEndSub.Itclosesthefunction
or subroutine. For the functionality of VB's End command, use the QUIT
command. It ends the program immediately. All windows are closed, and
everythingisfreedupinmemoryascleanlyaspossible. InGambas,whenyou
wishtoexitaroutine,youcanusetheRETURNcommand.Usually,RETURNis
usedtoreturnavaluetothecallingprocedure.TheformatofRETURNis:

37
A Beginner's Guide to Gambas

RETURN[Expression]

WhenGambasexecutestheRETURNcommand,itquitsaprocedureora
functionandcompletesitsworkbyreturningthevalueofExpression.Now,enter
thefollowing code after the ' Gambas class file line (note thatcomments in
Gambasstartwiththe'[akathetickmark]) andbetweenthe STATICPUBLIC
SUBMain()andENDstatements.Onceyouhaveenteredthecodebelowinthe
Gambas code window, click the green button from the Project Explorer
ToolBartoexecuteyourprogram.Hereisthecodeyouwanttotryfirst:

STATICPUBLICSUBMain()
DIMNASInteger
DIMRASInteger
N=3
R=6
PRINT===>;N;"|";R;"and";N;"|";R;
END

Ifallgoeswell(anditshould),youwillseetheblueshrimp(a.k.a.,theGambas
mascot)danceandtheconsolewindowwillrespondwiththefollowing:
===>3|6and6|3

NotethatthevalueofvariableNchangedfromapositive3to3andthe
valueof6changedtoapositivevalueof6.Don'tworryaboutthesyntaxofthe
PRINTstatementortheuseofthekeywordDIMusedtodeclareourvariablesfor
now.Wewillcoverthesekeywordslaterinthebook.

Tosubtractvalues,usetheformat NumberNumber andGambaswill


subtractthesecondnumberfromthefirst.

STATICPUBLICSUBMain()
DIMNASInteger
DIMRASInteger
N=8
R=5
PRINT"===>";NR;
END

Theconsolewillrespondwiththefollowing:
==>3

38
A Beginner's Guide to Gambas

To multiply numbers, we use the format of Number * Number and


Gambaswillmultiplythetwonumbers.Hereisanotherconsoleexampletotry:

STATICPUBLICSUBMain()
DIMNASInteger
DIMRASInteger
N=8
R=5
PRINT"===>";N*R;
END

Theconsolewillrespondwiththefollowing:
==>40

Divisionisnodifferentthanmultiplication. Usetheformatof Number/


NumbertohaveGambasdividetwonumbers.Adivisionbyzeroerrorwilloccur
if the value of the number to the right of the slash is zero. Try this console
example:

STATICPUBLICSUBMain()
DIMNASInteger
DIMRASInteger
N=9
R=3
PRINT"===>";N/R;
END

Theconsolewillrespondwiththefollowing:
==>3

Nowtryusingthe\todivideinsteadofthe/character:

STATICPUBLICSUBMain()
DIMNASInteger
DIMRASInteger
N=9
R=5
PRINT"===>";N\R;
END

Theconsolewillrespondwiththequotient:
==>1

39
A Beginner's Guide to Gambas

If you use a backslash to divide numbers, i.e., Number \ Number Gambas


computesthequotientofthetwonumbers.Adivisionbyzeroerrorwilloccurif
the value of the number to the right of the backslash is zero. A \ B is the
equivalent of INT(A/B). To get the remainder, we can use the builtin MOD
functionlikethis:

STATICPUBLICSUBMain()
DIMNASInteger
DIMRASInteger
N=9
R=5
PRINT"===>";N\R;"andtheremainderis:";9MOD5;
END

Theconsolerespondswith:

===>1andtheremainderis:4

UsingNumberMODNumbercomputestheremainderofthequotientof
thetwonumbers.Adivisionbyzeroerrorwilloccurifthevalueofthenumberto
therightoftheMODoperatoriszero.Finally,wecantesttheDivisionbyZero
errorbytypingthisexample:

STATICPUBLICSUBMain()

DIMNASInteger
DIMRASInteger

N=9
R=0
PRINT"===>";N/R;
END

Gambaswillrespondwiththefollowing:

Figure14ADivisionbyZeroErrorDialog.

NOTE:ClicktheStopbuttonwhenyouseethisdialogappear.

40
A Beginner's Guide to Gambas

Inordertoraiseanumbertoagivenpower(exponent),usetheformatof
Number^PowerandGambasraisesNumbertothepowerthePoweroperator
specified.Trythis:

STATICPUBLICSUBMain()
DIMNASInteger
DIMRASInteger
N=2
R=3
PRINT"===>";N^R;
END

Theconsolewillrespondwiththefollowing:
==>8

Gambas also has the ability to support logical arithmetic operations12.


Using the format of Number AND Number instructs Gambas to use the AND
operator tocomputethemathematical AND ofthebinaryvaluesofbothofthe
numbers.Trythis:

STATICPUBLICSUBMain()
DIMNASInteger
DIMRASInteger

N=0
R=0
PRINT"=>";NANDR;"istheANDresultof";N;"and";R
R=1
PRINT"=>";NANDR;"istheANDresultof";N;"and";R
N=1
PRINT"=>";NANDR;"istheANDresultof";N;"and";R
END

Theconsolewindowrespondswith:
=>0istheANDresultof0and0
=>0istheANDresultof0and1
=>1istheANDresultof1and1

Likewise, Number OR Number used the OR operator and computes the


mathematicalORofthebinaryvalueofthetwonumbers.

12 In Gambas2, it will allow the use of concatenated operators. For example, a += 2 or B /= 4 will work just as if you were
programming in C or C++.

41
A Beginner's Guide to Gambas

STATICPUBLICSUBMain()
DIMNASInteger
DIMRASInteger

N=0
R=0
PRINT"=>";NORR;"istheORresultof";N;"OR";R
R=1
PRINT"=>";NORR;"istheORresultof";N;"OR";R
N=1
PRINT"=>";NORR;"istheORresultof";N;"OR";R
END

Theconsolewindowrespondswith:

=>0istheORresultof0OR0
=>1istheORresultof0OR1
=>1istheORresultof1OR1

Number XOR Number uses the XOR operator and computes the
mathematicalexclusiveORofthebinaryvalueofthetwonumbers.

STATICPUBLICSUBMain()
DIMNASInteger
DIMRASInteger

N=0
R=0
PRINT"=>";NXORR;"istheXORresultof";N;"XOR";R
R=1
PRINT"=>";NXORR;"istheXORresultof";N;"XOR";R
N=1
PRINT"=>";NXORR;"istheXORresultof";N;"XOR";R
END

Theconsolewindowrespondswith:

=>0istheXORresultof0XOR0
=>1istheXORresultof0XOR1
=>0istheXORresultof1XOR1

Additionally,thefollowingoperatorsmanipulateoneormorenumericvaluesand
returnanumericvalue:

DEC|INC|LIKE|NOT

42
A Beginner's Guide to Gambas

TheDECoperatorisusedtodecrementavaluebyone.TheINCoperator
willincrementthevaluebyone.Thevariablecanbeanytargetofanassignment
butmustbeanumericvalue.

STATICPUBLICSUBMain()
DIMNASInteger
DIMRASInteger

N=5
R=5
DECN
INCR
PRINT"===>";N;"|";R;
END

Theconsolewillrespondwiththefollowing:
==>4|6

LIKE isusedtoperformaBooleancomparisonofastring. Ittakesthe


format of String LIKE Pattern and it returns TRUE if the String matches the
Pattern.Thepatterncancontainthefollowingpatternmatchingcharacters:

* MatchNnumberofanytypeofcharacter.
? Matchanysinglecharacter.
[abc] Matchanycharacterspecifiedbetweenthebracketsymbols.
[xy] Matchanycharacterthatexistsintheintervalxy.
[^xy] Matchanycharacterthatdoesnotexistintheintervalxy.

STATICPUBLICSUBMain()
PRINT"Rittinghouse"LIKE"R*"
END

Theconsolerespondswith:

TRUE

Thespecialcharacter\preventsthenextcharacterfollowingitinastring
frombeinginterpretedasagenericpartofthestring.Thinkofthe\characteras
acontrolcode.Trythis:

STATICPUBLICSUBMain()
PRINT"Samson"LIKE"S*"

43
A Beginner's Guide to Gambas

PRINT"Gambas"LIKE"?[Aa]*"
PRINT"Leonard"LIKE"G[Aa]\\*"
PRINT"Alfred"LIKE"G[^Aa]*"
END

Theconsolerespondswith:

TRUE
TRUE
FALSE
FALSE

Note:youmustuseadoublebackslashcharacter,\\toprintabackslashorspecial
stringsequencecontainingbackslashes. Otherwisethe\willbeinterpretedbythe
compilerasaspecialcharacterlike'\n','\t','\*',etc.Alternatively,youcanusethis
patternstring:LIKE"G[Aa][*]"

TheNOToperatorisusedtoreturnaresultofanexpression.Theformatis
asfollows:
Result=NOTExpression

WhenGambasevaluatesthisexpression,itcomputesthelogicalNOTofthe
expression.Iftheexpressionisastringoranobject,GambasreturnsTRUEifthe
expressionisNULL.Herearesomeexamplestotryonyourconsole:

STATICPUBLICSUBMain()
PRINTNOTTRUE
PRINTNOTFALSE
PRINTNOT11
PRINTNOT"Gambas"
PRINTNOT""
END

Theconsolerespondswith:

False
True
12
False
True

StringOperators

InGambas,whenyouwanttocompareorconcatenatestrings,youcanuse

44
A Beginner's Guide to Gambas

thestringoperators. Theseoperatorsallowyoutoconcatenatestringsandfile
paths,performLIKEoperationsasexplainedabove,determineifstringsareequal
ornotequal,lessthan,greaterthan,lessthanorequalto,orgreaterthanorequal
to each other. The following table of string operations is shown for your
convenience:

Gambas String Operations


StringOperation Resulttodetermine
String&String Concatenatetwostrings.
String&/String Concatenatetwostringsthatcontainfilenames.Addapathseparatorbetween
thetwostringsifnecessary.
StringLIKEPattern PerformpatternmatchingusingtheLIKEoperator.
String=String Determineifthetwostringsareequal.
String<>String Determineifthetwostringsdifferent.
String<String Determineifthefirststringislowerthanthesecondstring
String>String Determineifthefirststringisgreaterthanthesecondstring
String<=String Determineifthefirststringislowerorequaltothesecondstring
String>=String Determineifthefirststringisgreaterorequaltothesecondstring

Note:allstringoperatorcomparisonsarecasesensitive.

HerearesomethingstotryusingGambasconsole:

STATICPUBLICSUBMain()
DIMaASString
DIMbASString
a="ham"
b="burger"
PRINT"===>";A&B;
a="Gambas"
b=1
PRINT"===>";A&"isnumber"&B;
END

Theconsolerespondswith:

===>hamburger
===>Gambasisnumber1

45
A Beginner's Guide to Gambas

Chapter 3 - Keywords and Program


Flow Control
InGambas,theprogrammercontrolstheprogrambyusingkeywordsand
conditionalexpressions.Gambasisaneventdrivenlanguage.Theprogrammer
has the ability to direct what happens whenever any event occurs. The
programmerusesGambaskeywords(whicharereservedwordswithveryspecific
syntax) to create instructions that guide what the program will do in a given
circumstance. Conditionals are testsof an expression or a variable. The test
couldbeanevaluationoftheresultofanoperationorcomparisonofequality,for
example. The following table shows all of the Gambas keywords currently
supported:

BREAK CASE CONTINUE DEFAULT DO ELSE


END ENDIF END SELECT END WITH
FOR FOREACHGOTO IF LOOP NEXT
QUIT REPEAT RETURN SELECT STEP THEN
TO UNTIL WAIT WEND WHILE WITH

Thebestwaytounderstandwhatthesekeywordsandconditionalsmeanis
tograduallyintroducethemwithexamples. Ratherthangothroughthelistof
keywordsinalphabeticalorder,let'staketheapproachofintroducingthembased
on the type of functionality they support. We will start with the most basic
statementsandcommandsandprogressthroughthemorecomplexonesaswe
continue.Let'sstartwiththeGambasPRINTstatement.

ThePRINTStatement

The PRINT statement prints expressions to the standard output. The


expressionsareconvertedtostringsbytheStr()function.PRINTtakestheformat
of:
PRINTExpression[(;|,)Expression...][(;|,)]

Bracketsusedinthesyntaxdefinitionaboveindicateoptionalparameters.
Ifthereisnosemicolonorcommaafterthelastexpression,anewlinecharacteris
automaticallyprintedafterthelastexpression. Ifacommaisusedinsteadofa
semicolontoseparateexpressions,thenatabcharacter(ASCIIcode9)isprinted
betweenoutputvaluestoseparatetheexpressions.PRINTcanalsousedtodirect
outputtoafile. Wewilldiscussprintingtofileswhenwegettothesectionon

46
A Beginner's Guide to Gambas

InputandOutput. WhenusingPRINTtowriteoutputtoafile,expressionsare
senttothestreamFileandthisformatisused:

PRINT#File,Expression[(;|,)Expression...][(;|,)]

HereissomethingtotryusingPRINT:

STATICPUBLICSUBMain()
DIMbASInteger

b=1
PRINT"===>"&"bis:"&B
PRINT"===>","bis:",B
PRINT"===>";"bis:"&B
END

Theconsoledisplaysthefollowingoutput:

===>bis:1
===>bis:1
===>bis:1

TheIFStatement

TheIFstatementisusedtomakeadecision.IFisoneofthemostcommon
structuresusedbyprogrammerstomakecomparisonsanddecisionsbasedonthe
resultofthatcomparison.UsingIFlogic,yourprogramcanperformcomparisons
usingoperatorsyouhavelearnedaboutandsubsequentlymakedecisionsbased
ontheresultofsuchcomparisons.IFtakesthegeneralformof:

IFExpressionTHEN
dosomething...
[ELSEIFExpressionTHEN
dosomethingelse...]
[ELSE
dosomethingcompletelydifferent...]
ENDIF

HereisanexampleusingIFthatyoucantryontheconsole:

STATICPUBLICSUBMain()

DIMbASInteger
b=1

47
A Beginner's Guide to Gambas

IFb=1THEN
PRINT"===>"&"Gambasisnumber"&B;
ELSEIFb<>1THEN
PRINT"Shouldnotprintme!";
ELSE
PRINT"Somethingbadishappening"
ENDIF
END

Theconsolerespondswith:

===>Gambasisnumber1

TheSELECT/CASEStatement

TheSELECTstatementevaluatesanexpression,comparingittoeachCASE
specified,andwillexecutethecodeenclosedinthematchingCASEstatementif
theexpressionevaluatedisTRUE.IfnoCASEstatementmatchestheexpression
under evaluation, the DEFAULT or CASE ELSE statement is executed. The
SELECT/CASEstatement allowsaprogrammertobuildacodeblockcapableof
evaluatingmanyexpressionresultswithouthavingtocodeanexcessiveamount
ofIF/ELSEIF/ELSEstatements.TheformatoftheSELECTstatementis:

SELECTExpression
[CASEExpression[,Expression...]
[CASEExpression[,Expression...]
[CASEELSE|DEFAULT...]
ENDSELECT

HereissomecodetoshowyouhowtousetheSELECTstatement:

STATICPUBLICSUBMain()

DIMwASInteger
w=1
'START:isaLABEL,usedwithGOTOexplainedbelow.
START:
PRINT"Thevalueofwis:"&w

SELECTCASEw
CASE1
INCw
GOTOSTART
CASE2

48
A Beginner's Guide to Gambas

INCw
GOTOSTART
CASE3
INCw
GOTOSTART
CASEELSE
PRINT"Thevariablewhasnohandlerfor:"&w
ENDSELECT
PRINT"FinalvalueofwIS:"&w
END

Theconsoleshouldrespondwiththefollowingoutput:

Thevalueofwis:1
Thevalueofwis:2
Thevalueofwis:3
Thevalueofwis:4
Thevariablewhasnohandlerfor:4
FinalvalueofwIS:4

Becausethevariablewwasincrementedtothevalueof4andtherewasto
CASE tohandlethatvalue,the CASEELSE block isexecuted. CASEELSEcan
alsobewrittenasCASEDEFAULT.Eitherway,itiswherecodedefaultstowhen
nocasesatisfiesthevalueofthevariablebeingchecked.

GOTOandLABELS

Notetheuseofthe LABEL named START: inthepreviouscodeexample.


Thecolonmustbeusedwiththelabelnameanditmustfollowitwithoutany
spacesbetweenthelabelandthecolon. Labelsarethetargetswherea GOTO
instructionwilldirectprogramflow.WhiletheuseofGOTOshouldbejudicious
itissometimesnecessary.Itisusedintheaboveexampletodemonstratehowto
useGOTOandLABELS.Later,whenwestudyloopingstructures,wewillrewrite
thiscodetouseaGambasloopingmechanism.

TheFOR/NEXTStatement

Many times when writing code, programmers find the need to iterate
throughasetofvalues(calledlooping)toprocessdata.TheFORstatementisa
loopingstatementcommonlyusedinprograms.Ittakesthegeneralformof:

FORVariable=ExpressionTOExpression[STEPExpression]...NEXT

49
A Beginner's Guide to Gambas

The FOR statement repeats a loop while at each iteration of the loop
incrementingavariable.Notethatthevariablemustbeanumericdatatype(i.e.,
abyte,ashort,anintegerorafloatingpointnumber)anditmustbedeclaredas
alocalvariable.Iftheinitialexpressionthe FORstatement evaluatesishigher
thantheTOexpression(forpositiveSTEPvalues)oriftheinitialexpressionisless
thantheTOExpression(fornegativeSTEPvalues)theloopwillnotbeexecuted
atall.TheSTEPkeywordallowstheprogrammertodefinethesizeoftheinterval
incrementedbetweenloopiterations.Hereisanexample:

STATICPUBLICSUBMain()
DIMIASInteger
DIMJASInteger

J=1
FORI=1TO21STEP3
PRINT"LOOPiteration:"&J&",Iisequalto:"&I
INCJ
NEXT
PRINT"JIS:"&J&"andIis:"&I
END

Thiscoderesultsinthefollowingoutput:

LOOPiteration:1,Iisequalto:1
LOOPiteration:2,Iisequalto:4
LOOPiteration:3,Iisequalto:7
LOOPiteration:4,Iisequalto:10
LOOPiteration:5,Iisequalto:13
LOOPiteration:6,Iisequalto:16
LOOPiteration:7,Iisequalto:19
JIS:8andIis:22

NotethatoncethevalueofJexceedsthetestof21intheloop,theloop
stopsandcode flowmovespastthe NEXTstatement. ThevalueofJremains
unchangedwhenexitingtheloop.Experimentwiththecodeabove,changingthe
STEPvaluefrom3to1,forexample.TrytomodifytheFORstatementlikethis:

FORI=21to1STEP1

Gambasalsoprovidesa FOREACH loopingstructurethatallowsyouto


iteratethroughthevaluesofacollection,array,enumerableclasses,etc.,without
theneedtomaintainanintegercounter.WewillfullycoverthedetailsofFOR
EACH when we discuss collections later in this book. At this point in your
introductiontoGambas,youareencouragedtoplayaroundwiththecodeinthe

50
A Beginner's Guide to Gambas

examplesandchangevariablevalues,practiceusingthe PRINTstatement,etc.
Get to know the console and you will quickly learn it is a great tool to test
expressions,codesegments,etc. DonotbeafraidtoexperimentwithGambas!
Theveryworstthingthatcanhappenisyourprogramblowsupandyouhaveto
restart your computer unlikely, but indeed possible. Play around and get
comfortablewithGambas.Itisthebestwaytolearn.

DO[WHILE]LOOP

The DO[WHILE]LOOPstructurebeginsexecutionofaloopthatwillnot
enduntilaconditionismetorcodewithintheloopstructureforcesanexit.The
codeexecutedintheloopisdelimitedbythekeywords DO and LOOP. Ifthe
optionalkeyword WHILE isnotspecified, theloopwould executeforever (an
infiniteloop)oruntilsomeconditionwithintheloopstructureforcedanexit.If
theoptionalkeywordWHILEisspecified,theloopisstoppedoncetheevaluated
resultoftheexpressionbecomesFALSE.Inotherwords,whiletheresultsofthis
expressionareTRUE,continuetoiterate(do)theloop.IftheexpressionisFALSE
whentheloopisstarted,theloopwillnotbeexecutedatall.Hereistheformat
oftheDOLOOP:

DO[WHILEExpression]
...
LOOP

Thefollowingcodeexampleshouldhelpyoubetterunderstandhowtousethe
DO...WHILELOOP:

STATICPUBLICSUBMain()
DIMaASInteger
a=1

DOWHILEa<=5
IFa=1THEN
PRINT"HelloWorld,looping"&a&"time."
ELSE
PRINT"HelloWorld,looping"&a&"times."
ENDIF
INCa
LOOP
DECa
PRINT
PRINT"GoodbyeWorld,Iloopedatotalof:"&a&"times."
END

51
A Beginner's Guide to Gambas

Theconsoleprintsthefollowing:
HelloWorld,looping1time.
HelloWorld,looping2times.
HelloWorld,looping3times.
HelloWorld,looping4times.
HelloWorld,looping5times.

GoodbyeWorld,Iloopedatotalof:5times.

WHILE[Expression]WENDLoops

This loop structure begins a loop delimited by the WHILE ... WEND
instructions.TheloopisrepeatedwhileExpressionisTRUE.If,oninitialentry,the
expression is FALSE, the loop is never executed. The DO WHILE LOOP and
WHILE...WENDstructuresareequivalent.Trythiscode:

STATICPUBLICSUBMain()

DIMaASInteger

a=1

WHILEa<=5
IFa=1THEN
PRINT"HelloWorld,WHILE...WENDlooping"&a&"time."
ELSE
PRINT"HelloWorld,WHILE...WENDlooping"&a&"times."
ENDIF
INCa
WEND
DECa
PRINT
PRINT"Goodbye,WHILE...WENDloopedatotalof:"&a&"times."
END

Theconsoleshouldprintthefollowing:

HelloWorld,WHILE...WENDlooping1time.
HelloWorld,WHILE...WENDlooping2times.
HelloWorld,WHILE...WENDlooping3times.
HelloWorld,WHILE...WENDlooping4times.
HelloWorld,WHILE...WENDlooping5times.

Goodbye,WHILE...WENDloopedatotalof:5times.

52
A Beginner's Guide to Gambas

TheREPEATUNTILloop

This loop structure begins to execute code that is delimited by the


keywords REPEATandUNTIL.Arepeatloopwillalwaysexecuteatleastonce,
eveniftheUNTILvalueisinitiallyFALSE.Hereisasampletotryontheconsole:

STATICPUBLICSUBMain()
DIMaASInteger
a=1

REPEAT
IFa=1THEN
PRINT"HelloWorld,REPEATUNTILlooping"&a&"time."
ELSE
PRINT"HelloWorld,REPEATUNTILlooping"&a&"times."
ENDIF
INCa
UNTILa>5
DECa
PRINT
PRINT"Goodbye,REPEATUNTILloopedatotalof:"&a&"times."
END

Theconsoleshouldprintthefollowing:

HelloWorld,REPEATUNTILlooping1time.
HelloWorld,REPEATUNTILlooping2times.
HelloWorld,REPEATUNTILlooping3times.
HelloWorld,REPEATUNTILlooping4times.
HelloWorld,REPEATUNTILlooping5times.

Goodbye,REPEATUNTILloopedatotalof:5times.

DefiningandUsingArraysinGambas

TherearetwokindsofarraysthatcanbeusedinGambas.Thefirsttypeof
Gambasarrayworkslikearraysusedinthe Java programminglanguage. The
othertypeofarraythatisusedinGambasisknownasa Nativearray. When
using Javalike arrays, you must remember that the arrays are objects of the
followingclasses:Integer[],String[],Object[],Date[],andVariant[].Allofthese
typesof Javalike arrayscanhaveonlyonedimension. Youdeclarethemlike
this:

DIMMyArrayASNEWInteger[]

53
A Beginner's Guide to Gambas

Arraysarealwaysinitializedasvoidatstartup. Theyaredynamic,and
havealotofusefulmethodsapplyingtothem. Whenusingsingledimension
arrays,thesearetherightchoice. Nativearrays ontheotherhandcansupport
multidimensionalimplementationsorarrayswitharraysobjectsofthefollowing
classes:Integer,String,Object,Date,andVariant.Theyaredeclaredlikethis:

DIMMyArray[Dim1,Dim2,...]ASInteger
DIMMyArray[Dim1,Dim2,...]ASString
DIMMyArray[Dim1,Dim2,...]ASVariant

Nativearrayscanhaveuptoeightdimensions. TheyareNOTobjects.
Theyareallocatedonthestackifyoudeclarethemlocaltoafunction.Theyare
allocatedinsidetheobjectdataifyoudeclarethemasglobalinscope. Native
arraysareNOTdynamic.Theycan'tgroworshrinkoncetheyaredeclared.You
canonlyonlysetorgetdatafromanelementinthesetypesofarrays.Hereisan
exampleofusingathreedimensionalnativearrayinGambas. Inthisexample,
thearrayisfilledwithintegervaluesrangingfrom0to26. Enterthiscodein
yourconsolecodewindow:

STATICPUBLICSUBMain()
DIMiASInteger
DIMiiASInteger
DIMiiiASInteger

DIMnarMatrix[3,3,3]ASInteger

FORi=0TO2
FORii=0TO2
FORiii=0TO2
PRINTi,ii,iii&"==>";
narMatrix[i,ii,iii]=i*9+ii*3+iii
PRINTnarMatrix[i,ii,iii]
NEXT
NEXT
NEXT
END

Whenyouexecutethiscode,youroutputintheconsolewindowshouldbesimilar
towhatisshownhere:

000==>0
001==>1
...
221==>25
222==>26

54
A Beginner's Guide to Gambas

Collections

Collections are groups of objects implemented with a hash table.


Collectionobjectsusekeysthatareimplementedas stringdatatypes. Thedata
valuescorrespondingtoanycollectionkeyisa Variantdatatype. Objectsina
collectionareenumerable.NULLisusedwhennothingisassociatedwithagiven
key.Consequently,associatingNULLwithakeyhasthesameeffectasremoving
itfromthecollection. Thesizeoftheinternalhashtablegrowsdynamicallyas
dataisinserted.Thisclassiscreatedusingthisgeneralformat:

DIMhCollectionASCollection
hCollection=NEWCollection([ModeASInteger])

NotethewordEACHaftertheFORstatement.TheFOREACHconstructis
discussednext.Also,wewillgointomuchgreaterdetailaboutcollectionslaterin
thisbookwhenwetalkaboutobjectorientedprogramming.Wewilldevelopan
application that makes extensive use of collections. For now, just note that
collectionelementsareenumeratedintheorderinwhichtheywereinsertedinto
thecollection.However,ifyoureplacethevalueofanalreadyinsertedkey,the
originalinsertionorderiskept.

TheFOREACHStatement

The FOR EACH statement executes a loop while simultaneously


enumeratinganobject. The Expression mustbeareferencetoanenumerable
object such as a collection or an array. The order of enumeration in not
necessarilypredictable.Thegeneralformatofthestatementis:

FOREACHExpression...NEXT
FOREACHVariableINExpression...NEXT

ThissyntaxmustbeusedwhenExpressionisanenumerableobjectthatis
not a container. For example, an object returned as the result of a database
query.Thestatementsabovecreateanewcollectionobject.Enterthefollowing
codeintoyourconsolecodewindowandrunit.

STATICPUBLICSUBMain()

DIMMyDictASNEWCollection
DIMstrElementASString

MyDict["absolute"]=3

55
A Beginner's Guide to Gambas

MyDict["basic"]=1
MyDict["carpet"]=2

FOREACHstrElementINMyDict
PRINTstrElement&"";
NEXT
END

Yourconsoleshoulddisplaythisoutput:

312

Atthispoint,youshouldbegettingaprettygoodfeelforthesyntaxand
structureofGambas.Wearegoingtomoveawayfromconsolebased(terminal)
applicationsandreturntoourfirstprojecttobeginexploringtheGambasToolBox
andlearnhowtodevelopaGUIbasedprogram. Itistimetotakeabreakand
whenyoucomebacktothenextchapter,youwillberefreshedandreadytocode.
Ah,heck.Ifyoujustcannotwaittojumpin,goaheadandturnthepage!

56
A Beginner's Guide to Gambas

Chapter 4 Introducing the Gambas


ToolBox
ThedefaultGambasToolBoxconsistsofmanycontrols.Asofthiswriting
usingrelease(1.0.9),thefollowingcontrolsarecurrentlysupported:

Button
Label
TextLabel
TextBox
TextArea
CheckBox
ComboBox
ListBox
RadioButton
ToggleButton
Frame
Panel
TabStrip
ProgressBar
Image
Timer
Dial
SpinBox
ScrollBar
Slider
LCDNumber
ListView
TreeView
IconView
GridView
ColumnView
ScrollView
DrawingArea
GambasEditor
TableView
Workspace

Asyoucansee,thereisawideselectionoftoolsforyoutoplaywithin

57
A Beginner's Guide to Gambas

Gambas.Ourintroductiontothetools(whicharealsocalledcontrols)willteach
youaboutwhateachcontroldoes,whatproperties,methods,andeventsyoucan
usetodirectthebehavioroftheinterfaceyouarebuilding,andhowtocodethe
controltomakeitworkexactlyasyoudesire.Alongtheway,wewillbebuilding
severalsimpleprojectstogetyoumoreexperiencedinusingtheGambasIDE.All
of the controls in the ToolBox are builtin using the gb.qt component. This
componentimplementstheGraphicalUserInterfaceclasses.ItisbasedontheQT
library.Hereisalistofthevariousfunctionalitythegb.qtcomponentprovides:

Clipboard
Containers
DragandDrop
Drawing
Fonts
IconView
KeyboardandMouse
Menus
ListView,TreeViewandColumnView
Printing

Wewillcoverothercomponentslaterinthisbook.AtthetopofFigure15,
you see the word Form displayed. This is the default toolkit for the gb.qt
component.Fornow,let'stakeaquicklookattheToolBoxagainandreviewthe
iconstherein.

Figure15TheGambasToolBox.

58
A Beginner's Guide to Gambas

FromthetopleftofFigure1,thecontrolsintheToolBox(Row1)are:

Select
Label
TextLabel
PictureBox
ProgressBar
Button
CheckBox

Onthesecondrowyouwillfind:

RadioButton
ToggleButton
ToolButton
TextBox
ComboBox
TextArea
ListBox

Onthethirdrowwehave:

ListView
TreeView
IconView
GridView
ColumnView
HBox
VBox

Thefourthrowofcontrolsdisplay:

HPanel
VPanel
Frame
Panel
TabStrip
ScrollView
DrawingArea
Timer

59
A Beginner's Guide to Gambas

AtthebottomoftheToolBoxwindow,thewordQTisseen.Ifyouclickon
that,youwillseethecontrolsspecifictotheQTuserinterfaceappear,similarto
Figure2below:

Figure16AdditionalcontrolsforQT.

TheQTSpecificControlsfoundonthetoprowofFigure2are:

Selector
LCDNumber
Dial
SpinBox
ScrollBar
Slider
MovieBox

Thesecondrowofcontrolsincludethesetools:

TableView
HSplit
VSplit
Workspace
TextView

ThegeneralapproachtoprogrammingGambasistodesignthelayoutof
yourforms,placethecontrolsthatmakeupyourinterfacetotheuseronthe
form,determineandhandlethevariouseventsthatcanoccurwitheachcontrol
usingacombinationofbuiltinGambasmethodsandyourowncode,anddirect
theoperationsoftheprogramusinginput/outputdata.Ifitsoundssimple,itis

60
A Beginner's Guide to Gambas

becauseonceyouunderstandthemechanicsofitall,itissimple.Onceyouget
usedtoprogrammingeventdrivenapplicationsinGambas,itwillbecomesecond
naturetoyou.

Thefirstgroupofcontrolswearegoingtolearnaboutaretextorientedin
natureandservetoeitherdisplayorgathertextdataortogenerateaneventthat
youcanwritecodefor,suchaspushingabutton.Thesecontrolsare:

Button
Label
TextLabel
TextBox
InputBox
TextArea

TheButtonControl

ThisclassobjectinheritsitsattributesfromtheControlclass,asdoallthe
controlsintheGambasToolBox.Usingthiscontrolimplementsapushbuttonon
aform.Apushbuttoncandisplaytext,apicture,orboth.Youhavetheabilityto
setonebuttoninsideawindowtobethe Defaultbutton.Then,whentheuser
pressestheRETURNkey,itwillactivatethatbuttonautomatically.Also,youcan
setonebuttoninsideawindowtobetheCancelbutton.PressingtheESCkey
willactivatetheCancelbuttonautomatically. Thisclass iscreatable,meaning
thatyoucanwritecodetodynamicallygenerateabuttononaformatruntime.
Todeclareabuttonobject,theformatbelowisused:

DIMhButtonASButton
hButton=NEWButton(ParentASContainer)

TheContainer,inmostcases,willbetheformwhereyouplacethebutton.
Itcould beany container object, however. This code will create a new push
buttoncontrol. Notethevariablenameisprecededbythelowercaseletter h.
Thisisastandardconventionprogrammersusetorefertothehandle(handlesare
really references to something) of an object. Since Gambas supports object
orientedprogramming,wewillgraduallyintroduceOO(ObjectOriented)concepts
to you as we encounter them. OO will be covered in much greater detail in
Chapter11ofthisbook.Generally,objectsarecreatedfromaclassbyassigninga
copyoftheobjecttoavariable,inthiscase hButton. Thisprocess,knownas
instantiating anobjectoccurswhenhButtonisassignedavalueusingtheNEW

61
A Beginner's Guide to Gambas

keyword. WhatthelinebelowmeansishButtonwillbeinstantiatedasaNEW
Button object and Parent is the property (read only) that will read a method
(thinkofmethodsasfunctionsthatsetorgetavalue)thatisimplementedinside
theContainerclass.TheContainerclassisusedbecauseitistheparentclassof
everycontrolthatcancontainothercontrols.Now,thislineofcodeshouldmake
perfectsensetoyou:
hButton=NEWButton(ParentASContainer)

CommonControlProperties

Buttonpropertiesareattributesthatyoucansetorreadusingtheproperty
windoworbyusingcodeinyourprogram.Forexample,thelineofcodebelow
willsettheTextpropertyofabutton:

hButton.Text=OK

Notetheformatofthestatementabove.Control.Property=Expressionis
thestandardconventionusedforsettingorgettingattributeinformationfroma
control.Manyofthepropertiesforcontrolsarecommonamongallcontrols,so
wewilltakethetimenowtoexplainallofthebuttonpropertieshere.Laterinthe
book,wewillonlyexplainthepropertiesthatareuniquetoagivencontrolwhen
weencounterthem.

BackColorisdefinedasPROPERTYBackColorASInteger

Thisintegervaluerepresentsthecolorusedforthecontrolbackground.It
is synonymous with the Background property. Note that PROPERTY is a
predefined datatype used internally in Gambas. You can use the Gambas
predefinedconstantsforcolortosetcommoncolorvalues:

Black Blue Cyan DarkBlue


DarkCyan DarkGray DarkGreen DarkMagenta
DarkRed DarkYellowDefault Gray
Green LightGray Magenta Orange
Pink Red TransparentViolet
White Yellow

TosettheBackColorpropertyforhButtontored,youwouldusethiscode:

hButton.BackColor=Color.Red

62
A Beginner's Guide to Gambas

Alternatively, if you know the RGB (red, green, blue) or HSV (hue,
saturation,value)valuesforaspecificcolor,Gambasprovidesameanstoconvert
thosevaluestoanintegervaluethatcanbepassedontotheBackColor(orother
colorrelated)property.TheclassColorprovidestwomethods,RGBandHSVthat
youcanuse.Hereishowthosefunctionsaredefined:

STATICFUNCTIONRGB(RASInteger,GASInteger,BASInteger[,AlphaAS
Integer])ASInteger

The RGB function returns a color value from its red, green and blue
components.FortheHSVfunction,usethis:
STATICFUNCTIONHSV(HueASInteger,SatASInteger,ValASInteger)ASInteger

HSVreturnsacolorvaluefromitshue,saturationandvaluecomponents.Touse
one of these functions to set the button's background color, here is what you
couldcode:

hButton.BackColor=Color.RGB(255,255,255)

Thiswouldsetthebutton'sbackgroundcolortowhite.Thisismostusefulwhen
youaretryingtosetcolorswhosevaluesfalloutsidethedefaultcolorconstant
valuesprovidedwithGambas.

Border This property is another common attribute found on many


controls.Thisclassisstatic.TheconstantsusedbytheBorderpropertyinclude
thefollowing:Etched,None,Plain,Raised,andSunken.Tosettheborderproperty
forourbutton,wecouldusethiscode:

hButton.Border=Border.Plain

Cancel isdefined as PROPERTY CancelASBoolean and itisused to


stipulatewhetherornotthebuttonisactivatedwhentheESCkeyispressed.The
followingcodewouldtriggerthisbuttoniftheuserpressedtheESCkeyontheir
keyboard.

hButton.Cancel=TRUE

IftheCancelpropertyisusedinyourprogram,itwouldallowyoutohandlethe
eventandgracefullyexittheformjustasiftheuserhadclickedaQuit,Exitor
Cancelbutton.

63
A Beginner's Guide to Gambas

Caption is defined as PROPERTY Caption AS String and the Caption


propertyissynonymouswiththeTextproperty.Thefollowingcode

hButton.Caption=OK

isthesameas

hButton.Text=OK

andcanbeusedinterchangeably.Let'strysomecode.StartGambasandopenup
theprojectwecreatednamedFirstProject.FromtheTreeView,doubleclickyour
mousecursorontheMainFormformandtheblankformwillopenup.Double
clickanywhereontheblankformandyouwillseethecodewindow. Itshould
looklikethis:

'Gambasclassfile
PUBLICSUBForm_Open()

END

Now, enter this code between the PUBLIC SUB Form_Open() and END
statementssoitlookslikethis:

PUBLICSUBForm_Open()
DIMhButtonASButton
hButton=NEWButton(ME)AS"hButton"

hButton.X=215
hButton.Y=60
hButton.Width=200
hButton.Height=40
hButton.Enabled=TRUE
hButton.Text="ClickorpressESCtoQuit"
hButton.Border=TRUE
hButton.Default=TRUE
hButton.Cancel=TRUE
hButton.Show

END

AfterthePUBLICSUBForm_Open()'sENDstatement,addthisroutine:

PUBLICSUBhButton_Click()
MainForm.Close
END

64
A Beginner's Guide to Gambas

Onceyouhaveenteredthecodeabove,clickthegreenprogramrunbutton
andyoushouldseesomethingsimilartothefollowing:

Figure17FirstButtoncoderesults.

Simply click the button or press the ESC key to exit this program.
Congratulations!YouhavejustcreatedyourfirstGUIbasedprograminGambas!
Yes, it is a little bit ugly but remember, you did it the hard way, using code
instead of taking advantage of the Gambas ToolBox. Remember, a good
programmerwillalwaystryusepredefinedconstantsiftheyareavailableinstead
ofhardcodingnumericvalues. Forexample,keycodesandmousestyleshave
thesamenamesastheyaredefinedasconstants,buttheirnumericvaluesare
totallydifferent.Theanticpatedgb.gtkcomponentwillnotworkwithgb.qtcode
ifyouarenotusingpredefinedconstantssowhenwritingcode,itisimperativeto
use these constants instead of numeric values. If not, the code will not be
portable.Goodcodeshouldneverusenumericvaluesforthesetasks.Now,save
yourprojectandexitGambasfornowandwewillproceedwithlearningmore
abouttheToolBox.

CursorisdefinedasPROPERTYCursorASCursor andyoucanusethe
Cursorpropertyforassigningacustomcursortoacontrol.Thisclassimplements
acustommousecursor.Thisclassiscreatable. Hereishowtodeclareacursor
objectvariableandinstantiateacursorobject:

DIMhCursorASCursor
hCursor=NEWCursor(MyPicASPicture[,XASInteger,YASInteger])

ThecodeformatabovecanbeusedtocreateanewcursorfromaPicture
objectandsetanoptionalhotspot.Ifitisnotspecified,thedefaulthotspotisthe
topleftofthepicture.Cursorhastwoproperties,XandY,thatcanbeusedtoset
orgetthecurrentmouseposition.Hereisanexamplethatshowsyouhowtouse
aCursorobjectinyourprogram:

65
A Beginner's Guide to Gambas

DIMhPictASPicture
DIMhCursorASCursor
hPict=Picture["torric.png"]
hCursor=NEWCursor(hPict)
ME.Cursor=hCursor

Default is defined as PROPERTY Default AS Boolean and you use the


Defaultpropertytoindicatewhetherornotthebuttonisactivatedwheneverthe
RETURNkeyispressed.Usingthecodebelow,itwouldforcetheusertoactually
clickabuttonratherthanhittheRETURNkeytoactivateit. Generally,when
creatinganOK/Canceltypedialog,youwouldwanttosetoneofthebuttonstoa
defaultactionusingthisproperty.ThinkaboutjusthittingtheRETURNkeyina
wizardtoacceptthedefaultsettingsandmoveon.

hButton.Default=FALSE

DesignisdefinedasPROPERTYDesignASBooleananditindicatesthat
thecontrolisindesignmode.ThismeansthatwhentheDesignpropertyissetto
TRUE,controlsindesignmodejustdrawthemselvesandwillnotreacttoany
inputevent. ThispropertyisusedbytheGambasDevelopmentEnvironment to
displaycontrolsintheformeditor.Whatthisreallymeansisyoudonotneedto
worryaboutthisproperty.

Drop isdefinedas PROPERTYDropASBooleanandisusedtocheckto


see if a control accept the drop from a drag and drop operation. The Drop
property iseitherTRUEorFALSEandyoucancheckthevaluebeforetryingto
dropsomethingontothecontrolbyusingcodelikethis:

IFhButton.Drop=FALSETHEN
hButton.ToolTip="NoDropsallowed"
ELSE
hButton.ToolTip="Dropsomethinghere"
ENDIF

Enabled isdefinedas PROPERTYEnabledASBoolean and itindicates


thatthecontrolisenabled.Todisableacontrol,simplysetit'sEnabledproperty
toFALSE.

IFExpression=FALSETHEN
hButton.Enabled=TRUE
ELSE
hButton.Enabled=FALSE
ENDIF

66
A Beginner's Guide to Gambas

The Expand property isdefinedas PROPERTYExpandASBoolean and


anditindicatesthatthecontrolisabletoexpandifitisincludedinacontainer
thatdynamicallyrearrangesitscontents.

FontisdefinedasPROPERTYFontASFontanditreturnsorsetsthefont
usedtodrawtextinthecontrol. Toset Fontproperty attributes,codelikethis
canbeused:

hButton.Font.Name="Lucida"
hButton.Font.Bold=TRUE
hButton.Font.Italic=FALSE
hButton.Font.Size="10"
hButton.Font.StrikeOut=FALSE
hButton.Font.Underline=FALSE

Theoutputoftheabovecodewouldbeasfollows:

Figure18Demonstratingfontcapabilities.

ForeColorisdefinedasPROPERTYForeColorASIntegerandthisinteger
valuerepresentsthecolorusedforthecontrolforeground.Itissynonymouswith
theForegroundproperty.YoucanusetheGambaspredefinedconstantsforcolor
tosetcolorvalue:

Black Blue Cyan DarkBlue


DarkCyan DarkGray DarkGreen DarkMagenta
DarkRed DarkYellowDefault Gray
Green LightGray Magenta Orange
Pink Red TransparentViolet
White Yellow

TosettheForeColorpropertyforhButtontored,youwouldusethiscode:

hButton.ForeColor=Color.Red

AswiththeBackColorproperty,ifyouknowtheRGBorHSVvaluesfora
specificcolor,youcanpassthemtotheForeColorpropertywiththiscode:

hButton.ForeColor=Color.RGB(255,255,255)

67
A Beginner's Guide to Gambas

Thiswouldsetthebutton'sforegroundcolortowhite.

TheXpropertyisdefinedasPROPERTYXASIntegeranditisusedtoset
orreturnthexpositionofthecontrol. X isthesameas Leftproperty. The Y
propertyisdefinedasPROPERTYYASIntegeranditisusedtosetorreturnthey
positionofthecontrol(topleftcorner).

TheHeightpropertyisdefinedasPROPERTYHeightASIntegeranditis
used to set or returnthe height of the control. Itissynonymous withthe H
property and can be used interchangeably. This value describes how tall the
controlisfromthexpositionmovingdownHeightpixels.TheWidthpropertyis
definedasPROPERTYWidthASIntegeranditisusedtosetorreturnthewidth
of the control. It is synonymous with the W property and can be used
interchangeably.Thisvaluedescribeshowwidethecontrolisfromthexposition
totherightWidthpixels.

The Handle property isdefinedas PROPERTYREADHandleASInteger


andisusedtoreturntheinternalX11windowhandleofthecontrol.Itisaread
onlyattribute.ItissynonymouswiththeId(PROPERTYREADIdASInteger).

The Mouse property isdefinedas PROPERTYMouseASInteger andis


usedtosetorreturntheappearanceofthecursortoapredefinedimagewhenit
hoversinsidetheboundariesofthecontrol. Predefined valuesforthe Mouse
propertyareshowninthetablebelow:

CursorShape Value

Default 1
Arrow 0

Cross 2
Wait 3

Text 4
SizeS 5

SizeE 6
SizeNESW 7

SizeNWSE 8
SizeAll 9

Blank 10
SplitV 11

SplitH 12
Pointing 13

68
A Beginner's Guide to Gambas

TheNextpropertyisdefinedasPROPERTYREADNextASControlandit
isusedtoreturnthenextcontrolhavingthesameparentwithinaContainer.Itis
usefulwheniteratingthroughaseriesofcontrolstosetfocus.Wewilldiscussthis
property in more detail when we discuss the SetFocus() method. To get the
previouscontrol,onewouldusethe Previous property,defined as PROPERTY
READPreviousASControl. Thispropertyreturnsthepreviouscontrolhaving
thesameparent.

The Parent property isdefinedas PROPERTYREADParentASControl


and is used to return the container that holds the control. It is a readonly
property.

The Picture property is defined as PROPERTY Picture AS Picture and


returnsorsetsthepictureshownonacontrol(i.e.,abutton).Wewilldiscussthe
Pictureclasslaterinthischapter.

TheScreenXpropertyisdefinedasPROPERTYREADScreenXASInteger
anditreturnsthepositionoftheleftborderofthecontrolinscreencoordinates.
Usually,itisusedinconjunctionwithScreenY.

TheScreenYpropertyisdefinedasPROPERTYREADScreenXASInteger
andreturnsthepositionofthetopborderofthecontrolinscreencoordinates.

TheTagpropertyisdefinedasPROPERTYTagASVariantandisusedto
return or sets the control tag. This property is intended for use by the
programmer and is never used by the component. It can contain any Variant
value.

TheTextpropertyisdefinedasPROPERTYTextASStringandreturnsor
setsthetextdisplayedinthebutton.Itisalmostalwaysusedandit'svaluecan
be changed dynamically. We have already used this property in the example
above:

hButton.Text="ClickorpressESCtoQuit"

The ToolTip property is defined as PROPERTY ToolTip AS String and


returnsorsetsthetooltip(atooltipisthelittleboxoftextthatpopsupovera
controlwhenthemousehoversoveritforafewseconds).

hButton.ToolTip="Clickme!"

69
A Beginner's Guide to Gambas

TheToppropertyisdefinedasPROPERTYTopASIntegerandreturnsor
setsthepositionofthetopborderofthecontrolrelativetoitsparent.

TheValue property isdefinedas PROPERTYValueASBoolean anditis


usedtoactivatethecontrol(i.e.,makethebuttonclick).Thisisdoneifyouset
thispropertytoTRUE.ReadingthispropertywillalwaysreturnavalueofFALSE.

The Visible property isdefinedas PROPERTYVisibleASBoolean andit


indicatesifthecontrolisvisibleornot.SettingthispropertytoFALSEwillmake
itdisappearfromview.Conversely,settingittoTRUEmakesitappear.

The Window property is defined as PROPERTY READ Window AS


Windowandreturnsthetoplevelwindowthatcontainsthecontrol.

Atthispoint,wehavecoveredallofthepropertiesfortheButtonControl
andyoushouldhaveaprettygoodunderstandingofwhattheyareusedforand
howtousethem.Rememberthatmostofthesepropertiesarecommontomany
controls. Next,wewillcoverthemethods(thingsyoucandowiththebutton)
andprovideyousomeexamplesofhowtousethem.

ButtonMethods

Methodsarethebuiltinroutinesprovidedforacontrolthatallowyouto
dothingslikeshowit,hideit,moveit,etc.Herearethemethodssupportedby
theButtoncontrol:Delete,Drag,Grab,Hide,Lower,Move,Raise,Refresh,Resize,
SetFocus,andShow.Usually,amethodiscalledinresponsetosomeevent.We
willdiscusseventsinthenextsection.Let'stakealookatthemethodsusedwith
Button:

The Delete method is defined as SUB Delete() and when invoked it


destroysthecontrol.Itisimportanttoknowthatadestroyedcontrolbecomesan
invalidobject. Whatthismeansisthatonceyouhavedestroyedit,ensureno
othercodesubsequentlyreferencesit.

The Drag method isdefinedas SUBDrag(DataASVariant[,Format


ASString])andwheninvokeditstartsadrag&dropprocess.Dataisthedata
tobedragged.ItcanbeaStringoranImage.IfDataisatextstring,thenyou
canspecifyin Format the MIMETYPE ofthetextbeingdragged.Forexample,
MIMETYPEtext/html.

70
A Beginner's Guide to Gambas

The Grab method isdefinedas FUNCTIONGrab()ASPicture and it


grabsapictureofthecontrolandreturnsit.

The Hide method andthe Show method aredefinedas SUBHide() and


SUBShow()andtheysimplyhideorshowthecontrol.Hereishowtheywould
beused:

IFExpression=TRUETHEN
hButton.Hide
ELSE
hButton.Show
ENDIF

The Lower method and Raise method aredefinedas SUBLower() and


SUBRaise(). Lowersendsthecontroltothebackgroundofitsparent. Raise
bringsthecontroltotheforegroundofitsparent. Asanexampleofhowthese
methodswork,let'sgobacktoourproject,FirstProject.Changethecodeinthe
hButton_Click()routinetoreadasfollows:

PUBLICSUBhButton_Click()
Button1.Hide
Label1.Text="Ouch!"
WAIT2.0
Button1.Show
Label1.Text="Betternow!"
END

Onceyouhaveenteredthecode,runtheprogramandseewhathappens.
WhenyouclickthebuttonitwilldisappearandLabel1.Textwillchange. After
twoseconds, it will reappearand change the label again. Also, note thatwe
slippedinanewcommandforyoutotry WAIT. WAITtakesafloatingpoint
valueasaparameterthatrepresentssecondsorfractionsofsecondsexpressedas
decimalvalues. Numberslessthan1areprocessedasmilliseconds. WAIT1.5
wouldpauseexecutionfor1,500 milliseconds. IfyouspecifyWAITwithouta
parameter,itwillrefreshtheinterfaceanditdoesnotallowtheusertointeract
withtheapplication.

TheMovemethodisdefinedasSUBMove(XASInteger,YASInteger[,
WidthASInteger,HeightASInteger])andisusedtomoveand/orresizethe
control.

hButton.Move(hButton.X50,hButton.Y20)

71
A Beginner's Guide to Gambas

The Refresh method isdefinedas SUBRefresh([XASInteger,YAS


Integer,WidthASInteger,HeightASInteger]) and isused toredrawthe
control,orinsomeinstances,justaportionofit.

TheResizemethodisdefinedasSUBResize(WidthASInteger,Height
ASInteger)andisusedtoresizethecontrol.

The SetFocus method isdefined as SUBSetFocus ( ) and youcallthis


methodtogivefocustothecontrol.Focusisroughlyequatedtowherethetext
cursorwouldbelocated.Whenacontrolhasfocusitisusuallyindicatedvisually
insomemanner.Forexample,abuttonwithfocusmayhaveasmalldottedline
aroundittoindicatewherefocuscontrolisontheform:

Figure19Thedottedlineindicates
focusforacontrol.

WehavecoveredallofthemethodsavailablefortheButtonclass(control)
andwillnowbegindiscussingtheeventsforthatclass.Asachangeofpace,let's
trytolearnabouteventswithamorehandsonapproach. Wecandothisby
buildinganewprogramandlearningwhattheeventsdoandhowtousethem.
CloseGambas(asmallquirkofGambasisthelackofacloseprojectmenuselection)
andrestartittoinitiatetheNewProjectWizard.Selectagraphicaluserinterface
projectandgothroughthewizardjustlikewedidwiththeprojectFirstProject.
NamethisprojectSecondProject. OncetheIDEappears,createanewstartup
classformandnameitForm1.Forthisproject,wearegoingtoplacethreeLabel
controlsontheform,asshowninFigure20below.

Figure20ThelayoutforSecondProjectForm1.form.

72
A Beginner's Guide to Gambas

The first label's text caption is set with the Label.Text property. The setting
shouldbeHereistheandthesecondisGambasMascotandthethirdis
> which points to a PictureBox control (where the shrimp lives). Name the
labelsLabel1,Label2andLabel3respectively.Next,namethePictureBoxcontrol
PictureBox1.

ToobtainthegraphicoftheGambasmascot,youcangototheofficial
Gambaswebsite13andrightclickonthemascot.Choosetosavetheimageand
samveitasgambasmascot.pngonyourcomputer. Movethefiletothedata
directory in the SecondProject folder. (Another Gambas quirk is that the file
explorerdialogsdon'tseemtobedynamic.Oncetheyhaveinitialized,changesmade
outside theGambasenvironment arenotupdateddynamically.) Once you have
done this, you can set the Picture property for PictureBox1 to the file named
gambasmascot.png.Atthispoint,thetopofyourformshouldlooklikethis:

Figure21Apartiallyconstructedformwithourfirstfourcontrols.

Now,selecttheProgressBarcontrolfromtheToolBoxandplaceitonthe
form so it looks like that shown in Figure 20 above. Finally, we have three
buttonstoaddtotheform.NamethesebuttonsFunBtn,NoFunBtn,andQuitBtn.
Allofthenecessarycontrolsforourexamplehavebeenaddedtotheformatthis
point. TrytogetthelayouttolookasclosetothepictureshowninFigure3
aboveaspossible. Atthispoint,youmaybeaskingwhatallofthisisgoingto
accomplish? Remember, we are going to learn how to use events with these
controls. Wehaveplacedthecontrolswherewewantthemandnowthenext
stepistodecidewhateventswearegoingtohandle.

Forthisexercise,wearegoingtohandlemouseeventswhenthemouse
movesoverlabels.Ifthemousemovesoffofthemainwindow(Form1.form)or
backontoitwewillhandlethoseevents.Wewillalsohandlebuttonclicksand
theESCkeyifitispressed.

Let's beginby settingtheProgressBar1.Valuetozerowhentheprogram


starts. Thatishandledwiththeinitializationroutinewhenopeningtheformat
programruntime,asshownbelow:

13 TheofficialGambassiteishttp://gambas.sourceforge.net/index.html.

73
A Beginner's Guide to Gambas

'Gambasclassfile

PUBLICSUBForm_Open()
ProgressBar1.Value=0.50
ProgressBar1.BackColor=Black
ProgressBar1.ForeColor=Yellow
END

Whenthemousemovesoverthestartupform(ourGambasprogramonthe
desktop),wewanttosetthethreetoplabel'stextpropertiestoblankvaluessoit
appearsthatthetextdisappears. Thisrequireschoosingan eventhandler. To
chooseaneventfromtheGambasIDE,movethemouseovertheform(butnot
directlyoveracontrol)andclickitonce. Next,rightclickthemouseandyou
shouldseeamenupopup,similartotheoneshowninFigure22below.Choose
theEventselectionitemfromthepopupandpicktheEnterevent.Addthiscode,
asshownbelow:
PUBLICSUBForm_Enter()
Label1.Text=""
Label2.Text=""
Label3.Text=""
END

Figure22Eventmenu.

Repeatthisprocesstochooseanotherevent,theLeaveevent,sothatwhen
themousemovesofftheprogramwindowwecandetectthatanddosomething
aboutit.Addthiscode:

74
A Beginner's Guide to Gambas

PUBLICSUBForm_Leave()
ProgressBar1.Value=0.50
Label1.Text="Wasn'tthat"
Label2.Text="somereal"
Label3.Text="funstuff?"
END

Thenextthingwewanttodoishandlethesituation(event)thatoccurs
whenthemousemovesoveranyofourlabels. Inthisevent,wearegoingto
changetheLabel.Textpropertyoftheaffectedlabeltoindicatethatamousehas
beendetectedoverthecontrol.Singleclickyourmousecursoronthefirstlabel
and whenthehandlesappear,rightclick and choose the Enter eventwhen it
appearsontheEventsubmenu. Inthecodewindow,findthe Label1_Enter()
subroutineandenterthiscode:

PUBLICSUBLabel1_Enter()
Label1.Text="Here'sthe"
END

RepeatthesameprocessfortheLabel2.TextandLabel3.Textproperties. Your
codeshouldlooklikethis:

PUBLICSUBLabel2_Enter()
Label2.Text="GambasMascot"
END

PUBLICSUBLabel3_Enter()
Label3.Text=">"
END

Wealsowanttodetectandrespondtoeventswhenthemousemovesover
ourmascotpictureaswell.ClickonceonthePictureBox1controlandchoosethe
EnterEvent.Gotothecodewindowandmakethecodelooklikethis:
PUBLICSUBPictureBox1_Enter()
Label1.Text=""
Label2.Text=""
Label3.Text=""

PictureBox1.Border=Border.Plain
END

Repeattheprocess,choosingtheLeaveeventandensureyourcodeistypedinthe
codeeditorasfollows:
PUBLICSUBPictureBox1_Leave()

75
A Beginner's Guide to Gambas

Label1.Text="Wasn'tthat"
Label2.Text="somereal"
Label3.Text="funstuff?"
PictureBox1.Border=Border.Sunken
END

ThenextcontrolthatwewanttotakecareofistheQuitbutton.Double
clickonitandthecodewindowdisplaystheQuitBtn_Click()subroutine,which
respondstoaClickevent.AddtheForm1.Closeline,asshownbelow.

PUBLICSUBQuitBtn_Click()
Form1.Close
END

Figure23AddingtheFunBtntoourform.

Now,wehavetowritecodefortheProgressBar.Forourexample,wewill
incrementitwhentheFunBtnisclickedanddecrementitwhentheNoFunBtnis
clicked.DoubleclickontheFunBtncontrolandaddthiscode:
PUBLICSUBFunBtn_Click()
ProgressBar1.Value=ProgressBar1.Value+0.01
IFProgressBar1.Value>0.99THEN
ProgressBar1.Value=0.0
ENDIF
END

Now,doubleclickontheNoFunBtnandaddthis:
PUBLICSUBNoFunBtn_Click()
ProgressBar1.Value=ProgressBar1.Value0.01
IFProgressBar1.Value<0.01THEN
ProgressBar1.Value=0.0
ENDIF
END

76
A Beginner's Guide to Gambas

Thatisnearlyallthereislefttodo!Now,savetheprojectandclicktherun
button.Youshouldseethisonprogramstart:

Figure24Whatourformlookslikewhenamouseisdetected
overtheform.Notethetextisblankedout.

Now, click the Click me for more fun button and the progress bar
changes.Clickitthreetimesandyoushouldseethis:

Figure25TheprogressbarwhentheFunBtnisclickedthreetimes.

Ifyoumoveyourmouseoverthemascotpicture,youshouldseethelabel
textappearanddisappearasyoumovethemouseonandoffthepicture.Finally,
youcanhitESCorclicktheQuitbuttontoexittheprogram.Thelasteventwe
are going to write code for in this example is the doubleclick event. This
requiresyoutoonceagainchooseaneventhandler.

FromtheGambasIDE,movethemouseovertheFunBtnandclickitonce.
Next,rightclickthemouseandyouwillseethemenupopupallowingyouto

77
A Beginner's Guide to Gambas

chooseEvents. FromtheEventssubmenu, pickthe Dblclick event.Addthis


code,asshownbelow:

PUBLICSUBFunBtn_DblClick()
ProgressBar1.Value=ProgressBar1.Value+0.1
IFProgressBar1.Value>0.90THEN
ProgressBar1.Value=0.0
ENDIF
END

RepeatthisprocessfortheNoFunBtnandaddthiscode:

PUBLICSUBNoFunBtn_DblClick()
ProgressBar1.Value=ProgressBar1.Value0.1
IFProgressBar1.Value<0.1THEN
ProgressBar1.Value=0.0
ENDIF
END

Now,savetheprojectandclicktherunbutton.Thistime,whenyouclick
the progress bar it works just as it did before, but if you doubleclick, it will
incrementthevalueby10unitsratherthanbyone.Onceyouexityourprogram,
saveyourprojectandexitGambas.Next,wearegoingtolookatthetheother
eventsthatcanusedwiththeButtoncontrol.

ButtonEvents

The Button events we have used in our previous example include the
Click,DblClick,Enter,andLeaveevents. Wewillreserveourdiscussionofthe
remaining events, namely Drag, DragMove, Drop, LostFocus and GotFocus for
when we deal with drag and drop operations. The Menu, KeyPress and
KeyRelease events will be covered when we talk about menu and keyboard
operations. Finally, when we cover mouse operations, we will discuss the
MouseDown,MouseMove,MouseUp,andMouseWheelevents.

ThePictureClass

Earlier in the chapter, when we used the Picture control to place our
mascotontheforminoursecondexample,wementionedthePictureClassand
saidwewouldcoveritlater.Well,nowitistimetotalkaboutthePictureClass.
Thisclassrepresentsapictureanditscontentsarestoredinthedisplayserver,not
inprocessmemorylikeanImagewouldbenormallystored.EvenifXWindows

78
A Beginner's Guide to Gambas

does not manage transparency (yet), each picture object can have a mask
assignedwithit.Thiscanbesetexplicitlyatthetimethepictureisinstantiated,
or it can be set implicitly when loading an image file that has transparency
attributes,likeaPNGfile.Whendrawingonapicturehavingamask,boththe
pictureandthemaskaremodified.Thisclassiscreatable.Itisdefinedas:

DIMhPictureASPicture

andtheprocessofinstantiatingitusesthisformat:

hPicture=NEWPicture([WidthASInteger,HeightASInteger,
TransparentASBoolean])

Thecodeabovewillcreateanewpictureobject.IftheWidthandHeightarenot
specified,thenewpictureisempty(void). Youcanspecifyifthepicturehasa
maskwiththeTransparentparameter. Thepictureclassactslikeanarray.For
example:

DIMhPictureASPicture
hPicture=Picture[PathASString]

willreturnaPictureobjectfromtheinternalpicturecache.Ifthepictureisnot
presentinthecache,itisautomaticallyloadedfromthespecifiedfile.Toinserta
pictureinthecache,usethiscall:

Picture[PathASString]=hPicture

PropertiesforthiscontrolincludeDepth,Height,Image,Transparent,and
Width.ThemethodsprovidedincludeClear,Copy,Fill,Flush,Load,Resize,and
Save.Wewillcovertheuseofthesemethodsandpropertiesinlaterexamplesin
thisbook.Atthispoint,youshouldhaveasolidunderstandingofhowtousethe
Gambas programming environment and it's various tools. In the next few
chapters,wewillpresentmorecontrolswithmorecomplexexamplesasthebest
waytolearnisbydoing.

79
A Beginner's Guide to Gambas

Chapter 5 Controls for Gathering Input


Inourintroductiontocontrols,welearnedaboutthemostbasictypesof
controlsandevents,namelypictures,labels,buttons,andaprogressbar.Wealso
learnedhowtodetectwhenthemouseisoveracontrolandwhatactionswecan
takewhenitmovesonoroffthecontrol.Thesetypesofcontrolsallpresentdata
orrespondtoeventslikethemouseorabuttonclick,buttheydonotallowusers
tochoosefromamongalternativessuchaspickingitemsfromalistortypingin
theirname,etc.Inthischapter,wewilladdtoourarsenalofGambasknowledge
bylearninghowtoaccomplishthosetasksandrespondtoevenmoreevents.We
aregoingtobuildaprogramthatwillintroduceyoutothefollowingcontrolsand
teachyouhowtousethem:

TextLabel
TextBox
ComboBox
ListBox
ToggleButton
Panel
Frame
Checkbox
RadioButton

Hereiswhatourprogramwilllooklikewhenwearefinishedwithit:

Figure26ThirdProject(almost)finalresult.

80
A Beginner's Guide to Gambas

Inthisexercise,wewilllearntoputtitlesonourprogramwindow,usean
inputboxtogatherHTMLformattedinputfromtheuseranddisplaythatresultin
anewtypeoflabel,theTextLabel.Wewillalsolearnhowtogroupandorganize
our controls on the form, using panels and frames, and place controls like
RadioButtonsandCheckBoxeswithinthoseorganizationalcontrols.Finally,we
willlearnhowtouseListBoxesandComboBoxestoallowtheusertoselectfrom
oneofmanychoices.Alongtheway,wewilllearnabitmoreabouteventcoding
andtrytomakeitinteresting. Let'sgetstartedbycreatinganewProjectwith
Gambas.StartGambasandchoosetocreateanewprojectusingaGraphicalUser
Interface. Gothroughthewizardmakingtheprojecttranslatableandtheform
controlspublic. Selectthename ThirdProject andputitinadirectoryofyour
choosing.WhentheIDEstarts,createanew,startupclassform.Doubleclickon
the blank form and the code editor window will appear. You should see
somethinglikethis:

'Gambasclassfile

PUBLICSUBForm_Open()

END

Now,wewillstartbyputtingthetitleofourprogramatthetopofthe
window when the program runs. To accomplish this, we will set the form's
Captionproperty tothetextwewanttouseasthetitle. Enterthislineinthe
Form_Open()subroutine:

ME.Caption="***ThirdProject***"

Thattakescareofthetextforthewindowtitle. Now,ifwelookatour
finalresultpicture,westillhavetoaddourcontrols. Wewillstartatthetop,
addingthecontrolswealreadyknowabout:Label,TextBox,andButton.Place
eachcontrolontheformasshowninFigure26above.NamethecontrolsLabel1,
TextBox1,and UpdateBtn. Thesecontrolswereusedinthelastchapter,soyou
shouldbecomfortableusingtheminyourprograms.Next,wewilladdtheQuit
Buttonatthebottomrightcorneroftheform.NamethiscontrolQuitBtn.Now,
let'saddthecodeforthesecontrols.DoubleclickthemouseontheQuitBtnand
addthiscodetotheQuitBtn_Click()subroutine:

PUBLICSUBQuitBtn_Click()
Form1.Close
END

81
A Beginner's Guide to Gambas

Fortheupdatebutton,wearegoingtotransferthetexttheusertypedinto
the TextBoxcontrol totheTextLabel,reflectingany HTML formattingthatthey
entered.Hereisthecodeneededforthat:

PUBLICSUBUpdateBtn_Click()
TextLabel1.Text=TextBox1.Text
END

Fromthispointon,wewillbelearningtousenewcontrolsandfeaturesof
Gambas.WehavealreadywrittencodetoassigninputdatatotheTextLabel,so
let'stakethetimenowtolearnallwecanaboutit.Beforewestart,itisprobably
agoodideatogoaheadandclickthesavebuttonontheIDEtosaveyourwork.

TextLabel

ThisclassiscreatableanditinheritsitsattributesfromtheControlclass.It
implementsacontrolcapableofdisplayingsimpleHTMLtext.YoucanuseHTML
entitiessuchas&ltand&gttodisplaycharacterslike<and>.ForHTMLthat
requirestheuseof quotemarks, avoid the because itwill notwork. For
example,entering:

<divalign="center"><b>Thiswon'twork.</b>

Thefigurebelowshowsyouanexampleofhowthisworks:

Figure27UsingHTMLtoformatTextLabeloutput.

TextLabelisdefinedas DIMhTextLabelASTextLabel andyoudeclareitlike


this:

hTextLabel=NEWTextLabel(ParentASContainer)

Whatwewanttodonowiscodetheupdatebuttontotakeadvantageof
thesecool HTML features. Toaccomplishthis,weneedtomodifythecodewe
previously entered for the update button's click event. Doubleclick on the

82
A Beginner's Guide to Gambas

UpdateBtncontrolandchangethecodetolooklikethis:

PUBLICSUBUpdateBtn_Click()
TextLabel1.Text="<divalign=center><b>"&TextBox1.Text&"</b>"
END

Instead of simply assigning the input text from the TextBox to the
TextLabel1.Textproperty,wearegoingtomakeitlookfancy.Now,anythingthe
user types will automatically be centered in boldface and placed on the
TextLabel1.Ifyousaveyourprojectandrunitatthistime,yourresultsshouldbe
likethatofFigure28below:

Figure28ModifiedTextLabeloutputusingHTMLformatting.

TextBox

OurnexttaskistolearnmoreabouttheTextboxcontrolwejustused.You
alreadyknowthatitisusedtolettheuserenteralineoftextinputandreturn
thatinputtotheprogramasastring. TextBoxinheritsitsattributesfromthe
Controlclassandthisclassimplementsasinglelinetexteditcontrol.Thisclassis
creatableandisdeclaredas:

DIMhTextBoxASTextBox

Tocreateandinstantiateanew TextBoxcontrol inyourcode,youcanusethis


format:

hTextBox=NEWTextBox(ParentASContainer)

Let's try something else now. Suppose that we want to streamline our
applicationsothattheuserdoesnothavetoclicktheupdatebuttonwhenthey
entertext. Also,itwouldbenicetohavethetextfieldclearitselfifthemouse
entered the control area and to put back the default prompt when when the
mouseismovedawayfromthecontrol. Wewouldwanttopreservewhatever
wastypedintothefieldbytheuserwhenthemouseleavesthecontrolsowehave

83
A Beginner's Guide to Gambas

toremembertoassignthevaluethatiscurrentlyintheTextBox1.Textfieldtothe
TextLabel1.Text field. We want to continue to use the HTMLcapable format
capabilitiesoftheTextLabel.

Wewillneedtomodifyourcode.First,wemustcreatetheeventhandlers
forthemouseenteringthecontrolandleavingthecontrol. Clickonceonthe
TextBox1controlontheformandrightclickthemousetoselecttheEventitem.
FromtheEventsubmenuchooseEnter.RepeatthisprocessandchoosetheLeave
event.Now,gotothecodeeditor,findthefirstsubroutine(TextBox1_Enter())
andinsertthefollowingcodebetweenthefirstandlastline:

TextBox1.Clear

That'sitforthisroutine.WejustcallthebuiltinmethodtocleartheTextBoxand
wearedone.Now,westillneedtogototheTextBox1_Leave()subroutineand
enterthiscode:

TextLabel1.Text="<divalign=center><b>"&TextBox1.Text&"</b>"
TextBox1.Text="<Entertexthere>"

The first line of code will use HTML to format and center the
TextBox1.Textstringandsetittoaboldfacefont.Thenextlineofcodeassigns
thedefaultpromptstringweinitiallycreatedtotheTextBox1.Textsowhenthe
mouse leaves we have saved whatever the user typed and reset it to what it
lookedlikebeforethemouseenteredthecontrol. Saveyourworkandrunthe
programtoseehowitworks.

TherearenotreallyanyTextBoxuniqueMethodstodiscuss,butwhilewe
arelearningaboutevents,let'splayaroundwiththecodealittleandlearnabout
theShowandHidemethodsandhowtheymaybeusedinaprogram.Clickonce
ontheform(becarefulnottoclickonanycontrolontheform)andrightclickthe
mousetoselecttheEventitem.FromtheEventsubmenuchooseMouseDown.
RepeatthisprocessandchoosetheDblClickevent.Now,gotothecodeeditor,
findthesubroutineForm_MouseDown()andinsertthefollowingcodebetween
thefirstandlastline:

UpdateBtn.Hide

ThatisallweneedtodotohidetheUpdateBtncontrol.Ifyouuseropts
nottousethebuttonnow,alltheneedtodoisclicktheformanditwillhidethe
button.Howdowebringitback?Doubleclickwilldothetricknicely.Fromthe

84
A Beginner's Guide to Gambas

codeeditor,findtheForm_DblClick()subroutineandenterthiscode:

UpdateBtn.Show

Right now, you may be asking yourself How the user would ever know
this? Goodpoint. Let'sletthemknowwithaToolTipproperty.Clickonthe
UpdateBtncontrol. NowgotothepropertywindowandfindToolTip. Onthe
rightsideofthatentryisaninputfieldandwithagrayboxwiththreedots(...).
Thatmeansanotherdialogwilltakeplacewhenyouclick. Inthiscase,itwill
openaneditwindowsoyoucanformatyourToolTipusingHTML.Clickitand
whentheeditdialogappears,enterthistext(orcode,asyouwish):

Click<b>(ordoubleclick)</b>ontheformtohide<b>(orshow)</b>me.

Now,saveyourworkandruntheprogramtoseehowitworks.Hoverthe
mouseovertheUpdateButtonandthenicelyformattedToolTipwillappear. It
shouldlooklikethefigurebelow.Cool,huh?

Figure29AddingaToolTiptoinform
theuserhowtoshow/hideacontrol.

ThereareacoupleofTextBoxuniqueeventswecoulddiscussatthispoint,
namely KeyPress and KeyRelease,butwearegoingtoholdoffonthoseuntil
laterinthebookwhenwestartworkingwiththekeyboarddirectly. Readyto
moveon?Wearegoingtoaddsomeselectorcontrolstoourprogramnext.The
ComboBoxandListBoxallowuserstoselectfromamongseveralchoices.Wewill
startwiththeComboBoxfirst.

ComboBox

The ComboBox control inherits its attributes from the Control class. It
implementsatextboxcombinedwithapopuplistbox. Thisclassiscreatable
andisdeclaredusingtheformatbelow:

85
A Beginner's Guide to Gambas

DIMhComboBoxASComboBox

Toinstantiatethevariablewejustdeclared,usethisformat:

hComboBox=NEWComboBox(ParentASContainer)

ThiswillcreateanewComboBoxcontrol.Thisclassactslikeareadonly
array. Inotherwords,declaringthevariable,instantiatingit,andretrievinga
valuefromcodedirectlywouldworklikethis:

DIMhComboBoxASComboBox
DIMhComboBoxItemAS.ComboBoxItem
DIMIndexasInteger

hComboBoxItem=hComboBox[Index]

Thelineofcodeabovewillreturnacomboboxitemfromitsintegerindex.
Notethatthe.ComboBoxItem representsaniteminthecomboboxpopuplist
box.Thisclassisvirtual.Youcannotuseitasadatatypeanditisnotcreatable.
It has a single property, Text which returns a string value representing the
ComboBoxitemrepresentedbyIndex. WearegoingtocreateaComboBoxon
ourformnow.Hereiswhatourcontrolwilllooklike:

Figure30OurComboBox.

OK,iagreethatitisnothingveryfancyanditprobablyrankskindoflow
onthecreativitylist,butitwillgetthejobdoneandteachyouwhatyouneedto
knowtouseComboBoxes.Tobuildournewcontrol,wewillgototheGambas
ToolBoxand selectthe ComboBoxcontrol. Placeitontheform(refertoour
initialFigureattheverybeginningofthischaptertoseewhereitshouldgo)andtry
togetitasclosetowhatyouseeinthatpictureasyoucan.Onceyouaredone
withthat,clickonitonceifyoudonotseethehandlesandgototheProperties
Window.FindtheListproperty.Theinputboxtotherightofthiswillenablea

86
A Beginner's Guide to Gambas

selectordialogifyouclickinsideit.Clicktheselectordialogbutton(remember,
withthethreedots?)anditwillbringuptheEditlistpropertyDialog:

Figure31TheEditlistpropertyeditor.

Toinsertaniteminthelist,typetheitemintheTextBoxatthebottomof
theeditor.Thefirstiteminthelististhedefault.Itismostoftenusedtoseta
defaultselection(likeNoneorPicksomething,etc.)Inourcase,typePickanitem
andclickinsert.AddItem1,Item2,Item3,andItem4tothelist.Makesurethey
appearintheordershowninFigure31abovesoitwilllookrightwhenitruns.
Onceyouhaveitsetthewayyouwant,justclicktheOKbuttonandtheeditor
willcloseandsaveyourwork. Saveyourprojectandruntheprogramtosee
whatitlookslikeonyourform.Whenyouhavefinishedlookingattheworkwe
havedonesofar,exittheprogramandwewillcontinuebyaddingsomecodeto
processComboBoxselections.

IftheuserselectssomethingfromtheComboBox,theitemwillchangeand
thischangegeneratesaneventthatyoucanhandle. Fromtheform,selectthe
ComboBox control and rightclick. Choose Event and select Change from the
submenu. Now, go to the code editor and find the subroutine PUBLIC SUB
ComboBox1_Change().Addthecodesothesubroutinelookslikethis:

PUBLICSUBComboBox1_Change()
DIMresultASString

result=Trim(ComboBox1.Text)
TextLabel1.Text=result&"wasselectedfromtheComboBox"
END

Saveyourprojectandruntheprogramtoseewhathappens.Noticethat
whenanitemisselectedtheTextLabel1.Textvalueisupdatedbutdoesnothave

87
A Beginner's Guide to Gambas

anyfancyformattingthatitiscapableof.Well,thatiseasytofix.Let'schange
thecodelikethis:

PUBLICSUBComboBox1_Change()
DIMresultASString
result="<divalign=center><b>"&Trim(ComboBox1.Text)&"</b>"
TextLabel1.Text=result&"wasselected."
END

Changethecodeandruntheprogramagain.Youshouldseesomethingsimilarto
thisintheTextLabel1control:

Figure32FormattingaTextLabelwithHTML.

Sotherealprogrammersouttherearealreadyaskinghowtodothiswith
code,eh?Ithoughtyouwouldneverask!Seriously,itisnothard.Let'smodify
our program slightly to allow dynamically add or remove items from the
ComboBox.Todothis,wearegoingtoneedabuttonthatwillindicateaddingan
itemandanotherbuttontoremoveanitem.Addtwobuttons,onecalledPlusBtn
andtheothercalledMinusBtntotheform,asshownbelow:

Figure33Plusandminusbuttons
toaltertheComboBoxlist.

DoubleclickonthePlusBtnandinsertthiscode:

PUBLICSUBPlusBtn_Click()
DIMItemASString
DIMNumItemsASInteger

ComboBox1.Refresh
NumItems=ComboBox1.Count
IFNumItems=0THEN
Item="PickanItem"
ELSE
Item="Item"&Str(NumItems)
ENDIF
ComboBox1.Refresh
ComboBox1.Add(Item,NumItems)
END

88
A Beginner's Guide to Gambas

Inthecodeabove,wedeclaretwovariables,ItemandNumItems.Itemisa
stringandNumItemsanInteger.WewilluseNumItemstodeterminehowmany
itemsarealreadyinthelist.Thisisdoneusingthe.Countproperty.Ifthereare
noitemsinthelist,wewillsetourdefaultpromptofPickanItemasItemzero.

ComboBoxarraysarezerobased,meaningthecountingstartsatzero,not
one.IttheNumItemsvalueiszerowewillcreateadefaultstring.Otherwise,we
aregoingtoconcatenatetheitemnumbertothewordItemsoitwilladdtothe
nextopenslotinthelist.WecalltheRefreshmethodtoforcetheComboBoxto
refreshitscountpropertysoiftheusertriestoselectagainitwillbecurrent.The
lastlineofcodeusesthe.AddmethodtoaddtheitemtotheComboBoxitemlist.
Now,doubleclickontheMinusBtnandaddthiscode:

PUBLICSUBMinusBtn_Click()
DIMNumItemsASInteger

'Thecomboboxarraystartsatzero
ComboBox1.Refresh
NumItems=ComboBox1.Count
IFNumItems>0THEN
DECNumItems
IFNumItems<>0THEN
ComboBox1.Remove(NumItems)
ENDIF
ComboBox1.Refresh
ENDIF
END

Removingelementsfromthelistismuchsimpler.Weonlyneedaninteger
variabletodeterminethenumberofelementsinthelist.Onceagain,thisisdone
usingthe.Countproperty.Inourexample,Countwillreturnavalueof5thefirst
timeitisread.Iftherearenoitemsinthelist,wewillnotdoanything.Because
the ComboBoxitems arestoredinazerobasedarray,wemustdecrementthe
count by one if it is not already zero. Now, save your project and run the
program.Tryremovingalltheitemsinthelistandreinsertingthem.Cool,eh?
MorecoolstufftocomewiththeListBox,whichwediscussnext.

ListBox

TheListBoxcontrolalsoinheritsitsattributesfromtheControlclass.The
ListBoximplementsalistofselectabletextitems. Thisclassiscreatable. The
followingcodewilldeclareaListBoxandcreateit:

89
A Beginner's Guide to Gambas

DIMhListBoxASListBox
hListBox=NEWListBox(ParentASContainer)

LiketheComboBox,thisclassactslikeareadonlyarray.

DIMIndexasInteger
DIMhListBoxASListBox
DIMhListBoxItemAS.ListBoxItem
hListBoxItem=hListBox[Index]

ThelineofcodeabovewillreturnaListBoxitemfromitsintegerindex.
Notethatthe.ListBoxItemrepresentsanitemintheListBoxpopuplistbox.This
classisvirtual.Youcannotuseitasadatatypeanditisnotcreatable.Ithasa
singleproperty,TextwhichreturnsastringvaluerepresentingtheListBoxitem
representedbyIndex.WearegoingtocreateaListBoxonourformnow.Here
iswhatournewcontrolwilllooklike:

Figure34WhatourListBoxwill
looklike.

Inordertobuildournewcontrol,wewillgototheGambasToolBoxand
selecttheListBoxcontrol.Placeitontheform(refertoourinitialpictureatthe
verybeginningofthischaptertoseewhereitshouldgo)andtrytogetitascloseto
whatyouseeinthatpictureasyoucan.Onceyouaredonewiththat,clickonit
onceifyoudonotseethehandlesandgotothePropertiesWindow.FindtheList
property. Theinputboxtotherightofthiswillenableaselectordialogifyou
clickinsideit.Clicktheselectordialogbutton(remember,withthethreedots?)
anditwillbringuptheEditlistpropertyDialog:

Figure35ListBoxEditlistpropertyeditor.

90
A Beginner's Guide to Gambas

ThisisexactlythesameeditorweusedtobuildtheComboBox1control.
Thistime,wearegoingtoadditemstothelistandalsolearnabouttheSystem
class.The Systemclass ispartofthe Gambas componentlibrary andprovides
supportforalltheclassesincludedintheinterpreterbydefault.TheSystemclass
is static and provides readonly information about the operating system
environment. The properties of this class that you can read include Charset,
Domain,Home,Host,Language,Path,andUser.Usetheeditorandenterthe
followingitemsinthelist:

Charset
Domain
Home
Host
Language
Path
User

Next,doubleclickontheListBox1controlontheform.Thiswilltakeyou
to the code editor and you should be in the PUBLIC SUB ListBox1_Click()
subroutine.Thefollowingcodewillshowyouhowtoaccessthesevalues.Enter
itasfollows:

PUBLICSUBListBox1_Click()

IFTrim(ListBox1.Text)="System.Charset"THEN
TextLabel1.Text=System.Charset
ELSEIFTrim(ListBox1.Text)="Domain"THEN
TextLabel1.Text=System.Domain
ELSEIFTrim(ListBox1.Text)="Home"THEN
TextLabel1.Text=System.Home
ELSEIFTrim(ListBox1.Text)="Host"THEN
TextLabel1.Text=System.Host
ELSEIFTrim(ListBox1.Text)="Language"THEN
TextLabel1.Text=System.Language
ELSEIFTrim(ListBox1.Text)="Path"THEN
TextLabel1.Text=System.Path
ELSEIFTrim(ListBox1.Text)="User"THEN
TextLabel1.Text=System.User
ENDIF
END

Now,saveyourprojectandruntheprogram.Tryselectingalltheitemsin
thelistandseewhatinformationisreturned. ListsandComboBoxesarevery

91
A Beginner's Guide to Gambas

easytoimplementanduse. Agreatadvantageofusingthesetypesofselector
components is that it virtually eliminates the possibility of a user typing data
incorrectly. In the next section, we are going to learn how to organize the
controlsonourformtobettermanagethepresentationtocontrolstotheuser.
Also,wewilllearnwhyframesandpanelsareagoodthingtoconsiderearlyin
thedevelopmentprocess.

Frame

The Frame class inherits its attributes from the Container class. This
controlisacontainerwithanetchedborderandalabel.Thisclassiscreatable.
DodeclareandinstantiateaFrame,usethisformat:

DIMhFrameASFrame
hFrame=NEWFrame(ParentASContainer)

Thegreatthingaboutaframeisthatitworkssortoflikeawindowwithin
awindow.Anycontrolyouplaceintheframebecomesapartoftheframe,ina
mannerofspeaking. Whatthismeansisthatifyouput CheckBoxcontrolsor
buttonsorwhateverintheframeanddecidetomovetheframe,theyallmove
withit.Theycanberearrangedwithintheframe,butiftheframemoves,hides,
etc.,sodothey.Hereiswhatourframeandthecontrolswewilladdtoitlook
like:

Figure36Whattheexampleframewebuildwilllooklike.

Tocontinuedevelopmentofourproject,wewillfirstaddaFramecontrol
totheform(nameitFrame1)andplaceitsimilartothatfoundinFigure24atthe
beginningofthischapter.Next,wewilladdtwoToggleButtoncontrols(named
ToggleButton1 and ToggleButton2) and three CheckBox controls (named
CheckBox1,CheckBox2,andCheckBox3). ArrangethemtolooklikeFigure 33
above.Onceyouhaveeverythingplacedcorrectlyontheform,let'sgotothenext
stepandwritecodefortheeventswewillrespondtoinourprogram.

92
A Beginner's Guide to Gambas

ToggleButton

TheToggleButtoncontrolinheritsitsattributesfromtheControlclassand
implementsatogglebutton.Thismeansiteithertogglesupordown.Thisclass
iscreatable.Todeclareandinstantiatethiscontrol,usetheformat:

DIMhToggleButtonASToggleButton
hToggleButton=NEWToggleButton(ParentASContainer)

Doubleclick on the ToggleButton1 control and add this code to the


PUBLICSUBToggleButton1_Click()subroutine:

PUBLICSUBToggleButton1_Click()
IFToggleButton1.Value=TRUETHEN
Frame1.Text="Toggled1down"
ELSE
Frame1.Text="Toggled1up"
ENDIF
END

RepeatthepreviousstepfortheToggleButton2controlandenterthiscode:

PUBLICSUBToggleButton2_Click()
DIMresultASString
IFToggleButton2.Value=TRUETHEN
Frame1.Text="Toggled2down"
ELSE
Frame1.Text="Toggled2up"
ENDIF
END
WhatwehavedonewiththecodeaboveischecktheToggleButton.Value
propertytoseeifitisTRUE,indicating thatthebuttonwasclickeddown. If
FALSE,anotherclicktoggledittotheupposition.Regardlessofthepositionitis
at,wewanttheFrame1.Texttodisplaythestatusofthebuttonlastclicked.Now,
let'smoveontolearnabouttheCheckBoxcontrols.

Checkbox

TheCheckBoxclassinheritsitsattributesfromtheControlclass.Thisclass
implementsacheckboxcontrolanditiscreatable. Declareandinstantiatethe
variablelikethis:

DIMhCheckBoxASCheckBox

93
A Beginner's Guide to Gambas

hCheckBox=NEWCheckBox(ParentASContainer)

WhenaCheckBoxcontrolisclickedinourprogram,wewanttodetectthe
click event and immediately respond. In this case, we will change the
Checkbox.TextpropertywhenevertheCheckBox.Valueischeckedandturnsout
tobeTRUE.Thiswillshowthatwecaughttheclickeventandrespondedtothe
valueofTRUEorFALSE(checkedorunchecked). Iftheboxisunchecked,we
willwanttoreturnittotheNormalstate.ForCheckBox1,doubleclickonthe
control and enter this code in the code editor for the PUBLIC SUB
CheckBox1_Click()subroutine:

PUBLICSUBCheckBox1_Click()
DIMoutline1ASString
DIMoutline2ASString
DIMoutline3ASString

IFCheckBox1.Value=TRUETHEN
Checkbox1.Text="Iwaspicked"
ELSE
Checkbox1.Text="Checkbox1"
ENDIF
END

RepeatthisprocessforCheckBox2andCheckBox3:

PUBLICSUBCheckBox2_Click()
IFCheckBox2.Value=TRUETHEN
Checkbox2.Text="Iwaspicked"
ELSE
Checkbox2.Text="Checkbox2"
ENDIF
END

PUBLICSUBCheckBox3_Click()
IFCheckBox3.Value=TRUETHEN
Checkbox3.Text="Iwaspicked"
ELSE
Checkbox3.Text="Checkbox3"
ENDIF
END

Now, save your project and run the program. Once you have satisfied
yourselfthattheyworkasweplanned,endtheprogramandwewillcontinueour
projectbyaddingthelasttwocontrolsthatwearegoingtocoverinthischapter,
thePanelandRadioButton.

94
A Beginner's Guide to Gambas

Panel
The PanelclassinheritsitsattributesfromtheContainerclass.Thisclass
implementsa Panelcontrol withachangeableborder. Thisclassiscreatable.
Declareandinstantiateapanellikethis:

DIMhPanelASPanel
hPanel=NEWPanel(ParentASContainer)

Inourprogram,wearegoingtousethePaneltogroupourRadioButtons
insideit.Hereiswhatthispanelwilllooklikewhenwearefinished:

Figure37APanelwithRadioButtons.

WewillfirstneedtoaddaPanelcontroltotheform(nameitPanel1)and
placeittolooklikethePanelfoundatthebeginningofthischapter. Next,we
will add two RadioButton controls (named RadioButton1 and RadioButton2).
ArrangethemtolooklikeFigure37above.

RadioButton

The RadioButtonclass inheritsitsattributesfromtheControlclassandis


usedtoimplementaradiobuttoncontrol. RadioButtoncontrolsthatsharethe
sameparent(inthiscase,thePanelcontainer)aremutuallyexclusive.Onlyone
RadioButton can be selected at once. This class is creatable. Declare and
instantiateaRadioButtonlikethis:

DIMhRadioButtonASRadioButton
hRadioButton=NEWRadioButton(ParentASContainer)

SelecttheRadioButtoncontrolfromtheToolBoxandplaceitontheform.
Namethe firstRadioButton RadioButton1 and repeat thisprocessfor another,
namedRadioButton2. Onceyouhaveeverythingplacedcorrectlyontheform,
let'sgotothenextstepandwritecode.DoubleclickonthefirstRadioButtonand
enterthiscode:

95
A Beginner's Guide to Gambas

PUBLICSUBRadioButton1_Click()
RadioButton1.Text="HaHaRB2"
RadioButton2.Text="RadioButton2"
END

Repeatthisprocessforthesecondone:

PUBLICSUBRadioButton2_Click()
RadioButton2.Text="HaHaRB1"
RadioButton1.Text="RadioButton1"
END

Now, save your project and run the program. Once you have satisfied
yourselfthateverythingwehavedoneinthischapterwillworkasweplanned,
takeawelldeservedbreakandwewillstartfreshonthenextchapter.

96
A Beginner's Guide to Gambas

Chapter 6 Menus, Modules, Dialogs


and Message Boxes
AlmosteveryGUIbasedprogramyouencounterwillusesomecombination
of menus,MessageBoxes, and standard dialogstocommunicate with theuser.
Gambasisnotanydifferent.Additionally,thereisnoprogramminglanguagethat
provideseverythingthataprogrammerwoulduseasaprebuiltcomponent.That
iswhatmodulesareusedforwritingwhatyouneedoutsidethescopeofwhat
Gambasprovides.Forexample,ifyouneedafunctionthatreturnsthenameofa
colorbasedonwhatischoseninastandardcolorselectiondialog,youaregoing
tohavetowriteone,andwewilldojustthatinournextsampleproject.Inthis
chapter, we will learn how to use each of these controls and build another
exampleprogramtohelpyoulearntomasterGambas.Hereisascreenshotofthe
finalversionofwhatourprojectwilllooklike:

Figure38MenuProjectFinalresults.

We are going to create four menus. Each menu will be used to


demonstratethecontrolsorstandarddialogswearegoingtolearnaboutinthis
chapter. Wewillfirstbuildthemenu,asshownabove,thenwewillshowyou
howtousethestandardcolorandfiledialogs,MessageBoxes,and,asanadded
bonus,wewillshowyouhowtocreateamoduleinGambasanduseit.Tobegin
our project, open Gambas and create a new Graphical User Interface project.
NameitMenuProjectandsetallthecontrolstranslatableandpublic.Onceyou
gettotheIDE,createaform,Form1andmakeitaStartupclass. AddaQuit
Buttontotheform,asshownaboveandenterthiscodetobeexecutedwhena
userclickstheQuitbutton:

97
A Beginner's Guide to Gambas

PUBLICSUBQuitBtn_Click()
Form1.Close
END

Doubleclickontheformanywhereoutsideacontrolboundaryandyou
willgetthePUBLICSUBForm_Open()subroutinetoappearinthecodeeditor.
Insertthiscodeinthatemptysubroutine:

ME.Caption="WorkingwithMenus"

Next, add a TextLabel, named TextLabel1 to the window as shown in


Figure38above.Thattakescareofthepreliminariesforourproject.Now,let's
seehowtobuildthemenuandusethestandarddialogsprovidedbyGambas.

TheGambasMenuEditor

Gambas has a builtin Menu Editor. You can access it from the form
windowbypressing CTRLE orbyrightclickingontheformandselectingthe
MenuEditor optionfromthepopupthatappears. Eitherway,the MenuEditor
willappearandyouwillseesomethinglikethis:

Figure39TheGambasMenuEditorwhenitfirststarts.

98
A Beginner's Guide to Gambas

WhenyoufirststarttheMenuEditor,theeditorwindowwill,ofcourse,be
blank. It is not anintuitively obvious tool to use, so let's spend a minute to
explaintheMenuEditor.First,somecommonterminology.Thetextthatyousee
runninghorizontallyacrossthetopofaformisreferredtoasamenu.Amenu
cancontainMenuItems(whicharelistedverticallybelowthemenu).MenuItems
cancontain subMenus,whicharebasicallynewnestedmenusthatbelongtoa
MenuItemand willpopupanddisplay anotherlistof MenuItems. Menus can
containseverallayersofnestedsubMenus.

ToinsertamenuyouwillhavetousetheInsertbutton.TheNextbutton
willmovethecurrentmenucursorpositiontothenextiteminthewindow. It
onlymovesdownandthereisnopreviousbutton.Ifyoureachtheendofthelist,
itwillstopandtheonlythingyoucandoisclickthemouseonamenuentryor
insertanewone.TheDeletebuttonwillremovethemenuentryunderthemenu
cursor.

Thefirsttwo and arrowbuttons(upanddown)totherightofthe


Deletebuttonwillmovetheentryunderthemenucursorupordownthelistof
menuentries.Ifyouclickthe or (unindentandindent)arrowbuttons,the
will work much likeindentation in an outline works. Theindented itemwill
become either a MenuItem or subMenuItem depending on the level of
indentation. Indented items with three ... preceding the name indicate
MenuItems. More than three dots preceding the name indicates it is a
subMenuItemoftheentryatthepreviousindentationlevel. Onceyoubuilda
menuortwo,itwillbeeasytounderstand.Onceyouclicktheinsertbutton,you
willseeseveralnewfieldsappearatthebottomoftheMenuEditor,namelythese:

Figure40EditfieldsfortheMenuEditor.

99
A Beginner's Guide to Gambas

TheNamefieldshouldprobablyhavebeencalledVariable Namebecause
thatiswhatthisfieldisusedfor.Thisisthevariablenamethatyourcodeinthe
classfilewillusetoreferencethisparticularobject.

TheGroupfieldreferstoaControlGroup.ControlGroupsareusedinthe
GambasIDEtocreateandhandlegroupsofcontrolsasasingleentity.Whenyou
selectanycontrolonaform,inthePropertiesdialog,youshouldnoticeaGroup
propertythatdoesn'tcorrespondtoanydocumentedpropertyofthatcontrol.This
specialpseudopropertyallowsyoutoassigncontrolgroups.Essentially,whenthat
controliscreatedatruntime,itwillbetreatedasthoughyouhadcreateditin
codelikeso:

myControl=NEWColumnView(ME)AS"myGroup"

anditseventhandlersmustbenamedlikeso:

PUBLICSUBmyGroup_Click()

You can refer to the control that generated the event with the LAST
keyword,oryoucanassignaTagtoeachcontroltodifferentiatethembyusing
thetagvalue.

Captionisthetextthattheenduserwillseewhentheprogramruns.Tag
isreservedforprogrammerstostoredataandisacommonpropertyfornearlyall
controls. WewillcoverhowtousetheTagpropertylater. Fornow,youonly
needtoknowthatitcancontainANYVarianttypedata.

The Shortcut CheckBoxes allow you to define keyboard shortcut key


combinationslikeControlAtoautomaticallyinvoketheclickeventforthatmenu
entry. Remember, menu entries basically only respond to click events or
keyboardshortcuts. The Picture fieldallowsyoutospecifythefilenameofan
iconthatwilldisplaywiththemenuentry.Apreviewwindow(a.k.a.,apicture
box)appearstotherightofthisfield.

The CheckBoxes to the right of the input fields, Visible, Enabled, and
Checked refertothe state ofthemenuentry. Bydefault,allmenuentriesare
createdtobeenabledandvisible.Youcanspecifyiftheitemischeckedornot.
Incode,youcanseeiftheentryischeckedornotbylookingatthemenuentry's
Checkedproperty.ItwillreturnaTRUEorFALSEvalueindicatingthestatusof
theitem. Hereisanexampleofhowtotoggleacheckmarkonoroffwhena
menuitemispicked:

100
A Beginner's Guide to Gambas

IFMenu2Item1.CheckedTHEN
Menu2Item1.Checked=FALSE
ELSE
Menu2Item1.Checked=TRUE
ENDIF

TheIFstatementwilltesttheCheckedpropertyoftheMenu2Item1object
andiftheBooleanvalueisTRUEwillsetittoFALSE(togglingit).IftheBoolean
valueisNOTTRUEtheELSEclauseisexecuted,togglingthe.Checkedvalueto
TRUE.ThislogiccanbeusedtotoggleanymenuorsubMenuItem.

NOTE:AwordofcautionusethisfeaturesparinglyforgoodGUIdesign. Many
users feel overwhelmed when they are presented with too much gadgetry in an
interface.

BuildingMenus

Now,let'screateourmenu.Whenyouarefinished,itwilllooksomething
likethisfromthemenueditor:

Figure41Buildingourprojectmenu.

Tobegin,clicktheInsertbutton.First,wewillinsertthetoplevelmenus,
ColorDialog,MessageBoxes,FileDialogs,andHelp. Tomakethiseasy,usethe

101
A Beginner's Guide to Gambas

tablebelowtofillintheinputfielddata:

MainMenu (Variable)Name Group Caption


ColorDialog Menu1 ColorDialog
MessageBoxes Menu2 MessageBoxes
FileDialogs Menu3 FileDialogs
Help Menu4 Help

Now,let'sputthemenuitemsintothefirstmenu.Thesemenuitemswillbelong
totheColorDialogmenu:

ColorDialog (Variable)Name Group Caption


ForegroundColor Menu1Item1 ForegroundColor
BackgroundColor Menu1Item2 BackgroundColor
Font Menu1Item3 Font

After you have inserted these items with the editor, ensure they are
positionedbelowtheColorDialogentryandindentedonelevel.Now,movethe
menucursoroverthesecondmainmenuentry,MessageBoxesandwewillinsert
themenuitemsforthismenu.

MessageBoxes (Variable) Group Caption


Name
InfoMessage Menu2Item1 InfoMessage
AlertMessages Menu2Item2 AlertMessages
ErrorMessage subMenuItem1 ErrorMessage
WarningMessage subMenuItem2 WarningMessage
DeleteMessage subMenuItem3 DeleteMessage
QuestionMessage Menu2Item3 QuestionMessage

Ensure theError,Warning,andDeleteentriesareindented TWO levels


belowthemenuentryforAlertMessages.Now,thelastmenuitemfortheHelp
menuneedstobeadded.

Help (Variable)Name Group Caption


About Menu4 About

102
A Beginner's Guide to Gambas

That'sallthereistoit!ClicktheOKbuttontoleavethemenueditorand
whenyourreturntotheform,amenuwillbethere.Ifitdoesnotlooklikeour
example,gobacktothemenueditorandadjusttheentriesuntilitdoes. After
youarecompletelysatisfiedwiththemenu'sformatandappearance,thenextstep
istocodeactionsforeachmenuclickevent. However,beforewedothat,we
needtolearnaboutthestandarddialogsandMessageBoxesthatareprovidedin
Gambas.

Dialogs

TheDialogclassisusedtoimplementalloftheGambasstandarddialogs.
Thisclasscontainsstaticmethodsusedtocallthestandard dialogboxes.This
classisstatic. TheDialogmethodssupported (i.e.,thestandard dialogs) are:
OpenFile,SaveFile,SelectColor,SelectDirectory,andSelectFont.Theproperties
supportedbythisclassare:Color,Filter,Font,Path,andTitle.

Colorisanintegervaluethatthe SelectColorDialog returnsrepresenting


thecolorselected.ItisinterestingtonotethatGambashas32predefinedcolor
constantsbutthestandard SelectColorDialog consistsof48colors. Thismeans
youcannotusethe predefinedconstants likeRed,Black,etc.,withanysenseof
suretyina CASEstatement orelsewhere. Whenacolorischosen,howdoyou
determineifitisapredefinedconstantoranothercoloroutsidetherangeofthe
32predefinedinGambas?Youwriteamoduletodeterminethat,ofcourse!We
willcomebacktothistopicafterexplaininghowtousetheSelectColorDialog.

WhenworkingwiththefilerelatedDialogs,theFilterandPathproperties
arereturned. Filterisdefinedas STATICPROPERTYFilterASString[] andit
returnsorsetsthefilters(i.e.,categorizebyfileextension,suchasall.docor.png
files)usedinthestandardfiledialogs.Thispropertyreturnsorreceivesastring
array.Eachelementinthearrayrepresentsonefiltertousewhenthefiledialog
callismade.Eachfilterstringmustfollowthefollowingsyntax:

Thefiltername.
Aspace.
Anopeningbracket.
Oneormorefilepatterns,separatedbysemicolons.
Aclosingbracket.

HereisanexamplethatalsodemonstratestheuseoftheDialogTitleproperty:

103
A Beginner's Guide to Gambas

Dialog.Title="Chooseafile"
Dialog.Filter=["Pictures(*.png;*.jpg;*.jpeg)","Allfiles(*.*)"]
Dialog.OpenFile

ThefilerelatedDialogcalls(SelectDirectory,OpenFileDialogandSaveFile
Dialog)allreturnthePathproperty,whichisastringthatcontainsthefilepath
selected.InthecaseoftheSelectDirectoryDialogcall,thestringistruncatedat
thedirectorylevel.Now,let'sstartcodingourfirstmenuitem,ForegroundColor.
Fromtheformwindow,choosetheForegroundColoritemfromthemenuwejust
builtandyouwillbetakentothecodewindowinasubroutinecalled PUBLIC
SUBMenu1Item1_Click()whereyouwillwanttoinsertthiscode:

PUBLICSUBMenu1Item1_Click()
Dialog.Title="Chooseaforegroundcolor"
Dialog.SelectColor
TextLabel1.ForeColor=Dialog.Color
TextLabel1.Text="<b>Colorselectedwas</b>"&ColorName&"."
END

First,wesettheTitleoftheDialogtoChooseaforegroundcolorsothe
userhassomeideaofwhattheDialogisusedfor. Wecallthestandarddialog
withDialog.SelectColor.Oncetheuserhaspickedacolororcanceledfromthe
dialog, we will place the name of the color returned in the TextLabel1.Text
control wecreated atthe beginning of ourproject. We choose the TextLabel
becauseitallowsustoformatouroutputlikethis:

TextLabel1.Text="<b>Colorselectedwas</b>"&Str$(Dialog.Color)&"."

ThelineofcodeabovewillsettoboldfacetheColorselectedwaspartof
thestring,concatenatetheColorvaluetothestringafterconvertingtheintegerto
astringusingtheStr$conversionfunction,andthenconcatenatetheterminating
punctuationtothestring(wedowantittolookprofessional,don'twe?).Nowrun
thecodeandyoushouldseesomethinglikethis:

Figure42Aformattedtextlabeldisplayingthecolorvalue.

104
A Beginner's Guide to Gambas

Well,21760isnotveryusefulinformation. Thisnumberistheinternal
representationofthatgreenishcolorIselected.Weneedtodevelopsomemethod
ofknowingifthecolorisred,blue,green,i.e.,anamedcolorconstant.Thisis
whatwewerealludingtointheprevioussectionabouttheproblemwithcolors.
Hereisweremodulescomeintoplay.

Modules

Wearegoingtocreateamoduletoreturnthenameofacolorifitisa
predefinedconstant.Ifnot,wewantastringthattellsusitis not apredefined
colorconstant.Oncewedefineourmodule,wewillcomebackandmodifyour
codetousethemodule.FromtheProjectwindow,findModulesintheTreeview
andselectanewmodule,namedModule1.Whenthedialogappears,leavethe
CheckBoxes blank and just take the default name and click OK. You will be
presentedwithanewcodewindowtitledModule1.module. Itshouldstartout
withacommentlikethis:

'Gambasmodulefile

Now, we write all the code for our function, which we will call
SetColorName.First,wemustdeclarethefunctionandidentifywhatinputand
outputparametersitwillprocess.Hereishowwedothat:

PUBLICFUNCTIONSetColorName(iValASInteger)ASString

WedeclareapublicFunctionthattakesanintegerparameterandreturnsa
string. Thismodulewillthattheintegervaluethatthe SelectColorDialog has
returned,andcheckitagainstthe32predefinedcolorconstantsusedinGambas.
Ifitmatchesacolorconstant,wewillsetatemporarystringtothenameofthat
color.Ifnot,wewillcreateastringthatidentifiestheconstantvalueandreturn
thattothecallingcode.Wewillneedtocreateatemporarystringvariabletodo
this,soaddthisvariabledeclarationasthefirstlineofcodeinsidethefunction:

rvalASString

Now,wehavetoaddourCASESELECTstatement.Itwillusetheinteger
parameteriValthatispassedintothefunctionfromthecallingsubroutine.Here
isthefulllistingforyoutoenter:

'Gambasmodulefile
PUBLICFUNCTIONSetColorName(iValASInteger)ASString

105
A Beginner's Guide to Gambas

rvalASString
SELECTiVal
CASEColor.Black
rval="Black"
CASEColor.Blue
rval="Blue"
CASEColor.Cyan
rval="Cyan"
CASEColor.DarkBlue
rval="DarkBlue"
CASEColor.DarkCyan
rval="DarkCyan"
CASEColor.DarkGray
rval="DarkGray"
CASEColor.DarkGreen
rval="DarkGreen"
CASEColor.DarkMagenta
rval="DarkMagenta"
CASEColor.DarkRed
rval="DarkRed"
CASEColor.DarkYellow
rval="DarkYellow"
CASEColor.Gray
rval="Gray"
CASEColor.Green
rval="Green"
CASEColor.LightGray
rval="LightGray"
CASEColor.Magenta
rval="Magenta"
CASEColor.Orange
rval="Orange"
CASEColor.Pink
rval="Pink"
CASEColor.Red
rval="Red"
CASEColor.Transparent
rval="Transparent"
CASEColor.Violet
rval="Violet"
CASEColor.White
rval="White"
CASEColor.Yellow
rval="Yellow"
DEFAULT
rval=Str$(ival)&"anditisnotapredefinedcolorconstant"
ENDSELECT
RETURNrval
END

106
A Beginner's Guide to Gambas

Onceyouhavecompletedthiscode,savethismodulefileandreturnback
to the code window for Form1. We have to modify our code in the
Menu1Item1_Clicksubroutine.Hereisthenewsubroutine:

PUBLICSUBMenu1Item1_Click()

Dialog.Title="Chooseaforegroundcolor"
Dialog.SelectColor
ColorName=Module1.SetColorName(Dialog.Color)
TextLabel1.ForeColor=Dialog.Color
TextLabel1.Text="<b>Colorselectedwas</b>"&ColorName&"."
END

WehaveaddedthelineColorName=...buthavenotdeclaredColorName
yet.Thisvariablemustbeglobalbecausewearecallingamoduletoreturnthe
valueColorName. AttheverybeginningoftheForm1.classcodefile,addthis
codejustbeforethePUBLICSUBForm_Open():

'Gambasclassfile
'declareaglobalvariabletobeusedwithourSetColorNamemodule
ColorNameASString

Now,whentheprogramexecutes,thevariablewillbeknown.Inthecodebelow,
thecallto:

ColorName=Module1.SetColorName(Dialog.Color)

anditwillreturnthestringtoourColorNamevariable.Wewanttosetthecolor
oftheforegroundtexttothecolorjustpicked:

TextLabel1.Forecolor=Dialog.Color

Now,wewilltakethestringanddisplayit(formatted,ofcourse)byassigningit
totheTextLabel1.Textproperty.

TextLabel1.Text="<b>Colorselectedwas</b>"&ColorName&"."

ThefinalversionofourMenu1Item1_Clickroutineshouldlooklikethis:

PUBLICSUBMenu1Item1_Click()
Dialog.Title="Chooseaforegroundcolor"
Dialog.SelectColor
ColorName=Module1.SetColorName(Dialog.Color)
TextLabel1.ForeColor=Dialog.Color

107
A Beginner's Guide to Gambas

TextLabel1.Text="<b>Colorselectedwas</b>"&ColorName&"."
END

Wewillwanttodothesamethingforthebackgroundcolor.Thesecond
menuitemintheColorDialogmenuisBackgroundColorsolet'sclickonthat
fromtheIDEandcodethefollowing:

PUBLICSUBMenu1Item2_Click()
Dialog.Title="Chooseabackgroundcolor"
Dialog.SelectColor
ColorName=Module1.SetColorName(Dialog.Color)
TextLabel1.BackColor=Dialog.Color
TextLabel1.Text="<b>Colorselectedwas</b>"&ColorName&"."
END

ThefinaloptioninourfirstmenuistochangetheFont. The SelectFont


Dialogisusedtoaccomplishthis.Onceagain,gototheformmenuandchoose
theFontoptionintheColorDialogmenuofourprojecttogettheclickeventsetin
thecodewindow.FontsarehandledinGambaswiththeFontclass.Thisclass
representsa font used fordrawing or displaying textincontrols.This class is
creatable.Todeclareafontvariable,usethisformat:

DIMhFontASFont
hFont=NEWFont([FontASString])

Thecodeabovecreatesanewfontobjectfromafontdescription.Thisclass
acts like a readonly array. This code creates a new font object from a font
descriptionandreturnsit:

DIMhFontASFont
hFont=Font[FontASString]

ThepropertiesthatyoucanusewithFontinclude:

Ascent
Bold
Descent
Fixed
Italic
Name
Resolution
Size
StrikeOut

108
A Beginner's Guide to Gambas

Styles
Underline

HereisanexampleofhowtousecodetosettheFontproperties:

Form1.Font.Name="Utopia"
Form1.Font.Bold=TRUE
Form1.Font.Italic=TRUE
Form1.Font.Size="14"
Form1.Font.StrikeOut=FALSE
Form1.Font.Underline=TRUE

The Font class has three Methods you can call: Height, ToString, and
Width.Heightisafunctionthatreturnstheheightofthetextdisplayedwiththe
font.Itisdeclaredas:

FUNCTIONHeight(TextASString)ASInteger

ToStringreturnsthefullnameofafontasadescriptionstring.Thisstringisa
concatenationofallthefontpropertiesseparatedbycommas.Itisdeclaredas:

FUNCTIONToString()ASString

AnexamplecalltoToStringwouldbe:

PRINTApplication.Font.ToString()

WidthisafunctionjustlikeHeightbutitreturnsthewidthofthetextdisplayed
withthefont:

FUNCTIONWidth(TextASString)ASInteger

Now,let'scontinuetoenterourcodeforourMenuProjectprograminthe
PUBLIC SUB Menu1Item3_Click() routine. First, we will declare two local
variables,fontdataandoldfontdata.Wewanttogetthenewfontfromthecallto
the SelectFontDialog,butwealsowanttoretaintheoldfontdataincasewe
need it. Next, we declare two string variables, attr and sel (attribute and
selection)tobeusedtosetthefontattributestring;selectionisaworkstringwe
willbuilddynamically,basedonthevariousselectionstheusercouldmakeinthe
dialog.

PUBLICSUBMenu1Item3_Click()
DIMfontdataASfont

109
A Beginner's Guide to Gambas

DIMoldfontdataASFont
DIMattrASString
DIMselASString

Atthispoint,youmaybeaskingyourselfifyoucouldnotsimplyusethe
ToStringpropertytodothis.Yes,butyouwouldnotlearnasmuch.Bearwith
meandcodealong.Thefollowinglineofcodesimplyblanksoutourattrstring:

attr=""

Now,weassignthecurrentTextLabel1.fontpropertytotheoldfontdatavariable:
oldfontdata=TextLabel1.Font

Next,let'ssetthetitleforthedialogandcalltheSelectFontDialogwiththesetwo
lines:
Dialog.Title="Pickafont..."
Dialog.SelectFont

Whentheuserselectsafontfromthe SelectFontDialog,wewanttoassignthe
fontselectedtothefontdatavariable:
fontdata=Dialog.Font

Atthispoint,wewillchecktoseewhatattributestheuserhaschosenand
dynamically build an output string. We could have built this IF THEN ELSE
statementtocheckeverypropertysupportedbythe Fontclass,butwearenot
interestedinallofthemforthisexercise.
IFfontdata.ItalicTHEN
sel="Italic"
attr=attr&sel
ENDIF
IFfontdata.BoldTHEN
sel="Bold"
attr=attr&sel
ENDIF
IFfontdata.StrikeoutTHEN
sel="Strikeout"
attr=attr&sel
ENDIF
IFfontdata.UnderlineTHEN
sel="Underline"
attr=attr&sel
ENDIF

110
A Beginner's Guide to Gambas

Next,wewillsetthefontintheTextLabel1controltobewhattheuser
selectedanddisplaythedynamicallycreatedstringoffontdatatotheuser:
TextLabel1.Font=fontdata
TextLabel1.Text="Font:"&fontdata.Name&","&Str(Round(fontdata.Size))&attr

Wewillwaitfivesecondstoletthetakealookattheresult,thengivethem
achoiceastowhetherornottheywanttokeepthesesettingsorrevertbackto
theprevioussettings.

WAIT5.0

SELECTMessage.Question("Keepthenewfont?","Yes","No","Don'tknow")
CASE1
TextLabel1.Text="Thisisnowthedefaultfont."
CASE2
TextLabel1.Font=oldfontdata
TextLabel1.Text="Revertedtopreviousfontsetting."
CASE3
TextLabel1.Font=oldfontdata
TextLabel1.Text="Nochangewasmadetodefaultfont."
ENDSELECT
END

Note that we have jumped the gun a bit and introduced the use of
MessageBoxeswithoutexplainingthem. Thatisournexttask,butIwantedto
giveyouapreview. Saveyourprojectandexecuteitatthistime. Yourresults
shouldbesimilartothis,dependingonthecolorsandfontyouselected:

Figure43Selectingcolorsandfonts.

Andifyoudecidetokeepitasthedefault,youwillseesomethinglikethis:

111
A Beginner's Guide to Gambas

Figure44MakinganewdefaultfontfortheTextLabel1control.

Atthispointinyourlearningjourney,youknowhowtodoquiteabitin
Gambas. Wemustcontinuethisjourneybyexpandingourabilitytodealwith
inputandoutputfromtheuser.TheMessageBoxesareanothervaluabletoolin
ourGambasarsenal.Let'sfindoutmoreaboutusingthem.

MessageBoxes

MessageBox controls are a quite handy means of communicating


informationtotheuserorgettinganswersthatareoftheTRUE/FALSE,YES/NO
type. Generallyspeaking,MessageBoxesfallintooneoffourbroadcategories:
queryand/or confirmation, information,warning,and error/alertnotifications.
TheMessageclassisusedfordisplayingtheseMessageBoxes.Thisclassisstatic
anditcanbeusedasafunction.Itisdeclaredas

STATICFUNCTIONMessage(MessageASString[,ButtonASString])ASInteger

TheMethodsthataresupportedbythe Messageclass areInfo,Question,


Delete,Error,andWarning.YouhaveseentheMessage.Questionmethodused
used already. Each method serves a specific purpose and should be used
appropriatelyinyourcode. Let'sstartwiththeeasiestMessageBoxmethod,the
Informationmethod.

InformationMessages

TheInfomethodisdeclaredas:

STATICFUNCTIONInfo(MessageASString[,ButtonASString])ASInteger

anditisusedtodisplayaninformationMessageBox,withonlyonebutton.Since
theuserdoesnothavetomakeadecision,theyonlyneedtoacknowledgethe
message.Hence,onlyonebuttonisneeded.Hereiswhatourcodewillproduce:

112
A Beginner's Guide to Gambas

Figure45AnInformationMessageBox.

To continue building our example program, from the form go to the


MessageBoxesmenuandclickonInfoMessagemenuitem.Itwilltakeyoutothe
codeeditorwindowandyouwillbeinthe Menu2Item1_Clicked() subroutine.
Hereitis:

PUBLICSUBMenu2Item1_Click()
Message.Info("Hereissomeinformationtoconsider.")
END

Prettysimple,eh?Whatifwewantedtotogglethecheckedpropertyvalue
fromTRUEtoFALSEorviceversaeachtimethismenuitemwasselected.Modify
thecodeaboveasfollows:

PUBLICSUBMenu2Item1_Click()
IFMenu2Item1.CheckedTHEN
Menu2Item1.Checked=FALSE
ELSE
Menu2Item1.Checked=TRUE
ENDIF
Message.Info("Hereissomeinformationtoconsider.")
END

Figure46Achecked
menuitem.

Figure 43 above showsthe checked menu item. Selecting it again will


uncheckit. Well,thatwasnottoodifficult,wasit?See,Gambasmakesthings
easy.Now,let'smoveontothenextpart.

113
A Beginner's Guide to Gambas

Query/ConfirmMessages

QuestionandDeletefallintothiscategory.Questionisdefinedas:

STATICFUNCTIONQuestion(MessageASString[,Button1ASString,
Button2ASString,Button3ASString])ASInteger

InvokingitdisplaysaquestionMessageBoxwithuptothreebuttons.Theindex
ofthebuttonclickedbytheuserisreturned.Let'sgobacktoourpreviouscode
andexamineitindetail:

SELECTMessage.Question("Keepthenewfont?","Yes","No","Don'tknow")
CASE1
TextLabel1.Text="Thisisnowthedefaultfont."
CASE2
TextLabel1.Font=oldfontdata
TextLabel1.Text="Revertedtopreviousfontsetting."
CASE3
TextLabel1.Font=oldfontdata
TextLabel1.Text="Nochangewasmadetodefaultfont."
ENDSELECT

Becausetheindexofthebuttonclickedbytheuserisreturned,itiseasiest
toembedthecalltoMessage.QuestioninaSELECT/CASEstatement. SELECT
takestheintegerreturnvalueand,becauseweknowitcanonlybereturnedas
CASE1,2,or3,wewillnotneedtomakeaDEFAULTsection. Wecould,of
course,butitisnotnecessary.Dependingonthevaluereturned,wewilleither
takea Yes action,a No action,ora Don'tknow actionbecausethatiswhatwe
specifiedinourcalltotheDialog(intheSELECTstatementabove).Let'swrite
newcodeforourMessageBoxesMenumenuitemQuestionnow.Chooseitfrom
theformwindowandenterthiscode:

PUBLICSUBMenu2Item3_Click()

SELECTMessage.Question("Didyoulikethis?","Yes","No","Don'tknow")
CASE1
TextLabel1.Text="Likedit."
CASE2
TextLabel1.Text="Didnotlikeit."
CASE3
TextLabel1.Text="Didnotknow."
ENDSELECT
END

114
A Beginner's Guide to Gambas

Whenyouexecutetheprogram,hereiswhatyoushouldsee:

Figure47AQuestionMessageBox.

ErrorMessages

TheErrorfunctiondisplaysanerrorMessageBox,withuptothreebuttons.
Theindexofthebuttonclickedbytheuserisreturned.Errorisdefinedas:

STATICFUNCTIONError(MessageASString[,Btn1ASString,Btn2ASString,Btn3
ASString])ASInteger

GototheformandclicktheErrorMessagesubMenuItemtosetupaclickevent
andenterthiscode:

PUBLICSUBsubMenuItem1_Click()
Message.Error("Wow!Thiswasamistake.")
END

Hereiswhatyoushouldseewhenyouruntheprogram:

Figure48AnErrorMessage.

WarningorAlertMessages

Warning messages display a warning MessageBox, with up to three


buttons. Theindexofthebuttonclicked bytheuserisreturned. Warningis

115
A Beginner's Guide to Gambas

declaredas:

STATICFUNCTIONWarning(MessageASString[,Btn1ASString,Btn2AS
String,Btn3ASString])ASInteger

Inourexampleprogram,error,warninganddeletemessagesarepartof
the submenu we created to appear when the menu item Alert Messages is
activated.Tocodethewarningmessage,weneedtosettheclickeventbygoing
tothemenuandclickingontheWarningMessagesubMenuItem.Thiswillputus
inthecodewindowwherewewillenterthiscode:

PUBLICSUBsubMenuItem2_Click()
Message.Warning("Youhavebeenwarnedaboutthis!")
END

Whenyouexecutetheprogram,hereiswhatyoushouldsee:

Figure49AWarningmessage.

DeleteMessages

The Delete function displays a deletion MessageBox, with up to three


buttons. The index of the button clicked by the user is returned. Delete is
declaredas:

STATICFUNCTIONDelete(MessageASString[,Btn1ASString,Btn2AS
String,Btn3ASString])ASInteger

SettheclickeventforthesubMenuItemDeleteMessageandenterthiscode:

PUBLICSUBsubMenuItem3_Click()
SELECTMessage.Delete("Delete?","Yes","No","Cancel")
CASE1
TextLabel1.Text="Deletedit"
CASE2
TextLabel1.Text="NotDeleted"
CASE3
TextLabel1.Text="Canceled!"

116
A Beginner's Guide to Gambas

ENDSELECT
END

Whenyouexecutetheprogram,hereiswhatyoushouldsee:

Figure50Deletemessagewiththreebuttons.

DialogClassFilerelatedFunctions

The standard dialogs provided with Gambas also support file operation
suchasopeningafile,savingafile,andchoosingadirectorypath. Theyare
prettystandardbutthegreatadvantageisthatyoudon'thavetobuildthemevery
time you want to write a program. Consistency in user interface is now
demandedfromusersandanythinglessmakesyourprogramlessapproachable
and,resulting,lessacceptedbyusersthanitcouldbe.Thissectionwillshowyou
howeasyitistouseGambasstandarddialogsforfileoperations.

DialogOpenFileFunction

TheOpenFileDialogfunctioncallsthefilestandarddialogtogetthename
ofafiletoopen. ThisfunctionreturnsTRUEiftheuserclickedontheCancel
button,andFALSEiftheuserclickedontheOKbutton.Itisdeclaredasfollows:

STATICFUNCTIONOpenFile()ASBoolean

Fromtheexampleprogramformwindow,clickonthemenuFileDialogs
andselecttheFileopen...menuitem. Thissetsuptheclickeventandwewill
enterthiscode:

PUBLICSUBMenu3Item1_Click()
Dialog.Title="Openfile..."
Dialog.OpenFile
TextLabel1.Text="OPEN:"&Dialog.Path
END

117
A Beginner's Guide to Gambas

Thecodeabovesimplysetsthetitleandcallsthestandarddialog.When
theuserfinishesthestringreturnedfromtheOpenFileDialogfunctionisassigned
totheTextLabel1.Textvariable. Hereiswhatitshouldbringupwhenyourun
thecode:

Figure51TheOpenFileDialog.

Prettyeasystuff.Savingfilesisjustaseasy.

DialogSaveFileFunction

The SaveFileDialog functionalsocallsthefilestandarddialogtogetthe


nameofafiletosave.ItreturnsTRUEiftheuserclickedontheCancelbutton,
andFALSEiftheuserclickedontheOKbutton.SaveFileisdeclaredas:

STATICFUNCTIONSaveFile()ASBoolean

CreateaclickeventforourFileSave...menuitemandinthecodewindowenter
thiscode:

PUBLICSUBMenu3Item2_Click()

Dialog.Title="Savefileto..."
Dialog.SaveFile
TextLabel1.Text="SAVE:"&Dialog.Path

END

Hereistheresult:

118
A Beginner's Guide to Gambas

Figure52SaveFileDialog.

DialogSelectDirectoryFunction

TheSelectDirectoryDialogfunctioncallsthefilestandarddialogtogetan
existingdirectoryname.ItreturnsTRUEiftheuserclickedontheCancelbutton,
andFALSEiftheuserclickedontheOKbutton.SelectDirectoryisdeclaredas:

STATICFUNCTIONSelectDirectory()ASBoolean

Thisisthefinalclickeventweneedtocodeforourprogram.Choosethe
SelectDirmenuitemandenterthiscode:

PUBLICSUBMenu3Item3_Click()
Dialog.Title="Pickadir..."
Dialog.SelectDirectory
TextLabel1.Text="SAVEtoDIR:"&Dialog.Path
END

Saveyourprojectandrunthecode.HereiswhatyoushouldseeforSelectDir:

Figure53TheSelectDirectoryDialog.

119
A Beginner's Guide to Gambas

Now we have written all the code needed to finish our MenuProject
program. Save it and execute the program. The next section presents the
completeclassfileforyoutoreview.Itistimeforustomoveontobiggerand
betterthings.Inthenextchapter,wewillstartlearninghowtohandleinputand
outputfromtheuserbyusingstringsandfiles.

CompleteExampleListing

'Gambasclassfile
'declareaglobalvariabletobeusedwithourSetColorNamemodule
ColorNameASString

PUBLICSUBForm_Open()
ME.Caption="WorkingwithMenus"
END

PUBLICSUBQuitBtn_Click()
Form1.Close
END

PUBLICSUBMenu1Item1_Click()
Dialog.Title="Chooseaforegroundcolor"
Dialog.SelectColor
ColorName=Module1.SetColorName(Dialog.Color)
TextLabel1.ForeColor=Dialog.Color
TextLabel1.Text="<b>Colorselectedwas</b>"&ColorName&"."
END

PUBLICSUBMenu1Item2_Click()
Dialog.Title="Chooseabackgroundcolor"
Dialog.SelectColor
ColorName=Module1.SetColorName(Dialog.Color)
TextLabel1.BackColor=Dialog.Color
TextLabel1.Text="<b>Colorselectedwas</b>"&ColorName&"."
END

PUBLICSUBMenu1Item3_Click()
DIMfontdataASfont
DIMoldfontdataASFont

DIMattrASString
DIMselASString
attr=""
oldfontdata=TextLabel1.Font

Dialog.Title="Pickafont..."
Dialog.SelectFont

120
A Beginner's Guide to Gambas

fontdata=Dialog.Font
IFfontdata.ItalicTHEN
sel="Italic"
attr=attr&sel
ENDIF
IFfontdata.BoldTHEN
sel="Bold"
attr=attr&sel
ENDIF
IFfontdata.StrikeoutTHEN
sel="Strikeout"
attr=attr&sel
ENDIF
IFfontdata.UnderlineTHEN
sel="Underline"
attr=attr&sel
ENDIF
TextLabel1.Font=fontdata
TextLabel1.Text="Font:"&fontdata.Name&","&Str(Round
(fontdata.Size))&attr
WAIT5.0

SELECTMessage.Question("Keepnewfont?","Yes","No","Don'tknow")
CASE1
TextLabel1.Text="Thisisnowthedefaultfont."
CASE2
TextLabel1.Font=oldfontdata
TextLabel1.Text="Revertedtopreviousfontsetting."
CASE3
TextLabel1.Font=oldfontdata
TextLabel1.Text="Nochangewasmadetodefaultfont."
ENDSELECT
END

PUBLICSUBMenu2Item1_Click()
IFMenu2Item1.CheckedTHEN
Menu2Item1.Checked=FALSE
ELSE
Menu2Item1.Checked=TRUE
ENDIF
Message.Info("Hereissomeinformationtoconsider.")
END

PUBLICSUBsubMenuItem1_Click()
Message.Error("Wow!Thiswasamistake.")
END

PUBLICSUBsubMenuItem2_Click()

121
A Beginner's Guide to Gambas

Message.Warning("Youhavebeenwarnedaboutthis!")
END

PUBLICSUBsubMenuItem3_Click()
SELECTMessage.Delete("Delete?","Yes","No","Cancel")
CASE1
TextLabel1.Text="Deletedit"
CASE2
TextLabel1.Text="NotDeleted"
CASE3
TextLabel1.Text="Cancelled!"
ENDSELECT
END

PUBLICSUBMenu2Item3_Click()
SELECTMessage.Question("Didyoulikethis?","Yes","No","Don'tknow")
CASE1
TextLabel1.Text="Likedit."
CASE2
TextLabel1.Text="Didnotlikeit."
CASE3
TextLabel1.Text="Didnotknow."
ENDSELECT
END

PUBLICSUBMenu3Item1_Click()
Dialog.Title="Openfile..."
Dialog.OpenFile
TextLabel1.Text="OPEN:"&Dialog.Path
END

PUBLICSUBMenu3Item2_Click()
Dialog.Title="Savefileto..."
Dialog.SaveFile
TextLabel1.Text="SAVE:"&Dialog.Path
END

PUBLICSUBMenu3Item3_Click()
Dialog.Title="Pickadir..."
Dialog.SelectDirectory
TextLabel1.Text="SAVEtoDIR:"&Dialog.Path
END

PUBLICSUBMenu4Item1_Click()
Message.Info("Thisisallabout<br><b>GambasProgramming</b>!")
END

122
A Beginner's Guide to Gambas

Module1.modulelisting
'Gambasmodulefile
PUBLICFUNCTIONSetColorName(iValASInteger)ASString
rvalASString

SELECTiVal
CASEColor.Black
rval="Black"
CASEColor.Blue
rval="Blue"
CASEColor.Cyan
rval="Cyan"
CASEColor.DarkBlue
rval="DarkBlue"
CASEColor.DarkCyan
rval="DarkCyan"
CASEColor.DarkGray
rval="DarkGray"
CASEColor.DarkGreen
rval="DarkGreen"
CASEColor.DarkMagenta
rval="DarkMagenta"
CASEColor.DarkRed
rval="DarkRed"
CASEColor.DarkYellow
rval="DarkYellow"
CASEColor.Gray
rval="Gray"
CASEColor.Green
rval="Green"
CASEColor.LightGray
rval="LightGray"
CASEColor.Magenta
rval="Magenta"
CASEColor.Orange
rval="Orange"
CASEColor.Pink
rval="Pink"
CASEColor.Red
rval="Red"
CASEColor.Transparent
rval="Transparent"
CASEColor.Violet
rval="Violet"
CASEColor.White
rval="White"
CASEColor.Yellow

123
A Beginner's Guide to Gambas

rval="Yellow"
DEFAULT
rval=Str$(ival)&"anditisnotapredefinedcolorconstant"
ENDSELECT
RETURNrval
END

124
A Beginner's Guide to Gambas

Chapter 7 Handling Strings and


Converting Data-types
Oneofthemostimportantthingsaprogrammerneedstoknowishowto
handle strings and use the builtin functions provided by the development
languageheorshemaybeworkingwith. Manipulatingstringsandconverting
fromonedatatypetoanotherisalmostalwaysrequiredwhenprogramming.The
moreadeptaprogrammerisatusingthebuiltinfunctions,themorelikelyitis
theirprogramwilloperateefficiently.

StringFunctions

InGambas,thereisarichsetofstringfunctions.Wewillusetheconsole
forthischapterandlearnaboutthefollowingfunctions:

Len
Upper$/Ucase$andLower$/LCase$
Trim$/RTrim$andLTrim$
Left$/Mid$/Right$
Space$
Replace$
String$
Subst$
InStr
RInStr
Split

Wewillneedtocreateanewconsoleapplicationtodoourworkinthis
chapter.StartGambasandcreateanewterminalapplicationnamedStringTests.
When the IDE appears, create a new startup class named Class1. The code
windowshouldappearandyoushouldseesomethinglikethis:

'Gambasclassfile

STATICPUBLICSUBMain()

END

Wenowhaveallthepreliminariesoutofthewayandarereadytobegin

125
A Beginner's Guide to Gambas

learningaboutthestringsinGambas.Youmayrememberfromanearlierchapter
thatinGambasastringdatatypeisareferencetoavariablelengthstring.Itis
fourbytesininitialsizeandwhenitiscreateditisinitializedwithaNullvalue.

Len

Lenreturnsthelengthofastring.ThereturnvalueisanInteger.Hereis
howLenwouldbeusedincode:

Length=Len(String)

Fromthecodewindow,let'stypethefollowing:

STATICPUBLICSUBMain()
DIMsStringLengthASInteger
DIMsTestStringASString

sTestString="12345678901234567890"
sStringLength=Len(sTestString)
PRINT"==>"&sStringLength&"isthelengthofourteststring."

sTestString="12345"
sStringLength=Len(sTestString)
PRINT"==>"&sStringLength&"isthelengthofourteststring."

sTestString="12345678901"
sStringLength=Len(sTestString)
PRINT"==>"&sStringLength&"isthelengthofourteststring."
END

Theconsolewillrespondwiththis:

==>20isthelengthofourteststring.
==>5isthelengthofourteststring.
==>11isthelengthofourteststring.

Itisimportanttoknowthatstringlengthbeginscountingatposition1,not
zerolikeinCandsomeotherlanguages. Nowthatwecanfindouthowmany
charactersareinastring,let'slearnhowtoconvertthestringfromonecaseto
another.

Upper$/Ucase$/UcaseandLower$/Lcase$/Lcase

Upper$ returnsa stringconverted touppercase. Ucase$ and Ucase are

126
A Beginner's Guide to Gambas

synonynmsforUpper$andcanbeusedinterchangeably.Lower$returnsastring
convertedtolowercase.Lcase$andLcasearesynonymsforLower$andcanalso
be used interchangeably. Note that these functions do not work with UTF8
strings.HereisthestandardGambaslanguagesyntaxforusingthesefunctions:

Result=Upper$(String)

Result=UCase$(String)

Typethisinthecodewindowandexecutetheprogram:

STATICPUBLICSUBMain()
DIMsStringLengthASInteger
DIMsTestStringASString

sTestString="abcdefg"

PRINT"==>"&sTestString&"isourstartingstring."
PRINT"==>"&UCase$(sTestString)&"isnowuppercase."
PRINT"==>"&LCase$(sTestString)&"isnowbacktolowercase."
PRINT"==>"&Upper$(sTestString)&"isnowbacktouppercase."

sTestString="123abc456def789ghiZZZ"

PRINT"==>"&sTestString&"isourstartingstring."
PRINT"==>"&UCase(sTestString)&"isnowuppercase."
PRINT"==>"&LCase(sTestString)&"isnowbacktolowercase."
PRINT"==>"&Upper(sTestString)&"isnowbacktouppercase."
PRINT"==>"&Lower$(sTestString)&"isnowbacktolowercase."
END

Theconsolerespondswith:

==>abcdefgisourstartingstring.
==>ABCDEFGisnowuppercase.
==>abcdefgisnowbacktolowercase.
==>ABCDEFGisnowbacktouppercase.
==>123abc456def789ghiZZZisourstartingstring.
==>123ABC456DEF789GHIZZZisnowuppercase.
==>123abc456def789ghizzzisnowbacktolowercase.
==>123ABC456DEF789GHIZZZisnowbacktouppercase.
==>123abc456def789ghizzzisnowbacktolowercase.

Trim$,LTrim$,andRTrim$

Trim$stripsawayallwhitespacesfromeitherendofastring.Itwillnot

127
A Beginner's Guide to Gambas

strip white spaces away after the first nonwhitespace is encountered and
basically ignores all whitespace until the last nonwhitespace character is
encountered,whereuponitwillbegintotrimtrailingwhitespace.Awhitespace
isanycharacterwhoseASCIIcodeisstriclylowerthan32.Trim$isbasicallya
calltoLtrim$andRtrim$simultaneously.Itisusedlikethis:

Result=Trim$(String)

TrythisonyourconsoleseehowtheTrim$functionworks:

STATICPUBLICSUBMain()
DIMsTestStringASString
DIMsResultASString
DIMiLengthASInteger

PRINT"12"
PRINT"12345678901234567890"
sTestString="<abcdef"
iLength=Len(sTestString)

PRINTsTestString&">isourstartingstring."
PRINT"Itis"&Str$(iLength)&"characterslong"
sResult=Trim$(sTestString)
PRINTsResult&">istheresultofTrim$call."
END

Theconsolerespondswiththis:

12
12345678901234567890
<abcdef>>isourstartingstring.
Itis14characterslong
<abcdef>istheresultofTrim$call.

Left$,Mid$,andRight$

Left$ returns the first Length characters of a string. If Length is not


specified,thefirstcharacterofthestringisreturned.IfLengthisnegative,allof
the string except the Length last characters are returned. Standard Gambas
languagesyntaxis:

Result=Left$(String[,Length])

Mid$ returnsasubstringcontainingthe Length charactersfromthefirst

128
A Beginner's Guide to Gambas

position.IfLengthisnotspecified,everythingfromthestartpositionisreturned.
If Length isnegative,everythingfromthestartpositionexceptthe Length last
charactersisreturned.StandardGambaslanguagesyntaxis:

Result=Mid$(String,Start[,Length])

Right$ returns the Length last characters of a string. If Length is not


specified,thelastcharacterofthestringisreturned.IfLengthisnegative,allof
the string except the Length first characters are returned. Standard Gambas
languagesyntaxis:

Result=Right$(String[,Length])

Trythisonyourconsole:

STATICPUBLICSUBMain()
DIMsTestStringASString
DIMsResultASString
DIMiLengthASInteger

PRINT"12"
PRINT"12345678901234567890"
sTestString="abcdefghi"
iLength=Len(sTestString)

PRINTsTestString&"isourstartingstring."
PRINT"Itis"&Str$(iLength)&"characterslong"

sResult=Left$(sTestString,3)
PRINTsResult&"istheresultofLeft$call."
sResult=Mid$(sTestString,4,3)
PRINTsResult&"istheresultofMid$call."
sResult=Right(sTestString,3)
PRINTsResult&"istheresultofRight$call."
END

Theconsolerespondswiththis;

12
12345678901234567890
abcdefghiisourstartingstring.
Itis9characterslong
abcistheresultofLeft$call.
defistheresultofMid$call.
ghiistheresultofRight$call.

129
A Beginner's Guide to Gambas

Space$

Space$ returns a string containing Length spaces. Standard Gambas language


syntaxis:

String=Space$(Length)

Trythisontheconsole:

STATICPUBLICSUBMain()
DIMsTestStringASString
DIMsResultASString

PRINT"12"
PRINT"12345678901234567890123456"
sTestString="a"
PRINTsTestString&Space$(24)&"z"
END

Replace$

Replace$ replaces every occurrence of the string Pattern in the string


StringbythestringReplaceString,andreturnstheresult.IfStringisnull,thena
null string is returned. If Pattern is null, then the string String is returned.
StandardGambaslanguagesyntaxisasfollows:

Result=Replace$(String,Pattern,ReplaceString)

Trythisprogramonyourconsole:

STATICPUBLICSUBMain()
DIMsTestStringASString
DIMsResultASString

sTestString="abc123ghi"
PRINTsTestString&"isourstartingstring."
sResult=Replace$(sTestString,"123","def")
PRINTsResult&"istheresultofReplacecall."

sTestString="abcdefghi"
PRINTsTestString&"isourstartingstring."
sResult=Replace$(sTestString,"","")
PRINTsResult&"istheresultofReplacecall."

sTestString="\ta\tb\tc\tdef"

130
A Beginner's Guide to Gambas

PRINTsTestString&"isourstartingstring."
sResult=Replace$(sTestString,"\t","")
PRINTsResult&"istheresultofReplacecall."
END

Theconsolerespondswith:

abc123ghiisourstartingstring.
abcdefghiistheresultofReplacecall.
abcdefghiisourstartingstring.
abcdefghiistheresultofReplacecall.
A b c defisourstartingstring.
abcdefistheresultofReplacecall.

String$

String$ simply returns a string containing Length times the Pattern. Use this
format:

String=String$(Length,Pattern)

Trythisontheconsole:

STATICPUBLICSUBMain()
DIMsTestStringASString
DIMsResultASString

PRINT"12"
PRINT"12345678901234567890123456"
sTestString="a"

PRINTsTestString&String(24,".")&"z"
END

Theconsolerespondswith:
12
12345678901234567890123456
a........................z

Subst$

Subst$replacesarguments&1,&2,etc.inapatternwiththefirst,second,
andsubsequentReplaceStringsrespectively,andreturntheresult. IfPatternis
null, then a null string is returned. For C developers, this is not unlike a

131
A Beginner's Guide to Gambas

simplifiedsprintf.Thisfunctionisveryusefulwhenyoumustconcatenatestrings
thatmustbetranslated.Donotusethe&operator,astheorderofconcatenation
mightchangewiththelanguage.StandardGambaslanguagesyntaxis:

Result=Subst(Pattern,ReplaceString[,ReplaceString])

Trythislittleapplicationonyourconsole:

STATICPUBLICSUBMain()
DIMsTestStringASString
DIMsResultASString

sTestString="abcdef"
sResult="ghijkl"
PRINT"Ourstartstringis:"&sTestString
PRINTSubst$("OurSubststringis:&1",sResult)
END

Theconsolerespondswith:

Ourstartstringis:abcdef
OurSubststringis:ghijkl

InStr

InStrreturnsthepositionofthefirstoccurrenceofSubstringinString.If
Startisspecified,thesearchbeginsatthepositionStart. Ifthesubstringisnot
found,InStr()returnszero.

Position=InStr(String,Substring[,Start])

Thefollowingcodeisabitmoreinvolvedandwilldemonstratethepower
ofthisfunction.Wewanttofindeveryspace(setinthestringatevennumbered
positions)andprintoutthepositionwhereeachspaceoccurs.Enterthiscodein
theconsolecodewindow:

'Gambasclassfile

STATICPUBLICSUBMain()
DIMsTestStringASString
DIMsResultASString
DIMiLengthASInteger
DIMiPositionASInteger
DIMiNextCharPosASInteger

132
A Beginner's Guide to Gambas

DIMiCounterASInteger

sTestString="abcdefghi"
iPosition=Instr(sTestString,"")
PRINTsTestString&"isourstartstring."
PRINT"Firstspaceisatposition:"&iPosition
iNextCharPos=iPosition+1
iPosition=Instr(sTestString,"",iNextCharPos)
PRINT"Nextspaceisatposition:"&iPosition
PRINT

sTestString="abcdefghijklmnopqrstuvwxyz"
PRINT"123456"
PRINT"123456789012345678901234567890123456789012345678901234567890"
PRINTsTestString&"isournewteststring."
PRINT
iLength=Len(sTestString)
PRINT"LengthofsTestStringis:"&iLength

iPosition=Instr(sTestString,"")
PRINT"Firstspaceisatposition:"&iPosition
FORiCounter=iPositionTOiLength/2
iNextCharPos=iPosition+1
iPosition=Instr(sTestString,"",iNextCharPos)
PRINT"Nextspaceisatposition:"&iPosition
NEXT
END

Theresultingoutputis:

abcdefghiisourstartstring.
Firstspaceisatposition:4
Nextspaceisatposition:8

123456
123456789012345678901234567890123456789012345678901234567890
abcdefghijklmnopqrstuvwxyzisournewtest
string.

LengthofsTestStringis:51
Firstspaceisatposition:2
Nextspaceisatposition:4
Nextspaceisatposition:6
.
.
Nextspaceisatposition:46
Nextspaceisatposition:48
Nextspaceisatposition:50

133
A Beginner's Guide to Gambas

RInStr

RInStrreturnsthepositionofthelastoccurrenceofSubstringinString.If
Startisspecified,thesearchstopsatthepositionStart. Ifthesubstringisnot
found,RInStr()returnszero.StandardGambaslanguagesyntaxis:

Position=RInStr(String,Substring[,Start])

Enterthiscodeintheconsole:

STATICPUBLICSUBMain()
DIMsTestStringASString

DIMiPositionASInteger

sTestString="abcdefabcdefabc"
PRINT"12"
PRINT"12345678901234567890"
PRINTsTestString

iPosition=RInstr(sTestString,"abc")
PRINT
PRINT"lastoccurrenceofabcstartsatposition:"&iPosition
END

Theconsolerespondswith:

12
12345678901234567890
abcdefabcdefabc

lastoccurrenceofabcstartsatposition:17

Split

Splitsplitsastringintosubstringsdelimitedbytheseparator(s)designated
asparameters.Escapecharacterscanbespecifiedalso.Anyseparatorcharacters
enclosedbetweentwoescapecharactersareignoredinthesplittingprocess.Note
thatSplittakes onlythreeargumentssoifyouwanttouseseveralseparators,
youshouldpassthemasthesecondparameter,concatenatedinasinglestring.
By default, the comma character is the separator, and there are no escape
characters. This function returns a string array filled with each detected
substring.TheGambaslanguagesyntaxis:

134
A Beginner's Guide to Gambas

Array=Split(String[,Separators,Escape])

Hereisaprogramtotryonyourconsole:

STATICPUBLICSUBMain()
DIMaWordArrayASString[]
DIMsWordASString
'noteweuseaspacedelimiter
aWordArray=Split("ThisisindeedaverycoolfeatureofGambas!","")

FOREACHsWordINaWordArray
PRINTsWord
NEXT
END

Theconsolerespondswith:

This
is
indeed
a
very
cool
feature
of
Gambas!

ConvertingDatatypes

AscandChr$

AscreturnstheASCIIcodeofthecharacteratpositionPositionintheString
.IfPositionisnotspecified,theASCIIcodeofthefirstcharacterisreturned.Chr$
returnsthecharacterwhoseASCIIcodeisCode.Awordofcaution:Gambasuses
the UTF8 charset internally, soany charactercode greaterthan 128 maynot
havethesamemeaningastheywouldhavewithanothercharset(forexample,
ISO88591).HereistheGambaslanguagesyntax:

Code=Asc(String[,Position])
Character=Chr$(Code)

HereisasampleprogramthatillustratestheuseofbothASCandCHR$:

'Gambasclassfile

135
A Beginner's Guide to Gambas

STATICPUBLICSUBMain()
DIMiAsciiCodeASInteger
DIMsTestStringASString
DIMiLengthASInteger
DIMcounterASInteger

sTestString="Gambasisgreat."
iLength=Len(sTestString)
PRINT"LengthofsTestStringis:"&Str$(iLength)
FORcounter=1TOiLength
iAsciiCode=Asc(sTestString,counter)
IFiAsciiCode<>32THEN
PRINTiAsciiCode&"ischar:"&Chr(9)&Chr$(iAsciiCode)
ELSE
PRINTiAsciiCode&"ischar:"&Chr(9)&"<space>"
ENDIF
NEXT
END

Inthecodeabove,Chr(9)isusedtorepresenttheTABcharacter.Theresulting
outputfromtheconsoleis:

LengthofsTestStringis:16
71ischar: G
97ischar: a
109ischar: m
98ischar: b
97ischar: a
115ischar: s
32ischar: <space>
105ischar: i
115ischar: s
32ischar: <space>
103ischar: g
114ischar: r
101ischar: e
97ischar: a
116ischar: t
46ischar: .

Bin$

Bin$ returns the binary representation of a number. If Digits is specified, the


representationispaddedwithunnecessaryzerossothatDigitsdigitsarereturned.

String=Bin$(Number[,Digits])

136
A Beginner's Guide to Gambas

Examplecodeyoucantryontheconsole:

STATICPUBLICSUBMain()
DIMsBinaryCodeASString
DIMcounterASInteger

FORcounter=0TO15
sBinaryCode=Bin$(counter,4)
PRINTsBinaryCode
NEXT
END

Theoutputshouldlooklikethis:

0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111

CBool

CBoolconvertsanexpressionintoaBooleanvalue.Anexpressionisfalseif
anyofthefollowingconditionsaremet:

AfalseBooleanvalue
Azeronumber
Azerolengthstring
Anullobject

Otherwise,theexpressionistrueinallothercases.HereistheGambaslanguage
syntax:

137
A Beginner's Guide to Gambas

Boolean=CBool(Expression)

Hereisanexample:

STATICPUBLICSUBMain()
PRINTCBool(0);"";CBool(1)
END

Theconsolerespondswith:

FALSETRUE

CByte

CByteconvertsanexpressionintoabyte.Expressionisfirstconvertedinto
aninteger.Then,ifthisintegeroverflowsthebyterange,(32767to32768)itis
truncated.

Byte=CByte(Expression)

Example:

STATICPUBLICSUBMain()
PRINTCByte("17")
PRINTCByte(32769)
PRINTCByte(TRUE)
END

Theconsolerespondswith:
17
1
255

CDate

CDate converts an expression into a date/time value. Be careful! The


currentlocalizationisNOTusedbythisfunction.Gambaslanguagesyntaxis:

Date=CDate(Expression)

Example:

STATICPUBLICSUBMain()

138
A Beginner's Guide to Gambas

DIMsDateStringASString
sDateString=CDate(Now)
PRINTsDateString;"isourstarttime."
WAIT1.0
PRINTCDate(Now);"isonesecondlater."
PRINTCDate(sDateString);"isstillwherewestarted."
WAIT1.0
PRINTNow;"isonesecondlater."
END

Theconsolerespondswith:

08/21/200520:52:40isourstarttime.
08/21/200520:52:41isonesecondlater.
08/21/200520:52:40isstillwherewestarted.
08/21/200520:52:42isonesecondlater.

CFloat

CFloatconvertsanexpressionintoafloatingpointnumber. Becareful!
Thecurrent localization isNOTusedbythisfunction. Gambaslanguagesyntax
is:

Float=CFloat(Expression)

Example:

STATICPUBLICSUBMain()
DIMsFloatStringASString
DIMfFloatNumASFloat

sFloatString="0.99"
fFloatNum=0.01

PRINTfFloatNum+CFloat(sFloatString)
PRINTCFloat("3.0E+3")
END

Theconsolerespondswith:

1
3000

139
A Beginner's Guide to Gambas

CInt/CintegerandCShort

CIntissynonymouswithCInteger.Eithercallconvertsanexpressioninto
aninteger.ThestandardGambaslanguagesyntaxis:

Integer=CInt(Expression)
Integer=CInteger(Expression)

CShort converts an expression into a short integer. Expression is first


convertedintoaninteger.Then,ifthisintegeroverflowstheshortrange,itis
truncated.HereistheGambaslanguagesyntaxforCShort:

Short=CShort(Expression)

Hereisanexamplethatslightlymodifiesthepreviousconsoleexampleto
showbothofthesefunctions:

STATICPUBLICSUBMain()
DIMsFloatStringASString
DIMfFloatNumASFloat

sFloatString="0.99"
fFloatNum=120.901

PRINTfFloatNum+CFloat(sFloatString)
PRINTCInt(fFloatNum);"wasafloat,nowanint."
PRINTCShort(fFloatNum);"wasafloat,nowashort."
END

Theresultis:

121.891
120wasafloat,nowanint.
120wasafloat,nowashort.

CStr/CString

CStr/CStringconvertsanexpressionintoastring.Becareful!Thecurrent
localization is NOTused by this function. Here is howthe Gambas language
syntaxforCStrworks:
String=CStr(Expression)
String=CString(Expression)

140
A Beginner's Guide to Gambas

Example:

STATICPUBLICSUBMain()
DIMsFloatStringASString
DIMfFloatNumASFloat

fFloatNum=120.901
sFloatString=CStr(fFloatNum)
PRINTsFloatString;"isnowastring."
END

Consoleoutputis:

120.901isnowastring.

Hex$

Hex$returnsthehexadecimalrepresentationofanumber.IfDigitsisspecified,
the representation is padded with unnecessary zeros so that Digits digits are
returned.HereistheGambaslanguagesyntax:

String=Hex$(Number[,Digits])

Hereisanexampleprogram:

STATICPUBLICSUBMain()
DIMcounterASInteger

FORcounter=1TO15
PRINTHex$(counter,2);"";
NEXT
END

Thisistheresult:

0102030405060708090A0B0C0D0E0F

Conv$

Conv$ converts a string from one charset to another. A charset is


represented by a string like "ASCII", "ISO88591", or "UTF8". The GAMBAS
interpreter internallyusesthe UTF8charset.Thecharsetusedbythesystemis
returnedbyacalltoSystem.Charset.ItisISO88591onMandrake9.2operating

141
A Beginner's Guide to Gambas

system,butitisUTF8onaRedHatLinuxoperatingsystem.Inthefuture,nearly
allLinuxsystemswillprobablybeUTF8based.Thecharsetusedbythegraphical
userinterfaceisreturnedbyacallto Desktop.Charset.ItisUTF8withthe Qt
component.TheGambaslanguagesyntaxis:

ConvertedString=Conv$(StringASString,SourceCharsetASString,
DestinationCharsetASString)

Theconversionreliesontheiconv()GNUlibraryfunction.Hereisacode
exampletotry:

STATICPUBLICSUBMain()
DIMsStrASString
DIMiIndASInteger

sStr=Conv$("Gambas","ASCII","EBCDICUS")
FORiInd=1TOLen(sStr)
PRINTHex$(Asc(Mid$(sStr,iInd,1)),2);"";
NEXT
END

Hereistheoutput:

C781948281A2

ValandStr$

ValconvertsastringintoaBoolean,anumberoradate,accordingtothe
contentofthestring. Thecurrent localization isusedtoconvertnumbersand
dates.Theconversionalgorithmusesthefollowingorderofprecedence:

Ifstringcanbeinterpretedasadate&time(withdateortime
separators),thenthedate&timeisreturned.
Elseifstringcanbeinterpretedasafloatingpointnumber,then
afloatingpointnumberisreturned.
Elseifstringcanbeinterpretedasaintegernumber,thenan
integernumberisreturned.
ElseifstringisTRUEorFALSE,thematchingBooleanvalueis
returned.
ElseNULLisreturned.

StandardGambaslanguagesyntaxis:

Expression=Val(String)

142
A Beginner's Guide to Gambas

Str$convertsanexpressionintoitsprintablestringrepresentation.Itisthe
exactcontraryofVal().Thecurrentlocalizationisusedtoconvertnumbersand
dates.Gambaslanguagesyntaxis:

String=Str$(Expression)

Trythis:

STATICPUBLICSUBMain()
DIMsDateTimeASString
DIMdDateASDate

PRINTNow;"iscurrentsystemtime."

sDateTime=Val(Str$(Now))
PRINTsDateTime;"isastringrepresentationofcurrentsystemtime."
PRINTVal(sDateTime);"isVALconvofthestringrepresentation."

dDate=Val(sDateTime)
PRINTdDate;"istheDATEvariableconvertedwithVAL."
PRINTStr(dDate);"isastringrepresentationofthedatevariable."
END

Hereistheoutput:

08/21/200521:42:45iscurrentsystemtime.
08/21/200521:42:45isastringrepresentationofcurrentsystemtime.
08/21/200521:42:45isVALconvofthestringrepresentation.
08/21/200521:42:45istheDATEvariableconvertedwithVAL.
08/21/200521:42:45isastringrepresentationofthedatevariable.

Hereisanothersampleprogramtotry:

'Gambasclassfile

STATICPUBLICSUBMain()

DIMsInputLineASString
DIMvalueASVariant

DOWHILEsInputLine<>"quit"
PRINT"==>";
LINEINPUTsInputLine
IFsInputLine=""THEN
sInputLine="<CRLF>"
ENDIF

143
A Beginner's Guide to Gambas

PRINT"Youtyped:";sInputLine
value=Val(sInputLine)
PRINT
IFIsBoolean(value)THEN
PRINTsInputLine;"isBoolean."
ELSEIFIsDate(value)THEN
PRINTsInputLine;"isadate."
ELSEIFIsInteger(value)THEN
PRINTsInputLine;"isanInteger."
IFvalue=0ORvalue=1THEN
PRINT"ItcouldalsobeBoolean."
ENDIF
IFvalue>0ANDvalue<255THEN
PRINT"ItcouldalsobeaByte."
ENDIF
IFvalue>32767ANDvalue<32768THEN
PRINT"Itcouldalsobeashort."
ENDIF
PRINT""
ELSEIFIsFloat(value)THEN
PRINTsInputLine;"isafloat."
ELSEIFIsString(value)THEN
PRINTsInputLine;"isastring."
ELSEIFIsNull(value)THEN
PRINTsInputLine;"isNULL."
ELSE
PRINTsInputLine;"issomethingelse."
ENDIF
LOOP
PRINT
PRINT"Wearedone!"
END

Theoutputshouldbesimilartothis:

==>true
Youtyped:true

trueisBoolean.
==>214
Youtyped:214

214isanInteger.
ItcouldalsobeaByte.
Itcouldalsobeashort.

==>08/23/0512:23:55
Youtyped:08/23/0512:23:55

144
A Beginner's Guide to Gambas

08/23/0512:23:55isadate.
==>John
Youtyped:John

Johnisastring.
==>32756
Youtyped:32756

32756isanInteger.
Itcouldalsobeashort.

==>quit
Youtyped:quit

quitisastring.

Wearedone!

Format$

Format$convertsanexpressiontoastringbyusingaformatthatdepends
onthetypeof theexpression.Formatcan bea predefined format(an integer
constant)orauserdefinedformat(astringthatdepictstheformat).IfFormatis
not specified, gb.Standard component formats are used. This function uses
localization information to format dates, times and numbers. The Gambas
languagesyntaxis:

String=Format$(Expression[,Format])

Auserdefinednumberformatisdescribedbythefollowingcharacters:

FormatSymbol Meaning
"+" printsthesignofthenumber.
"" printsthesignofthenumberonlyifitisnegative.
"#" printsadigitonlyifnecessary.
"0" alwaysprintsadigit,paddingwithazeroifnecessary.
"." printsthedecimalseparator.
"%" multipliesthenumberby100andprintsapercentsign.
"E" introduces theexponential part of afloat number. The sign of the exponentis always
printed.

145
A Beginner's Guide to Gambas

Auserdefineddateformatisdescribedbythefollowingcharacters:

FormatSymbol Meaning
"yy" printsyearusingtwodigits.
"yyyy" printsyearusingfourdigits.
"m" printsmonth.
"mm" printsmonthusingtwodigits.
"mmm" printsmonthinanabbreviatedstringform.
"mmmm" printsmonthinit'sfullstringform.
"d" printsday.
"dd" printsdayusingtwodigits.
"ddd" printsweekdayinanabbreviatedform.
"dddd" printsweekdayinitsfullform.
"/" printsdateseparator.
"h" printshour.
"hh" printshourusingtwodigits.
"n" printsminutes.
"nn" printsminutesusingtwodigits.
"s" printsseconds.
"ss" printssecondsusingtwodigits.
":" Printsatimeseparator.

Hereisaprogramthatdemonstratesseveralexamples:

STATICPUBLICSUBMain()
PRINT""
PRINT"UserdefinednumericFormatexamples:"
PRINTFormat$(Pi,"#.###")
PRINTFormat$(Pi,"+0#.###0")
PRINTFormat$(Pi/10,"###.#%")
PRINTFormat$(11^11,"#.##E##")
PRINT""
PRINT"Userdefineddateandtimeformatexamples:"
PRINT
PRINTFormat$(Now,"mm/dd/yyyyhh:nn:ss")
PRINTFormat$(Now,"m/d/yyh:n:s")
PRINTFormat$(Now,"dddddmmmyyyy")
PRINTFormat$(Now,"ddddddmmmmyyyy")
END

146
A Beginner's Guide to Gambas

Hereistheoutput:

UserdefinednumericFormatexamples:
3.142
+03.1416
31.4%
2.85E+11

Userdefineddateandtimeformatexamples:
08/21/200521:55:14
8/21/0521:55:14
Sun21Aug2005
Sunday21August2005

Datatypemanagement

Manytimeswhencheckingvariables,itisimportanttoknowwhatdata
typeyouaredealingwith.Gambasprovidesahostoffunctionsforthatpurpose.
Youcancheckforthefollowingdatatypes:

IsBoolean/Boolean? IsByte/Byte?
IsDate/Date? IsFloat/Float?
IsInteger/Integer? IsNull/Null?
IsNumber/Number? IsObject/Object?
IsShort/Short? IsString/String?

Each of the functions above are called using the standard Gambas language
syntaxof

BooleanResult=IsBoolean?(Expression)
BooleanResult=IsByte?(Expression)
BooleanResult=IsDate?(Expression)
BooleanResult=IsFloat?(Expression)
BooleanResult=IsInteger?(Expression)
BooleanResult=IsNull?(Expression)
BooleanResult=IsNumber?(Expression)
BooleanResult=IsObject?(Expression)
BooleanResult=IsShort?(Expression)
BooleanResult=IsString?(Expression)

and the given function will return TRUE if an expression is of the datatype
queriedorFALSEifitisnot.

147
A Beginner's Guide to Gambas

TypeOf

TypeOfreturnsthetypeofanexpressionasanintegervalue.Gambashas
definedseveralpredefinedconstantsforthedatatypesreturnedbythisfunction.
The predefinedconstants Gambassupportsareshowninthetablebelow. The
standardGambaslanguagesyntaxforthisfunctionis:

Type=TypeOf(Expression)

Predefined data-type constants


Datatype Value
gb.Null Nullvalue
gb.Boolean Booleanvalue
gb.Byte Byteintegernumber
gb.Short Shortintegernumber
gb.Integer Integernumber
gb.Float Floatingpointnumber
gb.Date Dateandtimevalue
gb.String Characterstring
gb.Variant Variant
gb.Object Objectreference

That'saboutallwewillcoverinthischapter.Inthenextchapter,wewill
return to the Gambas ToolBox and start learning to use some of the more
advancedcontrols,suchasiconview,listview,etc.Youshouldnowbeadequately
preparedtodealwithmoreadvanceddatahandlingtechniquesrequiredforthose
controls.

148
A Beginner's Guide to Gambas

Chapter 8 Using Advanced Controls


Inthischapter,wearegoingtostudyafewofthemoreadvancedcontrols,
suchastheIconView,ListView,GridView,ColumnViewandTabstripcontrolsand
learnhowtousethem.FortheIconViewcontrol,wearegoingtotakeadifferent
approachthistime,usingoneoftheexampleprogramsprovidedbyGambas.We
are going to review the Explorer program written by Gambas creator Benot
Minisiniandgothrougheachandeverylineofcodetounderstandexactlywhatis
goingonintheprogramandhowtheIconViewcontrolisused.

IconViewControl

Firstofall,startGambasandselecttheExplorerprojectfromtheMiscellaneous
sectionoftheExampleprograms:

Figure54ChoosingtheExplorerexample.

Once youselecttheExplorerproject,theIDEwillopenupandwewill
needtogettothecode.Youcandothisbydoubleclickingontheclassfileorif
theformisalreadyup,doubleclickonacontrolandthenmovetothetopofthe

149
A Beginner's Guide to Gambas

codewindow. Eitherwaywillworkaslongasyoustartatthetopofthecode
windowwhereyouseethefirstline:

'Gambasclassfile

Thefirstthingweseedoneinthiscodeisthedeclarationoftheprogram's
globalvariables.Notethattheyareprefixedwitha'$'characterforclarity.The
$sPathvariableisdeclaredasPRIVATEandusedtoholdthenameofthecurrent
filepath.

PRIVATE$sPathASString

$bHiddenisaPRIVATEBooleanvariablethatwillactasaflagtobeusedto
determineIFafileishiddenornot. Wewillusethe Stat function tocheckits
status.
PRIVATE$bHiddenASBoolean

$bCtrlisaPRIVATEBooleanusedasaflagwhenaCTRLkeyispressed.If
theuserholdsdowntheCTRLkeywhendoubleclickingonafolderitwillopen
upinanewwindow.

PRIVATE$bCtrlASBoolean

ThisisthefirstsubroutineGambaswillexecutewhentheprogramisrun:

STATICPUBLICSUBMain()

Thenexttwolineswilldeclarealocalvariablefortheformwewantto
displaytotheuserandcreateaninstanceoftheformnamed FExplorer,passing
theparameterSystem.Hometoaconstructorroutine,whichisidentifiedas_new
()),andwhichtakesastringparametersPath(System.Home)thevalueofwhich
weobtainedfromtheSystemclass.

DIMhFormASForm
hForm=NEWFExplorer(System.Home)

Now,showtheform:
hForm.Show

END

150
A Beginner's Guide to Gambas

ThisnextsubroutineistheconstructorthatiscalledwhentheMain()subroutine
isactivatedandtheFExplorerformisinstantiated:

PUBLICSUB_new(sPathASString)

Wewillassignthepathpassedin(System.Home)asaparametertoourglobal
variable$sPath:

$sPath=sPath

Finally, we must call the subroutine RefreshExplorer() to populate the


iconviewcontrolnamedivwExplorertorefreshthedisplayforthenewcontrol:

RefreshExplorer
END

HereistheRefreshExplorer()subroutine.Itisessentiallythemeatofthe
program:
PRIVATESUBRefreshExplorer()

First, we declare the local variables. Let's start with a string var to hold file
names:

DIMsFileASString

Next,declarepicturevariablesforouriconimages:parentdirectory,folderand
file:

DIMhPictDirASPicture
DIMhPictParDirASPicture'addedbytheauthor
DIMhPictFileASPicture

cDirisanarrayofstrings(representingthenamesoffilesordirectories):

DIMcDirASNEWString[]

sNameisaworkstringusedtorepresentfilenamesfoundinadirectory:

DIMsNameASString

The next statement is either not documented in Gambas or the


documentationisunreachableontheGambaswebsite.However,thiscallappears
toincrementtheBusyproperty valuethatisdefinedintheApplicationclass.It

151
A Beginner's Guide to Gambas

seemstobeusedasasemaphoresootherprocessescantesttheflagbeforetrying
to get computer time (remember, most applications use some sort of OS
implementedroundrobinCPUschedulingroutinetoshareprocessorresources).
Here,itisbasicallyaflagthattellsalltheothercallingprocessesthattheyhaveto
waituntiluntilthisprocessisnotbusyanymore(indicatedbydecrementingthe
valueoftheBusyproperty).ThisseemstobehowGambassetsflagstoprevent
criticalprocessesfrombeinginterrupted.

INCApplication.Busy

Oncethedon'tinterruptmeflagisthrown,wesetthewindowtitletothe
systempathandcallthebuiltinConv$14 functiontoconvertthesystemcharset
(thesetofcharacterstheoperatingsystemhasprovidedasdefault)towhattheuser
hasdefinedasthedesktopcharset(thesetofcharacterstheuserhaschosentosee
fromtheirdesktop). Notethat Conv isasynonymfor Conv$ andyoucanuse
eitheroneinterchangably.

ME.Title=Conv($sPath,System.Charset,Desktop.Charset)

Now, whatever may exist in the icon view is wiped out by calling the
iconview'sClearmethod:

ivwExplorer.Clear

Next,assigniconstothepicturevariableswedeclared.Wehaveaniconto
representfoldersandoneforfiles:

hPictDir=Picture["folder.png"]
hPictParDir=Picture["ParentFolder.png"]'addedbytheauthor
hPictFile=Picture["file.png"]

Iftheglobalpathvariableisnotsettothehighestlevel(i.e.,theparent)
indicatedbythe"/"string,thenwewanttocreateafolderthattheusercanclick
togototheparentdirectoryofthecurrentchild. Weaddthisfolderthethe
iconviewcontrolnamedivwExplorerbyusingitsAddmethod:

IF$sPath<>"/"THENivwExplorer.Add("D..","..",hPictParDir)

Inthestatementabove,the.Addmethodtakesthreeparameters.Thefirst
isthenameofthekey,inthiscaseD..whichisourkeyfordirectories. The
secondisthetextplacedbelowtheiconintheIconViewcontrol,andthefinal
14 Common string functions do not deal with UTF-8 very well. In UTF-8, a character can have 1-3 bytes. The Gambas String
class methods are able to handle UTF-8 so they should be used whenever possible.

152
A Beginner's Guide to Gambas

parameteristhenameofthevariablethatisahandletothefilenameoftheicon
wewanttodisplaywiththisentry.Now,wewillbegintoloopthrougheveryfile
inthecurrentdirectorytoseeifitisahiddenfileornotandtotageachfilename
aseitheradirectoryorafile.

FOREACHsFileINDir($sPath)

Gambasinitializesstringstonullwhencreated,sotheveryfirsttimewe
comehere,the$bHiddenvaluewillnotbeTRUEandtheIFstatementwillbe
executedinthecodebelow:

IFNOT$bHiddenTHEN

Thisnextlineofcodeisalittletrickertodecipher.TheStatfunctiontakes
afilenamestringasitsparameter. Inthiscase,thecurrentpathheldinglobal
variable $sPath is catenated with the work string sFile using the &/ symbol
combination. ThisisaspecialcatenationsymbolusedinGambasspecificallyto
catenate filenames. The Stat function is called with the catenated filename
passedasaparameterandsimultaneouslythe Stat.Hidden propertyischecked.
Ifthe Stat.Hidden propertyis set to aTRUE value,the CONTINUE statement
executes,forcingprogramflowtothenextiterationoftheFORloop.Thiswhole
processbasicallyforcestheprogramtoignoreanyhiddenfilesitencounters.

IFStat($sPath&/sFile).HiddenTHEN'isithidden?
CONTINUE'ifso,gotonextloopiteration
ENDIF'IFStat
ENDIF'IFNOT$bHidden

Ifwereachedthispointinthecode,thefilewasnothidden.Now,wewill
usethebuiltinfilemanagementfunctionIsDirtoseeifthecurrentpathandfile
string(catenatedintheStatcall)isafolderorafile.Ifwehaveafolder,wewill
addittothecDirstringarray,firsttaggingitwithaletter'D'fordirectoryor'F'for
fileandthenappendingthefilenameheldintheworkstringsFiletothe'D'or'F'
tag:

IFIsDir($sPath&/sFile)THEN'itwasadirectory
cDir.Add("D"&sFile)'weaddittothedirectorieskey
ELSE'notadirectoryandweaddittothe"F"keyasafile
cDir.Add("F"&sFile)
ENDIF
NEXT'thisistheendoftheFORloop...
OnceeverythingisloadedinthecDirarraywiththeFOR/NEXTloopwe
callthebuiltinSortmethodandsortthearrayofstrings:

153
A Beginner's Guide to Gambas

cDir.Sort

NowthatthecDirarrayissorted,wewillloopthroughthearrayusingthe
FOREACHstatementwhichisusedspecificallyforenumeratedobjectsinarrays
orcollections.

FOREACHsFileINcDir

ForeverystringinthecDir array,wewillfilltheworkstring sName with


thenameofthefile.However,wehavetoremovethetagfirst.Wewillusethe
Mid$builtinstringfunctiontotakeallthelettersofthestringafterthefirst(our
tag)startingatposition2inthestring:

sName=Mid$(sFile,2)

Now,wecheckthetagofthefilenameusingthestringfunctionLeft$:

IFLeft$(sFile)="D"THEN

If the 'D' tag is found, it is a directory and we add a directory to the


IconViewcontrol usingthe Addmethod andourpictureofafolderasthelast
parameterinthecall.

ivwExplorer.Add(sFile,sName,hPictDir)
ELSE'otherwiseitwasafileandweadditwithafileicon
ivwExplorer.Add(sFile,sName,hPictFile)
ENDIF

WealsowanttosettheIconView .EditpropertytoTRUEsotheusercan
renameitems:

ivwExplorer.Item.Editable=TRUE
NEXT'exittheFOREACHLoop

Thestatementsbelowwerecommentedoutbutappeartohavebeenused
toalterthesortorderofthe IconViewcontrol. Wewillsimplyskipoverthese
commentsandgototheFINALLYstatement:

'ivwExplorer.Sorted=FALSE
'ivwExplorer.Ascending=TRUE
'ivwExplorer.Sorted=TRUE

FINALLY'thisisthelastinstructiontoexecuteinthesubroutine

154
A Beginner's Guide to Gambas

ThelastthingweneedtodoissettheApplication.busyflagbacktonormalstate:

DECApplication.busy

Ifanerroroccurs,wewillcatchitwiththecatchclausebelow:

CATCH

Ifanyerroroccurs,itshouldpopupaMessageBoxwiththeerrortextdisplayed:

Message.Error(Error.Text)

END'ofourRefreshExplorerroutine

ThissubroutineiscallediftheFExplorerformisresizedgeneratingaresize
event.ItwillmoveourIconViewcontroltothetopleftcornerandadjustwidth
andheighttoaccommodatethenewsizeofthewindow:

PUBLICSUBForm_Resize()
ivwExplorer.Move(0,0,ME.ClientW,ME.ClientH)
END

Iftheuserchoosesthequitoptionfromthemenu,thenthisroutineexecutes:

PUBLICSUBmnuQuit_Click()
ME.Close
END

If the user selects the Refresh option, we will call the RefreshExplorer
subroutinedescribedpreviously.
PUBLICSUBmnuViewRefresh_Click()
RefreshExplorer
END

Thissubroutineiscalledwhentheactivateeventistriggeredbyauserby
doubleclickingonafolderintheIconViewcontrol:

PUBLICSUBivwExplorer_Activate()

Asalways,wemustdeclareourlocalvariables.WedeclaresNewPathasa
stringtoholdthefilepathforthetargetpaththeuserclicked(eitheranewfolder
ortherootfolder).Also,wedeclareanewformtoshowthedestinationcontents,
hForminaseparatewindowifthecontrolkeyispressedwhenthedestinationis

155
A Beginner's Guide to Gambas

selected.
DIMsNewPathASString
DIMhFormASForm

Thisifchecklooksatthetagweputonthestringtoseeifthedestinationis
adirectoryortherootlevelofthesystem. Ifweareattherootlevel,thenwe
simplyreturn.Otherwise,thecodewillassignthecatenatedvaluesof$sPathand
thevalueheldbytheLAST.Current.KeyoftheIconViewcontrol.Thisisobtained
withtheMid$callstartingatposition2(tobypassourtagcharacter).
IFLAST.Current.Key="D.."THEN
IF$sPath="/"THENRETURN
sNewPath=File.Dir($sPath)
ELSE
sNewPath=$sPath&/Mid$(LAST.Current.Key,2)
ENDIF

Wecheckthenewlyassignedstringvaluedatatypetoensureitis,infact,
adirectoryand,ifitis,wewillsubsequentlychecktoseeiftheuserhelddown
thecontrolkey. Remember,holdingdownthecontrolkeyinourprogramwill
activateanewwindow,whichiswhywedeclaredthelocalhFormvariable.
IFIsDir(sNewPath)THEN

Ifthecontrolkeywashelddown,wewilltogglethevaluebacktoFALSE
beforeinstantiatinganewwindow.Then,wewillmoveourcontroltobeoffset
16pixelsrightandbelowthecurrentwindow,havingthesameheightandwidth
using the hForm.Move method. Finally, we show the form and refresh the
ExplorerwithourRefreshExplorersubroutine.

IF$bCtrlTHEN
$bCtrl=FALSE
hForm=NEWFExplorer(sNewPath)
hForm.Move(ME.X+16,ME.Y+16,ME.W,ME.H)
hForm.Show
ELSE

Othewise, the control key was not held down so we simply assign the
sNewPathvaluetotheglobal$sPathandrefreshtheexplorer:
$sPath=sNewPath
RefreshExplorer
ENDIF
ENDIF

156
A Beginner's Guide to Gambas

END

When the user clicks this routine, it calls our subroutine to show the
hiddenfilesor,iftheyareshowing,turnoffviewingofhiddenfiles:

PUBLICSUBmnuViewHidden_Click()
ToggleViewHidden
END

Iftheuserchoosestoshowhiddenfilesintheexplorerbyselectingthe
ShowHiddenFilesoption,thenthisnextroutineisexecuted.Thefirstlinechecks
the value of the mnuViewHidden.Checked property and toggles the value by
essentially making $bHidden become whatever the logical NOT value of
mnuViewHidden.Checked is at the moment it is checked. It then assigns the
oppositevaluetothepropertyandrefreshestheviewbycallingRefreshExplorer.
Theresultisthatthehiddenfilesareshown.

PRIVATESUBToggleViewHidden()
$bHidden=NOTmnuViewHidden.Checked
mnuViewHidden.Checked=$bHidden
RefreshExplorer
END

This subroutine is executed when the menu's about item is clicked. It


simplydisplaysaMessageBoxcreditingthecodetoGambasfounder,B.Minisini:

PUBLICSUBmnuAbout_Click()
Message("IconViewexamplewrittenby\nBenotMinisini")
END

Thenextsubroutineisexecutedwhentheusersingleclicksonanitemin
theexplorerandoptstorenametheitem.Asitwasoriginallywritten,itdoesnot
checktoseeiftherenameactuallychangedtheitem. Forexample,iftheuser
pressedESC,theitemwouldreverttoitsoriginalname.
PUBLICSUBivwExplorer_Rename()

Message("'"&Mid$(LAST.Item.Key,2)&
"'hasbeenrenamedto'"&LAST.Item.Text&"'")
END

157
A Beginner's Guide to Gambas

Wecanremedythisoversightbysimplychangingthecodetoreadlikethis:

PUBLICSUBivwExplorer_Rename()
IFMid$(LAST.Item.Key,2)<>Last.Item.TextTHEN
Message("'"&Mid$(LAST.Item.Key,2)&
"'hasbeenrenamedto'"&LAST.Item.Text&"'")
ELSE
Message('&Mid$(LAST.Item.Key,2)&'wasleftunchanged.')
ENDIF
END

Thefinaltwosubroutinestoggletheglobalvariable$bCtrlwheneverthe
controlkeyispressedorreleased.
PUBLICSUBivwExplorer_KeyPress()
IFKey.ControlTHEN$bCtrl=TRUE
END

PUBLICSUBivwExplorer_KeyRelease()
IFKey.ControlTHEN$bCtrl=FALSE
END

Thereyouhaveit.EverythingyouneedtoknowaboutusingtheIconView
controlinacoolapplication.Next,wewilllookattheListViewcontrol.

ListViewControl

The ListView control inheritsControlandimplementsalistofselectable


textitemswithicons.ListViewitemsareindexedbyakey.Theydisplayastring
andanicon.Thiscontrolhasaninternalcursorusedforaccessingitsitems.You
mustusetheMovemethods(MoveAbove,MoveBelow,MoveCurrent,MoveFirst,
MoveLast,MoveNext MovePrevious,MoveTo)tomovetheinternalcursor,and
youneedtousetheItempropertytogetthetextoftheitemthecursorpointsat.
ThisclassiscreatableandthestandardGambaslanguagesyntaxis:

DIMhListViewASListView
hListView=NEWListView(ParentASContainer)

Theabovecodecreatesanew ListViewcontrol thatactslikeareadonly


array.Let'screateaprogramthatwillimplementtheListViewcontrol.Createa
newprojectnamedListViewthatisagraphicaluserinterfacetypeproject.When
theIDEappearsafteryougothroughtheprojectwizard,createsimpleformthat
lookslikethis:

158
A Beginner's Guide to Gambas

Figure55LayoutforourListViewexample.
From the left top of the picture, you have our ListView control named
ListView1, a Textbox named Textbox1, and the Insert Item button named
Button1. TherearetwoRadioButtons,namedRadioButton1andRadioButton2
and the Remove Itembutton named Button2. Atthe botton of the form isa
TextLabelnamedTextLabel1andtheQuitbuttonnamedButton3. Onceyou
havecreatedtheformandmadeitastartupclass,weneedtoaddthefollowing
codetothecodewindowtoseehowtoimplementaListViewcontrol:

'Gambasclassfile
sStatusasString

PUBLICSUBForm_Open()
DIMpicSquareASNEWPicture
DIMpicCircleASNEWPicture

picCircle.Load("circle.png")
picSquare.Load("square.png")
'ThiswilladdanitemtotheListViewwithastartingentry
ListView1.Add("ListItem1","ListItem1",picSquare)
TextLabel1.Text=ListView1.Item.Text
ListView1_Click
END

Whentheprogrambeginsandtheformisfirstdisplayed onscreen,the
routineaboveisexecuted.Wecreatetwolocalvariablesforouriconsthatwillbe
usedinthelistandloadthemintomemory.Next,weaddadefaultkeyanditem
tothelistusingtheListView1.Addmethod,specifyingthepicSquareicontobe
associatedwiththisitem.Don'tworryabouttheiconsfornowwewillcreate
themlast.Next,weneedtocreateaneventtorefreshthelistanytimeanitemis
addedoritisclickedonbytheuser.
PUBLICSUBListView1_Click()
ListView1.MoveCurrent
ListView1.Item.Selected=TRUE
TextLabel1.Text=ListView1.Item.Text&sStatus
END

159
A Beginner's Guide to Gambas

IntheListView1_Clicksubroutine,thefirstlineofcodemovestheinternal
cursor to the most current item and highlights it by setting the Item.Selected
property to TRUE in the second line. Finally, the third line updates our
TextLabel1.Textvaluewiththetextofthecurrent(ornewlyadded)selectionand
thecurrentstatus(heldinglobalvarsStatusASString)appended. Iftheuser
clicks on the Insert item button (we named it Button1), this next routine is
executed:
PUBLICSUBButton1_Click()

Declarealocalvariable,picToUse,forouricontobedisplayed:

DIMpicToUseASNEWPicture

Next, check which radioButton has been clicked. If the first button has been
clicked,wewillloadtheimageforsquare.png,otherwise,circle.pngisloaded.

IFTextbox1.Text<>NULLTHEN
IFRadioButton1.ValueTHEN
picToUse.Load("square.png")
ELSE
picToUse.Load("circle.png")
ENDIF

Getthecurrentitem(ordonothing)iftheListViewisempty:

ListView1.MoveCurrent()

Nowwewilladdanewentrywithakeyandnameinthetextbox:

ListView1.Add(Textbox1.Text,Textbox1.Text,picToUse)

Thisemptiesouttextbox:

TextBox1.Text=""
sStatus="current."'setstatustocurrent

This call to the ListView1_Click subroutine will update (refresh) our ListView
control:
ListView1_Click

Next,wemustensurethenewitemisinthevisibleareaofthecontrol:

160
A Beginner's Guide to Gambas

ListView1.Item.EnsureVisible
ENDIF
END

TheButton2_Clicksubroutineiscalledwhenevertheuserdecidestodelete
thecurrentlyselecteditemintheListViewcontrol.
PUBLICSUBButton2_Click()

Thisnextlineofcodegetsoutcursorlineduptothecurrentselection.The
MoveCurrentmethodmovestheinternalcursortothecurrentitem.Itreturnsa
TRUEvalueifthereisnocurrentitem,inwhichcasewewillsimplyreturnas
thereisnothingtodelete:
IFListView1.MoveCurrent()THENRETURN

Ifwereachedthispoint,wehavemovedthecursortoandneedtoremove
thecurrentcursoritem:
ListView1.Remove(ListView1.Item.Text)

CleanupourTextLabel1.Textdisplaywiththiscall:
TextLabel1.Text=""

Now,weneedtoupdatethecursorpositiontothenewcurrentitem(since
wearenowpointedatadeleteditem). Butfirst,weneedtocheckthe.Count
propertytoseeifwehavejustdeletedthelastiteminthelist. Ifthecountis
greaterthanzero,thenwehaveitemsleftinthelist.Otherwise,theIFstatement
willnotbetrueandthecodewillbebypassed:

IFListView1.Count>0THEN

ListView1.MoveCurrent

ListView1.Item.Selected=TRUE'Selectsthecurrentitem

sStatus=selected.

ListView1_Click'thiswillforceanupdate

ENDIF
END

If the user clicks their mouse on an item in the ListView control, this

161
A Beginner's Guide to Gambas

routineiscalled. WewillsimplyupdatetheTextLabel1.Textpropertywiththe
text of the item selected and refresh the ListView control by calling our
ListView1_Clicksubroutine.
PUBLICSUBListView1_Select()
TextLabel1.Text=ListView1.Item.Text
sStatus=selected.
ListView1_Click
END

IftheuserdoubleclickstheirmouseonanitemintheListViewcontrol,it
willraisethe Activateevent,indicatingtheuserhaspickedthisitemforsome
actiontooccur.Inthiscase,wewillsimplyupdatetheTextLabel1.Textproperty
withthetextoftheitemselected,appendedwiththewordactivated,andrefresh
theListViewcontrolbycallingourListView1_Clicksubroutine.
PUBLICSUBListView1_Activate()

TextLabel1.Text=ListView1.Item.Text&activated.

sStatus=activated.

ListView1_Click

END

IftheuserclickstheirmouseontheButton3(Quit)button,thisroutineis
called.Wewanttoexitcleanlysoweinvoketheclosemethodfortheformusing
theME.Closecall.
PUBLICSUBButton3_Click()
ME.Close
END

UsingtheGambasIconEditTool

Atthispoint,allthecodeiscreatedforourListViewexampleprogram.We
stillneedtocreatethecircle.pngandsquare.pngicons.WewillusetheGambas
IconEditor todothat. Tobringuptheiconeditor,wewillgototheProject
WindowintheIDE.IntheProjectTreeView,findtheDatafolderandrightclick
yourmouse.PicktheNewitemandtheImagesubMenuitem.Youwillseethis
dialogpopup:

162
A Beginner's Guide to Gambas

Figure56CreatinganewIconimageinGambas.

SimplytypesquareintheNamefieldandclickok.Now,theiconeditor
appears and you can create an icon. Use the rectangle option from the Icon
EditorToolBoxandcreateabluesquareandsaveitwiththediskshapedicon.

Figure57Oursquareicon
Figure59Ourcircleicon
image.
image.

Figure58Icon
EditorToolBox.

Repeatthisprocess,creatinganothericonnamedcircle.pngandsavethat
too.Thatisit!Yourprogramisreadytorun.TryitoutandseehowtheListView
controlworks.

TheTreeView
Control

TheTreeViewcontrolworksalmostidenticallytotheListViewcontrol.The
chiefdifferenceisthattheTreeViewsupportsnestedchildrenandallowsyouto
traversefromaninner(child)leveloutwardtotheparentofthechild,alltheway

163
A Beginner's Guide to Gambas

outtothetopofthetree. Thiscontroladdsafewmethodsspecificallyforthe
purposeofmanagingthetraversaloftheparent/childtrees.

TreeView, like all othercontrols,inheritsitsattributesfromtheControl


class. Thiscontrolimplementsatreeviewofselectabletextitemswithicons.
Treeviewitemsareindexedbyakey.Theydisplayastringandaniconforeach
item. Thiscontrolhasaninternalcursorusedforaccessingitsitems.Usethe
Move methods (Move, MoveAbove, MoveBack, MoveBelow, MoveChild,
MoveCurrent, MoveFirst, MoveLast, MoveNext, MoveParent, MovePrevious,
MoveTo)tomovetheinternalcursor,andtheItempropertytogettheitemit
pointsat.Thisclassiscreatable.ThestandardGambaslanguagesyntaxis:

DIMhTreeViewASTreeView

hTreeView=NEWTreeView(ParentASContainer)

ThecodeabovecreatesanewTreeViewcontrol.Thisclassactslikeareadonly
array:

DIMhTreeViewASTreeView

DIMhTreeViewItemAS.TreeViewItem

hTreeViewItem=hTreeView[KeyASString]

The line of code above will returns a TreeView item from its key. The
internal cursorismoved tothecurrentitem. Now,let'suse another example
programfromtheGambasIDE.StartGambasandselecttheExamples|Basic|
TreeViewsampleprogram. WhentheIDEopensup,youshouldseesomething
similartoFigure60onthefollowingpage.

Figure60TheTreeViewProject
window.

164
A Beginner's Guide to Gambas

Next,doubleclickontheTreeViewExampleformandbringuptheform.
Doubleclickontheformtoopenupthecodeeditwindowandyouwillseethe
followinglisting,whichwewilldissectlinebylinetounderstandhowitworks:

'Gambasclassfile
PUBLICintEventNumberASInteger

TheglobalvariableintEventNumber isusedtotrackthenumberofevents
thatoccurforoureventstack.Eachtimeweprocessanevent,wewillincrement
thisvariable.WedeclaretwolocalPicturevariables,picMaleandpicFemaleand
loadthemintomemoryfortheprogrambyusingthePicture.Loadmethod.

PUBLICSUBForm_Open()
DIMpicMaleASNEWPicture
DIMpicFemaleASNEWPicture

picFemale.Load("Female.png")
picMale.Load("Male.png")

'ThiswillpopulateourTreeViewwithourstartingentries
'Note:I'llkeeptheentriestextanditskeythesametokeep
'itsimple

Next,wewilladdthestartingvaluesofourTreeViewcontrol.Wewilladd
fouritemstothecontrol.Eachitemkeywillbethesameastheitemname.The
itemsTedandSallywillbechildrenofitemBill,whileitemFrankwillbeachild
ofSally.
TreeView1.Add("Bill","Bill",picMale)
TreeView1.Add("Ted","Ted",picMale,"Bill")
TreeView1.Add("Sally","Sally",picFemale,"Bill")
TreeView1.Add("Frank","Frank",picMale,"Sally")

After adding theitems,we willmovethecursortothe lastitemadded


using the TreeView1.MoveCurrent method and highlight it by setting the
TreeView1.Item.Selected property to TRUE. Finally, we set the
TreeView1.Item.Expanded property to TRUE to allow the item to collapse or
expandwhentheuserclicksontheplus/minusicon. (NOTE:the GambasWiki
documentationforthispropertylistsitasExpand,notExpanded.UsingExpandwill
NOTwork.)
TreeView1.MoveCurrent
TreeView1.Item.Selected=TRUE

165
A Beginner's Guide to Gambas

TreeView1.Item.Expanded=TRUE
END

IftheuserclicksonanitemintheTreeView,wewanttorecordtheClick
eventinoureventstackandupdatethestackdisplay(TextArea1.Text).Wethen
incrementtheeventnumberbyone.NotethatinupdatingtheTextArea1.Text
value, we simply take the new event and append everything else in the
TextArea1.Textmemoryafterthelinefeedcharacter, Chr(10). Theneteffectof
thiscallinaninsertionoftheneweventatthetopofthedisplayedtext.

PUBLICSUBTreeView1_Click()
'Thisjustupdatesoureventstack
TextArea1.Text="Event("&intEventNumber&"):Click"&Chr(10)&
TextArea1.Text
intEventNumber=intEventNumber+1

Next, we find out whether the item clicked is a parent (determined by


whetherornotithaschildren).Ifthenumberofchildrenisgreaterthanone,we
wantourlabel(TextLabel1.Text)tousethepluralformofchild.Ifthereisonly
onechild,ourlabelwillsaychildandiftherearenone,wewantittosaytheitem
hasnochildren.WeusetheIFTHEN/ELSEstatementtomakethischeck:
'Thislittlecheckjustupdatesourlabelsothatweknowhowmany
'childrenanentryhas.
IFTreeView1.item.Children>1THEN
textlabel1.Text=(TreeView1.Item.Text&"has"&
TreeView1.Item.Children&"children.")
ELSEIFTreeView1.item.Children=0THEN
textlabel1.Text=(TreeView1.Item.Text&"hasnochildren.")
ELSE
textlabel1.Text=(TreeView1.Item.Text&"has1child.")
ENDIF
END

Iftheuserentersdatainthe Textboxcontrol andclickstheInsertName


button(Button1),thefollowingclickeventisexecuted.Itfirstdeclarestwolocal
variables. ThepicToUsevariablewilldeterminewhichpicturetoloadbasedon
whichRadioButtonwasclickedatthetimetheInsertNamebuttonwasclicked.
Thestringvariable,sParent,isassignedthevalueofthecurrentitem'skey.Ifthe
MoveCurrentmethod triestomovetheinternalcursortothecurrentitemand
thereisnoitem,itreturnsTRUE. Otherwise,FALSEwillbereturnedandwe
assignthesParentstringthevalueofthekeythatiscurrent.
PUBLICSUBButton1_Click()
DIMpicToUseASNEWPicture

166
A Beginner's Guide to Gambas

DIMsParentASString

IFTextbox1.Text<>NULLTHEN
IFRadioButton1.ValueTHEN
picToUse.Load("Male.png")
ELSE
picToUse.Load("Female.png")
ENDIF
'Getstheparentitem:thecurrentitem,ornothingistheTreeView
'isvoid

IFNOTTreeView1.MoveCurrent()THEN
sParent=TreeView1.Key
ENDIF
Now,weneedtoaddthenewentrywithakeyandanameofwhatwasin
thetextbox.WewillplaceitintheTreeViewcontrolasachildofthecurrently
selected entry. Note that the key names must be unique or it will crash the
program.WecouldusetheExistmethodtofindoutifakeyexistswiththename
Textbox1.TextbeforemakingthecalltotheAddmethod,butthatwasnotdone
here.Ifwedidthat,thecodewouldmakeachecksimilartothis:

IFExist(Textbox1.Text)<>TRUETHEN
TreeView1.Add(Textbox1.Text,Textbox1.Text,picToUse,sParent)
ENDIF

However,thecodeintheprogramsimplyforcesthe Addmethod totake


theTextbox1.Textandputitinthelist:
TreeView1.Add(Textbox1.Text,Textbox1.Text,picToUse,sParent)
TextBox1.Text=""'Thisemptiesouttextbox

Thisnextlinewillupdateourlabelandreflectthenewnumberofkids:

TreeView1_Click

ThiscalltoEnsureVisiblewillmakesurethattheitemwejustaddedtothe
listisinthevisibleareaofthecontrol.Ifnecessary,thecontrolwillscrollsothe
itemisvisible.

TreeView1.Item.EnsureVisible
ENDIF
END

If the user wantsto remove a name fromthe TreeView by clicking the


RemoveNamebutton(Button2)thenthissubroutineisexecuted:

167
A Beginner's Guide to Gambas

PUBLICSUBButton2_Click()

Firstofall,wemustgetthecursorlineduptoourcurrentselectionand
makesurethatthecurrentitemisn'tanemptyornullvalue.IftheMoveCurrent
method returns a true value, the list was empty and we are done. The code
invokestheRETURNcallandwejumpbacktothecallingprocess. Otherwise,
whateverthecurrentitemiswillberemovedbycallingtheRemovemethodinthe
secondline,below:

IFTreeView1.MoveCurrent()THENRETURN
'Letsremovethecurrentcursoritem

TreeView1.Remove(TreeView1.Item.Text)

Now we must move the cursor to the current item (since we are now
pointing at a deleted item). Before we do that we need to check the count
propertytomakesurewedidn'tdeletethelastiteminthelist.Ifwedid,thenwe
obviouslydon'trunthispartofthecode. The IFstatement checksforacount
greaterthanzeroand,ifTRUE, willmovetothecurrentitem,selectitsothe
cursorishighlighted,andupdatethecontrolwithacalltotheTreeView1_Click
subroutine.

IFTreeView1.Count>0THEN
TreeView1.MoveCurrent

'Thisselectsor'highlights'ourcurrentitem
TreeView1.Item.Selected=TRUE

'Thiswillupdateourlabelandreflectthenewnumberofkids
TreeView1_Click
ENDIF
END

Iftheuserclicksontheminusiconinthe TreeViewcontrol,itsetsoffa
Collapseevent.Theroutinebelowiscalled.Itsimplyupdatestheeventstack,as
describedpreviously,andincrementstheeventcounter,intEventNumber,byone.
PUBLICSUBTreeView1_Collapse()
'Thisjustupdatesoureventstack
TextArea1.Text="Event("&intEventNumber&"):Collapse"&Chr(10)
&TextArea1.Text
intEventNumber=intEventNumber+1
END

168
A Beginner's Guide to Gambas

Iftheuserdoubleclicksonaniteminthe TreeViewcontrol,itsetsoffa
Dbl_Clickevent.ItisbasicallythesameasanActivateevent.Theroutinebelow
is called. It simply updates the event stack, as described previously, and
incrementstheeventcounter,intEventNumber,byone.
PUBLICSUBTreeView1_DblClick()
'Thisjustupdatesoureventstack
TextArea1.Text="Event("&intEventNumber&"):DoubleClick"&Chr
(10)&TextArea1.Text
intEventNumber=intEventNumber+1
END

PUBLICSUBTreeView1_Select()
'Thisjustupdatesoureventstack
TextArea1.Text="Event("&intEventNumber&"):Select"&Chr(10)&
TextArea1.Text
intEventNumber=intEventNumber+1
END

This next routine is dead code. It never gets executed because the
Button2_Click subroutine takes care of the removal of an item. To use it
effectively,itshouldbecalledfromtheButton2_Clicksubroutinejustbeforethe
linecallingtheTreeView1_Clicksubroutine.Ifthisisdone,thentheeventstack
wouldbeproperlyupdated,firstwiththedeleteandthentheclickevents.

PUBLICSUBTreeView1_Delete()
'Thisjustupdatesoureventstack
TextArea1.Text="Event("&intEventNumber&"):Delete"&Chr(10)&
TextArea1.Text
intEventNumber=intEventNumber+1
END

Iftheuserclicksontheplusiconinthe TreeViewcontrol,itsetsoffan
Expandevent.Theroutinebelowiscalled.Itsimplyupdatestheeventstack,as
describedpreviously,andincrementstheeventcounter,intEventNumber,byone.
PUBLICSUBTreeView1_Expand()
'Thisjustupdatesoureventstack
TextArea1.Text="Event("&intEventNumber&"):Expand"&Chr(10)&
TextArea1.Text
intEventNumber=intEventNumber+1
END

PUBLICSUBButton3_Click()

169
A Beginner's Guide to Gambas

TextArea1.Text=""
'IntEventNumber=0
END

TheHelp | Aboutmenuitemgeneratesaclickeventthatcallsthisnext
subroutine.Itsimplygivescredittotheauthorofthisexample,C.Packard.

PUBLICSUBAbout_Click()
Message.Info("TreeViewexamplewrittenbyC.Packard."&Chr(10)&
"Aug2004")
END

Iftheuserdoubleclicksonaniteminthe TreeViewcontrol,itsetsoffa
Activateevent.ItisbasicallythesameasaDblClickevent.Theroutinebelowis
called.Itsimplyupdatestheeventstack,asdescribedpreviously,andincrements
theeventcounter,intEventNumber,byone.
PUBLICSUBTreeView1_Activate()
'Thisjustupdatesoureventstack
TextArea1.Text="Event("&intEventNumber&"):Activate"&Chr(10)
&TextArea1.Text
intEventNumber=intEventNumber+1
END

Thisnextroutineisalsodeadcode. Itnevergetsexecutedbecausethe
nothingcreatesaneventtogethere.Touseiteffectively,amenuitem,Rename
should be added to the Help menu and it should be called from the
MenuItem.Clickevent.Ifthisisdone,thentheeventwouldbegeneratedandyou
couldwriteabitofcodetogetthenewnamefromtheuserandchangeit.The
eventstackwouldbeproperlyupdated,firstwiththerenameeventandthenwith
theclickevent.
PUBLICSUBTreeView1_Rename()
'Thisjustupdatesoureventstack
TextArea1.Text="Event("&intEventNumber&"):Rename"&Chr(10)&
TextArea1.Text
intEventNumber=intEventNumber+1
END

ThatisallthereistotheTreeViewprogram.Youcanplayaroundwiththe
code and implement the suggestions made herein. Once you are able to
understand how to use these controls effectively, your Gambas interfaces will
becomemoresophisticated. Next,wewilltakealookatthelasttwoadvanced
viewcontrols,theGridViewandColumnViewcontrols.

170
A Beginner's Guide to Gambas

TheGridViewControl

TheGridViewcontrol,likealltheothercontrolsintheToolBox,inheritsits
attributesfromtheControlclass. GridViewimplementsacontrolthatdisplays
data in a grid. This class is creatable. Standard Gambas language syntax for
GridViewis:

DIMhGridViewASGridView
hGridView=NEWGridView(ParentASContainer)

ThecodeabovewillcreateanewGridView.Thisclassactslikeareadonly
array. Toretrievethecontentsofacellinthegrid,usethiscodetodeclarea
GridCellvariablethatcanreadtheGridViewarray(theGridCellisavirtualclass):

DIMhGridViewASGridView
DIMhGridCellAS.GridCell

hGridCell=hGridView[RowASInteger,ColumnASInteger]

Thelineabovereturnsacellfromitsrowanditscolumn. Ourexample
programforthiscontrolwillcreateagridthatisfourrowsofthreecolumns.We
willpopulatethefirstthreerowswithtextandthelastrowwithpictures.Wewill
takethelastrowoftextanddemonstratehowthealignmentpropertyworksfor
textdata.Ourprogramwillhavethreebuttons,Quit,Clear,andReset.

The Quit button will simply close the program. Clear will invoke the
GridView.Clearmethodtoerasethecontentsofthegridanddisplayemptygrid
cells.TheResetbuttonwillrepopulatethecontentsofthegridwiththedatathe
program started with (i.e., the data populated when the form's constructor
methodwascalled.Ourprogramwilllooklikethis:

171
A Beginner's Guide to Gambas

Figure61WhatourGridViewwilllooklike.
To begin, start Gambas and select the New Project option, choosing to
createaGraphicalUserInterfaceproject.Maketheprojecttranslatableandform
controls public by checking the two boxes in the Wizard. Name the project
GridViewExampleandputitintheGridViewdirectory.WhentheIDEappears,
wewillneedtogototheprojectwindowandbringuptheICONEditor.Wewill
createthreeicons,namedGridPic,GridPic1,andGridPic2,asshownabove.Try
togetthemreasonablyclosetowhatyouseeinthepictureaboveifyoucan.
Create a new formthat is a startup class form and put the GridView control,
namedGridView1 on the formasshown above. Thenadd thethreebuttons,
named Button1, Button2, and Button3 to the form. Make the Button.Text
propertiesreflectwhatisshowninthepictureabove.

Now,wehavetheformdesignedanditlookslikewhatweexpect. Lets
startcoding.Doubleclickontheform,butnotonacontrol,andtheForm_Open
subroutine will display in the code window. We will set the caption to your
programhere:

'Gambasclassfile

PUBLICSUBForm_Open()
Form1.Caption="GridViewExample"
END

Whentheprogramstarts,ifaconstructorexists,itisexecutedfirst. Our
constructorwillloadourthreeiconsandpopulatethegrid. First,declarethree
localvariablesforthepictures,hPic1,hPic2,andhPic3,asshownbelow:
PUBLICSUB_new()
DIMhPic1ASPicture
DIMhPic2ASPicture
DIMhPic3ASPicture

172
A Beginner's Guide to Gambas

Now,wemustinstantiatethepicturevariablesandloadthepictures.
hPic1=NEWPicture
hPic1.Load("GridPic.png")

hPic2=NEWPicture
hPic2.Load("GridPic2.png")

hPic3=NEWPicture
hPic3.Load("GridPic1.png")

Thenextthingweneedtodoisdefinethedimensionsofthegrid. Our
gridwillhavethreecolumnsandfourrows,sowesettheColumnsandRows
propertiesusingtheirvirtualclassgridcolumnandgridrowproperty,counttoset
therowsandcolumnsasshownbelow:

GridView1.Columns.Count=3
GridView1.Rows.Count=4

Wecanalsodefinethewidthandheightdimensionsofthegridcolumns
androws.Bearinmindthatitispossibletosetdifferentheightvaluesforevery
rowanddifferentwidthvaluesforeverycolumn. WewillsetthetheWandH
propertiesforourrowsandcolumnsasshownbelow:
GridView1.Columns.Width=72
GridView1.Rows.Height=36

Next, we will populate the grid with some data, simply identifying the
row,columnpositionwithtext:

GridView1[0,0].Text="0,0"
GridView1[0,1].Text="0,1"
GridView1[0,2].Text="0,2"

GridView1[1,0].Text="1,0"
GridView1[1,1].Text="1,1"
GridView1[1,2].Text="1,2"

Forthelasttextrow,wewanttodemonstratehowtousetheAlignmentproperty:

GridView1[2,0].Alignment=Align.Center
GridView1[2,1].Alignment=Align.BottomLeft
GridView1[2,2].Alignment=Align.TopRight

Aftersettingthealignmentpropertiesforeachcellintherow,wewilladdtext:

173
A Beginner's Guide to Gambas

GridView1[2,0].Text="2,0"
GridView1[2,1].Text="2,1"
GridView1[2,2].Text="1,2"

Finally,wewilladdourthreeiconstothegrid:

GridView1[3,0].Picture=hPic1
GridView1[3,1].Picture=hPic2
GridView1[3,2].Picture=hPic3
END

Theconstructoriscomplete.Now,doubleclickontheQuitButtontoget
theButton1_Clickeventsubroutine,wherewewilladdourMe.Closecalltoshut
downtheprogram:
PUBLICSUBButton1_Click()
ME.Close
END

The Clear button is next. Doubleclick on the Clear Button to get the
Button2_Clickeventsubroutine,wherewewilladdourcodetoresetthegridto
blankvalues:
PUBLICSUBButton2_Click()
GridView1.Clear
END

Theeasiestwaytorepopulatethedataistosimplyinvoketheconstructor
onceagain.Addthiscodesothatiswhatwewilldo.
PUBLICSUBButton3_Click()
_new
END

Ourprogramiscomplete. Runitandseehowitworks. Afteryou are


satisfiedthatitworksasadvertised,closeitdownandnextlet'slearnaboutthe
ColumnViewcontrolnext.

174
A Beginner's Guide to Gambas

TheColumnViewControl

Forournextexample,wearegoingtocreateaprogramthatdisplaysdata
inaColumnView,asshownbelow:

Figure62OurColumnViewexample.

Our simple example will create three columns and five rows. We will
populatethecolumndatawiththerow,columnidoftheparticularitem.Todo
this,wewillneedtosetthewidthofeachcolumntobedynamicallycalculated
basedonthewidthofthecontrolandthenumberofcolumnsspecified.Wewill
dothisintheconstructor.Whentheprogramstartsup,allwearegoingtodo
ontheForm_Opencallissetthewindowcaption,asshownintheForm_Open()
subroutine:
'Gambasclassfile
PUBLICSUBForm_Open()
Form1.Caption="ColumnViewExample"
END

Theconstructormethodiswherealltheworktopopulatethecontrolis
done.Weneedtodeclarethreelocalintegervariables,iwidthtoholdthevalueof
thecalculatedcolumnwidth,irowcounterandicolcounter,whichareusedforour
loopstructures.
PUBLICSUB_new()
'declareourlocalvars
DIMiwidthASInteger
DIMirowcounterASInteger
DIMicolcounterASInteger

'setthenumberofcolumnsto3
ColumnView1.Columns.Count=3
'calculatethecolumnwidthbasedonthenumberofcolumnsset
iwidth=ColumnView1.Width/ColumnView1.Columns.Count

175
A Beginner's Guide to Gambas

'forthefirstcolumn,setthecolumnwidthandaddacolumntitle
ColumnView1.Columns[0].Width=iwidth
ColumnView1.Columns[0].Text="FirstCol"
'forthesecondcolumn,setthecolumnwidthandaddacolumntitle
ColumnView1.Columns[1].Width=iwidth
ColumnView1.Columns[1].Text="SecondCol"
'forthethirdcolumn,setthecolumnwidthandaddacolumntitle
ColumnView1.Columns[2].Width=iwidth
ColumnView1.Columns[2].Text="ThirdCol"

Now, we need to set up the outer (row) and inner (column) loops.
Basically,wewillloopthrougheveryeveryrowinthecontroland,ateachrow,
wewillloopthrougheachcolumn,populatingtheColumnView1[row][column]
arrayitemswithadynamicallybuiltstringoftextthatwillrepresentthecurrent
positionwithintheinnerandouterloop.

FORirowcounter=0TO4'forallfiveofourrows
'calltheAddmethodwith[row][col]toaddtoColumnView1control
ColumnView1.Add(irowcounter,icolcounter)'startouter(row)loop
FORicolcounter=0TOColumnView1.Columns.Count1
'addtexttothe[row][col]item
ColumnView1[irowcounter][icolcounter]="Col:"&icolcounter&"
Row:"&irowcounter
NEXT'column
NEXT'row
END'ourconstructor

TheQuitButtonhereworksjustlikeinthepreviousexample.Togetthe
Button1_Clickeventsubroutine,doubleclickandaddtheMe.Closecalltoshut
downtheprogram:
PUBLICSUBButton1_Click()
ME.Close
END

The Clear button is next. Doubleclick on the Clear Button to get the
Button2_Clickeventsubroutine,wherewewilladdourcodetoresetthegridto
blankvalues:
PUBLICSUBButton2_Click()
ColumnView1.Clear
END

ForourResetbutton,theeasiestwaytorepopulatethedataistosimply
invoketheconstructoronceagain.Addthiscodesothatiswhatwewilldo.

176
A Beginner's Guide to Gambas

PUBLICSUBButton3_Click()
_new
END

ThatisallthereistobuildingandpopulatingtheColumnViewcontrol.Next,we
willtakealookathowtousethevariouslayoutcontrolsinGambas.

LayoutControlsHBox,VBox,HPanelandVpanel

All of the controls in this group are similar in that they try to arrange
controls they contain automatically. They do so by using the .Arrangement
property which relies upon constants that are defined in the Arrange class.
ConstantsusedbytheArrangementpropertyofthesecontainercontrolsinclude
thefollowing:Fill,Horizontal,LeftRight,None,TopBottom,andVertical.If
youdonotspecifyan.Arrangementpropertyvalue,thenthecontroldefaultsto
whatever it is designed to do, i.e., HBox would arrange controls horizontally,
VBoxvertically,etc.

HBoxandVBox

Both of these classes are containers that arrange their children either
horizontally or vertically. Like all other ToolBox controls, they inherit their
attributesfromtheContainerclass.BothofthesecontrolsactlikeaPanelwithout
aborderwhoseArrangementpropertywouldbesettoArrange.Horizontal.These
classesarecreatable.StandardGambaslanguagesyntaxtocreateanewHboxis:

DIMhHBoxASHBox
DIMhVBoxASVBox
hHBox=NEWHBox(ParentASContainer)
hVBox=NEWVBox(ParentASContainer)

HPanelandVpanel

Bothoftheseclassesarecontainersthatarrangestheirchildrenfromtopto
bottom,andthenlefttorightfortheHpanelandlefttoright,toptobottomfor
theVPanel. Theyarebothlikeanordinary Panelcontrol withoutaborderbut
whose Arrangement property would be set to Arrange.TopBottom ( where a
containerstacksitschildrenfromtoptobottom;ifthechildrencontrolscan'tfit
vertically,anewcolumnofcontrolsisstartedjustafterthepreviouscolumn)or
Arrange.LeftRight (whereacontainerstacksitschildrenfromlefttoright;ifthe
childrencontrolscan'tfithorizontally,anewrowofcontrolsisstartedbelowthe

177
A Beginner's Guide to Gambas

previous row). Both these types of controls inherit their attributes from the
Containerclass.Thisclassiscreatable.StandardGambaslanguagesyntaxis:

DIMhHPanelASHPanel
DIMhVPanelASVPanel
hHPanel=NEWHPanel(ParentASContainer)
hVPanel=NEWVPanel(ParentASContainer)

Let'screateasimpleprogramthatwilldemonstrateeachofthese layout
controlsandshowhowtheycanbeusedinanapplication.Forthisapplication,
startGambasandcreateagraphicaluserinterfaceprogram.NameitLayoutsand
createastartupclassform,Form1.Forthisapplication,wewillneedtousesome
icons.MostLinuxbaseddistributionshaveiconfilesstoredinthefoldernamed:

file:/usr/share/icons/defaultkde/32x32/actions

Yoursystemmaybedifferent.Regardlessofwhereyoufindthem,pickoutseven
iconsandcopythemtotheLayoutfolder. Forourpurposes,anysevenwilldo
butifyoucanfindundo,redo,help,configure,colorize,printer,andexittype
iconsitwillbeeasier.HerearetheiconsIchosetouseforthisproject:

Figure63Layoutprojecticons.

Ourprogramisquitesimple.WearegoingtocreateanHBox,aVBox,an
HPanel,andaVPanelandputsomesimplecontrolsineachcontainer. Wewill
simplyupdateatextlabeltoshowwhensomethinghasbeenclicked.Hereishow
ourformwilllookindesignmode:

178
A Beginner's Guide to Gambas

Figure64Form1designmodeshowinglayoutofourcontrols.

Fromthetopleftofthefigureabove,westartwithaVBoxandaTextLabel.
BelowtheTextLabelistheHBox. Whenyoucreatethesecontrols,Gambaswill
suggestdefaultnamesforeachcontrol.Takethedefaultnamesforeachcontrol
becauseourprogramusesthosedefaults. PlacethreeToolButtonsintheVBox
and four ToolButtons in the HBox. Next, set the picture properties of each
ToolButtontotheiconsyouchosetouse(hopefullythesameasthoseabove)for
ourproject. Onceyouhavetheiconsdisplayed,weneedtostartwiththefirst
ToolButtonintheVBoxanddoubleclicktobringupthecodewindow.Youwill
needtodothisforeachoftheseveniconsandaddcodeasfollows:

'Gambasclassfile
PUBLICSUBToolButton1_Click()
TextLabel1.Text="VertUndoclicked."
END

PUBLICSUBToolButton2_Click()
TextLabel1.Text="VertRedoclicked."
END

PUBLICSUBToolButton3_Click()
TextLabel1.Text="VertHelpclicked."

179
A Beginner's Guide to Gambas

END

PUBLICSUBToolButton4_Click()
TextLabel1.Text="HorizConfigureBtnclicked."
END

PUBLICSUBToolButton5_Click()
TextLabel1.Text="HorizColorButtonclicked."
END

PUBLICSUBToolButton6_Click()
TextLabel1.Text="HorizPrinterBtnclicked."
END

PUBLICSUBToolButton7_Click()
TextLabel1.Text="HorizExitButtonclicked."
WAIT0.5
ME.Close
END

ThenextcontrolcontainerwewillcreateistheHPanel,asshowninthe
figureabove. WewilladdfourRadioButtonsandthreeregularbuttonstothis
containercontrol.Trytoarrangethebuttonsasshowninthefigure.Youwillsee
why this is important once you run the program and see how the HPanel
rearrangesthecontrols.Onceagain,doubleclickoneachradiobuttonandadd
thefollowingcode:

PUBLICSUBRadioButton1_Click()
TextLabel1.Text="RadioBtn1clicked."
END

PUBLICSUBRadioButton2_Click()
TextLabel1.Text="RadioBtn2clicked."
END

PUBLICSUBRadioButton3_Click()
TextLabel1.Text="RadioButton3clicked."
END

PUBLICSUBRadioButton4_Click()
TextLabel1.Text="RadioButton4clicked."
END

180
A Beginner's Guide to Gambas

PUBLICSUBButton1_Click()
TextLabel1.Text="Button1clicked."
END

PUBLICSUBButton2_Click()
TextLabel1.Text="Button2clicked."
END

PUBLICSUBButton3_Click()
TextLabel1.Text="Button3clicked."
END

The last thing we will do is create the VPanel with three CheckBoxes.
RemembertoarrangetheCheckBoxesinyourformlikethoseinthepictureabove
toseehowthecontrolrearrangesthemautomatically. Addthiscodewhenyou
haveplacedtheCheckBoxesintheVPanel:

PUBLICSUBCheckBox1_Click()
IFCheckBox1.Value=TRUETHEN
TextLabel1.Text="Checkbox1checked."
ELSE
TextLabel1.Text="Checkbox1unchecked."
ENDIF
END

PUBLICSUBCheckBox2_Click()
IFCheckBox2.Value=TRUETHEN
TextLabel1.Text="Checkbox2checked."
ELSE
TextLabel1.Text="Checkbox2unchecked."
ENDIF
END

PUBLICSUBCheckBox3_Click()
IFCheckBox3.Value=TRUETHEN
TextLabel1.Text="Checkbox3checked."
ELSE
TextLabel1.Text="Checkbox3unchecked."
ENDIF
END

Nowsaveyourworkand executethissimpleprogram. Youshouldsee


somethingsimilartothis:

181
A Beginner's Guide to Gambas

Figure65Layoutprogramwhenitstartsup.

NoticehowtheRadioButtonsintheHPanelhavealignedverticallyfrom
RadioButton4toRadioButton1and,becausetherewasroom,itplacedthebutton
controlstotherightandcontinuedthealignmentfromtoptobottom,lefttoright.
For the VPanel, see how the CheckBoxes aligned themselves. These types of
controlsareunpredictableinhowtheywilllayouttheirchildren.Itisbesttouse
theseincodedynamicallywhenyouhavetocreateformsontheflyanddonot
havetheopportunitytolaythemoutinafixedpanelindesignmode.

TheVBoxandHBoxcontrolsholdtheToolButtonsandallowyoutocreate
nifty little toolbars that work well with iconic driven controls, such as those
depictedwithouricons. Onceyouhavefinishedplayingaroundwithourlittle
application,closetheprogramandwewillmoveontolearnaboutTabStrips.

TheTabStripControl

TheGambasTabStripcontrolimplementsatabbedcontainercontrol.Like
all controls, it inherits its attributes from the Container class. This class is
creatable.Thisclassactslikeareadonlyarray.ThestandardGambaslanguage
syntaxis:

DIMhTabStripASTabStrip
hTabStrip=NEWTabStrip(ParentASContainer)

DIMhTabAS.Tab
hTab=hTabStrip[IndexASInteger]

Invoking the code above will return a virtual tab object from its index.
TabStripsareusefulfororganizingandpresentinginformationinselfcontained
units.TabStripsallowyoutoobtaininputfromusersbypresentingasimple,easy
tofollowinterfacethatcanliterallyguidethemthroughaconfigurationorsetup

182
A Beginner's Guide to Gambas

process.HereisasampleofaTabStripinuse:

Figure66ATabStripcontrol.

TodemonstratehoweasyTabStripsaretocreate,wewillbuildasmall
applicationthatimplementsthetabbedinterfaceyouseeabove.Ourapplication
thatwillshowyouhowtousetabbedcontrolstopresentinformationtoauser
andrespondtoitinyourapplications.StartGambasandcreateanewgraphical
userinterfaceprogram.NametheprojectTabs,clickthroughtheProjectCreation
WizardandwhenyougettotheGambasIDE,makeanewform,Form1thatisa
startupclass. Next,youwillneedtoplacea TabStripcontrol onthenewform.
OnceyouplacetheTabStrip,youwillonlyseeonetabdisplayed.Youmustgoto
thepropertieswindowandsettheCountpropertyto5tohavethecontrollook
liketheoneweshowabove.NotethattabnumberingstartsatzeroinGambas.
Eachtabactslikeacontainerforthecontrolsyouplaceonit.Wewillalsoneed
toaddaTextLabelandabuttontoourform.TheTextLabelwillbeusedtoshow
theuseractionsinresponsetoourtabbedinterface. ThebuttonwillbeaQuit
buttonwhichwewillusetoterminatetheapplication. Hereiswhatyourform
shouldlooklikeasyoustarttodesigntheinterface:

Figure67TabProjectForm1.formDesign.

183
A Beginner's Guide to Gambas

Youwillalsoneed tocopy theconfigure,help,and exit iconsfromthe


LayoutprojecttotheTabsfoldersowecanusethemwiththisproject.Gambasis
designtocontainallprojectworkfromtheIDEtothefolderyoucreatewhenyou
startaproject. Asaresult,youneedtomoveoutoftheIDEtocopyfilesfrom
anotherfoldertothecurrentproject(aquirkbydesign,perhaps?).Anyway,let's
get going on this project. For Tab0 we will add a frame and place two
RadioButtonsinit,likethis:

Figure68Tab0layout.

Next,doubleclickoneachRadioButtonandenterthiscode:

PUBLICSUBRadioButton1_Click()
TextLabel1.Text="Youhaveclicked:<br><center><strong>RadioButton1"
END

PUBLICSUBRadioButton2_Click()
TextLabel1.Text="Youhaveclicked:<br><center><strong>RadioButton2"
END

HereiswhatwewilldoforTab1:

Figure69Tab1layout.

DoubleclickoneachCheckBoxandenterthiscode:

PUBLICSUBCheckBox1_Click()
IFCheckBox1.Value=TRUETHEN
TextLabel1.Text="Youhavechecked:<br><center><strong>CheckBox1"

184
A Beginner's Guide to Gambas

ELSE
TextLabel1.Text="Youhaveunchecked:<br><center><strong>CheckBox1"
ENDIF
END

PUBLICSUBCheckBox2_Click()
IFCheckBox2.Value=TRUETHEN
TextLabel1.Text="Youhavechecked:<br><center><strong>CheckBox2"
ELSE
TextLabel1.Text="Youhaveunchecked:<br><center><strong>CheckBox2"
ENDIF
END

Thecodeabovewilldeterminewhethertheuserischeckinganitemor
uncheckingitbyfirstlookingattheValueproperty.IfitisTRUE,thentheboxis
already checked and we will indicate that fact in the update of the
TextLabel1.Text.Otherwise,itisbeinguncheckedandwewillupdatethelabelto
statethatfact.

ForTab2,wearegoingtoplaceaPanelcontrolontheTabandaddthree
ToolButtons. DonotmakethemistakeofplacingoneToolButtonandtryingto
copyitandmovethecopyintothepanel.Itwillnotberecognizedasachildof
thepanel control. Itwill appearonalltabs(I believethisis another quirkof
Gambas). Inorderforthe Panelcontrol toaccepttheToolButtonsaschildren,
youmustindividuallyclicktheToolButtonontheToolBoxandcreateeachone
justasyoudidwiththefirstToolButton.ForeachToolButton,assignthepicture
propertythenameoftheiconweareusingforthatbutton,asshownhere:

Figure70Tab2ToolButtonlayoutwith
icons.

ThenextstepistodoubleclickoneachToolButtonandaddthiscode:

PUBLICSUBToolButton1_Click()
TextLabel1.Text="Youclicked:<br><center>the<strong>ConfigureIcon"
END

185
A Beginner's Guide to Gambas

PUBLICSUBToolButton2_Click()
TextLabel1.Text="Youhaveclicked:<br><center>the<strong>HelpIcon"
END

PUBLICSUBToolButton3_Click()
TextLabel1.Text="Youhaveclicked:<br><center>the<strong>ExitIcon"
END

Now,wearegoingtoaddaComboBoxtoTab3. Nothingfancy,justa
simpleComboBoxwiththreeitems.SelecttheComboBoxcontrolandplaceiton
thetabasshownbelow:

Figure71Tab3layoutwithaComboBox.

Remember,inordertosettheitemsintheComboBox,youneedtogoto
thePropertieswindowandselecttheListproperty.Abuttonwiththreedotswill
appear(indicatingthatitleadstotheListEditor)andyouneedtoclickthat.Add
the following items: Pick something (to display as our default text), This
thing,Thatthing,andSomeotherthingtothelist.Finally,weneedtosetan
eventfortheComboBoxbysingleclickingonthe ComboBoxcontrol thenright
clicking themouse. Choose Events and selectthe Change event. Anytimethe
ComboBoxchanges,wewanttodisplaythechangedtextonourTextLabel.Now,
addthiscodeintheCodeEditorfortheComboBox1_Change()event:

PUBLICSUBComboBox1_Change()
DIMcomboitemASString

comboitem=ComboBox1.Text
TextLabel1.Text="Youpickeditem:<br><center><strong>"&comboitem
END

Forourlasttab,Tab4,wearegoingtosimplydisplaythecurrenttime.
ThiswillrequireuseoftheTimercontrol.WearegoingtoneedtoaddaLabel
andaTimercontroltoTab4,asshownbelow:

186
A Beginner's Guide to Gambas

Inorderforthetimertowork,wemustenableitwhentheformfirststarts.
Doubleclickontheformsomewhereexceptonacontroland youwillseethe
Form_Open() subroutine appear in the code window. Add this code to the
routine:

PUBLICSUBForm_Open()
Form1.Caption="PlayingwithTabStrips"
Timer1.Enabled=TRUE
TextLabel1.Text=""
END

Toactuallyusethetimer,weneedtosetanEvent.Wedothisbysingle
clickingontheTimercontrolthenrightclickingthemouse. Choose Events and
selecttheTimerevent.YouwillbeplacedintheCodeEditorandyouneedtoadd
asinglelineofcode:

PUBLICSUBTimer1_Timer()
Label1.Text=Str$(Now)
END

ThislineofcodewillupdatetheLabel1.Textfieldeverysecondthatthe
Tab4isdisplayed.Ineffect,youhavecreatedaclockontheTabbydoingthis.
Thatisallthereistoit.RuntheprogramandseehowTabStripswork.Next,we
movetoFileoperations.

187
A Beginner's Guide to Gambas

Chapter 9 Working with Files


We are going to introduce you to Gambas file management and
input/output(filei/o)operationsinthischapter.Gambashasafullfeaturedset
offunctionsandsubroutinestosupportnearlyanykindoffilei/ooperationyou
mayneedtoimplementinyourprograms.

Access
Dir
Eof
Exist
IsDir/Dir?
Lof
Stat
Temp/Temp$
OPENandCLOSE
INPUT,LINEINPUT,andPRINT
READ,SEEK,WRITEandFLUSH
COPY,KILLandRENAME
MKDIRandRMDIR
LINK

Access

Accessisafunctionusedtodetermineifafileisaccessibleornot. The
Gambaslanguagesyntaxis

Accessible=Access(Path[,Mode])

The Access function call returns TRUE if the file specified by Path is
accessible.IfthevalueofModeisgb.Read,thenthefunctionreturnsTRUEifthe
filecanberead.Thisisthedefaultvalueforallfiles.IfModeisgb.Write,then
AccessreturnsTRUEifthefilecanbewrittento.Whengb.Execisspecifiedfor
Mode,thefunctionreturnsTRUEifthefilecanbeexecuted.Thepreviousflags
canbecombinedwiththeORoperator.Foradirectory,theexecutionflagmeans
thatthedirectorycanbebrowsed.Forexample:

PRINTAccess("/home/rabbit",gb.WriteORgb.Exec)

wouldreturn

188
A Beginner's Guide to Gambas

True

whilethestatement

PRINTAccess("/root",gb.Write)

willreturn

False

Dir

The Dir function returns a string array that contains the names of files
located in Directory that matches the specified File pattern. If no pattern is
specified,anyfilenamethatexistsinthedirectoryisreturned.Thepatternmay
containthesamegenericcharacterspermittedforthe LIKE operator. Inother
words,thosecharactersfoundinthefollowingtable:

Genericcharacter Matches
* Anynumberofanykindofcharacter.
? Anysinglecharacterofanytype.
[abc] Anycharacterspecifiedbetweenthebrackets.
[xy] Anycharacterthatlieswithinthespecifiedinterval.
[^xy] Anycharacterthatisnotfoundwithintheinterval.

The special generic character \ prevents the character following itfrom


beinginterpretedasageneric.StandardGambaslanguagesyntaxis:

Filenamearray=Dir(Directory[,Filepattern])

Hereisanexamplecodesegmenttohelpyou

'Printadirectory
SUBPrintDirectory(DirectoryASString)
DIMsFileASString

FOREACHsFileINDir(Directory,"*.*")
PRINTsFile
NEXT
END

189
A Beginner's Guide to Gambas

Eof

TheEoffunctionreturnsaBooleanvalueofTRUEifweareattheendof
thestream.StandardGambaslanguagesyntaxis:

Boolean=Eof(File)

AnexampleofhowEofisusedfollows:

...
OPENFileNameFORREADAS#hFile
WHILENOTEof(hFile)
LINEINPUT#hFile,OneLine
PRINTOneLine
WEND
CLOSE#hFile
...

Exist

The Existfunction returnsTRUEifafileoradirectoryexists.Using~as


directoryidentifierdoesnotwork.Ifthepathspecifieddoesnotexist,FALSEis
returned.Gambaslanguagesyntaxis:

Boolean=Exist(Path)

HereisanexampleofusingExisttodetermineifafileexistsbeforecallingOPEN
toreadthefile:
...

DIMsCurrentFileNameASString

sCurrentFileName="TheRaven.txt"
IFExist(sCurrentFileName)THEN
...'openthefile
ELSE
Message.Info("File"&sCurrentFileName&"doesnotexist.")
ENDIF

...

190
A Beginner's Guide to Gambas

IsDir/Dir?

TheIsDirfunctionreturnsTRUEifapathpointstoadirectory.Ifthepath
does not exist or is not a directory, this function returns FALSE. Gambas
languagesyntaxforIsDiris:

Boolean=IsDir(Path)

Some examples of how to use IsDir that were provided on the Gambas
documentationWikiare:

PRINTIsDir("/etc/password")
False

PRINTIsDir(Application.Home&/".gambas")
True

PRINTIsDir("/windows")
False

Stat

TheStatfunctionreturnsinformationaboutafileoradirectory.TheFile
objectinformationreturnedincludesthetype,size,lastmodificationdate/time,
permissions,etc.Thefollowingfilepropertiescanbeobtainedusingthisfunction:

.Group .Hidden .LastAccess .LastChange .LastUpdate


.Mode .Perm .SetGID .SetUID .Size
.Sticky .Time .Type .User

ThestandardGambaslanguagesyntaxforStatis:

Fileinfo=Stat(Path)

Here is an example of how to use Stat and what will be returned from the
console:

WITHStat("/home")
PRINT.Type=gb.Directory
PRINTRound(.Size/1024);"K"
ENDWITH

Theconsolewillrespondwith:

191
A Beginner's Guide to Gambas

True
4K

Temp/Temp$

TheTemp$functionreturnsauniquefilenameusefultocreatetemporary
files. The filename created will be located in the /tmp directory. Gambas
languagesyntaxis:

Filename=Temp$()

Example:

PRINTTemp$()
/tmp/gambas.0/12555.1.tmp

OPENandCLOSE

OPENandCLOSEworkasateam.OPENopensafileforreading,writing,
creatingorappending data. UnlesstheCREATEkeywordisspecified,thefile
mustexist.IftheCREATEkeywordisspecified,thenthefileiscreated,orcleared
ifitalreadyexists.Ifthefileisopenedforwriting,thepathtoitmustbeabsolute
becauserelativepathsare,bydefault,assumedtorefertofilesthatexistinside
thecurrentGambasprojectorarchivefolder.GambaslanguagesyntaxforOPEN
is:

OPENFilenameFOR[READ][WRITE][CREATE|APPEND][DIRECT]
[WATCH][BIG|LITTLE]AS#Variable

Ifthe APPENDkeyword isspecified,thenthefilepointerismovedtothe


endoffilejustafterthefileisopened.IftheDIRECTkeywordisspecified,the
inputoutputarenotbuffered. Ifthe WATCHkeyword isspecified,thefileis
watchedbytheinterpreterusingthefollowingconditionalguidelines:

Ifatleastonebytecanbereadfromthefile,theeventhandlerFile_Read()iscalled.
Ifatleastonebytecanbewrittentothefile,theeventhandlerFile_Write()iscalled.

IftheBIGorLITTLEkeywordisspecified,allsubsequentREADandWRITE
operationsonthisfilewill use bigEndian or littleEndian data representation.
Variable receives the object that represents the opened stream. CLOSE is the
reciprocalfunctionandsimplyclosesanopenedfile.SyntaxforusingCLOSEis:

192
A Beginner's Guide to Gambas

CLOSE#File

Hereisanexamplethatopensandclosesafile:

'GambasClassFile
sCurrentFileNameASString
sCurrentFileLengthASInteger

PUBLICSUBForm_Open()

DIMsInputLineASString
DIMhFileInASFile

sCurrentFileName="TheRaven.txt"
IFExist(sCurrentFileName)THEN
OPENsCurrentFileNameFORREADAShFileIn
sCurrentFileLength=Lof(hFileIn)
WHILENOTEof(hFileIn)
LINEINPUT#hFileIn,sInputLine'LINEINPUTisexplainedbelow
TextArea1.Text=TextArea1.Text&Chr(13)&Chr(10)&sInputLine
WEND
CLOSEhFileIn
ELSE
Message.Info("File"&sCurrentFileName&"doesnotexist.")
ENDIF
END

LINEINPUT

LINEINPUTreadsanentirelineoftextonthestandardinput.Itcanbe
usedontheconsoleorwithfiles.TheGambaslanguagesyntaxis:

LINEINPUTVariable

or,forfileswherethedataisreadfromthestreamFile:

LINEINPUT#File,Variable

HereisanexampleyoucantrytoseehowLINEINPUTworks:
STATICPUBLICSUBMain()
DIMhFileASFile
DIMsInputLineASString

193
A Beginner's Guide to Gambas

DIMlineCtrASInteger

OPEN"TheRaven.txt"FORREADAS#hFile
WHILENOTEof(hFile)
LINEINPUT#hFile,sInputLine
PRINTStr(lineCtr)&Chr(9)&sInputLine
INClineCtr
WEND
CLOSE#hFile
END

NOTE:Youshould not usetheLINEINPUTcalltoreaddatafromabinaryfile


becauseitwilllosethelinefeedcharacters. Forreadingdatafrombinaryfiles,
youmustusetheREADcommandinstead:

READ#hFile,OneLine,256

where 256 isthemaximumnumberofbytesyouwantread(precededwitha


dash) symbol. The 256 can be any number, but you should limit it to the
maximumsizeofanyvariableyourprogramwillusetoholdthereaddata.

READ,SEEK,WRITEandFLUSH

TheREADfunctionreadsdatafromthestandardoutput.Ittreatstheinput
streamasbinarydatawhosedatatypeisspecifiedbythetypeofthevariablethe
dataisstoredinduringthereadoperation.Thebinaryrepresentationofthedata
shouldbethesamerepresentationcreatedbyuseoftheWRITEinstruction. If
Variableisastring,youcanspecifyalengththatindicatesthenumberofbytesto
read.IfthevalueoftheLengthparameterisnegative,thenLengthbytesareread
fromtheendofstream.IfnoLengthparameterisspecifiedforastring,theentire
stringisreadfromthestream.Thestringvaluethenmusthavebeenwrittenwith
theWRITEinstruction.StandardGambaslanguagesyntaxforREADis:

READVariable[,Length]

IfREADisusedwithfileoperations,theGambaslanguagesyntaxis:
READ#File,Variable[,Length]

TheWRITEfunctionwritesexpressionstothestandardoutputusingtheir
binary representation. If Expression is a string, you can specify a length that
indicatesthenumberofbytestowrite.Ifnolengthisspecifiedforastringvalue,
theentirestringvalueiswrittendirectly tothestream. HereistheGambas

194
A Beginner's Guide to Gambas

languagesyntaxforstandardinputstreams:

WRITEExpression[,Length]

andforwritingtoafile,thisistheconvention:

WRITE#File,Expression[,Length]

TheSEEKfunctiondefines(ormoves)thepositionofthestreampointer,
most often in preparation for the next read/write operation. If the position
specifiedbythe Length parameterisnegative,thenthestreampointerismoved
backwards Length bytesfromtheendofthefile. Tomovethestreampointer
beyondtheendofthefile,youmustusethe Lof()function. StandardGambas
languagesyntaxis:

SEEK#File,Position

HerearesomeexamplesofusingSEEK:

'Movetothebeginningofthefile
SEEK#hFile,0

'Moveaftertheendofthefile
SEEK#hFile,Lof(#hFile)

'Move100bytesbeforetheendofthefile
SEEK#hFile,100

TheFLUSHfunctioniscalledtoempty(orflush)thecontentsofabuffered
data stream.Ifnostreamisspecified,everyopenstreamisflushed. Typically,
FLUSHiscalledaftermultiplewriteoperationsandbeforeclosingoutaprogram
or routine toensure all data held in a bufferis written out to the file before
exiting.HereistheGambaslanguagesyntaxforFLUSH:

FLUSH[#File]

COPY,KILLandRENAME

The COPYfunction willcopyasourcefiletoaspecifieddestinationfile.


Thedestinationpathneednothavethesamenamethanthesourcepath. You
cannot copy directories recursively with this function. The Gambas language
syntaxforthisfunctionis:

195
A Beginner's Guide to Gambas

COPYSource_pathTODestination_path

HereisanexampleofhowtouseCOPY:

'Savethegambasconfigurationfile
COPYSystem.Home&/".gambas/gambas.conf"TO"/mnt/save/gambas.conf.save"

The KILLfunction removesafile. TheGambaslanguagesyntaxis KILL


Path and whatever exists in Path is permanently deleted. RENAME simply
changesthenameofafileorfolderfrom Oldname to Newname. Hereisan
example:

RENAMEOldnameASNewname

MKDIR,RMDIR

TheMKDIRfunctionisusedtocreate(make)afolderonyourfilesystem
andRMDIRisusedtoremoveafolder.Bothfunctionstakeasingleparameter,a
Filepathandname.TheGambaslanguagesyntaxis:

MKDIRfile:/rittingj/MyDocuments/Gambas/test
RMDIRfile:/rittingj/MyDocuments/Gambas/test

InordertodemonstratemostofthefileandI/Ofunctionsdescribedinthis
chapter,wearegoingtocreateanapplicationthatwillactasasimpletexteditor.
Theintenthereisnottocreateafullblowntexteditor,buttoshowyouhowto
usethesefunctionsinthecontextofanapplication.Theapplicationwewillbuild
inthischapterisalittlemorecomplexthanwhatwehaveseensofarinthatwe
willbecreatingtwoforms,aninputfile,ahelpfile,andusingquiteafewsystem
iconswhichwillbecopiedfromtheLinuxOSdistribution'ssystemIconfolder(s).
Hereiswhatourapplicationwilllooklikeatruntime:

Figure72TheFileOpsprogramatruntime.

196
A Beginner's Guide to Gambas

Inthisprogram,wewillcreateamainmenu,atextareatodisplayandedit
textwith,andwewillcreatestatuselementsatthebottomofthedisplay.Wewill
alsointroductuseoftheTimercontrol(shownastheclockinthepicturebelow).
Thisform,namedForm1.form,willlooklikethisindesignmode:

Tostart,loadGambasandcreateanewgraphicaluserinterfaceproject.
NameitFileOpsandwhenyougettotheGambasIDE,createanewform,Form1
andmakeisastartupclass.Whentheformdisplaysonyourscreen,wearegoing
tobeginbycreatingthemenus. Youcanpress CTRLE tobringupthe Menu
Editor.Addthefollowingmenuitemsshowninthetablesbelowusingtheeditor.
Fortheicons,youwillneedtocopyiconsfromthesamedirectorywespecifiedin
thelastchapter. Most Linuxbaseddistributionshaveiconfilesthatareusually
stored in the folders namedfile:/usr/share/icons/defaultkde/32x32/actions
orfile:/usr/share/icons/defaultkde/32x32/applications. Your particular system
maybeslightlydifferent.Regardlessofwhereyoufindtheicons,pickouticons
appropriateforourprogramandcopythemtotheFileOpsfolder.Herearethe17
iconsIchosetouseforthisproject:

FileNew FileOpen FileSave FileSaveAs FilePrint Exit

Edit EditUndo EditRedo EditCut EditPaste EditCopy


SelectAll

Edit Format Format HelpAbout Help


Configure Colors Fonts Contents

197
A Beginner's Guide to Gambas

If you cannot find the exact same icon, simply pick one that is most
appropriateandsaveitwiththefilenameforthatoptionasshowninthetables
below.Itisnotcrucialthateveryiconbeexactlythesame.Infact,theSelectAll
iconwascreatedusingtheGambasIconEditor.

FileMenu
VariableName Caption IconProperty(filename)
FileNewItem "New" Picture["filenew.png"]
FileOpenItem "Open..." Picture["fileopen.png"]
FileSaveItem "Save..." Picture["filesave.png"]
FileSaveAsItem "Saveas..." Picture["filesaveas.png"]
FilePrintItem "Print" Picture["fileprint.png"]
FileExitItemMenu "Exit" Picture["exit.png"]

EditMenu
VariableName Caption IconProperty(filename)
EditSelectAllItem "SelectAll" Picture["selectall.png"]
EditUndoItem "Undo" Picture["undo.png"]
EditRedoItem "Redo" Picture["redo.png"]
EditCutItem "Cut" Picture["editcut.png"]
EditCopyItem "Copy" Picture["editcopy.png"]
EditPasteItem "Paste" Picture["editpaste.png"]
EditPrefsItem "Preferences" Picture["configure.png"]

FormatMenu
VariableName Caption IconProperty(filename)
FomatColorItem "Colors" Picture["colorize.png"]
FormatFontItem "Font" Picture["charset.png"]

HelpMenu
HelpContentsItem "Contents" Picture["contents.png"]
HelpAboutItem "About" Picture["buildingblocks.png"]

198
A Beginner's Guide to Gambas

HereisthecodeforwewilluseforForm1.Wewillgothruthislinebyline
soeverythingisfullyexplained. Westartourprogrambydeclaringtwoclass
globalvariables,sCurrentFileNameandsCurrentFileLength.

'Gambasclassfile
sCurrentFileNameASString
sCurrentFileLengthASInteger

Whentheprogramstarts,thissubroutineiscalled.Itcallsaconstructor,_new()
toinitialize.Theconstructorisexplainedinthenextsection.Whenourprogram
starts,wearegoingtohaveitautomaticallyloadourdefaulttextfile,namedThe
Raven.txt.ThisfilewascopiedofftheInternetandyoucanplaceanytextfilein
theFileOpsprojectfoldertouseforthisproject.Justrememberthatthefilename
has to be changed in the code below if you choose not to use our default
filename.

PUBLICSUBForm_Open()
DIMsInputLineASString
DIMhFileInASFile

WewillassignourfilenametothesCurrentFileNamestringvariableand
checktoseeifthefileexistsintheprojectfolder.Ifitexists,thentheprogram
willopenthefileandgettheinitialfilelength.Wewilldisplaythefilenameand
sizeintheForm1.Captionproperty.Whileitisnotcustomarytodisplaythefile
sizelikethis,itisdoneheresimplytodemonstratetheuseoftheLoffunction.
sCurrentFileName="TheRaven.txt"
IFExist(sCurrentFileName)THEN
OPENsCurrentFileNameFORREADAShFileIn
sCurrentFileLength=Lof(hFileIn)'toshowhowtogetfilesize
Form1.Caption=""&sCurrentFileName&",size:"&Str
(sCurrentFileLength)&"bytes."

Now,wewillenteraloopstructuretoreadallthelinesofthetextfileinto
ourTextArea1.Textproperty.Wewillcontinuetoloopuntilwehavereachedthe
endofthefile. Aswereadeachlineintomemoryandassignittothevariable
sInputLine,wemustremembertoaddtheCRLF(aCarriageReturn(Chr(13)and
aLineFeed(Chr(10)) totheendofthelinesoitwilldisplayproperlyinthe
control.
WHILENOTEof(hFileIn)
LINEINPUT#hFileIn,sInputLine
TextArea1.Text=TextArea1.Text&Chr(13)&Chr(10)&sInputLine
WEND

199
A Beginner's Guide to Gambas

Assoonasweexittheloop,meaningwehavereachedtheendofthefile,
wewillclosethefile.

CLOSEhFileIn

Ifourchecktoseeifthefileexistsfailed,wewouldenterthisELSEblock
ofcodeanddisplayamessageindicatingthatthefiledidnotexist.Next,wecall
ourFileOpenItem_Click()subroutinetohavetheuserpickafiletoopen.
ELSE
Message.Info("File"&sCurrentFileName&"doesnotexist.")
FileOpenItem_Click()'forceafiletobepickedifnodefault.
ENDIF
END

ThatisallthereistotheForm_Open()subroutine.Hereistheconstructorforthe
form:
PUBLICSUB_new()
Timer1.Delay=1000
Timer1.Enabled=TRUE
END

Theconstructorsimplysetsthetimerdelayto1second(1000ms)andsets
theenabledpropertytotrue. Theneteffecthereisthatthetimerwillupdate
itselfeverysecond.Wewillimplementthetimercontrollaterinthiscode.

Let'snowturnourattentiontotheFile|Newmenuoption.Foranewfile
tobecreatedbytheuser,wemustfirstblankoutthetextintheTextArea1.Text
property.Wewillprompttheuserforanewfilenameandsavetheblankfileto
disktocreateit. Whateverchangestheuserwillmakewillbesavedonexitor
whenevertheuserchoosestosavefromthemenu.Thelastthingwedointhis
subroutineissettheForm1.Captionpropertytothenewlysavedfilename.

PUBLICSUBFileNewItem_Click()
TextArea1.Text=""
Dialog.Title="Enternewfilename..."
Dialog.Filter=["Textfiles(*.txt)","Allfiles(*.*)"]
Dialog.SaveFile
Form1.Caption=Dialog.Path
END

ThenextroutineisactivatedwhentheuserclickstheFile|Openmenuitem.

200
A Beginner's Guide to Gambas

PUBLICSUBFileOpenItem_Click()

Thisroutinerequirestwolocalvariables.hFileInisthehandletotheFILEobject
wewillopenandsInputLineisastringvariablethatwewillusetoreadthetext
fileintoourTextArea1.Textproperty.

DIMhFileInASFile
DIMsInputLineASString

Justbeforethecalltothestandarddialog,wecansetthewindowcaption
(ortitle)usingtheDialog.Titleproperty.Wewillalsosetafilterforthedialogto
onlylookforfileswitha.txtextension. Asalastresort,wewilllettheuser
choosetoviewalltypesoffilesbyselectingthefilter*.*fromwithinthedialog.
Dialog.Title="Chooseatextfile"
Dialog.Filter=["Textfiles(*.txt)","Allfiles(*.*)"]

WhenthecalltoDialog.OpenFileismade,rememberthatitwillreturna
TRUEvalueiftheuserclicksontheCancelbutton,otherwise,FALSEisreturned.
WewillcheckforaTRUEvalueandreturnifthatiswhatweget.Otherwise,it
meanstheuserselectedafileandwewillprocessit.

IFDialog.OpenFile()THEN
RETURN
ELSE

The filename of the file that was selected by the user is stored in the
Dialog.Pathproperty.WewillassignthattotheglobalvariablesCurrentFileName
so other parts of the program will have access to it. We will set the
Form1.Caption property to the name of the newly opened file and clear the
currentTextArea1displaybyinvokingtheClearmethod.
sCurrentFileName=Dialog.Path
Form1.Caption=""&sCurrentFileName&""
TextArea1.Clear

Next,wewillopenthefileandreadeachlineintomemoryusingtheLINE
INPUTfunctionandourstringvariablesInputLine. Oncethedataisstoredin
sInputLine, we will add it to the end of whatever is currently stored in the
TextArea1.Textproperty(effectively concatenating ontotheendofthecurrent
textvalue)andaddourCRLFcharacters.Oncewereachtheendofthefile,we
willexittheloopandclosethefile.

201
A Beginner's Guide to Gambas

OPENsCurrentFileNameFORREADAShFileIn
WHILENOTEof(hFileIn)
LINEINPUT#hFileIn,sInputLine
TextArea1.Text=TextArea1.Text&Chr(13)&Chr(10)&sInputLine
WEND
CLOSEhFileIn
ENDIF
END

TheFile | Savemenuitem,whenclicked,willinvokethissubroutine. It
worksalmostlikethepreviousoneexceptthatwealreadyknowthenameofthe
file held in the global variable sCurrentFileName. When we return from the
standarddialogcall,weupdatetheglobalvariablewithwhateverwasreturned
notcaringifthefileisthesamenameornot.Whateveritisorhasbecomewill
bewhatissaved.

PUBLICSUBFileSaveItem_Click()

Dialog.Title="Savetextfile"
Dialog.Filter=["Textfiles(*.txt)","Allfiles(*.*)"]
IFDialog.SaveFile()THEN
RETURN
ELSE
sCurrentFileName=Dialog.Path
File.Save(sCurrentFileName,TextArea1.Text)
ENDIF
END

ThenextsubroutinewewillcodeistheFileSaveAsmenuitem.Iftheuser
wantstosavetheexistingfileunderadifferentfilename,thisistheroutineto
handle thatoption. Forthissubroutine,itwillworkalmostidenticallytothe
FileSavesubroutinebutwewillneedtochecktoseeifthefilenamereturnedfrom
thestandardfiledialogisactuallydifferentthanthecurrentfilename. Ifitis
different,thenwewillsavethefileunderthenewname.Ifthenameisthesame,
wewillpopupaMessageBoxandinformtheuserthatnosaveactionwastaken
becausethenameswereidentical.
PUBLICSUBFileSaveAsItem_Click()
DIMsTmpNameASString

WeusethelocalstringvariablesTmpNametomakeourcheck.Firstofall,
we need to the the full path to the application and concatenate the current
filenametothattogetthefullyqualifiedpathnameforourfile. Weusethe
Applicationclassforthatpurpose,checkingthePathpropertytogetthenameand
path of the running application. Note the use of the &/ operator which is

202
A Beginner's Guide to Gambas

specificallyusedtocatenatefilenames.
sTmpName=Application.Path&/sCurrentFileName
Justaswedidpreviously,wewillsetthetitleandfilterproperties,then
callthestandardfiledialog.
Dialog.Title="Savetextfileas..."
Dialog.Filter=["Textfiles(*.txt)","Allfiles(*.*)"]

IfthestandarddialogcallreturnsTRUE,theuserhascancelledoutofthe
routineandwewillsimplyreturntothecallingprocess(i.e.,ourstandardevent
loop).

IFDialog.SaveFile()THEN
RETURN

Ifthefilenamesarethesame,wewillpopuptheMessageBoxandreturn:

ELSEIFsTmpName=Dialog.PathTHEN
Message.Info("Filenotsaved:namesameascurrentfile.","OK")
RETURN

Otherwise,wesettheglobalvariabletothefilenamereturnedfromthe
standardfiledialogandcalltheSavemethod,passingthefilenameandourtext
asparameters. Weupdatethecaptionofthewindowasthelastthingwedo
beforereturningtothecallingprocess.

ELSE
sCurrentFileName=Dialog.Path
File.Save(sCurrentFileName,TextArea1.Text)
Form1.Caption=sCurrentFileName
ENDIF
END

PrintinganytypeofitemisprettyeasyinGambas.OurFile|Printmenu
itemwillinvokethissubroutinewhenclicked.Wewilldeclareourlocalvariables
first:

PUBLICSUBFilePrintItem_Click()

'integervariablestoholdourmarginvalues
DIMiLeftMarginASInteger
DIMiTopMarginASInteger
DIMiRightMarginASInteger
DIMiBottomMarginASInteger

203
A Beginner's Guide to Gambas

'stringvariableswewilluse
DIMarsTxtToPrintASString[]
DIMiTxtPosYASInteger
DIMsTxtLineASString
DIMstrMsgASString

'integervariablesourprogramusestocalculatepagedimensions
DIMiPrinterAreaWidthASInteger
DIMiPrinterAreaHeightASInteger

We MUST call the Printer.Setup() subroutine before we actually try to print


something.ItismandatorytocallthisfunctioninGambas.
IFPrinter.Setup()THENRETURN

Thenextcallensuresthedefaultpapersizeissetto8.5by11(Letter).If
youarenotintheUnitedStates,itshouldprobablybesettoA4asthatisthe
standardusedinmostplacesoutsidetheU.S.TheGambasPrinter.Setupdialog
defaultstoA4settingseverytimeyoucallit,soifyouareusingaprinterthat
onlyusesLettersizepaper,overridingthispropertyistheeasiestwaytohandle
thatsituation.

'overridetheprinter.setupdialogsoyoudon'thave
'tosetthiseverysingletimeyouprintsomething
Printer.Size="Letter"'orA4,orwhateveryouuse

'olderprintersdonotseemtobesettoDPIslowerthan600inGB
'sowewillsetitmanuallyforanolderHPLaserjetIIIprinter
'ifyourprinterisnewer,youcancommentthislineout
Printer.Resolution=300'myHPLJIIIsettings

Fora300dpiprinter,avalueof300wouldequalaoneinchmargin.Now,
wesetthemarginvaluesbyusingthePrinterproperties(ortheonesweoverrode
above)returnedfromthePrinter.Setupcall.
'setleftmargintooneinch,equaltotheDPIoftheprinter
iLeftMargin=Printer.Resolution

'settopmargintooneinch,equaltotheDPIoftheprinter
iTopMargin=Printer.Resolution

'setrightmargintooneinch,equaltotheDPIoftheprinter
iRightMargin=Printer.Resolution

'settopmargintooneinch,equaltotheDPIoftheprinter

204
A Beginner's Guide to Gambas

iBottomMargin=Printer.Resolution

'DefinethePrintableareawidth
iPrinterAreaWidth=Printer.WidthiLeftMarginiRightMargin

'DefinethePrintableareaheight
iPrinterAreaHeight=Printer.HeightiTopMarginiBottomMargin

The calculation for obtaining iPrinterAreaWidth and iPrinterAreaHeight


subtracttheleft/rightandtop/bottommarginsfromthetotalpagewidth/height.
ForLettersizedpaper(8.5x11)thewidthvaluewouldbe8.5inchestimes300
dpior2550 and theheightwouldbe11 inchestimes300 dpi or3300. Our
calculationsubtracts600(300forleftmargin+300forrightmargin)fromboth
thewidthandtheheightvaluesreturnedfromthePrinter.Setupcall. Next,we
needtobuildtheoutputstringforourMessage.Infocallanddisplaythatdatato
user:
'buildastringforMessageBoxwithdatafromprintersetupcall
strMsg="Res:"&Str(Printer.Resolution)&",Width:"&Str
(Printer.Width)&",Height:"&Str(Printer.Height)

'showaMessageBoxwithdataobtainedfromtheprintersetupcall
message.Info(strMsg)

Next, we need to parse all of the content of the text in the TextArea1
controlintoastringarray.ItisveryeasytodoinGambasandonlytakesasingle
line of code. To do this,we willuse theSplitfunction and setthe delimiter
parametertothe'\n'characterwhichdesignatestheendofthelineoftext:

'useanarrayofstringstostoreeachlineoftextinTextArea1.Text
arsTxtToPrint=Split(TextArea1.Text,"\n")

Weare ready to print. To do so,you MUST firstcalltheBeginmethod and


specifythatyouwantthePrinterobjecttobetheoutputdeviceusedbytheDraw
method:
Draw.Begin(Printer)'InitializesthedrawroutineforPrinter

Inourcodebelow,wehavecalledtheDraw.Rectfunctiontodrawaborderatone
inchmarginsaroundourpage.
'makeaborderaroundthepage
Draw.Rect(iLeftMargin,iTopMargin,iRightMargin,iBottomMargin)

'nowwewillloopthrougheachlineinthearrayandprintit

205
A Beginner's Guide to Gambas

FOREACHsTxtLineINarsTxtToPrint

'incrementthevertical(Y)linepositionforeachlineprinted
iTxtPosY=iTxtPosY+Draw.TextHeight(sTxtLine)

'testthelineposition...ifis>thebottomoftheprinter
'areathenweneedtoresetittozeroandperformanewpage
IFiTxtPosY>=(iPrinterAreaHeight)THEN
iTxtPosY=0'reinittheCurrentTextPositionY
Printer.NewPage

'makeaborderaroundthenewpage
Draw.Rect(iLeftMargin,iTopMargin,iRightMargin,iBottomMargin)
ENDIF'ourtesttoseeiflinefallspastbottommargin

Now,wewillmakethecalltoDraw.Texttoactuallyprintthetext. The
firstparameterDraw.TexttakesisthestringobjectsTxtLinerepresentingourline
of text to be printed from the array of string arsTxtToPrint. The next two
parameters, iLeftMargin and (iTopMargin+iTxtPosY) areused todefine theleft
marginandthecurrentverticalTextYposition.Eachlineisincrementedbythe
valueheldintheproperty Draw.TextHeight. Optionally,youcanspecifyright
andbottommargins,andanalignmentproperty.Inourcasebelow,wespecified
the right margin, defined by iPrinterAreaWidth (as we calculated above) and
omittedthebottommarginsinceitismaintainedinthecodeoftheFORLOOP
above.Finally,wehavespecifiedthealignmentofthetexttobeleftaligned.
'Nowweprintthetextlineatthenewlineposition
Draw.Text(sTxtLine,iLeftMargin,iTopMargin+iTxtPosY,iPrinterAreaWidth,,Align.Left)
NEXT'iterationoftheFORLOOP

Tofinishtheprintprocess,youMUSTremembertocallDraw.End:
Draw.End'Thenprintfinalcontentsandejectlastpage
END

Sinceourexampleprogramonlyworkswithtextfiles,thereisanalternate,
sometimeseasiermethodofprinting.Youcanusethesystem'sbuiltinpr(print)
command. ItisinvokedusingtheGambasSHELLmethod. Thiscallcanallow
youtoprintanytextfilefromwithinyourprogramdirectlytothedefaultprinter.
Toseehowthismethodworks,let'saddamenuitemtoourprogramandtrythis.
GototheForm1.formandpressCTRLEtobringupthemenueditor.Belowthe
File|Printmenuitem,addanewitem, FileSysPrintItem andgiveitthecaption
Print(systemmethod).Createaclickeventandaddthiscode:

PUBLICSUBFileSysPrintItem_Click()

206
A Beginner's Guide to Gambas

DIMaStringASString

aString="prh\""&sCurrentFileName&"\""&"o10<\""&
sCurrentFileName&"\"|lpr"

message.Info(aString,"Ok")
SHELLaString
END

Itlooksalotmoredifficultthatitreallyis.Let'sgolinebylinethroughthe
code.First,wedeclareastringvariable,aString.Nextweneedtobuildthestring
thatwillbepassedofftothesystemasaconsolecommandandassignittoyour
aString variable. Becausewemustensurethestringisbuiltexactlyasitwould
have to be typed from the console, we must ensure it contains quote marks
embeddedinit.Thefirstpartofthestring:

"prh\""

willinvokethesystemcommandpr.Thehparameterspecifiesthatwewantto
haveaheaderprintedoneachpage,inthiscase,itwillbethecurrentfilename,
heldinthevariablesCurrentFileName,which,inourprogram,isglobalinscope.
This filename has to be embedded in quote marks so we need to use the \
characterbeforetheopeningquotemarkandterminatethispartofthestringwith
anotherquotemark.Thenextpartofthestring:

&sCurrentFileName&"\""

concatenatesthefilenameandtheterminatingquoteforthefilenamepassedinas
astringvariable,onceagainprecededbya \ character. Thenextquotemark
terminates this portion of the string. The next part of the command to
concatenateis:

&"o10<\""

whichaddstheoparameter(whichspecifiesanoffset)andavalueof10spaces.
The<characterisusedonthecommandlinetodesignatetheinputstreamcomes
fromthefilenamethatfollowsthe<character.Inthiscase,weneedtodelimit
our string with quotes again, so the \ character is used to allow the quote
charactertobepartoftheoutputstring. Thenextquotecharacterbeginsthe
quotedfilenamestring.Thelastpartofourcommandis:

sCurrentFileName&"\"|lpr"

207
A Beginner's Guide to Gambas

Itspecifiesthefiletoread(andprint)andterminatesthefilenamewith
quotemarksasexplainedbefore. Thefinalpartofthestringisthe|character
which pipes (redirects)theoutputtothelineprinter(lpr). Inall,ittakesone
variabledeclarationandthreelinesofcodetoprintafileusingthistechnique.
Eithertechniquewillworksochoosetheonethatsuitsyoubest.Anothermethod
thatyoucanuseifyouhaveKDEinstalledistoprinttoapostscriptfileandsend
the.psfileto'kprinter'.ThiswillprovideyouwithaccesstotheKDEprintdialogs
andalloftheCUPSprintersandfeaturesinstalledonyoursystem.

IftheuserclicksontheFile|Exitmenuitemwecouldsimplyclosethe
program.However,wewanttogivetheuserachancetosavebeforeexitsowe
willpopupaquestiondialogtoaskiftheywanttosavethefile. Ifso,wewill
saveit.Ifnot,wesimplyexittheprogram.

PUBLICSUBFileExitItem_Click()
DIMiResultASInteger
iResult=Message.Question("Saveyourwork?","Yes","No","Cancel")
SELECTCASEiResult
CASE0
File.Save(sCurrentFileName,TextArea1.Text)
CASE1
CASE2
CASEELSE
ENDSELECT
ME.close
END

That'sitfortheFileMenu. Now,therealpowerofGambaswillbecome
obviousaswebuildthecodefortheEditmenufunctions. Fromthismenu,we
wanttheusertobeabletoselectalltext,undo,redo,cut,paste,copyorcalla
configurationroutine.Forourpurposes,theconfigurationroutinewillbepretty
simple,butitshouldbeenoughtoshowyouhowtoaccomplishthetask.

IftheuserclicksontheEdit|SelectAllmenuitem,itwillselectallthetext
in the TextArea. This is done be obtaining the length of the text using the
TextArea1.Length property and passing that value to the TextArea1.Selection
MethodwithastartingpointofzeroandanendingpointLengthcharactersfrom
thatstartpoint,asshowninthecodebelow.
PUBLICSUBEditSelectAllItem_Click()
DIMilengthASInteger
ilength=TextArea1.Length
TextArea1.Selection(0,ilength)
END

208
A Beginner's Guide to Gambas

Thecodeabovecouldalsohavebeenwritteninamoresimplifiedmanner
withoutusingtheIntegervariableiLength.Itcouldhavebeenreducedtoasingle
line,asshownbelow:
PUBLICSUBEditSelectAllItem_Click()
TextArea1.Selection(0,TextArea1.Length)
END

Eithermethodwillworkbuttheauthor'spreferenceistousethesecond
methodasitreflectsthesimplicityofGambaswhenprogramming.Thissimplicity
is seen in the use of the builtin Undo, Redo, Cut, Paste and Copy methods
providedbyGambasforTextArea1.Textaswell.Gambasprovidesthesemethods
soprovidingthiscapabilityforyourprogramusersisasimplematterofaddinga
singlelineofcodeforeachmenuitem'sclickevent,asshownbelow:
PUBLICSUBEditUndoItem_Click()
TextArea1.Undo
END

PUBLICSUBEditRedoItem_Click()
TextArea1.Redo
END

PUBLICSUBEditCutItem_Click()
TextArea1.Cut
END

PUBLICSUBEditPasteItem_Click()
TextArea1.Paste
END

PUBLICSUBEditCopyItem_Click()
TextArea1.Copy
END

OurEdit|Preferencesmenuoptionwillbeusedtoshowyouhowtobring
upasecondforminyourprogram. Wewillsavethedatagatheredfromthe
Form2.forminaconfigurationfilenamedFileOps.confandthatwillenableusto
passthosesavedvaluesbackandforthbetweenthemainform,Form1.formand
thesecondform,Form2.form.Thisistheeasiestwaytoexchangedatabetween
classes but it is possible to pass data as parameters between forms. We will
discuss that later in this book. The EditPrefsItem_Click() subroutine is pretty
simple.Wejustshowthesecondform.
PUBLICSUBEditPrefsItem_Click()

209
A Beginner's Guide to Gambas

Form2.Show
END

HereiswhatForm2.formwilllooklike:

Figure73Form2.formdesignmode.

Asyoucansee,itisprettybasic.ATextLabelisusedtodisplaythedefault
path. There are two buttons, one to change the default path by calling the
standard Dialog.SelectDirectory routine and the other to return to the calling
process,Form1.forminthiscase.Whentheformisopened,wewilldisplaythe
captionPreferencesatthetopofthewindow.Theconstructorroutine_new()is
calledautomatically.HereisthecodeforourForm2:

'Gambasclassfile
PUBLICSUBForm_Open()
Form2.Caption="Preferences"
END

TheconstructorwillcalloursubroutineReadPrefs,passingthenameofthe
configurationfileasaparameter.FileOps.confisthenamewewilluseforholding
ourapplication'sconfigdata. Next,wepopulate theTextLabel1.Textproperty
withthecurrentdefaultdirectory,whichdefaultstowheretheapplicationresides
ondisk.
PUBLICSUB_new()
ReadPrefs("FileOps.conf")
TextLabel1.Text=Application.Path&"isthedefaultdirectory."
END

WhentheuserclickstheChangeDefaultPathbutton,thefollowingroutine
iscalled:
PUBLICSUBButton1_Click()
Dialog.SelectDirectory
TextLabel1.Text=Dialog.Path
END

210
A Beginner's Guide to Gambas

The subroutine above simply callsthe Gambas standard dialog function


Dialog.SelectDirectoryand updatestheTextLabel1.Textpropertywithwhatthe
userhaschosenasthedefaultvalue.Whentheuserreturnsfromthissubroutine,
theonlyotheroptionontheformistoclicktheReturnbutton,whichexecutes
thiscode:
PUBLICSUBButton2_Click()
DIMMyPathASString

MyPath=application.Path&/"FileOps.conf"
WritePrefs(MyPath)
Form2.Close
END

Asyoucanseefromabove,alocalstringvariableMyPathisdeclaredand
populatedbyconcatenatingthecurrentapplicationpathwiththeconfiguration
filenameFileOps.conf.Next,wecallourWritePrefssubroutineandpassthevalue
ofMyPathasaparameter.Thatpathwillbestoredinthefileandcanbereadby
anyotherclassthatneedstofindoutthisinformation. HereistheReadPrefs()
subroutineforaccomplishingthistask:
PUBLICSUBReadPrefs(filenameASString)
'declareourlocalvariables
DIMsInputLineASString
DIMhFileInASFile

'seeifthefilealreadyexists,ifsoopenit.
IFExist(filename)THEN
OPENfilenameFORREADAS#hFileIn

'readoursinglelineofdata
'ifthereweremorelines,wecouldsetupaWHILENOTEofLOOP
LINEINPUT#hFileIn,sInputLine

'updatethedisplaydata
TextLabel1.Text=sInputLine

'closethefile
CLOSE#hFileIn
ELSE
'therewasno.conffiletoopen
Message.Info("Nopreferences.conffilepresent.","OK")
ENDIF
END

211
A Beginner's Guide to Gambas

Thereciprocalroutine,WritePrefs()isshownbelow:
PUBLICSUBWritePrefs(filenameASString)

'declareourlocalvariables
DIMMyPathASString
DIMhFileOutASFile

'noteweareusingtheDialog.Pathvalue,notApplication.Path
MyPath=Dialog.Path&/filename

'ifthereisalreadyaconfigfile,openitforwrite
'ifnot,openforcreateandwrite
IFExist(MyPath)THEN
OPENMyPathFORWRITEAS#hFileOut
ELSE
OPENMyPathFORWRITECREATEAS#hFileOut
ENDIF

'printourdatatothefile
PRINT#hFileOut,MyPath

'closethefile
CLOSE#hFileOut
END

As you can see, it is pretty simple but it can easily be expanded to


accommodatealmostanysetofconfigurationdatayourapplicationmayneedto
store. YouareonlylimitedbyyourimaginationinGambas. Now,let'slookat
ourFormatmenucode. IntheFormatmenu,theonlyoptionswehaveareto
change colors or fonts. We are going to use theGambas standard dialogs to
accomplishbothtasks.Hereishowitisdone:

PUBLICSUBFormatColorItem_Click()

'first,popupamessagetoexplainhowwearegoingtowork
Message.Info("SelectBackgroundcolorfirst,textcolorsecond.","OK")

'setdialogcaptiontoremindtheuserweareselectingBACKGROUND
Dialog.Title="SelectBackgroundColor"

'callthestandarddialogroutinetoselectcolor
Dialog.SelectColor

'updateourTextArea1.Backcolorwiththevalueselected.
TextArea1.BackColor=Dialog.Color

212
A Beginner's Guide to Gambas

'setdialogcaptiontoremindtheuserweareselectingFOREGROUND
Dialog.Title="SelectTextColor"

'callthestandarddialogroutinetoselectcolor
Dialog.SelectColor

'updateourTextArea1.ForeColorwiththevalueselected.
TextArea1.ForeColor=Dialog.Color
END

Selectingthefontanditsattributesforourprogramisjustassimpleasit
wastochoosecolors.Basically,wewillsetthedialogcaption,callthestandard
Dialog.SelectFontroutine,andupdateourTextArea1.Fontproperty,likethis:

PUBLICSUBFormatFontItem_Click()
Dialog.Title="Selectfont"
Dialog.SelectFont
TextArea1.Font=Dialog.Font
END

Atthebeginningofour program,inthe constructorroutine,wehadto


enablethetimer.Toactuallymakethetimerdoanything,youmustprogramit.
Doubleclicking on the timer control will take you to the Timer1_Timer()
subroutine,shownbelow.Ifyourecall,wearegoingtohaveourprogramdisplay
thecurrenttimeononelabelandthecurrentcursorpositionwithinthetextarea
onanotherlabel.Hereishowweaccomplishthattask:

PUBLICSUBTimer1_Timer()
'getthetimeforrightnowandconverttoastring
'toputintheTimeLabel.Textproperty
TimeLabel.Text=Str$(Now)

'wewillgetlineandcolumndatafromthe.Lineand
'.ColumnpropertiesoftheLabelcontrolandupdatethe
'PosLabel.Textpropertywiththeirvalues:
PosLabel.Text="Line:"&Str(TextArea1.Line)&"Col:"&Str
(TextArea1.Column)
END

ThelastmenuisourHelpmenu.Ithastwooptions,ContentsandAbout.
PUBLICSUBHelpContentsItem_Click()
SHELL"konqueror\"file:/root/MyDocuments/GambasforBeginners/FileOps/Help.html\""
END

Theshellcallabovepointstoafilenamed Help.html. Forpurposesof

213
A Beginner's Guide to Gambas

demonstrating this feature, simply copy any .html file on your system to the
programdirectoryand renameithelp.html. Asanalternative,youcancreate
yourown.htmlfileifyouknowhowtodothat.Thatiswhatrealprogrammers
woulddo.Hereisthelastthingweneedtodo:

PUBLICSUBHelpAboutItem_Click()
Message.Info("<b>SimpleTextEditor</b>by<br>J.Rittinghouse","OK")
END

Runtheprogramandwhenyouaresatisfied,let'smoveontodosomemath.

214
A Beginner's Guide to Gambas

Chapter 10 Math Operations


Gambasperformsmathematicaloperationswithalibraryof intrinsicand
derivedfunctions.AccordingtotheonlineencyclopediaWikipedia15,anintrinsic
function is a function available in a given language whose implementation is
handled specially by the compiler. Typically, it substitutes a sequence of
automaticallygenerated instructions for the original function call, similar to an
inlinefunction.Compilersthatimplementintrinsicfunctionsgenerallyenablethem
only when the user has requested optimization, falling back to a default
implementationprovidedbythelanguageruntimeenvironmentotherwise.

Intrinsicfunctionsarebuiltintothecompilerofaprogramminglanguage,
usuallytotakeadvantageofspecificCPUfeaturesthatareinefficienttohandle
via external functions. The compiler's optimizer and code generator fully
integrate intrinsic functions, which can result in some surprising performance
speedups in calculation. Derived functions, on the other hand, are built in
Gambasbyusingknownmathematicalformulastoapplyspecificalgorithmsthat
implement intrinsic functions. A table of derived functions and their
correspondingalgorithmscanbefoundattheendofthischapter.

PrecedenceofOperations

WhenyouusevariousoperatorsinanexpressioninGambas,thereisa
specificprecedenceofoperationsthatGambasusestoperformtheoperation.A
welldefinedprotocolisfollowed:

Allexpressionsaresimplifiedwithinparenthesesfromtheinsideoutside
Allexponentialoperationsareperformed,proceedingfromlefttoright
Allproductsandquotientsareperformed,proceedingfromlefttoright
Allsumsanddifferencesareperformed,proceedingfromlefttoright

Bearinginmindtheorderofoperations(i.e.,theprecedence),youcanuse
themathematicalfunctionsinGambastoperformjustaboutanymathematical
operationneededforyourprograms.Wewillcovereachfunction,eitherintrinsic
orderivedinthischapterandprovideexamplesofhowtheyareused.Thereisa
tableprovidedattheendofthischapterthatshowsyoutheofficialdeveloper
version of the hierarchy of operations, as defined in the gb_reserved_temp.h
Gambassourcefile.
15 See URL: http://en.wikipedia.org/wiki/Intrinsic_function.

215
A Beginner's Guide to Gambas

Abs

Absisanintrinsicfunctionthatreturnstheabsolutevalueofanumber.
Theabsolutevalueofanumberisitsunsignedmagnitude.Forexample,Abs(1)
and Abs(1) both return 1. The number argument can be any valid numeric
expression.IfnumbercontainsNull,anerrorisreturned;ifitisaninitialized
variable,zeroisreturned.StandardGambaslanguagesyntaxis:

Abs(number)

ThefollowingexampleusestheAbsfunctiontocomputetheabsolutevalueofa
number.Trythisonyourconsole:

STATICPUBLICSUBMain()
DIMMyNumASVariant

MyNum=Abs(1.03E3)
PRINTMyNum
MyNum=Abs(2.5+6.5)
PRINTMyNum
END

Acs/ACos

Acs/ACosisaderived functionthatcomputestheinversecosine(arc
cosine)ofanumber.Y=ACos(X)returnsthearccosineforeachelementofX.
ForrealelementsofXinthedomain[1,1],ACos(X)isrealandintherange.For
real elementsof X outside thedomain [1,1], ACos(X) iscomplex. The ACos
function operates elementwise on arrays. The function's domains and ranges
includecomplexvalues.Allanglesarereturnedinradians.Syntaxis:

value=ACos(Number)

Example:

PRINTAcs(0.5)
1.047197551197

PRINTAcs(1)
3.14159265359

216
A Beginner's Guide to Gambas

Acsh/ACosh

TheAcsh/ACoshisaderivedfunctionthatcomputesthehyperbolicarc
cosine(inversehyperboliccosine)ofanumber X. Itoperateselementwiseon
arrays.Allanglesareinradians.ThedomainincludesrealnumbersXsuchthat
X >= 1. The range of the hyperbolic arccosine function is limited to non
negativerealnumbersYsuchthatY>=0.Gambaslanguagesyntaxisasfollows:

value=Acsh(Number)
value=ACosh(Number)

Hereisanexampletotryontheconsole:

STATICPUBLICSUBMain()
DIMyASVariant
Y=2
PRINTAcsh(Y)
END

Theconsolerespondswith:
1.316957896925

Asn/ASin

Asn/ASinisaderivedfunctionthatcomputesthearcsineofanumber.
TheASin()functioncomputestheprincipalvalueofthearcsineofx.Thevalueof
xshouldbeintherange[1,1]. Uponsuccessfulcompletion,Asn()returnsthe
arcsineofx,intherange[p/2,p/2]radians.Ifthevalueofxisnotintherange
[1,1]0.0isreturned.TheASin()functionwillfailifthevalueusedforxisnot
intherange[1,1].StandardGambaslanguagesyntaxis:

value=Asn(Number)
value=ASin(Number)

Hereisanexample:

STATICPUBLICSUBMain()
DIMyASVariant
Y=0.5
PRINTAsn(Y)
Y=1.0
PRINTAsn(Y)

217
A Beginner's Guide to Gambas

END
Theconsolerespondswith:

0.523598775598
1.570796326795

Asnh/ASinh

Asnh/ASinhisaderivedfunctionthatcomputestheinversehyperbolic
sine (hyperbolic arcsine)for eachelementof X. The ASinh function operates
elementwise on arrays. The function's domains and ranges include complex
values.Allanglesareexpressedinradians.StandardGambaslanguagesyntaxis:

value=Asnh(Number)
value=ASinh(Number)

Anexampleisasfollows:

STATICPUBLICSUBMain()
DIMyASVariant

Y=2
PRINTAsnh(2)
END

Theconsolerespondswith:

1.443635475179

Atn/ATan

Atn / ATan is an intrinsic function that computes the arctangent of a


number.ForrealelementsofX,ATan(X)isintherange[p/2,p/2].TheATan
function operates elementwise on arrays. The function's domains and ranges
includecomplexvalues.Allanglesareinradians. Standard Gambaslanguage
syntaxis:

value=Atn(Number)
value=ATan(Number)

Example:

218
A Beginner's Guide to Gambas

STATICPUBLICSUBMain()
DIMyASVariant

Y=0.5
PRINTATan(Y)
END

Theconsolerespondswith:

0.463647609001

Atnh/ATanh

Atnh/ATanh is a derived function that computes the inverse hyperbolic


tangent(orhyperbolicarctangent)ofanumber.Thefunctionoperateselement
wiseonarrays.It'sdomainsandrangesincludecomplexvalues.Allanglesarein
radians. TheGambaslanguagesyntaxof Y=ATanh(X) returnsthehyperbolic
arctangentforeachelementofX.

value=Atnh(Number)
value=ATanh(Number)

HereisanexampleyoucantryontheconsoleusingAtanh():

STATICPUBLICSUBMain()
DIMMyResultASFloat
DIMMyNumASFloat

MyNum=0.5
MyResult=ATanh(0.5)
PRINT"Thehyperbolicarctangentof"&MyNum&"is:"&MyResult
END

Theconsolerespondswith:

0.549306144334

Cos

Cos()inanintrinsicfunctionthatreturnsthecosineofanangle.TheCos
functiontakesanangleandreturnstheratiooftwosidesofarighttriangle.The
ratioisthelengthofthesideadjacenttotheangledividedbythelengthofthe
hypotenuse.Theresultliesintherange1to1. Toconvertdegreestoradians,

219
A Beginner's Guide to Gambas

multiplydegreesby /180.Toconvertradianstodegrees,multiplyradiansby
180/ .StandardGambaslanguagesyntaxis:

Result=Cos(number)

Thenumberargumentcanbeanyvalidnumericexpressionthatexpresses
anangleinradians. ThefollowingexampleusestheCosfunctiontoreturnthe
cosineofanangle:

STATICPUBLICSUBMain()
DIMMyAngleASFloat
DIMMySecantASFloat

MyAngle=1.3'Defineangleinradians.
MySecant=1/Cos(MyAngle)'Calculatesecant.
PRINT"Secantofangle"&MyAngle&"(inradians)is:"&MySecant

END

Theconsolerespondswith:

Secantofangle1.3(inradians)is:3.738334127075

Cosh

Cosh is a derived function that computes the hyperbolic cosine of a


number. The Cosh function operates elementwise on arrays. The function's
domainsandrangesincludecomplexvalues.Allanglesareinradians.Standard
Gambaslanguagesyntaxis:

Value=Cosh(Number)

Hereisanexampletotryontheconsole:

STATICPUBLICSUBMain()
DIMMyAngleASFloat
DIMMyResultASFloat

MyAngle=1.0'Angleexpressedinradians.
MyResult=Cosh(MyAngle)
PRINT"Cosh()ofangle"&MyAngle&"(inradians)is:"&MyResult
END

Theconsolerespondswith:

220
A Beginner's Guide to Gambas

Cosh()ofangle1(inradians)is:1.543080634815

DegandRad

Degisanintrinsicconversionfunctionthatconvertsradianstodegrees.
Rad isa reciprocal conversion function thatconvertsdegreesto radians. The
GambaslanguagesyntaxforDegandRadis:

Value=Deg(Angle)
Value=Rad(Angle)

Anexampletotryontheconsoleis:

STATICPUBLICSUBMain()
PRINTDeg(Pi/2)
PRINTRad(90)
PRINTRad(180)Pi
END

Theconsolerespondswith:

90
1.570796326795
0

Exp

Expisanintrinsicfunctionthatcomputestheexponentialofanumber.It
returns e (thebaseofnaturallogarithms,wheretheconstant e isapproximately
2.718282)raisedtoapower.Thenumberargumentcanbeanyvalidnumeric
expression.Ifthevalueofnumberexceeds709.782712893,anerroroccurs.The
Exp function complements the action of the Log function and is sometimes
referredtoastheantilogarithm.TheGambaslanguagesyntaxis:

Value=Exp(Number)

Hereisanexample:

STATICPUBLICSUBMain()
PRINTExp(1)
END

221
A Beginner's Guide to Gambas

Theconsolerespondswith:

2.718281828459

HereisanotherexamplethatusestheExpfunctiontoreturneraisedtoapower:

STATICPUBLICSUBMain()
DIMMyAngleASFloat
DIMMyHSinASFloat'Defineangleinradians.

MyAngle=1.3'Calculatethehyperbolicsine
MyHSin=(Exp(MyAngle)Exp(1*MyAngle))/2
PRINTMyHSin
END

Theconsolerespondswith:

1.698382437293

FixandFrac

Fixisanintrinsicfunctionthatreturnstheintegerpartofanumber.Frac
isanintrinsicfunctionthatcomputesthefractionalpartofanumber.Notethat
intheexamplebelow,Frac()returnstheabsolutevalueofthefractionalresultof
.ThestandardGambaslanguagesyntaxis:

Value=Fix(Number)
Value=Frac(Number)

Example:

STATICPUBLICSUBMain()
PRINTFix(Pi)
PRINTFrac(Pi)
PRINTFix(Pi)
PRINTFrac(Pi)
END

Theconsolerespondswith:

3
0.14159265359
3
0.14159265359

222
A Beginner's Guide to Gambas

Int

Int(Number)returnsthemathematicalintegerpartofanumber,i.e.,the
greaterintegersmallerthanNumber.

Value=Int(Number)

Herearesomeexamplesyoucantryontheconsole:

PRINTInt(Pi)
3

PRINTInt(Pi)
4

Log

Logisanintrinsicfunctionthatcomputesthenaturallogarithmof e.The
logarithmhavingbase e.Theconstant eisapproximately2.718282whereeisa
unique number with the property that the area of the region bounded by the
hyperbola y = 1/x,the xaxis, and the vertical lines x=1 and x=e is 1. The
notationlnxisusedinphysicsandengineeringtodenotethenaturallogarithm,
whilemathematicianscommonlyusethenotationlogx.TheNumberargument
canbeanyvalidnumericexpressiongreaterthan0.StandardGambaslanguage
syntaxis:

value=Log(Number)

Hereisanexample:

STATICPUBLICSUBMain()
PRINTLog(2.71828)
PRINTLog(1)
END

Theconsolerespondswith:

0.999999327347
0

Youcancreateaderivedfunctiontocalculatebasenlogarithmsforany
numberxbydividingthenaturallogarithmofxbythenaturallogarithmofnas

223
A Beginner's Guide to Gambas

follows:

Logn(x)=Log(x)/Log(n)

Hereisanexampletotry:
STATICPUBLICSUBMain()
DIMnASFloat
DIMxASFloat
DIMlognASFloat

n=2
x=10
logn=Log(x)/Log(n)
PRINTlogn&"istheresultofLogn("&x&")"
END

Theconsolerespondswith:

3.321928094887istheresultofLogn(10)

Log10

Log10 is a derived function that computes the decimal logarithm of a


number.Log10(x)=Log(x)/Log(10).Gambaslanguagesyntaxis:

value=Log10(Number)

Example:

PRINTLog10(10)
1

MaxandMin

Maxreturnsthegreaterexpressionofthelist.Expressionsmustbenumbers
ordate/timevalues.Minreturnsthesmallerexpressionofthelist.Expressions
mustbenumbersordate/timevalues.

value=Max(Expression[,Expression...])
value=Min(Expression[,Expression...])

224
A Beginner's Guide to Gambas

Examples:

STATICPUBLICSUBMain()
PRINTMax(6,4,7,1,3)
PRINTMax(Now,CDate("01/01/1900"),Cdate("01/01/2100"))
PRINT
PRINTMin(6,4,7,1,3)
PRINTMin(Now,CDate("01/01/1900"),CDate("01/01/2100"))
END

Theconsolerespondswith:

7
01/01/2100

1
01/01/1900

Pi

Pireturnsp*Number.IfNumberisnotspecified,itisassumedtobeone.
StandardGambaslanguagesyntaxis:

Result=Pi([Number])

Examples:

PRINTPi
3.14159265359

PRINTPi(0.5)
1.570796326795

RandomizeandRnd

Randomize initializes a pseudorandom number generator. It uses a


methodology that seeds itself with the current date and time. The Gambas
languagesyntaxis:

Randomize(Number)

wherethenumberargumentcanbeanyvalidnumericexpression. Randomize
uses the parameter Number to initialize the Rnd function's randomnumber

225
A Beginner's Guide to Gambas

generator,givingitanewseedvalue.Ifyouomitnumber,thevaluereturnedby
thesystemtimerisusedasthenewseedvalue.IfRandomizeisnotused,theRnd
function(withnoarguments)usesthesamenumberasaseedthefirsttimeitis
called,andthereafterusesthelastgeneratednumberasaseedvalue. Inother
words,foranygiveninitialseed,thesamenumbersequenceisgeneratedbecause
eachsuccessivecalltotheRndfunctionusesthepreviousnumberasaseedfor
thenextnumberinthesequence.

Inordertorepeatsequencesofrandomnumbers,callRndwithanegative
argumentimmediatelybeforeusingRandomizewithanumericargument.Before
callingRnd,usetheRandomizestatementwithoutanargumenttoinitializethe
randomnumber generator with a seed based on the system timer. Using
Randomize with the same value for number does not repeat the previous
sequence.

Rndcomputesapseudorandomfloatingpointnumber,usingtheLehmer
algorithm.Ifnoparametersarespecified,Rndreturnsapseudorandomnumber
intheinterval[0,1].Ifonlyoneparameterisspecified,Rndreturnsapseudo
randomnumberintheinterval[0,Min].Ifbothparametersarespecified,Rnd
returnsapseudorandomnumberintheinterval[Min,Max].StandardGambas
languagesyntaxforRndis:

Rnd([Min[,Max])

The number argument can be any valid numeric expression. The Rnd
functionreturnsavaluelessthan1butgreaterthanorequalto0.Thevalueof
numberdetermineshowRndgeneratesarandomnumber. Toproducerandom
integersthatfallwithinanygivenrange,usethisformula:

Int((upperboundlowerbound+1)*Rnd+lowerbound)

Here, upperbound is the highest number in the range, and lowerbound is the
lowestnumberintherange.Hereisanexampleprogramtotryontheconsole:

STATICPUBLICSUBMain()
DIMDiceASInteger

PRINT"Between0and1:";
PRINTRnd
PRINT"Between0and2:";
PRINTRnd(2)
PRINT"BetweenPiandPi*2:";

226
A Beginner's Guide to Gambas

PRINTRnd(Pi,Pi(2))
PRINT
Randomize

DOWHILEDice<>1
Dice=Int(Rnd(1,7))
'producearandomnumberbetween1and6tosimulatethedicethrow
PRINT"Youthrewa"&dice
LOOP
END

Theconsolerespondswith:

Between0and1:7.826369255781E6
Between0and2:0.263075576164
BetweenPiandPi*2:5.515396781706

Youthrewa6
Youthrewa4
Youthrewa1

Round

RoundroundsanumbertoitsnearestintegerifDigitsisnotspecified.If
Digitsisspecified,roundsto10^Digits.

Value=Round(Number[,Digits])

Example:

STATICPUBLICSUBMain()
PRINTRound(Pi,2)
PRINTRound(1972,2)
END

Theconsolerespondswith:

3.14
2000

Sgn

Sgnreturnsanintegerindicatingthesignofanumber. Ifthenumberis
zero, it returns zero. If the number is strictly positive, it returns the integer

227
A Beginner's Guide to Gambas

number+1.Ifthenumberisstrictlynegative,itreturnstheintegernumber1.
Gambaslanguagesyntaxis:

Sign=Sgn(Number)

Example:

STATICPUBLICSUBMain()
PRINTSgn(Pi)
PRINTSgn(Pi)
PRINTSgn(0)
END

Theconsolerespondswith:

1
1
0

Sin

Sinisanintrinsicfunctionthatcomputesthesineofanangle.Theangleis
specified in radians. The sine function sin x is one of the basic functions
encounteredintrigonometry(theothersbeingthecosecant, cosine,cotangent,
secant,andtangent).Let beananglemeasuredcounterclockwisefromthex
axisalonganarcoftheunitcircle.Thensinistheverticalcoordinateofthearc
endpoint.Asaresultofthisdefinition,thesinfunctionisperiodicwithperiod2.
BythePythagoreantheorem,sinalsoobeystheidentitysin2 + cos2 = 1. The
standardGambaslanguagesyntaxforSinis:

Value=Sin(Angle)

Example:

STATICPUBLICSUBMain()
PRINTSin(Pi/2)
END

Theconsolerespondswith:
1

228
A Beginner's Guide to Gambas

Sinh

Sinhisaderivedfunctionthatcomputesthehyperbolicsineofanumber.
StandardGambaslanguagesyntaxforSinhis:

Value=Sinh(Number)

ThefollowingexampleusestheExpfunctiontocalculatehyperbolicsineofan
angle:

STATICPUBLICSUBMain()
DIMMyAngleASFloat
DIMMyHSinASFloat'Defineangleinradians

MyAngle=1.3'Calculatehyperbolicsine
MyHSin=(Exp(MyAngle)Exp(1*MyAngle))/2
PRINTMyHSin
END

Theconsolerespondswith:
1.698382437293

Sqr

Sqrisanintrinsicfunctionthatreturnsthesquarerootofanumber.The
numberargumentcanbeanyvalidnumericexpressiongreaterthanorequalto0
(nonnegative).TheGambaslanguagesyntaxis:

Value=Sqr(Number)

Hereisanexample:

PRINTSqr(2)
1.414213562373

Thefollowingexampleuses theSqrfunctiontocalculate thesquarerootofa


number:

STATICPUBLICSUBMain()

DIMMySqrASFloat

229
A Beginner's Guide to Gambas

MySqr=Sqr(4)'Returns2
PRINTMySqr&"istheresultofSqr(4)"
MySqr=Sqr(23)'Returns4.795831523313
PRINTMySqr&"istheresultofSqr(23)"
MySqr=Sqr(0)'Returns0
PRINTMySqr&"istheresultofSqr(0)"

'MySqr=Sqr(4)'Generatesaruntimeerror
'PRINTMySqr&"istheresultofSqr(4)"
END

Theconsolerespondswith:

2istheresultofSqr(4)
4.795831523313istheresultofSqr(23)
0istheresultofSqr(0)

Tan

Tanisanintrinsicfunctionthatcomputesthetangentofanangle.The
angleargumentcanbeanyvalidnumericexpressionthatexpressesananglein
radians.Tantakesanangleandreturnstheratiooftwosidesofarighttriangle.
Theratioisthelengthofthesideoppositetheangledividedbythelengthofthe
sideadjacenttotheangle.Toconvertdegreestoradians,multiplydegreesbypi/
180. To convert radians to degrees, multiply radians by 180/pi. Standard
Gambaslanguagesyntaxis:

Value=Tan(angle)

ThefollowingexampleusestheTanfunctiontoreturnthetangentofanangle:

STATICPUBLICSUBMain()
DIMMyAngleASFloat
DIMMyCotangentASFloat

MyAngle=1.3'Defineangleinradians.
MyCotangent=1/Tan(MyAngle)'Calculatecotangent.
PRINTMyCotangent
PRINTTan(Pi/4)
END

Theconsolerespondswith:

0.277615646541

230
A Beginner's Guide to Gambas

Tanh

Tanh is a derived function that computes the hyperbolic tangent of a


number.ThestandardGambaslanguagesyntaxforTanhis:

Value=Tanh(Number)

Example:

STATICPUBLICSUBMain()
PRINTTanh(1)
END

Theconsolerespondswith:
0.761594155956

DerivedMathFunctions

Thenonintrinsic(derived)mathfunctionsshowninthetablebeloware
providedinGambasfromthebuiltinintrinsicmathfunctions.

Gambas Derived Math Functions


Function Derivedequivalents
InverseSine ASin(X)=Atn(X/Sqr(X*X+1))
InverseCosine ACos(X)=Atn(X/Sqr(X*X+1))+2*Atn(1)
HyperbolicSine Sinh(X)=(Exp(X)Exp(X))/2
HyperbolicCosine Cosh(X)=(Exp(X)+Exp(X))/2
HyperbolicTangent Tanh(X)=(Exp(X)Exp(X))/(Exp(X)+Exp(X))
InverseHyperbolicSine ASinh(X)=Log(X+Sqr(X*X+1))
InverseHyperbolicCosine ACosh(X)=Log(X+Sqr(X*X1))
InverseHyperbolicTangent ATanh(X)=Log((1+X)/(1X))/2
Logarithmtobase10 Log10(X)=Log(X)/Log(N)

Belowisatablelistingotherderivedmathfunctionsthatcanbebuiltusingthe
formulasshowninthetablebelow:

231
A Beginner's Guide to Gambas

Other Derived Math Functions


Secant Sec(X)=1/Cos(X)
Cosecant Cosec(X)=1/Sin(X)
Cotangent Cotan(X)=1/Tan(X)
InverseSecant Arcsec(X)=Atn(X/Sqr(X*X1))+Sgn((X)1)*(2*Atn(1))
InverseCosecant Arccosec(X)=Atn(X/Sqr(X*X1))+(Sgn(X)1)*(2*Atn(1))
InverseCotangent Arccotan(X)=Atn(X)+2*Atn(1)
HyperbolicSecant HSec(X)=2/(Exp(X)+Exp(X))
HyperbolicCosecant HCosec(X)=2/(Exp(X)Exp(X))
HyperbolicCotangent HCotan(X)=(Exp(X)+Exp(X))/(Exp(X)Exp(X))
InverseHyperbolicSecant HArcsec(X)=Log((Sqr(X*X+1)+1)/X)
InverseHyperbolicCosecant HArccosec(X)=Log((Sgn(X)*Sqr(X*X+1)+1)/X)
InverseHyperbolicCotangent HArccotan(X)=Log((X+1)/(X1))/2
LogarithmtobaseN LogN(X)=Log(X)/Log(N)

Since Gambas does not directly provide you with builtin functions for
theseotherderivedfunctions,wearegoingtobuildamodulethatwillextend
Gambascapabilitiesbyprovidingallofthefunctionslistedinthetableaboveasa
finalexerciseinthischapter.OurmodulewillbenamedDerivedandyouwillbe
able to access all of the functions in your code by using the format
Derived.function_namewherefunction_namewillbeoneofthefunctionswebuild
in the next section. Start Gambas and create a terminal application named
MyMath. Createanewclass,Class1fromtheIDEandmakeitastartupclass.
NextcreateanewmoduleandnameitDerived.Openthenewcodewindowfor
theClass1.classfileandenterthefollowing:
'Gambasclassfile
STATICPUBLICSUBMain()
DIMmyValASFloat

myVal=51.5
WHILEmyVal<>0.0

PRINT"Enteranumber>1orenter0toquit:";
LINEINPUTmyVal
IFmyVal=0.0THENBREAK

IFmyVal<=1.0THEN
PRINT"Numberwas<=1.0"
CONTINUE
ENDIF

232
A Beginner's Guide to Gambas

PRINTDerived.Sec(myVal)&"issecant"
PRINTDerived.CoSec(myVal)&"iscosecant"
PRINTDerived.CoTan(myVal)&"iscotangent"
PRINT
PRINTDerived.ArcSec(myVal)&"isarcsecant"
PRINTDerived.Arccosec(myVal)&"isarccosecant"
PRINTDerived.Arccotan(myVal)&"isarccotangent"
PRINT
PRINTDerived.HSec(myVal)&"ishyperbolicsecant"
PRINTDerived.HCoSec(myVal)&"ishyperboliccosecant"
PRINTDerived.HCoTan(myVal)&"ishyperboliccotangent"
PRINT
PRINTDerived.HArcSec(myVal)&"ishyperbolicarcsecant"
PRINTDerived.HArcCoSec(myVal)&"ishyperbolicarccosecant"
PRINTDerived.HArcCoTan(myVal)&"ishyperbolicarccotangent"
PRINT
PRINTDerived.LogN(myVal,2)&"isLogNof:"&myVal&"tobase2"
PRINT"ofmyVal:"&myVal
WEND
END

Now,openthecodewindowfortheDerived.modulefileandenterthiscode:

'GambasDerived.modulefile
PUBLICFUNCTIONSec(xASFloat)ASFloat
DIMresultASFloat
result=1.0/Cos(x)
RETURNresult
END

PUBLICFUNCTIONCoSec(xASFloat)ASFloat
DIMresultASFloat
result=1.0/Sin(x)
RETURNresult
END

PUBLICFUNCTIONCoTan(xASFloat)ASFloat
DIMresultASFloat
result=1.0/Tan(x)
RETURNresult
END

PUBLICFUNCTIONArcSec(xASFloat)ASFloat
DIMresultASFloat
result=Atn(x/Sqr(x*x1))+(Sgn(x)1)*(2*Atn(1))
RETURNresult
END

233
A Beginner's Guide to Gambas

PUBLICFUNCTIONArccosec(xASFloat)ASFloat
DIMresultASFloat
result=Atn(x/Sqr(x*x1))+(Sgn(x)1)*(2*Atn(1))
RETURNresult
END

PUBLICFUNCTIONArccotan(xASFloat)ASFloat
DIMresultASFloat
result=Atn(x)+(2*Atn(1))
RETURNresult
END

PUBLICFUNCTIONHSec(xASFloat)ASFloat
DIMresultASFloat
result=2.0/(Exp(x)+Exp(x))
RETURNresult
END

PUBLICFUNCTIONHCoSec(xASFloat)ASFloat
DIMresultASFloat
result=2.0/(Exp(x)Exp(x))
RETURNresult
END

PUBLICFUNCTIONHCoTan(xASFloat)ASFloat
DIMresultASFloat
result=(Exp(x)+Exp(x))/(Exp(x)Exp(x))
RETURNresult
END

'thisroutinecurrentlyproducesanerrorinGambas
'ifyoutrytousetheformularesult=Log((Sqr(x*(x+1))+1)/x)
'becausetheLogfunctiononlyworkswithnonnegativenumbers
'bydesign.Thisisaworkaroundtogetyouthesameresults

PUBLICFUNCTIONHArcsec(xASFloat)ASFloat
DIMresultASFloat
DIMTemp1ASFloat
DIMTemp2ASFloat
DIMTemp3ASFloat

Temp1=((x*1)*(x+1))+1
Temp2=Sqr(Abs(Temp1))
Temp3=Log(Temp2)
result=Temp3*1

'thiscallwillgenerateanerrorbecausethe
'Sqrfunctionwillnotworkwithnegativevalues
'result=Log((Sqr(x*(x+1))+1)/x)

234
A Beginner's Guide to Gambas

RETURNresult
END

PUBLICFUNCTIONHArccosec(xASFloat)ASFloat
DIMresultASFloat
result=Log((Sgn(x)*Sqr(x*x+1)+1)/x)
RETURNresult
END

PUBLICFUNCTIONHArccotan(xASFloat)ASFloat
DIMresultASFloat
result=Log((x+1)/(x1))/2
RETURNresult
END

PUBLICFUNCTIONLogN(xASFloat,nASFloat)ASFloat
DIMresultASFloat
result=Log(x)/Log(n)
RETURNresult
END

Whenyouruntheprogram,youwillreceiveaprompttoenteranumber>
1or0toquit.Enter4andyoushouldseethefollowingresults:

Enteranumber>1orenter0toquit:4
1.529885656466issecant
1.321348708811iscosecant
0.863691154451iscotangent

0.85707194785isarcsecant
0.801529994232isarccosecant
2.896613990463isarccotangent

0.036618993474ishyperbolicsecant
0.036643570326ishyperboliccosecant
1.000671150402ishyperboliccotangent

1.472219489583ishyperbolicarcsecant
0.247466461547ishyperbolicarccosecant
0.255412811883ishyperbolicarccotangent

2isLogNof:4tobase2
ofmyVal:4
Enteranumber>1orenter0toquit:

Now, you should be able to perform almost any type of mathematical


operationnecessaryformostprograms. Youhaveabsorbedalotofmaterialin

235
A Beginner's Guide to Gambas

thischapteranditistimetotakeabreaknow.Inthenextchapter,wearegoing
tocoverthebasicconceptsofobjectoriented(OO)programmingandshowyou
howpowerfulGambascanbewhenyoutakeadvantageoftheseOOfeatures.

236
A Beginner's Guide to Gambas

Chapter 11 Object-Oriented Concepts


In the field of computer science, objectoriented programming (OOP) is
considered a computer programming paradigm. The general idea is that a
computerprogramiscomposedofacollectionofindividualunits(calledobjects),
each of which is capable of receiving messages, processing data, and sending
messages to other units or objects. This differs from the traditional view of
programmingwhereaprogramisseenasalistofinstructionsthatareexecutedin
asequentialorderbythecomputer.

Proponents of objectoriented programming have claimed the approach


gives programmersmoreflexibilityandfacilitatesmakingchangestoprograms
when needed. The paradigm is very popular in companies and government
entitiesthatconductsoftwareengineeringanddevelopmentasamatterofcourse.
Furthermore, many people believe OOP to be easier to learn for novice
programmers when compared with other languages such as Java, C++, etc.
OOP,theyclaim,issimplertodevelopandmaintainandthatitlendsitselftoa
better understanding of complex situations and procedures than other
programmingmethods.

There are an almost as many critics of the OO paradigm as there are


proponents.SomeofthemostcommonargumentscriticsraisearethatOObased
languageslikeSmalltalk,Lisp,andothershavehadtheirprogressstalledwiththe
adventofnewerlanguageslikeC++,C#,andJava.Small,interpretedlanguages
likeTcl,Perl,andPythonhavedevelopedafairlylargefollowingbuttheyarenot
makinganyprogressinthedevelopmentofatrueOOparadigm.Criticsalsohave
saidtheobjectorientedapproachdoesnotadequatelyaddressfuturecomputing
requirements.Theyfeelobjectorientedlanguageshavesacrificedsimplicitythe
verythingthatmakesprogrammingapproachabletoawideraudience.Java,for
example, is an extremely complex implementation of OO concepts. Others
contend concepts like encapsulation and inheritance, which were originally
intendedtosaveprogrammersfromthemselveswhiledevelopingsoftware,have
failedbecausetheyimplementglobalproperties. Modularityisanotherwayof
keepingthingslocalinscopesopeoplecanunderstandcodebetter. Thatwas
whatencapsulationwassupposedtoaccomplish. Today,opensourcesoftware
seemstohaveevolvedaworkableapproachtotheproblemofcodemaintenance,
althoughitisnotwithoutitsownissues.

Objects promised reuse, and the programming community has not seen

237
A Beginner's Guide to Gambas

much success with that. The ability to maintain a program once it has been
writtenandtodolocalizeddebuggingandtodomuchlargerdevelopmentefforts
arealso reasonscited assignificant advantagesgained withtheuseofobject
oriented programming languages (OOPLs). In the 1990s, overoptimism
regarding the benefits of OO programming led businesses to expect miracles.
When software developers could not deliver on the outrageous business plans
basedonthosepromises,2001sawbusinessesfalllikedominos,leavingtheentire
techindustry inarecession. DefunctcompanieslitteredSilicon Valleylikeso
manybleachedbonesinadesert.

Fortunately, Gambas takes a very pragmatic approach to the


implementation of OO concepts, leveraging what works and, unlike C++,
avoidingthatwhichwillnoteverworkwell.TheGambasimplementationisan
elegant compromise between true OO theory and the business realities
programmershavetocontendwithtoday.

OOPisoftencalledaparadigmratherthanastyleortypeofprogramming
toemphasizethepointthatOOPcanchangethewaysoftwareisdevelopedby
changingthewaythatprogrammersandsoftwareengineersthinkaboutsoftware.
Much ofthe evolution of any language depends on theOS thatsupports that
language. Withtheadventof Linux andthehugegroundswellofsupportfor
opensourcesoftware,thefuturelooksverybrightforGambas.Now,let'stakea
lookatsomeofthebasicOOconceptsthatGambassupports.

FundamentalsofObjectOrientedProgramming

Objectorientedprogrammingisbaseduponseveralkeyconcepts:objects,
data abstraction, encapsulation, polymorphism, and inheritance. One
distinguishing feature of OOP is the methods used for handling data types.
Objecttypedataisgenerallyrequiredtosatisfyprogrammerdefinedconstraints.A
datatyperestrictedtoaspecificobjectisconsideredtobea private datatype.
Thistypeoflanguageimposedconstraintrestrictingdatatypestospecificobjects
forcesprogrammers(bydesign)tocodewithoutrelyingoncreatingalaundrylist
ofvariablesvisibletoeveryobjectintheprogram(globalvariables). Variables
canbeusedanddisposedofwithintheobjectorclassinwhichtheyareneeded
and they do not affect other parts of a program. The actions taken by the
program where such variables are used are referred to as methods. In more
traditionallanguages,methodsequatetofunctionsorsubroutines.InOOP,these
constraints also may extend to the use of methods and are not exclusive to
variables.

238
A Beginner's Guide to Gambas

Objectorientedlanguagesprovideinternalmechanismsforensuringthat
variablesandmethodsareonlyvisibleandavailablewithinthescopeoftheclass
ormethodinwhichtheyaredeclared.Albeit,somevariablesandmethodsare
designed to be visible to all other methods or classes of a project. In those
instances, they are referred to as public variables and methods. In Gambas,
variablesandmethodsthatarepublicareglobalinscopetotheclassinwhichthey
aredeclared.Variablesmeanttobevisibleonlytothemethodsinwhichtheyare
declaredas private withinagivenclassarecreatedwiththeDIMkeywordin
Gambas.

Objects

Objects arecomprisedofallthedataandfunctionalitythatexistwithin
distinct units in a running (executing) computer program. Objects are the
foundation of modularity and structure in an OOPL. They have two basic
attributes: they are selfcontained and they are uniquely identifiable. Having
thesetwoattributesallowsallofthevariousprogramcomponentstocorrelate
variablesinaprogramwithvariousrealworldaspectsofaproblemforwhicha
programisintendedtosolve.

DataAbstraction

DataAbstractionDataabstractionisamethodologyusedinOOPLsthat
enablesaprogrammertospecifyhowadataobjectisused.Abstractionallowsa
programmertoisolatedataobjectsfromtheunderlyingdetailsofhowthedatais
created(usuallybyusingevenmoreprimitivedataobjects).Inotherwords,the
useofadataobject,comprisedofoneormoreprimitivedataobjects, allowsa
programmer to structure his or her code to use data objects that operate on
abstractdata.

Dataobjectsthatarecomprisedofoneormoreprimitivedataobjectsare
called compound data objects. With abstraction, the program can use data
withoutmakinganyassumptionsaboutit(i.e.,theunderlyingdetailsofhowor
wherethatdatacamefrom)thatisn'tnecessaryforperformingagiventask. A
concretedatarepresentationisdefinedindependentofanyprogramsthatusethe
data.Theinterfacebetweentheconcreteandabstractdataisasetofprocedures,
called constructors, that implement abstract data in terms of the concrete
representation.Methods(subroutinesandfunctions)mayalsobesoabstractedin
theOOPparadigm.

239
A Beginner's Guide to Gambas

Encapsulation

EncapsulationEnsuresthatusersofanobjectcannotchangetheinternal
state of the object in unexpected ways; only the object's internally defined
methodsareallowedtoaccessitsstate(orattributes). Eachobjectexposesan
interfacethatspecifieshowotherobjectsmayinteractwithit.Otherobjectswill
not know of this object's internal methods and must therefore rely upon this
object'sinterfaceinordertointeractwithit.

Polymorphism

Polymorphismmeanstheabilitytotakemorethanoneform.InOOPLs,it
refers to a programming language's ability to process objects differently
depending on the datatype or class. More specifically, polymorphism is the
abilitytoredefinemethodsforderivedclasses.Anoperationmayexhibitdifferent
behaviorsindifferentcircumstances.Thebehaviorisdependentuponthedata
type used in the operation. For example, given a base class named shape,
polymorphism enables the programmer to define different methods of area
calculation for any number of derived classes, such as circles, rectangles and
triangles.Nomatterwhatshapeanobjectis,applyingtheareamethodtoitwill
return the correct results. Polymorphism is used extensively in OOPLs when
implementing inheritance and is considered to be a requirement of any true
OOPL.

Inheritance

Inheritance istheprocessbywhichobjectscanacquirethepropertiesof
objectsthatexistinanotherclass.InGambas,allofthecontrolsoftheToolBox
inheritthepropertiesoftheclassnamedControl. InOOP,inheritanceprovides
reusability and extensibility (adding additional features to an existing class
withouttheneedtomodifyit).Thisisachievedbyderivinganewclassfroman
existingclassandmakingchangestothenewinstanceofthatclass.Thenewclass
willhavecombinedthefeaturesofbothclasses.Inheritanceallowsobjectstobe
defined and created that are specialized implementations of alreadyexisting
objects. They can share (and extend) the existing object's behavior without
havingtoreimplementit.

240
A Beginner's Guide to Gambas

TheGambasApproachtoOOP

AnOOprogramisgenerallydesignedbyidentifyingalloftheobjectsthat
willexistinasystem.Thecodewhichactuallydoestheworkisirrelevanttothe
objectduetoencapsulation. ThebiggestchallengeinOOPisofdesigningan
objectsystemthatisunderstandableandmaintainable. Itshouldbenotedthat
therearedistinctparallelsbetweentheobjectorientedparadigmandtraditional
systems theory. While OOP focuses on objects as units in a system, systems
theory focuses on the system itself. Somewhere in between, one may find
software design patterns or other techniques that use classes and objects as
building blocks for larger components. Such components can be seen as an
intermediate step from the objectoriented paradigm towards the more
pragmaticallyorientedmodelsofsystemstheory.SuchappearstobetheGambas
approachtoOOP.Itisanelegant,pragmaticsolutionthattakesthebestofboth
approachesandmakesprogrammingeasyandsimple.

Gambashastriedtokeepsimplicityattheforefrontofanapproachthat
leverages OO concepts and compromises with systems theory where it makes
goodsense. Inthatregard,Gambashastakena classbasedapproach toOOP.
TheclassbasedOOPapproachisanOOPparadigmwheretheconceptofaclassis
central.Inthisapproachencapsulationpreventsusersfrombreakinginvariantsof
theclass.Classinvariantsareestablishedduringconstructionandareconstantly
maintained between calls to public methods. Temporarily breaking class
invariancebetweenprivatemethodcallsispossible,althoughitisnotencouraged.
Sometimes,itisusefulbecauseitallowstheimplementationofaclassofobjects
to be changed for aspects not visible to or exposed inside the class interface
withouthavinganimpactonusercodethatmayhaveimplementedfeaturesof
thatclass.

ThedefinitionofencapsulationinaclassbasedOOPparadigmfocuseson
groupingandpackagingofrelatedinformation(cohesion).OOPlanguagesdonot
normallyofferformalsecurityrestrictionstotheinternalobjectstate. Usinga
methodofaccessisamatterofconventionfortheinterfacedesign.Inheritanceis
typicallydonebygroupingobjectsintoclassesanddefiningclassesasextensions
ofexistingclasses. Thisgroupingofclassesissometimesorganizedintotreeor
latticestructures,oftenreflectingacommonsetofbehaviors.

GambasClasses

InGambas,youcandefineyourownclasses. Rememberthataclassis

241
A Beginner's Guide to Gambas

merelytemplatethatisusedbytheprogramatruntime. Theclassitselfisnot
useddirectly.Touseaclass,youmustmakeavariabledeclarationoftheclass
datatype,createacopyoftheclassfortheprogramtouse,theninstantiatethe
copy.Theinstantiatedcopyiscalledanobject.Sinceaclassisarealdatatype,
thedeclarationoftheobjectlookslikeanyothernormalvariabledeclaration:

object_nameASClass_name

Instantiatinganobjectmeanstocreateanewinstanceofthetemplateandassign
that instance the name on the left side of the equal sign. In GB, this is
accomplishedusingtheNEWkeyword:

object_name=NEWClass_name

Whenobject_nameisinstantiatedasanewcopyofthetemplatedefinedby
Class_name,theprogramminglanguageallows object_name toinheritallofthe
methods and attributes of Class_name. When the new object is created, it
automaticallyinvokesaconstructortoinitializeitselfwithdefaultvariables.Itis
important to note that the current version of Gambas does not support the
conceptofvirtualdispatch.Inotherwords,whenyouinvokeamethod(orset/get
a property value) for an object reference using the dot notation (i.e.,
class.object.method),themethodthatisactuallyexecutedisthemethodbelonging
tothedatatypeofthevariablethatownstheobjectreference,notthemethodof
therealdatatypeoftheobject.InGambas2,thisissuehasbeencorrected.

Sampleprogram:Contacts

ToillustratetheuseofaclassinGambas,wearegoingtocreateasample
programthatimplementsacontactsbook.Itisgoingtobefairlysimplebutwill
beusefultomaintaincontacts.Tobegin,createanewprojectnamedClassesand
whenyougettotheIDE,createaclass(notastartupclass)namedContact.This
iswherewewillstartwithourprogram,buildingaclassdefinitionforaContact.

TheContactclass

'GambasContact.classfile
PUBLICFirstNameASString
PUBLICLastNameASString
PUBLICInitialASString
PUBLICSuffixASString
PUBLICStreet1ASString

242
A Beginner's Guide to Gambas

PUBLICStreet2ASString
PUBLICCityASString
PUBLICStateASString
PUBLICZip5ASString
PUBLICZip4ASString
PUBLICAreacodeASString
PUBLICPrefixASString
PUBLICLast4ASString
PUBLICRecordIDASInteger

Wewantourclasstoprovidetwomethods,onetoretrieveourcontactdata
fromthefileitisstoredinandonetoputdataintothatfile.Appropriately,the
twomethodswillbenamedContact.GetDataandContact.PutData.

Contact.GetDataMethod

Let's start with the GetData method, which is decleared as a function


becauseitwilltakeacollectionvariableasaparameterandreturnacollection
filledwithdatafromthecontacts.datafileifthatdataexists.Wewilldeclarelocal
variableswithinourmethodsbyusingtheDIMkeyword. Notethatwecould
declare these variables as PRIVATE outside of the method definitions and it
wouldrenderthemvisibleonlytothemethodswithinthecontactclass.However,
declarationslocaltothemethodthemselvesfurtherrestrictsthescopeandmakes
theentireclassfilecleanerinappearancefromauserperspective.Theywillsee
allthepublicmethodsandvariablesandnothingmore.

Thecollectionvariableispassedinasaparameterfromtheconstructorcall
inForm1.classsoitisnotnecessarytodeclareitseparately. Thefunctionwill
returnacollectionvariablesoweadd ASCollection totheendofthefunction
declaration.WewillshowhowthecollectionvariablecTheDataispassedtothis
functionwhenitiscalledfromtheForm1.classfile.
PUBLICFUNCTIONGetData(cTheDataASCollection)ASCollection

'thisstringvarwillholdeachlineofdatareadfromthefile
DIMsInputLineASString

'weneedafilehandleandtwostringvarsforbuildingfilenames
DIMhFileInASFile
DIMfilenameASString
DIMfullpathASString

'thisclassvariableisusedtoconvertthestringdatawereadin
'fromfileintoacontactrecord.Wedeclarethevariablehereand

243
A Beginner's Guide to Gambas

'willinstantiateitbelow
DIMMyContactRecordASContact

'alocalintegervartokeeptrackofhowmanyrecordsweadded
DIMRecordNumASInteger

'thisvariablewilltakethestringreadinandconvertallthefields
'thatarecommadelimitedintoanarrayusingthesplitstatement
DIMarsInputFieldsASString[]

'thiscounterisusedtoloopthroughthearrayandassignvalues
'tothecontactrecords
DIMcounterASInteger

filename="contacts.data"'hardcodedbecauseitwillnotchange

'wewillusethecurrentdirwheretheappistobuildfullpathname
fullpath=Application.Path&/filename

'now,seeifthefilealreadyexists,ifsoopenitforREAD.
IFExist(fullpath)THEN
OPENfullpathFORREADAS#hFileIn

'startwithrecord1
RecordNum=1

'wewillloopthrougheverylineofdatauntilwereachEndoffile
WHILENOTEof(hFileIn)
'everycontactaddedtothecollectionmustbeinstantiated
'eachtimearecordisaddedtothecollection.YouCAN
'reusethesameclassvarforeachreinstantiationthough.
MyContactRecord=NEWContact'hereiswhereitrenewsitself

'readthelineinfromfileandstoreinstringvarsInputLine
LINEINPUT#hFileIn,sInputLine

'usedforconsoledebugging
PRINT"Reading:"&sInputLine

'now,fillourarrayofstringsusingSplittoconverttheline
'ofstringdatareadintofieldsinanarray
arsInputFields=Split(sInputLine,",")

'fordebugonlytoshowthatallfieldsconvertcorrectly
FORcounter=0TO14
PRINT"Loading:"&arsInputFields[counter]
NEXT

'now,weputthefielddataintoourlocalcontactclassvar

244
A Beginner's Guide to Gambas

'andwilladdthatcontactrecordtothecollectionofcontacts
MyContactRecord.FirstName=arsInputFields[0]
MyContactRecord.Initial=arsInputFields[1]
MyContactRecord.LastName=arsInputFields[2]
MyContactRecord.Suffix=arsInputFields[3]
MyContactRecord.Street1=arsInputFields[4]
MyContactRecord.Street2=arsInputFields[5]
MyContactRecord.City=arsInputFields[6]
MyContactRecord.State=arsInputFields[7]
MyContactRecord.Zip5=arsInputFields[8]
MyContactRecord.Zip4=arsInputFields[9]
MyContactRecord.Areacode=arsInputFields[10]
MyContactRecord.Prefix=arsInputFields[11]
MyContactRecord.Last4=arsInputFields[12]
MyContactRecord.RecordID=CInt(arsInputFields[13])
MyContactRecord.Deleted=CBool(arsInputFields[14])

'fordebugoutputtotheconsole
PRINT"Addingdataforrecord:"&RecordNum&"";
PRINTMyContactRecord.FirstName&""&MyContactRecord.LastName

'allrecordfieldsareassigneddata,soweaddtocollection
cTheData.Add(MyContactRecord,CStr(RecordNum))

'fordebugoutputtotheconsole
PRINTcTheData[CStr(RecordNum)].LastName&"stored."

'incrementourrecordcounterandclearthesInputLinevariable
INCRecordNum
sInputLine=""
WEND'loopformorerecords

'closethefilewhennomorerecordsexistinthefile
CLOSE#hFileIn
ELSE'nofilefound,putupamessagetotheuser
Message.Info("Nocontacts.datafilepresent.","OK")
ENDIF

'fordebugonly,wewilllistalltherecordsinthecollection
PRINT"HereiswhatisstoredincTheData:"
FOREACHMyContactRecordINcTheData
PRINTMyContactRecord.FirstName&""&MyContactRecord.LastName
NEXT
RETURNcTheData'returnthecollection(nowfilled)withdata
END'ofGetData

245
A Beginner's Guide to Gambas

Contact.PutDataMethod

The reciprocal routine to GetData is PutData, where we will store the


collectionofdata that isconsidered mostcurrent. Whatevereditsorchanges
havebeenmadewillbereflectedinthissaveoperation.Wewillsavethedateto
afile,storingtherecordasacommadelimitedstring. Eachlineofoutputwill
representonecontactrecord. ThePutDatamethodisdeclaredasasubroutine
sinceitdoesnotreturnavariable. Ittakesoneparameter,thecollectionobject
wewishtostore.cTheDataisthecollectionpassedtothissubroutine.

PUBLICSUBPutData(cTheDataASCollection)

'thisstringvarwillholdeachlineofdatareadfromthefile
DIMsInputLineASString

'weneedafilehandleandtwostringvarsforbuildingfilenames
DIMhFileOutASFile
DIMfilenameASString
DIMfullpathASString

'thisclassvariableisusedtoconvertthestringdatainto
'acontactrecord.Wedeclarethevariablehereand
'willinstantiateitbelow
DIMMyContactRecordASContact

'alocalintegervartokeeptrackofhowmanyrecordsweadded
DIMRecordNumASInteger

'instantiateanewrecordthatisblank.Notethatsincewearenot
'addingthisrecordtoacollection,itisnotnecessarytorenew
'itbyreinstantiatingiteachtime.
MyContactRecord=NEWContact

'startatrecord1
RecordNum=1

'wehaveahardcodedfilenamesoweonlyneedthepathtotheprogram
'becausewewillstorethedatawheretheprogramresides.
filename="contacts.data"
fullpath=Application.Path&/filename

'wehavetospecifyWRITECREATEwhenweopenthefile.Ifthefile
'exists,itwillbeopenedforWRITE.Ifitdoesnotexist,thenwe
'willcreateanewfileandwritetothat.
OPENfullpathFORWRITECREATEAS#hFileOut

'now,weloopthrougheachrecordinthecollection.Notethatwe

246
A Beginner's Guide to Gambas

'usetheFOREACHconstructtodothis.
FOREACHMyContactRecordINcTheData

'weconcatenateeachfieldtothelast,insertingcommas
'tobeusedasfielddelimitersforthereadoperation

sInputLine=sInputLine&MyContactRecord.FirstName&","
sInputLine=sInputLine&MyContactRecord.Initial&","
sInputLine=sInputLine&MyContactRecord.LastName&","
sInputLine=sInputLine&MyContactRecord.Suffix&","
sInputLine=sInputLine&MyContactRecord.Street1&","
sInputLine=sInputLine&MyContactRecord.Street2&","
sInputLine=sInputLine&MyContactRecord.City&","
sInputLine=sInputLine&MyContactRecord.State&","
sInputLine=sInputLine&MyContactRecord.Zip5&","
sInputLine=sInputLine&MyContactRecord.Zip4&","
sInputLine=sInputLine&MyContactRecord.Areacode&","
sInputLine=sInputLine&MyContactRecord.Prefix&","
sInputLine=sInputLine&MyContactRecord.Last4&","
sInputLine=sInputLine&MyContactRecord.RecordID&","
sInputLine=sInputLine&CStr(MyContactRecord.Deleted)&","
'fordebugonly,toshowwhatisbeingstored
PRINT"Storing:"&sInputLine

'thiscallisactuallywhatputsthedataintothefile
PRINT#hFileOut,sInputLine

'clearoutourstringvartobereusedinthenextiteration
sInputLine=""

NEXT'iterationofthelooptoenumerateobjects
'gotthemallwrittennow,soclosethefile
CLOSE#hFileOut
RETURN'withoutpassingavariableback,hencesubroutine
END

Form1.classfile

Save the Contact.class file and close it. Our contact class definition is
completesonowwewillneedtocreateaformnamedForm1.Form1willserve
asthemaininterfacebetweentheuserandtheprogramandit'sdata. Hereis
whatourfinishedformwilllooklike:

247
A Beginner's Guide to Gambas

Figure74FinishedContactsprogram.
Ourprogramwillallowausertoadd,changeordeleteacontactandstore
thatdatatoadatafile.Contactdataismanagedinourprogramasacollectionof
objectsthatareoftypeContact,whichwedefinedintheContact.classfileabove.
Wewillallowtheusertomovetotheveryfirstiteminthecollection,scrollto
nextorpreviousitems,gotothelastitem,updatedataonthecurrentform,save
thecurrentdatatofile,andexit.Allinall,itdoesmostofthebasicsnecessaryfor
contactmanagement. Wewillalsoaddasearchfeature(usingamodule)that
willfindthefirstinstanceofacontactbysearchingforalastname.Amazingly,to
accomplishallofthistakesverylittlecodeinGambas!

Now,let'slookattheprogramthatwillusethecontactclass.Theprogram
willrequirefourpublicvariables,asshownbelow. Our constructorroutine will
automatically look for and load the default contact file, which we named
contacts.data.Itisnotnecessaryfortheusertoknoworusethisfilenamesoitis
hardcodedintothemethodswhereitisused.Iftheconstructorroutine_new()
cannotloadafile,itwillcreateonedummyrecordsotheuserneverseesablank
startupscreen.

'GambasForm1classfile

'Contactswillrepresentthecollectionofrecordsfortheaddrbook
PUBLICContactsASCollection

'representsasinglecontactrecordusedbyallsubroutines
PUBLICContactRecordASContact

'indexthatpointstothecurrentrecord
PUBLICRecordPointerASInteger

'wewillneedastringvartousewhentheusersearchesbylastname
PUBLICSearchKeyASString
Form1Constructor

248
A Beginner's Guide to Gambas

'theconstructorroutinecalledwhenform1_open()iscalled
PUBLICSUB_new()

'instantiatethecollectionthatwillholdouraddressrecords
Contacts=NEWCollection

'instantiateanewcontact(record)thatisblank
ContactRecord=NEWContact

'fordebugonly
PRINT"CallingGetData..."

'calltheGetDatamethoddefinedinthecontactclassdefinition
ContactRecord.GetData(Contacts)

'settherecordpointertothelastrecordfoundinthedataset
RecordPointer=Contacts.Count

'fordebugonly
PRINT"In_new(),rtnfmGetDatawith:"&RecordPointer&"records."

'thedefaultconstructorwillensureatleastonerecordexists
'iftheContactscollection'scountpropertyshows<1record.
IFRecordPointer<1THEN
'addourdummydata
ContactRecord.FirstName="John"
ContactRecord.Initial="Q"
ContactRecord.LastName="Public"
ContactRecord.Suffix="II"
ContactRecord.Street1="12345GambasDrive"
ContactRecord.Street2="Apt101"
ContactRecord.City="Dancer"
ContactRecord.State="TX"
ContactRecord.Zip5="77929"
ContactRecord.Zip4="0101"
ContactRecord.Areacode="888"
ContactRecord.Prefix="666"
ContactRecord.Last4="4444"
ContactRecord.RecordID=1
ContactRecord.Deleted=FALSE
RecordPointer=ContactRecord.RecordID
Contacts.Add(ContactRecord,CStr(ContactRecord.RecordID))
ENDIF

'checkourcollectiontomakesurerecordsexist
IFContacts.Exist(CStr(RecordPointer))THEN

'fordebugonly

249
A Beginner's Guide to Gambas

PRINT"Recorddataexistsfor"&CStr(RecordPointer)&"records."

'thisforloopisfordebugonly
FOREACHContactRecordINContacts
PRINTContactRecord.FirstName&""&ContactRecord.LastName
NEXT
ELSE

'ifnorecords,putupaMessageBoxtoinformuser
Message.Info("Recordsdonotexist!","Ok")
ENDIF
END

Form_OpenSubroutine

Our program will automatically open the form using the Form_Open()
subroutine below. Since Form1.form is defined as a startup form, it is not
necessarytocalltheForm1.Showmethod.Allwearegoingtodohereissetthe
captiontodisplayatthetopofthewindowwhentheprogramrunsandgetthe
recordpointedtobythecurrentrecordpointer.Inthiscase,thepointershould
pointtothelastrecordloadedfromthecontactsfileafterprogramflowreturns
fromtheconstructor.
PUBLICSUBForm_Open()
'settheprogramcaption
Form1.Caption="ContactsManager"

'startwiththerecordpointedtoaftertheconstructorcall
'whichshouldbethelastrecordinthecollection
ContactRecord=Contacts[CStr(RecordPointer)]
'thissubroutinewillrefreshallfieldswithcurrentrecorddata
UpdateForm
END

AddingControlstoForm1.Form

Itistimetoputallofthecontrolsontheformandgivethemnames.We
willbeusingnineToolButtons,oneregularButton,14labelsand13TextBoxes.
We will also need to use nine icons, which we can obtain from the
usr/share/icons/defaultkde/32x32folder(NOTE:yoursystemmaybedifferentso
browsearoundtofindwheretheiconsarestoredifneeded).TheiconsIusedfor
thisprogramareasfollows:

250
A Beginner's Guide to Gambas

Startofdata Prev Next Endofdata Clearfields

Updatefields Addnew Deletecurrent Savetofile

The ToolButtons

The nine ToolButtons that use these icons in their Picture property are
named:

FirstRecordBtn PrevRecordBtn NextRecordBtn


LastRecordBtn ClearBtn Update
AddBtn DeleteRecordBtn SaveAllBtn

CreatenineToolButtonsandarrangethemontheformasshowninthe
figureatthebeginningofthischapter. Assignthenamesshownabovetothe
ToolButtonsandsettherespectivebuttonPicturepropertiestothenamesofthe
icons you chose for your program, based on what your system distribution
provides. Worst case scenario is that you can use the builtin icon editor in
Gambastocreateyourownicons.

The Quit Button

OnceyouhavecompletedtheToolButtons,wewilladdtheregularbutton
asourQuitbutton.SelectaButtonfromtheToolBoxandplaceitontheform
inthelowerrightcorner,ascloseasyoucantoFigure74.SettheTextproperty
forthisbuttontoQuit.Aslongaswearehere,wecancodetheprogram'sexit
routine,whichwillbecalledwhenthisbuttonisclicked.DoubleclickontheQuit
buttonandyouwillbeplacedinthecodeeditor.Addthiscode:

PUBLICSUBQuitBtn_Click()

'prompttosavedatabeforewequit
SELECTMessage.Question("Savebeforeexit?","Yes","No","Cancel")
CASE1
'iftheusersaysyes,wesave
SaveAllBtn_Click

CASE2'wedon'tsave,justclose

251
A Beginner's Guide to Gambas

CASE3'theycanceled,sowereturntotheprogram
RETURN

CASEELSE'wedonothingbutclose

ENDSELECT

ME.Close'hereweclosethewindow
END'programstops

Adding the Labels and TextBoxes

Probablythemosttediouspartofdevelopingthisprogramisnext,adding
theLabelandTextBoxcontrolstotheform.Trytoarrangethemasyouseein
Figure74above.FortheLabelcontrols,youcantakethedefaultvariablenames
providedbyGambasforallofthelabelsexcepttheoneatthebottomoftheform
where we will display our Record n of n data. That label should be named
StatusLabel. TheTextboxfields,asshownfromtoplefttobottomrightonthe
form,shouldbenamedasfollows:

FirstName
MI
LastName
Suffix
Street1
Street2
City
State
Zip5
Zip4
AreaCode
DialPrefix
DialLast4

Hopefully, the names should be selfexplanatory (i.e., selfdocumenting


code)andyouhavenoproblemscreatingtheform.Becarefultousethecorrect
caseandtypethenamesexactlyasshownabove,otherwiseyouwillbetracking
downundeclaredvariableswhenyoutrytoruntheprogram.Atthispoint,your
form,indesignmode,shouldlooklikethis:

252
A Beginner's Guide to Gambas

Figure75Form1seenindesignmode.

UpdateForm()Subroutine

TheUpdateForm()routinewillbecalledeverytimedataontheformhas
changedandneedstoberefreshedsotheuserwillseetheupdatesastheyoccur.
This routine posts each field on the form with the current data found in the
collection based on the current record pointer. Also, the label StatusLabel is
updatedwiththecurrentrecordnumberofnrecordsinthecollectionfromhere.
Let'swalkthroughthecode:

PUBLICSUBUpdateForm()

'checktoensuretherearerecordsbeforewedoanything
IFContacts.Exist(CStr(RecordPointer))THEN

'wefoundrecordssonowwemovetotherecordatcurrentpointer
ContactRecord=Contacts[CStr(RecordPointer)]

'fordebugonly
PRINT"InUpdateFormwithRecordPointerof:"&RecordPointer

'assignTextbox.Textvalueswhateverisstoredinthecontactrecord
FirstName.Text=ContactRecord.FirstName
MI.Text=ContactRecord.Initial
LastName.Text=ContactRecord.LastName
Suffix.Text=ContactRecord.Suffix
Street1.Text=ContactRecord.Street1
Street2.Text=ContactRecord.Street2
City.Text=ContactRecord.City
State.Text=ContactRecord.State
Zip5.Text=ContactRecord.Zip5
Zip4.Text=ContactRecord.Zip4
AreaCode.Text=ContactRecord.Areacode

253
A Beginner's Guide to Gambas

DialPrefix.Text=ContactRecord.Prefix
DialLast4.Text=ContactRecord.Last4

'updatethecurrentrecordstatusfieldwithcurrentdata
StatusLabel.Text="Record:"&CStr(RecordPointer)
StatusLabel.Text=StatusLabel.Text&"of"&CStr(Contacts.Count)

'calltheRefreshmethodtorepainttheformcontents
Form1.Refresh

'selectthecontentsoftheFirstNamefield
FirstName.Select

'setthecursorfocustotheFirstNamefield
FirstName.SetFocus
ELSE'norecordsexist!
'fordebugonly
PRINT"InUpdateForm,Record:"&RecordPointer&"notfound."
ENDIF
'fordebugonly
PRINT"LeavingUpdateForm..."
END

Coding Toolbuttons: First, Prev, Next, and Last

The first ToolButton we will code is the one that will move us to the
beginningofthedata. DoubleclickonthefirstToolButtonandyoushouldbe
takentothecodewindowwheretheFirstRecordBtn_Click()routineawaits.Add
thiscode:
PUBLICSUBFirstRecordBtn_Click()
'movetothefirstrecord
RecordPointer=1

'retrievethatrecordfromthecollection
ContactRecord=Contacts[CStr(RecordPointer)]

'updatetheformdisplaywiththenewdata
UpdateForm
END

Asyoucansee,movingtothefirstrecordwasprettysimple.Now,wewill
codethePrevandNextbuttons.DoubleclickonthesecondToolButton()and
youwillbetakentothePrevRecordBtn_Click()subroutine.Addthiscode:

PUBLICSUBPrevRecordBtn_Click()

254
A Beginner's Guide to Gambas

'fordebugonly
PRINT"inPrev:currentpointeris:"&RecordPointer

'wearemovingtoalowerrecordsowedecrementtherecordpointer
DECRecordPointer

'ifwemovedpastrecord1thenresettorecord1
IFRecordPointer=0THEN
RecordPointer=1
ENDIF

'updateourcontactvaraiblewiththenew(prev)recorddata
ContactRecord=Contacts[CStr(RecordPointer)]

'ifwearealreadyatthebeginningofthedatanotifytheuser
IFRecordPointer=1THEN
'fordebugonly
PRINT"Atfirstcontactalready!"
ELSE
'fordebugonly
PRINT"inPrevnowcurrentpointeris:"&RecordPointer
ENDIF
'updateourformwiththenewdata
UpdateForm
END

Now,wewillcodetheNextbutton.DoubleclickonthethirdToolButton
()andyouwillbetakentotheNextRecordBtn_Click()subroutine. Addthis
code:
PUBLICSUBNextRecordBtn_Click()

'fordebugonly
PRINT"inNext:currentpointeris:"&RecordPointer

'wemoveforwardthroughthecollectionsoweincrementthepointer
INCRecordPointer

'ifwemovedpastthelastrecord,resettothelastrecord
IFRecordPointer>Contacts.CountTHEN
RecordPointer=Contacts.Count
ENDIF

'updatethecontactrecordwiththenewdata
ContactRecord=Contacts[CStr(RecordPointer)]

'ifwearealreadyatthelastrecord,telltheuser
IFRecordPointer=Contacts.CountTHEN

255
A Beginner's Guide to Gambas

'fordebugonly
PRINT"AtLastcontactalready!"
ELSE
'fordebugonly
PRINT"inNext,thecurrentpointeris:"&RecordPointer
ENDIF

'updateourformagainwiththenewdata
UpdateForm
END'nextrecordmove

ThelastToolButtonweneedtocodeformovingaroundinthedataisfor
theLastRecordBtn_Click()subroutine.Thissubroutinewillplaceusattheendof
thedatacollection,atthelastrecord.DoubleclickonthefourthToolButtonand
addthiscode:

PUBLICSUBLastRecordBtn_Click()
'setrecordpointertolastrecordusingcollection.countproperty.
RecordPointer=Contacts.Count
'updateourrecordvarwiththenewdataforthelastrecord
ContactRecord=Contacts[CStr(RecordPointer)]
'updatetheformwiththenewdata
UpdateForm
END

Coding ToolButtons: Adding a record

Now,let'sgothroughhowtoaddanewcontacttothecollection.Double
clickonthefifthToolButton,thelittlepersonicon,andyouwillbeputinthecode
windowattheAddBtn_Click()subroutine.Let'sgothroughthecode:
PUBLICSUBAddBtn_Click()

'declarealocalcontactvaraiblejustforuseinthissubroutine
DIMMyContactRecordASContact

'instantiatethecontactrecordsowecanuseit
MyContactRecord=NEWContact

'ifthereisnofirstname,wewillnotaddarecord
IFFirstName.Text<>""THEN
'fordebugonly
PRINT"Adding"&FirstName.Text&"tocollection."

'weareheresowefoundafirstname.AssigntheTextboxdata
'tothefieldsstoredintherecord:
MyContactRecord.FirstName=FirstName.Text

256
A Beginner's Guide to Gambas

MyContactRecord.LastName=LastName.Text
MyContactRecord.Initial=MI.Text
MyContactRecord.Suffix=Suffix.Text
MyContactRecord.Street1=Street1.Text
MyContactRecord.Street2=Street2.Text
MyContactRecord.City=City.Text
MyContactRecord.State=State.Text
MyContactRecord.Zip5=Zip5.Text
MyContactRecord.Zip4=Zip4.Text
MyContactRecord.Areacode=AreaCode.Text
MyContactRecord.Prefix=DialPrefix.Text
MyContactRecord.Last4=DialLast4.Text

'incrementtherecordkeysoeachkeyisuniquewhenaddedto
'thecollection.Gambasrequiresthatthisbeconvertedtoa
'stringvariablewhenweactuallyadditbelow.
MyContactRecord.RecordID=Contacts.Count+1

'ifweaddingarecorditisnottaggedasdeleted
MyContactRecord.Deleted=FALSE

'setglobalrecordpointertothevalueoftheincrementedkey
RecordPointer=MyContactRecord.RecordID

'now,calltheCollection.Addmethodtoaddtherecord
Contacts.Add(MyContactRecord,CStr(RecordPointer))

'thisisfordebugonlytoshowwhathasbeenadded
IFContacts.Exist(CStr(RecordPointer))THEN
'fordebugonly
PRINT"Record"&CStr(RecordPointer)&"added!"
ELSE
'fordebugonly
PRINT"Recorddoesnotexist!"
ENDIF
ELSE'cannotaddacontactwithoutafirstname,telluser
Message.Info("Cannotaddwithoutafirstname","Ok")
ENDIF

'updatetheformwiththenewdata
UpdateForm

'thisisfordebugpurposes,showallrecordsinthecollection
FOREACHMyContactRecordINContacts
PRINT"Record"&CStr(RecordPointer)&":";
PRINTMyContactRecord.FirstName&""&MyContactRecord.LastName
NEXT
END'addroutine

257
A Beginner's Guide to Gambas

Coding ToolButtons: Clearing data

ThesixthToolButtonisusedtoclearthedataontheformtoallowusersto
startwithafresh,blankformtoenterdata. ItsimplyblanksouteachTextbox
field.DoubleclickontheClearBtnandenterthiscode:
PUBLICSUBClearBtn_Click()
FirstName.Text=""
MI.Text=""
LastName.Text=""
Suffix.Text=""
Street1.Text=""
Street2.Text=""
City.Text=""
State.Text=""
Zip5.Text=""
Zip4.Text=""
AreaCode.Text=""
DialPrefix.Text=""
DialLast4.Text=""
END

ValidatingUserInput

WhentheuserentersdataintheInitialfield,andalsointheSuffix,State,
Zip5,Zip4,AreaCode,DialPrefixandDialLast4fields,wewanttoensurethatthe
data fits and they cannot enter extraneous letters or characters. Each of the
routinesbelowareactivatedonachangeevent.Inotherwords,ifthetextinthe
TextBox.Textfieldchanges,itwillgototherespective_Change()routinebelow.
Eachroutineworksalmostidenticallytolimitthenumberofcharacterstheuser
can type. If they type more, the extra characters are truncated at the length
specifiedbytheprogram.Forexample,anareacodecanbenomorethanthree
digits.Wecouldalsoaddcodetoensureonlydigitsareenteredinnumericfields,
etc.,butthatisnotwhywearebuildingthisprogram.WIwillleavethattoyou
toaddasanexerciseattheendofthischapter.Foreachcheckbelow,wewill
need a temporary string var, sTemp. If the length of the TextBox.Text data
exceedsthelengthweallow,weuseMID$tocopythefirstnletterstosTempand
thencopythatvaluebackintotheTextBox.Textproperty.
PUBLICSUBMI_Change()
DIMsTempASString

IFLen(MI.Text)>1THEN
sTemp=Mid$(MI.Text,1,1)
MI.Text=sTemp

258
A Beginner's Guide to Gambas

ENDIF
END

PUBLICSUBSuffix_Change()
DIMsTempASString

IFLen(Suffix.Text)>3THEN
sTemp=Mid$(Suffix.Text,1,3)
Suffix.Text=sTemp
ENDIF
END

PUBLICSUBState_Change()
DIMsTempASString

IFLen(State.Text)>2THEN
sTemp=Mid$(MI.Text,1,2)
State.Text=sTemp
ENDIF
END

PUBLICSUBZip5_Change()
DIMsTempASString

IFLen(Zip5.Text)>5THEN
sTemp=Mid$(MI.Text,1,5)
Zip5.Text=sTemp
ENDIF
END

PUBLICSUBZip4_Change()
DIMsTempASString

IFLen(Zip4.Text)>4THEN
sTemp=Mid$(MI.Text,1,4)
Zip4.Text=sTemp
ENDIF
END

PUBLICSUBAreaCode_Change()
DIMsTempASString

IFLen(AreaCode.Text)>3THEN
sTemp=Mid$(AreaCode.Text,1,3)
AreaCode.Text=sTemp
ENDIF
END

PUBLICSUBDialPrefix_Change()

259
A Beginner's Guide to Gambas

DIMsTempASString

IFLen(DialPrefix.Text)>3THEN
sTemp=Mid$(DialPrefix.Text,1,3)
DialPrefix.Text=sTemp
ENDIF
END

PUBLICSUBDialLast4_Change()
DIMsTempASString

IFLen(DialLast4.Text)>4THEN
sTemp=Mid$(DialLast4.Text,1,4)
DialLast4.Text=sTemp
ENDIF
END

Asyoucansee,lotsofrepetitivebutnecessarycode.Youcangobacklater
andbulletprooftheinputofthisprogrambyaddingadditionalvalidationchecks
foreverypossiblethingyoucanthinkofbutIwillshowyoulaterinthisbooka
better way, building a customized InputBox that will perform the validation
processautomatically.

AddingaSearchFeature

Wewanttheusertobeabletofindacontactbysearchingforalastname.
There are so many controlson ourformnow that adding another onewould
detractfromtheoverallaestheticsandmakeitappearlessthanelegant.Abetter
solutionistouseamouseclickanywhereontheformitself.Itgeneratesanevent
andwillallowustocapturethateventandinitiateasearchprocess.Whenthis
happens,wearegoingtopopupacustomizedsearchformandprompttheuser
toenteralastnametowhichwewilluseasakeyforoursearch.Createanevent
forMouseDownontheform.HereisthecodefortheMouseDownevent:

PUBLICSUBForm_MouseDown()
SearchForm.ShowModal
Message.Info("Backtomainformwith:"&SearchKey,"Ok")
DoFind
END

NotethatweshowtheformusingtheShowModalmethodinsteadofjust
callingShow.Thisisbecausewewanttheusertoentersomethingandclickthe
Searchbutton.Hereiswhattheformitselflookslikeindesignmode:

260
A Beginner's Guide to Gambas

Prettybasic,justalabel,aTextbox,andabutton.FromtheIDEcreatea
newform,named SearchForm and add thelabel and buttonas shown below.
NamethebuttonSearchBtnandtheTextBoxshouldbenamedSearchInput.Here
isallthecodethatisneededfortheSearchForm:

'GambasSearchFormclassfile

PUBLICSUBSearchBtn_Click()

'thisisacalltoourcustommodule,search,whichhas
'asinglemethod,SearchOn,thatisexplainedbelow
Search.SearchOn(SearchInput.Text)

'fordebugonly
PRINT"returning:"&SearchInput.Text

'assignthesearchkeytotheglobalvarwenamedinForm1
Form1.SearchKey=SearchInput.Text

'nowcloseoursearchform
SearchForm.Close
END

PUBLICSUBForm_Open()
'setthecaptionforthesearchwindow
SearchForm.Caption="Findbylastname"

'highlightandselecttheSearchInputTextbox
'sincethereisonlyoneinputfield,ithasfocusalready
SearchInput.Select
END

Atthispoint,youmightbewonderingwhatexactlyisgoingon.Basically,
in Gambas, public variables are public to a class file. When we want to pass
parameters between classes,wecanusethemethodofpassingparameterswith

261
A Beginner's Guide to Gambas

functions like we did when we started the program and passed an empty
collectionvariabletotheGetDatamethod.

Another waytoaccomplishthisisby using modules. Thekey pointto


rememberisthatpublicvariablesinmodulesarepublictoallclasses.Essentially,
allwehavedoneiscreateaconduittopassoursearchkeyfromthesearchform
backtothemainprogramviathemodule.Notethattheonlycodeneededinthe
moduleisastatementthattakestheparameterpassedfromthesearchformand
returnsittothemainprogram.Assoonasitcomesbackfromthemodule,itis
assignedtotheForm1classpublicvariableSearchKey. Alsonotethatwefully
qualified the variable name, specifying Form1.SearchKey to ensure it resolves
correctly. This is necessary because the SearchButton_Click() subroutine that
invokedthemoduleisinadifferentclassfilethantheForm1classfilethatcalled
it.

'Gambasmodulefile

PUBLICFUNCTIONSearchOn(sKeyASString)ASString
RETURNsKey
END

The DoFind Subroutine

Atthispoint,wehavepoppeduptheform,obtainedtheuserinputofalast
nametosearchfor,andhavepassedthatvariablebacktoourprogramusingthe
moduleconduitmethoddescribedabove.Now,wearereadytoactuallysearch
thecollectionandfindtheentry.Hereisthecodetodothat:
PUBLICSUBDoFind()

'declareacontactobjectforlocaluse
DIMMyContactRecordASContact

'instantiateit
MyContactRecord=NEWContact

'settherecordpointertothefirstrecordinthecollection
RecordPointer=1

'fordebugonly
PRINT"InDoFindwith:"&SearchKey

'useFOREACHtoiteratethrougheachobjectinthecollection
FOREACHMyContactRecordINContacts

262
A Beginner's Guide to Gambas

'assigneachtemprecordtoourglobalcontactobject
ContactRecord=Contacts[CStr(RecordPointer)]

'ifthelastnamematchessearchkey,updatetheformandleave
IFContactRecord.LastName=SearchKeyTHEN
'fordebugonly
PRINT"Found:"&MyContactRecord.LastName
'nowupdatetheform
UpdateForm
BREAK'forcereturnwiththisstatement
ENDIF
'nomatchsoweincrementtherecordpointerandmovetothenext
INCRecordPointer
NEXT
END

ToolButtonsagain:UpdatingaRecord

Iftheuserhappenstoeditdataonanexistingrecordwhenitisdisplayed,
wewantthedatatobesavedtothesamerecord. Toaccomplishthisusinga
collectionobjectiscomplicatedbythefactthateachobjectinthecollectionmust
haveauniquekey.Togetaroundthis,wewilldeletetheobjectwiththecurrent
keyusingthebuiltinmethodRemove,andreaddtheobjectusingthesamekey
butwithupdateddata. Sortofsneaky,butitgetsthejobdonewithoutmuch
effort.Hereishowitworks:
PUBLICSUBUpdate_Click()
'declarealocalcontactobjectforustoworkwith
DIMMyContactRecordASContact

'instantiateit
MyContactRecord=NEWContact
'nowremovetheexistingrecordinthecollection
Contacts.Remove(CStr(RecordPointer))

'thenwepopulateourworkrecordwiththeformdata
MyContactRecord.FirstName=FirstName.Text
MyContactRecord.LastName=LastName.Text
MyContactRecord.Initial=MI.Text
MyContactRecord.Suffix=Suffix.Text
MyContactRecord.Street1=Street1.Text
MyContactRecord.Street2=Street2.Text
MyContactRecord.City=City.Text
MyContactRecord.State=State.Text
MyContactRecord.Zip5=Zip5.Text
MyContactRecord.Zip4=Zip4.Text
MyContactRecord.Areacode=AreaCode.Text

263
A Beginner's Guide to Gambas

MyContactRecord.Prefix=DialPrefix.Text
MyContactRecord.Last4=DialLast4.Text

'addtheworkcopytothecollectionwiththesame
'keythatbelongedtotherecordwedeletedabove
Contacts.Add(MyContactRecord,CStr(RecordPointer))

IFContacts.Exist(CStr(RecordPointer))THEN
'fordebugonly
PRINT"Record"&CStr(RecordPointer)&"updated!"
ELSE
PRINT"Recordnotupdated!"'wewantthisoutputififfailed
ENDIF
'updatetheformwiththenewdata
UpdateForm
END

Toolbuttonsagain:DeletingaRecord

Iftheuserwantstodeletearecordinacollectionwealsohavetothink
abouthowtohandlethat.Managingwhichkeysareavailableandwhicharenot
couldbeaprogrammer'snightmaresoaneasierapproachistosimplymarkthe
recordasdeletedandblankit.Thatway,itisavailableforreusewiththesame
key.Itblanksoutthedataand,whenthesaveoccurs,doesnotstoretheolddata,
effectivelydeletingit.Onlydifferenceis,wecanreusethekeybyhavingtheuser
simplyenterdatainanemptyrecordandclicktheupdatebutton.Hereishow
thisisaccomplished:
PUBLICSUBDeleteRecordBtn_Click()

'declareourlocalcontactobject
DIMMyContactRecordASContact

'instantiateit
MyContactRecord=NEWContact

'removethecurrentrecordusingthebuiltinRemovemethod
Contacts.Remove(CStr(RecordPointer))

'clearallthefieldsontheform
ClearBtn_Click

'setthefirstfieldwithanindicatorthattherecordisdeleted
MyContactRecord.FirstName="<DeletedRecord>"

'leavetherestblankbysimplyassigningthemafterclearing
MyContactRecord.LastName=LastName.Text

264
A Beginner's Guide to Gambas

MyContactRecord.Initial=MI.Text
MyContactRecord.Suffix=Suffix.Text
MyContactRecord.Street1=Street1.Text
MyContactRecord.Street2=Street2.Text
MyContactRecord.City=City.Text
MyContactRecord.State=State.Text
MyContactRecord.Zip5=Zip5.Text
MyContactRecord.Zip4=Zip4.Text
MyContactRecord.Areacode=AreaCode.Text
MyContactRecord.Prefix=DialPrefix.Text
MyContactRecord.Last4=DialLast4.Text

'markrecordasdeleted
MycontactRecord.Deleted=TRUE

'addtheblanked,deletedrecordasitexiststothecollection
Contacts.Add(MyContactRecord,CStr(RecordPointer))

IFContacts.Exist(CStr(RecordPointer))THEN
'fordebuggingonly
PRINT"Record"&CStr(RecordPointer)&"markeddeleted!"
ELSE
'ifitfails,wewantamessage
Message.Info("Recordnotmarkeddeleted!","Ok")
ENDIF
'updatetheform
UpdateForm
END

ToolButtonsagain:SavingData

Thelastthingweneedtocodeisthesavebutton. Thisisreallysimple
becausewehavealreadybuiltamethodinourContactclassfiletodothat.Here,
allwedoiscallthePutDatamethod:

PUBLICSUBSaveAllBtn_Click()

'invokethePutDatamethod
ContactRecord.PutData(Contacts)
'fordebugonly
PRINT"Contactssavedtocontact.datafile."
END

Thatisallwehavelefttodo.Runtheprogramandentersomedata.Be
suretotryalltheoptionsandcreateafewrecords. Saveyourdatatofileand
reloadit.Whenyouaresatisfiedthatitworksasweplanned,itisoktogoback
andcommentoutalltheconsoleoutput(thePRINTstatements)sotheywillnot

265
A Beginner's Guide to Gambas

displayatruntime. Foralltheotherprogramswehavecreated,wehavebeen
contenttosimplyexecutethemfromwithintheIDE.Sincethisprogramcanbea
usefuladditiontoyourdesktop,wewillnowshowyouhowtocreateastand
aloneexecutableandallowittorunindependentoftheGambasprogramming
environment.

CreatingaStandaloneExecutable

Itisveryeasytocreatetheexecutable.Simplymakesureyourprogramis
readyforrelease(testitfirst!)andthengototheProjectmenuandchooseMake
Executable.TheGambasIDEwillcreateanexecutionscriptthatwillinvokethe
GambasInterpreterandallowyoutoexecuteyourcode.Icreatedadesktoplink
totheprogramandusedthisfortheapplicationpathonmysystem:

'/rittingj/MyDocuments/GambasforBeginners/Classes/Classes'

Of course, your system will be different. You will need to point the
desktoplinktotheapplicationtowhereeveryouhadtheIDEsavetheexecutable
file.OntheLinuxdistributionIusedforthisprogram,itwouldnotworkuntilI
enclosedthefullpathwithtickmarks,asshownabove. Becausethe Gambas
Interpreter isinvokedasasystemcall,theticksareneededtokeepthesystem
from thinking it is passing parameters to /rittingj/My (where the first space
characteroccurs).Hereisthefinalresult,ourprogramexecutinginstandalone
modeonthedesktop:

Figure76ContactsManagerrunningstandaloneonmydesktop.

266
A Beginner's Guide to Gambas

Chapter 12 Learning to Draw


TheDrawclassistheclassusedinGambasfordrawingonanobject.The
objectmaybeoftypePicture,Window,Printer,Drawing,orDrawingAreaobject.
This class isstatic. Itisimportanttorememberthatbeforestarting todraw
anything,youmustcallthe Begin methodbypassingitahandletotheobject
typeyouwanttodraw. Onceyoudo that,you cancallanyofthedrawing
methodsGBprovidestodrawpoints,lines,texts,pictures,etc.However,itisnot
clearlydocumentedthatyoumustalsosettheDrawingArea'sCachedpropertyto
Trueifyouwanttoseeyourdrawingappearontheform.Whenyourdrawingis
finished,youmustcalltheEndmethod.

DrawProperties

EachitemyouwishtodrawinGambasissupportedwithseveralcommon
attributes,suchasbackgroundcolorandforegroundcolor,afillcolor,fillstyle,
etc. SomepropertiesinGambas,suchasClip,arereadonlyandsimplyreturn
datatoyouforuseinyourcode.

BackColor/BackgroundandForeColor/Foreground

As we explained in Chapter 4, many of the properties for controls are


common among all controls, so we will only explain the properties that are
uniquetoagivencontrolinthischapter.

BackColorisdefinedasPROPERTYBackColorASInteger
ForeColorisdefinedasPROPERTYForeColorASInteger

Thisintegervaluerepresentsthecolorusedforthecurrentdrawingbackground
or foreground color. It is synonymous with the Background/Foreground
properties. Note that PROPERTY is a predefined datatype used internally in
Gambas. You can usetheGambas predefined constantsfor color tosetcolor
value:

Black Blue Cyan DarkBlue


DarkCyan DarkGray DarkGreen DarkMagenta
DarkRed DarkYellowDefault Gray
Green LightGray Magenta Orange
Pink Red TransparentViolet
White Yellow

267
A Beginner's Guide to Gambas

TosettheBackColorpropertytored,youwouldusethiscode:

Draw.BackColor=Color.Red

Alternatively,aswestatedpreviously,ifyouknowtheRGBorHSVvalues
foraspecificcolor,GBprovidesameanstoconvertthosevaluestoaninteger
valuethatcanbepassedtotheBackColor(orothercolorrelated)property.The
Colorclass providestwomethods,RGBandHSVthatyoucan use. The RGB
functionreturnsacolorvaluefromitsred,greenandbluecomponents. HSV
returnsacolorvaluefromitshue,saturationandvaluecomponents.Touseone
ofthesefunctionstosetthebutton'sbackgroundcolor,hereiswhatyoucould
code:

Draw.BackColor=Color.RGB(255,255,255)

ThiswouldsettheDrawobject'sbackgroundcolortowhite.Thisismostuseful
whenyouaretryingtosetcolorswhosevaluesfalloutsidethedefaultconstants
valuesprovidedinGB.

Clip

The Clipclass isstatic.Clipisareadonlypropertythatreturnsavirtual


object(.DrawClip)thatisusedformanagingtheclippingareaofadrawing.The
virtualclass.DrawClip isusedfordefiningthe clippingarea ofadrawing. The
Gambas drawing methods never draw outside the boundaries of the defined
clippingarea. Youcannotusethisvirtualclassasadatatype. Thestandard
Gambaslanguagesyntaxis:

STATICPROPERTYREADClipAS.DrawClip

Thisclasscanbeusedasafunction.Toinvokethefunctiontodefineaclipping
area,usethisGambaslanguagesyntax:

STATICSUB.DrawClip(XASInteger,YASInteger,WASInteger,HASInteger)

Properties that are returned by this function include Enabled, H, Height, W,


Width,XandY.

FillColor,FillStyle,FillX,FillY

The FillColorproperty returnsorsetsthecolorusedbydrawingmethods

268
A Beginner's Guide to Gambas

capableoffillingapolygonwithacolororpatternorboth. Thisclassisstatic.
TheFillStylepropertyreturnsorsetsthestyleusedbydrawingmethodscapable
offillingapolygonwithacolororpatternorboth.TheFillclasssupportsseveral
predefinedFillStyleconstantsusedtorepresentfillpatternsfordrawing:

BackDiagonal Cross CrossDiagonal Dense12


Dense37 Dense50 Dense6 Dense63
Dense88 Dense94 Diagonal Horizontal
None Solid Vertical

GambaslanguagesyntaxforFillColorandFillStyleisasfollows:

STATICPROPERTYFillColorASInteger
STATICPROPERTYFillStyleASInteger

The FillX property and the FillY property are used to return or set the
horizontal/vertical origin of the brushes used by drawing methods capable of
fillingapolygonwithacolororpatternorboth. Gambaslanguagesyntaxfor
FillXandFillYis:

STATICPROPERTYFillXASInteger
STATICPROPERTYFillYASInteger

Font

The Font class returns or sets the font used for rendering text on the
drawingsurface.Gambaslanguagesyntaxis:

STATICPROPERTYFontASFont

Tosetcontrolfontattributes,thiscodecanbeused:

Draw.Font.Name="Lucida"
Draw.Font.Bold=TRUE
Draw.Font.Italic=FALSE
Draw.Font.Size="10"
Draw.Font.StrikeOut=FALSE
Draw.Font.Underline=FALSE

Invert

The Invert property is used to stipulate that all drawing primitives will
combinetheirpixelcolorswiththepixelcolorsofthedestinationusinganXOR
operation.Gambaslanguagesyntaxis:

269
A Beginner's Guide to Gambas

STATICPROPERTYInvertASBoolean

LineStyle/LineWidth

The LineStyle property returns or sets the style used for drawing lines.
LineWidthreturnsorsetsthewidthusedfordrawinglines.TheLineclassisstatic
anddefinestheconstantsusedbytheDraw.LineStyleproperty.Theseconstants
include:

Dash Dot DashDot


DashDotDot None Solid

StandardGambaslanguagesyntaxis:
STATICPROPERTYLineStyleASInteger
STATICPROPERTYLineWidthASInteger

Transparent

The Transparent property indicates that some drawing methods like


Draw.Text do not fill their background with anything (hence, they are
transparent).Gambaslanguagesyntaxis:

STATICPROPERTYTransparentASBoolean

DrawMethods

OneofthebestwaystolearnhowtouseGambasdrawingmethodsisto
writecodethatdemonstratestheuseofeachmethod. Inthismanner,youcan
seehowtoprogramthemethodandgetimmediategratificationbyseeingthe
results.Wearegoingtobuildademoapplicationthatwillshowyouhowtouse
nearlyallofthemethodsthataresupportedbytheDrawclass.

Wewillstartbecreatinganewgraphicaluserinterfaceapplication.Name
theprojectgfxDemoandwhentheIDEappears,createaform,Form1.Makesure
youspecifyitasastartupclassandensurethecontrolsarepublic.Hereiswhat
theForm1layoutwilllooklikeatruntime:

270
A Beginner's Guide to Gambas

Figure77gfxDemoForm1layout.
Settheformwidthto530andtheheightto490.Thedefaultsettingsfor
allotherpropertiesshouldbefineforourpurposes. Createeightbuttonsand
label them as shown in the picture above. The button names are TextBtn,
InvRectBtn, EllipseBtn, FillRectBtn, PolygonBtn, PolyLineBtn, TileBtn, and
QuitBtn.Eachbuttonshouldhaveawidthof60andaheightof25.Placethem
aslowontheformasyoucanwithoutcuttingoffthebottomofthebutton.For
eachbuttonyouhavecreated,wewillneedtocreateaclickeventbydouble
clickingonthebutton.

Aswegothroughtheexplanationsofeachofthefollowingmethods,we
willbeaddingcodewhereappropriate.Beforewegettothemethodsthemselves,
thereareacoupleofthingsweneedtodowithourprogram.First,weneedto
addaDrawingAreacontrol,nameddatotheform.Placeitatthetopleftcorner
ofForm1andmakeitabout1inchby1inch.Wewilldynamicallyresizeitinour
program.Next,wewilluseaconstructortostartthedrawingprocess,invoking
the Draw.Begin method and setting the parameters that will be used for our
program.Hereistheconstructorsubroutineyouneedtoadd:

PUBLICSUB_new()
'establishwidthofthedrawingarea
da.W=form1.W10

'establishheightofthedrawingarea
da.H=form1.H45

'makethemandatorycalltostartdrawoperations
Draw.Begin(da)
'setadefaultlinewidthof2pixels

271
A Beginner's Guide to Gambas

Draw.LineWidth=2
END

When the form opens at program start, it will first call the constructor
above,thenexecutethecodeintheForm_Opensubroutine.Allwearegoingto
doforthissubroutineissetthecaptionatthetopoftheform:

PUBLICSUBForm_Open()
Form1.Text="DrawingExamples"
END

ThefinalroutinewewillcreatebeforeexploringtheDrawmethodsisthecode
neededtostopourprogram.DoubleclickontheQuitbuttonandaddthiscode:

PUBLICSUBQuitBtn_Click()
Draw.End'closedrawingoperations
ME.Close'closeForm1
END

Now,wearereadytobeginaddingcodetoexploreourvariousdrawingtools,the
methodsoftheDrawclass.

Text/TextHeight/TextWidth

We will begin with Draw.Text and the two readonly text properties,
TextHeightandTextWidth.TheTextHeightpropertyreturnstheheightofatext
drawing while the TextWidth property returns the width of a text drawing.
StandardGambaslanguagesyntaxis:

STATICFUNCTIONTextHeight(TextASString)ASInteger
STATICFUNCTIONTextWidth(TextASString)ASInteger

DoubleclickontheTextbuttonandaddthiscode:

PUBLICSUBTextButton_Click()

'thisvarwillbeusedforourloopcounter
DIMcounterASInteger

'clearthecurrentdrawingarea
da.Clear

'setforegroundcolortoblack
Draw.ForeColor=color.Black

272
A Beginner's Guide to Gambas

'setcurrentfonttoArial
draw.Font.Name="Arial"

'turnonboldface
draw.Font.Bold=TRUE

'turnoffitalic
draw.Font.Italic=FALSE

'turnoffunderline
draw.Font.Underline=FALSE

'settextsizeto16points
draw.Font.Size="16"

'startaloopandcontinueuntilweiterate10times
FORcounter=0TO9

'outputtextandincrementtheypositionby40*counter
'theoptionalwidth,heightparametersaregivenas100,60
draw.Text("SampleText",10,10+40*counter,100,60)
NEXT'iterationoftheloop

'nowsetfontto24points
draw.Font.Size="24"
Draw.ForeColor=color.Blue'andchangecolortoblue

FORcounter=0TO9'loopanother10times
'allwechangeisxpositiontomovethetextright200pixels
draw.Text("MoreSampleText",200,10+40*counter,100,60)
NEXT'iteration

'refreshthedrawingareatoseewhatwasdone
da.Refresh
END'wearedonewithtextstuff!

Onceyouhaveaddedthecodeabove,saveyourworkandclicktheRUNbutton.
Hereiswhatyoushouldsee:

273
A Beginner's Guide to Gambas

Figure78ResultsofclickingtheTextButton.

DrawPrimitives:Point/Rect/Ellipse/Line

TheDraw.PointmethoddrawsasinglepixelwhiletheDraw.Rectmethod
drawsarectangle.Gambaslanguagesyntaxforthesetwomethodsis:

STATICSUBPoint(XASInteger,YASInteger)
STATICSUBRect(XASInteger,YASInteger,WidthASInteger,HeightASInteger)

WearegoingtousetheInvRectbuttontoillustratehowthesemethodsareused.
DoubleclickontheInvRectbuttonandenterthefollowingcode:

PUBLICSUBInvRectBtn_Click()
'usethisvarforourloopcounter
DIMcounterASInteger

'clearthedrawingarea
da.Clear

'makesurefillstyleissettoNone
draw.FillStyle=fill.None

'setcolortocyan
draw.ForeColor=color.cyan

'thiswillmakethecyanrectangleappearred
draw.Invert=TRUE
FORcounter=0TO15'loop16times

'drawarect,incthestartx,yandendx,ypositions5*counterval
Draw.Rect(5+5*counter,5+5*counter,da.W/2+5*counter,da.H/2+5*counter)

274
A Beginner's Guide to Gambas

'ifwehitanevennumber,invoketoggleInvertpropertyon/off
IFcounterMOD2=0THEN
draw.Invert=FALSE
ELSE
draw.Invert=TRUE
ENDIF
NEXT'iterationoftheloop

'ensureinvertissettooff
draw.Invert=FALSE
'setcurrentfgdcolortoblack
draw.Forecolor=color.Black
'setapointmidscreen
draw.Point(da.W/2,da.H/2)

'nowwewillmakeatinycrosshairfromthefirstpoint
'bymovingonepixelup,down,leftandrightofthecenter
'dotwesetwiththefirstdraw.pointcall
draw.Point(da.W/21,da.H/2)
draw.Point(da.W/2+1,da.H/2)
draw.Point(da.W/2,da.H/21)
draw.Point(da.W/2,da.H/2+1)

'updatethedisplaytoseewhatwedid
da.Refresh
END'oftherect/pointdemocode

Saveyourworkandruntheprogram.WhenyouclicktheInvRectbutton,
youshouldseesomethingsimilartothis:

Figure79ResultsofInvRectbuttonclick.Note
thetinyblackcrosshaircenterscreen.

275
A Beginner's Guide to Gambas

TheDraw.Linemethoddrawsaline.Thex1,y1pointsrepresentthestart
vertexoftheline,x2,y2representtheendvertexoftheline. Thelinemethod
uses properties from the Line class to establish line style and thickness. The
constantsusedbytheDraw.LineStyleproperty are Dash,DashDot,DashDotDot,
Dot,None,andSolid.LinethicknessissetusingtheDraw.LineWidthpropertyand
widthissetinpixels.TheGambaslanguagesyntaxforthismethodis:

STATICSUBLine(X1ASInteger,Y1ASInteger,X2ASInteger,Y2ASInteger)

TheDraw.Ellipsemethodwilldrawanellipseorcircle.Remember,acircle
isanellipsewithequalwidthandheightparameters,whichiswhyyoudonotsee
aDraw.CirclefunctioninGambas.TheGambaslanguagesyntaxforDraw.Ellipse
is:

STATICSUBEllipse(XASInteger,YASInteger,WidthASInteger,HeightAS
Integer[,StartASFloat,LengthASFloat])

XandYrepresentthecenterpointofthecircleorellipse. Widthcanbe
thoughofasaradiusalongthehorizontalplane, heightisaradiusalong the
verticalplane. Ifyouspecifytheoptionalparametersofstartandlength,these
representstartingangles(indegrees)wherethedrawingwillstartandstop.We
willillustratethisinourexamplebelowusingtheEllipsesbutton.Doubleclickon
theEllipsesbuttonandenterthiscode:

PUBLICSUBEllipseBtn_Click()
'declaresomevariablestoworkwith
DIMx1ASInteger
DIMx2ASInteger
DIMy1ASInteger
DIMy2ASInteger

'wewillneedacountervariable
DIMiASInteger

'andavartoholdthevalueoflinewidthaswechangeit
DIMlwidthASInteger

'clearourdisplaybeforewebegin
da.Clear

'setinitialvectors
x1=50
y1=50
x2=100
y2=100

276
A Beginner's Guide to Gambas

'changethecolortodarkblue
Draw.ForeColor=color.DarkBlue

'setupforasolidfill.Anyfillablecontainerthatiscalledafter
'thiscallwillbefilledwiththepatternspecifiedbelow
draw.FillStyle=fill.Solid

'setupaloopthatwillcreate12increments
FORi=0TO360STEP30
'ifwefallona90degreeincrement,switchcolors
IFiMOD45=0THEN
draw.FillColor=color.Yellow
ELSE
draw.FillColor=color.Red
ENDIF

'drawafilledellipseof12segments,startingateachvalueofi
'andsweepingfor30degrees,asspecifiedintheoptionalparms
Draw.Ellipse(x1,y1,x2,y2,i,30)
NEXT

'now,turnoffthefillstyle
draw.FillStyle=fill.None

'setourfgdcolortoblack
draw.ForeColor=color.Black

'letsdrawsomelines,startxatmidscreenhorizaxis25pixels
x1=da.W/225

'startouryatmidscreenontheverticalaxis
y1=da.H/2

'startwithalinewidthofasinglepixel
lwidth=1

'loop8times,movingdownalongtheyaxisin25pixincrements
FORi=10TO200STEP25

'drawaline
draw.Line(da.W/2,i,da.W/2+150,i)

'increaselinethicknessvariable
INClwidth

'setthenewwidth
draw.LineWidth=lwidth
NEXT'iterationoftheloop

277
A Beginner's Guide to Gambas

'outoftheloop,resettoadefaultof2pixwide
draw.LineWidth=2

'now,letsstartanotherloopanddrawsomeellipses
FORi=1TO40STEP3'letsmake13ofthem

'movingthisoneleftalongthehorizaxis
Draw.Ellipse(x1i*5,y1,75,200)

'andmovingthisonerightalongthehorizaxis
Draw.Ellipse(x1+i*5,y1,75,200)

'ifwehitanevennumberinourloopchangecolors
IFiMOD2=0THEN
draw.ForeColor=color.Red
ELSE
draw.ForeColor=color.Black
ENDIF
NEXT'iterationoftheloop

'refreshthedrawingareatoseeourwork
da.Refresh
END'endoftheellipsesandlinesdemocode

Saveyourworkandruntheprogram.WhenyouclicktheEllipsesbutton,
youshouldseesomethingsimilartothis:

Figure80Ellipsesdemonstratesdrawinglinesand
ellipses.

278
A Beginner's Guide to Gambas

OurnextcodesegmentwillusetheFillRectbutton.Wearerevisitingthe
Draw.Rect method to show you how to use the Draw.FillStyle to create filled
objects.Createaclickeventandenterthefollowingcode:

PUBLICSUBFillRectBtn_Click()
'createsomelocalvarstoworkwith
DIMx1ASInteger
DIMx2ASInteger
DIMy1ASInteger
DIMy2ASInteger

'clearthedrawingarea
da.Clear

'settherecttopleftcorner
x1=20
y1=80

'settherectbotrightcorner
x2=x1+50
y2=y1+50

'setfgdcolortored
draw.FillColor=color.Red

'specifyahorizstylefillpattern
draw.FillStyle=fill.Horizontal

'drawarect,ifafillpatternisspecified,itisautofilled
Draw.Rect(x1,y1,x2,y2)

'settherecttopleftcorner
x1=220
y1=180

'settherectbotrightcorner
x2=x1+50
y2=y1+50

'setfgdcolortoblue
draw.FillColor=color.Blue

'specifyacrossstylefillpattern
draw.FillStyle=fill.Cross

'drawarect,ifafillpatternisspecified,itisautofilled
Draw.Rect(x1,y1,x2,y2)

279
A Beginner's Guide to Gambas

'turnoffthefill
draw.FillStyle=fill.None

'refreshtoseeourwork
da.Refresh
END

Saveyourworkandruntheprogram.WhenyouclicktheFillRectbutton,
youshouldseesomethingsimilartothis:

Figure81OutputafterclickingtheFillRectbutton.

DrawPrimitives:PolygonandPolyline

The Draw.Polygonmethod drawsapolygonwith n vertices. Thevertices


arespecifiedinanIntegerarrayusingthisGambaslanguagesyntax:

STATICSUBPolygon(PointsASInteger[])

ThePointsparameterisanarrayofIntegercontainingthecoordinatesof
thepolygonvertexes.Thecoordinatesareassumedtobeinx,yformatsothere
mustbetwointegersinthearrayforeachvertexofthepolygon.

The Draw.Polylinemethod worksnearlythesameasthePolygonroutine


exceptthatwithapolylinethefigurebeingdrawndoesnotneedtobeclosed.
Thisissometimesreferredtoasavoidpolygon.Apolylineisaseriesofvertices

280
A Beginner's Guide to Gambas

joinedfromonetothenextbyaline.Thelinewilldrawfromthelastvertexto
thenextvertexspecifiedinthearray.TheGambaslanguagesyntaxforPolyline
is:

STATICSUBPolyline(PointsASInteger[])

The Points parameter is an array of Integer containing the coordinates of the


polygonvertexes.Sotheremustbetwointegersinthearrayforeachvertex.We
will use the FillPoly button on our Form1 to demonstrate the use of the
Draw.Polygonmethod.DoubleclickontheFillPolybuttontocreateaclickevent
andwhenthecodewindowappears,enterthiscode:

PUBLICSUBPolygonBtn_Click()
'declaresomeworkvariablestocreateapolygon
DIMx1ASInteger
DIMy1ASInteger
DIMx2ASInteger
DIMy2ASInteger
DIMx3ASInteger
DIMy3ASInteger

'wearegoingtocreateatriangleforourpolygon
'andstoretheverticesintheintegerarraytriangle
DIMtriangleASInteger[]

'clearthedisplayarea
da.Clear

'settheverticesforeachlegofthetriangle
'startingwiththetoppartofanequilateraltriangle
x1=da.w/2'setthehorizaxistomidscreen
y1=10'setverticalaxistotop+10pixels

'now,wewilldotheleftlegofthetriangle
'startingontheextremeleftedgeplus10pixels
x2=da.Left+10

'andsettingourypositiontodrawingareaheight200pixels
y2=da.H200

'therightlegsetshorizpositionfarright20pixelsin
x3=da.W20

'andthevertaxiswillbesameasthesecondleg
y3=y2

'allverticesdefined,loadtheintegerarraywiththetriangle

281
A Beginner's Guide to Gambas

triangle=Array(x1,y1,x2,y2,x3,y3)
'setafillstyle
draw.FillStyle=fill.Dense63

'andafillcolor
draw.FillColor=color.DarkMagenta

'anddrawthepolygonusingthetrianglearraydata
draw.Polygon(triangle)

'remembertosetfillstyletoNone
draw.FillStyle=fill.None

'callrefreshtoseeourwork
da.Refresh
END'andwearedonewiththepolygonroutine

Saveyourworkandruntheprogram.WhenyouclicktheFillPolybutton,
youshouldseesomethingsimilartothis:

Figure82UsingDraw.Polygontodrawa
triangle.

Now,let'sseehowthe Draw.Polylinemethod works.Doubleclickonthe


Polylinebuttonandcreateaclickevent.Whenthecodewindowappears,enter
thiscode:

PUBLICSUBPolyLineBtn_Click()
'declaresomevariablestocreateourvertices
DIMx1ASInteger
DIMy1ASInteger
DIMx2ASInteger

282
A Beginner's Guide to Gambas

DIMy2ASInteger
DIMx3ASInteger
DIMy3ASInteger
DIMx4ASInteger
DIMy4ASInteger

'declareanintegerarraytoholdthepolylinedata
DIMlinesASInteger[]

'clearthedrawingarea
da.Clear

'startourfirstpointmidscreenabout10pixelsfromthetop
x1=da.w/2
y1=10

'thenextpointwillbe10pixelsinfromfarleft,down200pixels
x2=da.Left+10
y2=da.H200

'our3rdvertexwillbedeadcenterofthedrawingareaonhorizaxis
'andverybottomofthedrawingareaforvertaxis
x3=da.W20
y3=da.H20

'andthe4thvertexwillbedeadcenterxandyofthedrawingarea
x4=da.W/2
y4=da.H/2

'loadtheverticesintothearray
'ifwewantedtoclosethepolygon,allweneedtodoisaddthe
'x1,y1verticestotheendofthearray
'uncommentthenextlinetotryitandsee
'lines=Array(x1,y1,x2,y2,x3,y3,x4,y4,x1,y1)
lines=Array(x1,y1,x2,y2,x3,y3,x4,y4)

'ensureanyfillstylesareturnedoff
draw.FillStyle=fill.None

'setthecolortodarkgreen
draw.ForeColor=color.DarkGreen

'drawthelines
draw.Polyline(lines)

'refreshtoseeourwork
da.Refresh
END'ofthepolylinedemoroutine

283
A Beginner's Guide to Gambas

Saveyourworkandruntheprogram.WhenyouclickthePolylinebutton,
youshouldseesomethingsimilartothis:

Figure83UsingDraw.Polylinetodrawlines.

Image/Picture/Tile

The Image class draws an Image, or part of it. The image contentsare
storedintheprocessmemory,notinthedisplayserverlikeaPicture.Thisclassis
creatable. If Width and Height are not specified, then the new image is void.
Gambaslanguagesyntaxis:

STATICSUBImage(ImageASImage,XASInteger,YASInteger[,SrcX
ASInteger,SrcYASInteger,SrcWidthASInteger,SrcHeightAS
Integer])

Thefollowingcodewouldcreateanewimage:

DIMhImageASImage
hImage=NEWImage([WidthASInteger,HeightASInteger])

Thisclassactslikeanarrayofpixels. ThinkofXasrowsandYascolumnsof
imagepixels.Hereishowthecodetogetorsetapixelofanimagewouldwork:

DIMhImageASImage
DIManIntegerASInteger

anInteger=hImage[XASInteger,YASInteger]

ThecodeabovewillreturnthecolorofanimagepixelatX,Ywhilethefollowing

284
A Beginner's Guide to Gambas

codewillsetthecolorofanimagepixeltothevalueofanInteger:

hImage[XASInteger,YASInteger]=anInteger

Image allows you to use the following properties: Depth, Height, Picture, and
Width.

Depth returnsorsetsthedepthoftheimage. Whensettingdepthvalues,you


mustonlyusethefollowingvalues:2,8,16,and24.Itisdeclaredas:

PROPERTYDepthASInteger

Heightisareadonlyattributethatreturnstheheightoftheimageasaninteger.
Itisdeclaredas:

PROPERTYREADHeightASInteger

Widthisareadonlyattributethatreturnsthewidthinpixelsoftheimage.Itis
declaredas:

PROPERTYREADWidthASInteger

Picture (readonly) converts the image into a picture, and returns it. It is
declaredas:

PROPERTYREADPictureASPicture

TheImageclasssupportsseveralmethods.Theseinclude:Clear,Copy,Fill,Flip,
Load,Mirror,Replace,Resize,Rotate,Save,andStretch.

Clearwillcleartheimage,settingallpixelvaluestozero.

Copyreturnsacopyoftheimage,oracopyofapartofit.Thecopymethodis
declaredasafunction,asshownbelow:

FUNCTIONCopy([XASInteger,YASInteger,WidthASInteger,Height
ASInteger])ASImage

Fillfillstheimagewithaspecifiedcolor.Gambaslanguagesyntaxis:

SUBFill(ColorASInteger)

285
A Beginner's Guide to Gambas

Flipreturnsamirroredcopyoftheimage.Themirroredcopyiscreatedusingthe
horizontalaxisoftheimage.

FUNCTIONFlip()ASImage

LoadandSaveloadorsavesanimagefromafileortoafilerespectively.The
fileextensionof Path willspecifythegraphicsfileformatusedwiththesaved
image. CurrentlysupportedfileformatsareJPEG,PNG,BMP,GIFandXPM.
Gambaslanguagesyntaxis:

SUBLoad(PathASString)
SUBSave(PathASString)

Mirrorreturnsamirroredcopyoftheimage.Themirroredcopyiscreatedusing
theverticalaxisoftheimage.

FUNCTIONMirror()ASImage

ReplaceswapsanexistingOldColorvaluewiththecolorspecifiedbyNewColor,as
shownbelow:

SUBReplace(OldColorASInteger,NewColorASInteger)

ResizeResizestheimagetothesizespecifiedbythewidthandheightparameter
given:

SUBResize(WidthASInteger,HeightASInteger)

Rotate returns a rotated copy of the image. Gambas language syntax is as


follows:

FUNCTIONRotate(AngleASFloat)ASImage

Thefunctionwillrotatetheimage n degrees. Theangleisspecifiedindegrees,


notradians.

Stretchreturnsastretchedcopyoftheimage.IftheoptionalparameterSmooth
isspecifiedasTrue,asmoothingalgorithmisappliedtothereturnedresult.The
Gambaslanguagesyntaxis:

FUNCTIONStretch(WidthASInteger,HeightASInteger[,SmoothAS
Boolean])ASImage

286
A Beginner's Guide to Gambas

ThePictureclassdrawsapicture,orpartofapicture.Thepicturecontents
arestoredinthedisplayserver,notintheprocessmemorylikeanImage.Evenif
XWindowdoesnotmanagetransparencyyet,eachpicturecanhaveamask.This
featurecanbesetexplicitlyatpictureinstantiation,orimplicitlywhenloadingan
imagefilethathastransparencylikePNG.Whendrawingonapicturehavinga
mask, the picture and the mask are modified accordingly. Gambas language
syntaxis:

STATICSUBPicture(PictureASPicture,XASInteger,YASInteger[,
SrcXASInteger,SrcYASInteger,SrcWidthASInteger,SrcHeightAS
Integer])

Thisclassiscreatable.ThefollowingcodeshowsyouhowtocreateaPicture:

DIMhPictureASPicture

hPicture=NEWPicture([WidthASInteger,HeightASInteger,
TransparentASBoolean])

IftheoptionalWidthandHeightparametersarenotspecified,thenewpictureis
void.YoucanspecifyifthepicturehasamaskwiththeTransparentparameter.
Thisclassactslikeanarray.

DIMhPictureASPicture

hPicture=Picture[PathASString]

Thecodeabovewillreturnapictureobjectfromtheinternalpicturecache.
If the picture is not present in the cache, it is automatically loaded from the
specifiedfile. Inordertoinsertapictureintheinternalpicturecache,usethis
code:

DIMhPictureASPicture
Picture[PathASString]=hPicture

Depth returnsorsetsthedepthofthepicture. Whensettingdepthvalues,you


mustonlyusethefollowingvalues:2,8,16,and24.Itisdeclaredas:

PROPERTYDepthASInteger

Heightisareadonlyattributethatreturnstheheightofthepictureasaninteger.
Itisdeclaredas:

287
A Beginner's Guide to Gambas

PROPERTYREADHeightASInteger

Widthisareadonlyattributethatreturnsthewidthinpixelsofthepicture.Itis
declaredas:

PROPERTYREADWidthASInteger

Imageisareadonlypropertythatconvertsthepictureintoanimageandreturns
it.Itisdeclaredas:

PROPERTYREADImageASImage

Wewilluseaverysimpleexampletoshowyouhowthisworks.Wewill
showyouhowtotakeascreenshotwithcodeandsavetheimage.Theimageof
thedesktopistakenasapictureobjectwhenthebuttonontheformisclicked.
Thispictureobjectissubsequentlyconvertedintoanimageobjectanddisplayed
asanimageinaDrawingArea. StartGambasandcreateanewgraphicaluser
interfaceproject, namedgfxDemo2. Make theproject translatablewithpublic
controlsand whentheIDEappears,createastartupclassformnamedForm1.
FromthepropertieswindowforForm1,settheresizepropertytoTruesoyoucan
stretchtheformtoseetheimagewhenitisadded.AddabuttonnamedButton1
andaDrawingAreanamedDrawingArea1.PlacetheDrawingAreaatthetopleft
corneroftheformandmakeitaboutoneinchwideandoneinchhigh.Now,put
thebuttonatthebottomrightcorneroftheform.AddthecaptionSnapshotto
thebutton.Doubleclickonthebuttontocreateaclickeventandaddthiscode:

'Gambasclassfile

PUBLICSUBButton1_Click()
'declareavarforourpicture
pASNEWPicture

'andoneforourimage
iASNEWImage

'getthepictureojbectfromthedesktopusing.Grabmethod
p=Desktop.Grab()

'assignthepictureusingtheimagepropertyto
'convertscreenshottoanimage
i=p.image

'specifythatthecontentsofthedrawingareaarecachedinmemory
Drawingarea1.Cached=TRUE

288
A Beginner's Guide to Gambas

'resizedrawingareatosizeoftheimageconvertedfmpicture
DrawingArea1.Resize(i.Width,i.Height)

'clearthedrawingarea
DrawingArea1.Clear()

'calltheDraw.Begin(mandatory)methodtostarttodraw
Draw.Begin(DrawingArea1)

'puttheimageinthedrawingareastartingatorigin0,0
Draw.Image(i,0,0)

'callthe(mandatory)Draw.Endmethodtoquitdrawing
Draw.End

'maketheimagevisible
DrawingArea1.Visible=TRUE

'refreshthedrawingareatoseewhatwasdone
DrawingArea1.Refresh
END

Saveyourworkandruntheprogram.Clickthebuttonandascreenshotofyour
desktopwillbeplacedonthedrawingareaoftheform. Prettyeasyusingthe
Gambasmethods,isn'tit?

TransparentisaBooleanflagthatcanbereadorset.Itindicateswhetherornot
thepicturehasamask.Gambaslanguagesyntaxis:

PROPERTYTransparentASBoolean

MethodssupportedbyPictureincludeClear,Copy,Fill,Flush,Load,Resize,and
Save.

Clearwillclearthepicture,settingallpixelvaluestozero.

Copyreturnsacopyofthepicture,oracopyofapartofit.Thecopymethodis
declaredasafunction,asshownbelow:

FUNCTIONCopy([XASInteger,YASInteger,WidthASInteger,Height
ASInteger])ASImage

Fillfillsthepicturewithaspecifiedcolor.Gambaslanguagesyntaxis:

289
A Beginner's Guide to Gambas

SUBFill(ColorASInteger)

FlushFlushestheinternalpicturecache.Themethodtakesnoparametersandis
calledusingthisconvention:

STATICSUBFlush()

LoadandSaveloadsorsavesapicturefromafileortoafilerespectively.The
fileextensionof Path willspecifythegraphicsfileformatusedwiththesaved
picture. CurrentlysupportedfileformatsareJPEG,PNG,BMP,GIFandXPM.
Gambaslanguagesyntaxis:

SUBLoad(PathASString)
SUBSave(PathASString)

Resizeresizestheimagetothesizespecifiedbythewidthandheightparameter
given:

SUBResize(WidthASInteger,HeightASInteger)

The Tile method draws a tiled picture in the DrawingArea. Gambas


languagesyntaxisasfollows:

STATICSUBTile(PictureASPicture,XASInteger,YASInteger,Width
ASInteger,HeightASInteger)

Let'snowgobacktoouroriginalgfxDemoprogramandfinishcodingthelast
button. StartGambasandloadthegfxDemoproject.OpenForm1anddouble
clickontheTileImgbutton.Whenthecodewindowappears,addthiscode:
PUBLICSUBTileBtn_Click()
'declareourlocalvarshere
'wewillneedapicturevartoholdthepictureweload
DIMmypicASPicture

'weneedacountervarforourloopwork
DIMcounterASInteger

'wearealsogoingtoneedsomeintegervars
DIMiASInteger
DIMjASInteger

'setiandjtozerotostart
i=0

290
A Beginner's Guide to Gambas

j=0

'instantiatepicturevariable,setwidth,heightsoitisnotvoid
mypic=NEWPicture(170,105,FALSE)

'clearthedrawingarea
da.Clear

'nowloadthepictureusingtheloadmethod
mypic.Load("GambasShrimp.png")

'wewilltilethepictureicolumnsacrossperjrowsdown
'inourcasewewillhave4rowsof3imagesperrow
'sowewillneedtoloop12times
FORcounter=0TO11

'drawthetile
draw.Tile(mypic,i*175,j,170,105)

'incrementourcolumncounter
INCi

'checktoseeifwehavethreeacross
IFiMOD3=0THEN

'ifso,movevalueofj(ouryaxis)image.height+5pixelsdown
j=j+110

'resetcolumncountertozero
i=0
ENDIF'ourchecktoseeif3across
NEXT'iterationoftheloop

'refreshthedisplaytoseethework
da.Refresh
END'oftheTileImgbuttoncode

Thelastthingweneedtodoisgetanimagetouseforourprogram.For
ourprogarm,IhavechosentheGambasmascot,whichweusedfromanearlier
project.YoucancopythisimagefromourFirstProject.Fromtheprojectwindow,
ontheTreeViewDatafolder,selectNewImage.Whenthewindowappears,you
canselecttheExistingtabandbrowsetothefolderFirstProject(assumingyou
named your projects as we specified in the book) and choose the Gambas
mascot.pngimage.SaveittothegfxDemoprojectasGambasshrimp.pngand
thatisallthereistoit.If,forsomereason,youcannotfindtheimageonyour
system,simplygototheGambaswebsiteandusetherightmousebuttonoverthe
mascotimagetosaveacopytoourgfxDemoprojectfolder.Now,saveyourwork

291
A Beginner's Guide to Gambas

andruntheprogram. ClicktheTileImgbuttonandyoushouldseesomething
similartothis:

Figure84Usingtiledimageswiththe
TileImgbuttonofourdemoprogram.

DrawingwithaDrawingobject

In Gambas, a drawing object is based on the use of Scalable Vector


Graphics,or SVG. Accordingtothe SVGspecification16, SVGisalanguagefor
describingtwodimensionalgraphicsinXML.SVGallowsforthreetypesofgraphic
objects:vectorgraphicshapes(e.g.,pathsconsistingofstraightlinesandcurves),
images and text. Graphical objects can be grouped, styled, transformed and
composited into previously rendered objects. The feature set includes nested
transformations, clipping paths, alpha masks, filter effects and template objects.
SVG drawings can be interactive and dynamic. Animations can be defined and
triggeredeitherdeclaratively (i.e.,byembeddingSVGanimationelementsinSVG
content)orviascripting.

Inkscape17isapopularprogramusedintheLinuxcommunityforcreating
SVGimagesandiswhatthisauthorhaschosentousewiththisbooksinceitis
freelyavailableontheInternet.Inkscapeisanopensourcevectorgraphicseditor,
withcapabilitiessimilartoIllustrator,Freehand,CorelDraw,orXaraXusingthe
W3CstandardScalableVectorGraphics(SVG)fileformat.

In Gambas, you can load, save, clear, or copy an SVG image. The
16 See URL http://www.w3.org/TR/SVG/intro.html for more details on SVG.
17 See URL http://www.inkscape.org/ for more details on Inkscape.

292
A Beginner's Guide to Gambas

properties that you have available to you are the most basic, namely width,
height,anddepth. GambasisnotdesignedtobeanSVGeditor. Itsimplyhas
provisions for you to use SVG images in your program. Once you have the
drawinginyourprogram,itisuptoyoutodosomethingwithit.Asanexample,
wewillcreateanewprogramtosimplyloadanSVGimageanddisplayit.First,
wewillneedtofindanSVGimage.Ihavedownloadedafreelyavailablepublic
domainlicensedimagefromtheInternetathttp://openclipart.orgtouseforour
demo.Youcanchooseanyimageyouwishforthisdemo,solongasitisanSVG
formatted file. Now, we will create a new graphical user interface project in
Gambas named gfxDemo3. Make the project controls public and translatable.
Next,createanewstartupclassform,namedForm1.Wearegoingtoaddseveral
controls: Scrollview, DrawingArea, HBox, and two buttons. Your form should
looklikethisindesignmode:

Doubleclick on the formwhenitopens and thecode window appears.


Start with the ScrollView control, naming it ScrollView1. Next, add a

293
A Beginner's Guide to Gambas

DrawingAreaontopofthe ScrollViewcontrol. NametheDrawingAreadaSVG.


AddtheHBox,namedHBox1andthetwobuttonsnamedLoadBtnandQuitBtn.
Don'tforgettoaddthetextcaptionstothebuttons. Next,doubleclickonthe
Quitbuttonandaddthiscode:

PUBLICSUBQuitBtn_Click()
ME.Close
END

Now,doubleclickontheLoadBtnandaddthis:

PUBLICSUBLoadBtn_Click()

'declareourDrawingobjectfortheSVGfile
DIMdraASDrawing

'instantiateit
dra=NEWDrawing

'nowloaditusingtheLoadmethod
dra.Load("floppy.svg")

'setcachedpropertytoTRUEtocacheitinmemory
daSvg.Cached=TRUE

'setvisiblepropertytoTRUEsowecanseethepicture
daSvg.Visible=TRUE

'movethedrawingareaobjecttostartattopleft(0,0)origin
dasvg.Move(0,0,dra.Width,dra.Height)

'callthemandatoryDraw.Begintostarttodraw
draw.Begin(daSvg)

'dothedraw
draw.Drawing(dra,0,0)

'calltheDraw.Endmethodtoquitdrawing
draw.end

'refreshourformtoseewhatwasdone
Form1.Refresh
END

Onceyouhavedownloadedorcreatedthefloppy.svgfile,saveittothe
projectdirectory.ThatisallthecodeweneedtoaddtoviewanSVGfile.Save

294
A Beginner's Guide to Gambas

yourworkandruntheprogram.Whentheprogramstarts,clicktheLoadbutton
andyoushouldseeapicturesimilartothis:

Figure85LoadinganSVGfileinGambas.

IhopeyouhaveenjoyedourshortlittletourdeforceofGambasdrawing
capabilities. ThischapterhaspresentedallofthebasicsneededtouseGambas
foralmostanygraphicsrelatedneeds.Attheendofthisbook,inAppendixA,we
presentaspecialgraphicsprogramthatyoucanusetodrawevenmoreadvanced
2D/3DrenderedobjectsusingaGKStypegraphicsclasscreatedinGambas.

295
A Beginner's Guide to Gambas

ContentsofSVGfilefloppy.svgdownloadedfromhttp://openclipart.org:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>


<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<!-- Created with Sodipodi ("http://www.sodipodi.com/") --><svg height="400pt" id="svg548"
sodipodi:docbase="/home/nicu/svg_gal/computers/" sodipodi:docname="/home/nicu/svg_gal/computers/floppy.svg"
sodipodi:version="0.32" width="400pt" xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:xlink="http://www.w3.org/1999/xlink">
<metadata>
<rdf:RDF xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<cc:Work rdf:about="">
<dc:title>Clipart by Nicu Buculei - antenna</dc:title>
<dc:description></dc:description>
<dc:subject>
<rdf:Bag>
<rdf:li>hash</rdf:li>
<rdf:li></rdf:li>
<rdf:li>computer</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:publisher>
<cc:Agent rdf:about="http://www.openclipart.org">
<dc:title>Nicu Buculei</dc:title>
</cc:Agent>
</dc:publisher>
<dc:creator>
<cc:Agent>
<dc:title>Nicu Buculei</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>Nicu Buculei</dc:title>
</cc:Agent>
</dc:rights>
<dc:date></dc:date>
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/>
<dc:language>en</dc:language>
</cc:Work>
<cc:License rdf:about="http://web.resource.org/cc/PublicDomain">
<cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
<cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
<cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
</cc:License>
</rdf:RDF>
</metadata>
<defs id="defs550"/>
<sodipodi:namedview id="base" showgrid="true"/>
<path d="M 52.5712 53.9929 L 407.003 53.9929 L 443.463 89.6056 L 441.768 447.429 L 53.4191 445.733 L 52.5712
53.9929 z " id="path551" style="fill:#00007b;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-width:3.75;stroke-
linejoin:miter;stroke-linecap:butt;fill-opacity:1;stroke-dasharray:none;"/>
<path d="M 371.39 53.9929 L 371.39 145.569 C 371.39 145.569 368.846 159.135 355.279 163.375 C 341.713 164.222
156.866 164.223 156.866 164.223 C 156.018 165.071 144.995 157.439 144.147 152.352 C 143.299 147.264 142.451
145.569 142.451 145.569 C 142.451 145.569 144.147 53.145 143.299 53.145 C 142.451 53.145 372.238 53.9929
371.39 53.9929 z " id="path552" sodipodi:nodetypes="cccccccc" style="fill:#a3a6a6;fill-rule:evenodd;stroke:black;stroke-
opacity:1;stroke-width:2.32865;stroke-linejoin:miter;stroke-linecap:butt;fill-opacity:1;stroke-dasharray:none;"

296
A Beginner's Guide to Gambas

transform="matrix(1.000000,0.000000,0.000000,1.152582,0.000000,-6.413116)"/>
<rect height="185.694977" id="rect553" style="font-size:12;fill:#ffffff;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;"
width="321.362518" x="89.879768" y="249.862976"/>
<rect height="9.32714844" id="rect554" style="font-size:12;fill:#808080;fill-rule:evenodd;stroke-width:1pt;"
width="0.00000000" x="410.394348" y="240.535797"/>
<path d="M 334.929 76.0389 C 334.081 76.0389 282.358 76.0389 282.358 76.0389 L 282.358 165.071 L 334.929
165.071 L 334.929 76.0389 z " id="path555" style="fill:#00007b;fill-rule:evenodd;stroke:black;stroke-opacity:1;stroke-
width:2.5;stroke-linejoin:miter;stroke-linecap:butt;fill-opacity:1;stroke-dasharray:none;"/>
<rect height="55.1149292" id="rect556" style="font-size:12;fill:#dd8080;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;"
width="321.362549" x="89.8797607" y="249.862946"/>
<rect height="6.783386" id="rect557" style="font-size:12;fill:#dd8080;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;"
width="287.445648" x="105.142365" y="335.503052"/>
<rect height="5.935455" id="rect558" style="font-size:12;fill:#dd8080;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;"
width="287.445648" x="104.294426" y="371.115822"/>
<rect height="5.935455" id="rect559" style="font-size:12;fill:#df8080;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;"
width="286.597717" x="105.142365" y="406.728516"/>
<rect height="5.08750916" id="rect567" style="font-size:12;fill:#000000;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;"
width="78.8567657" x="159.409393" y="75.1909637"/>
<rect height="5.08754730" id="rect568" style="font-size:12;fill:#000000;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;"
width="58.5066528" x="161.105225" y="87.9097748"/>
<rect height="5.08750916" id="rect569" style="font-size:12;fill:#180003;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;"
width="76.3130035" x="161.105225" y="100.628624"/>
<rect height="5.93548584" id="rect570" style="font-size:12;fill:#ffffff;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;"
width="114.469490" x="105.990288" y="261.733826"/>
<rect height="5.08752441" id="rect571" style="font-size:12;fill:#ffffff;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;"
width="44.0919495" x="106.838211" y="277.844360"/>
<rect height="5.087512" id="rect572" style="font-size:12;fill:#ffffff;fill-rule:evenodd;stroke-width:1pt;fill-opacity:1;"
width="33.916901" x="178.063675" y="277.844386"/>
<path d="M 150.317 158.228 C 151.899 153.481 148.734 63.2911 155.063 63.2911 C 161.392 63.2911 292.722
61.7089 292.722 61.7089 C 232.595 68.038 164.557 66.4557 150.317 158.228 z " id="path566"
sodipodi:nodetypes="cccc" style="fill:#ffffff;fill-rule:evenodd;stroke:none;stroke-opacity:1;stroke-width:1pt;stroke-
linejoin:miter;stroke-linecap:butt;fill-opacity:0.5;"/>
</svg>

297
A Beginner's Guide to Gambas

Chapter 13 Error Management


Error management is a key area for developers doing any kind of
applicationdevelopment.Errormanagementisaverypowerfulconceptandcan
make development work much easier if it is used efficiently. As a Gambas
developer,itishighlyrecommendedthatyouadoptanappropriatestrategyfor
error management that will enable you to build high quality and robust
applications.Improperhandlingoferrorscanandwilldegradetheperformance
ofyourapplication,it'sperceptionbyyourusercommunity,andultimately,its
overallacceptance.Inordertounderstanderrormanagement,itisimportantto
knowthetypesoferrorsthatcanoccurinaprogram.Wewillbrieflyexplainthe
mostcommonerrorcategoriesinthefollowingsectionsandtrytopointoutsome
thingsyoushouldwatchforasyouwriteyourcode.

GeneralConceptsofErrorManagement

Errorscanhavemanycauses.Dependingonthecause,theerrormightbe
recoverable.Arecoverableerrorisoneforwhichyourapplicationcanidentifythe
errorcauseandtakesomeactiontoresolveormitigatetheproblem.Someerrors
mightberecoverablecanbehandledwithouttheneedtoindicatetotheuserthat
an error was even encountered. For example, an error generated when a
requestedfiledoesnotexistisrecoverable.Theapplicationcanbeprogrammedto
displayanerrormessageinsuchanevent. Errorssuchasvalidationerrors,for
whichtheapplicationcannotcontinueprocessingbutcanprovideerrorspecific
feedbackcanalsobeconsideredrecoverableifhandledproperly.Forexample,an
error that occurs when a user enterstextwhere a number is required can be
considered recoverable because the application can recognize the error and
redisplaythedatafieldalongwithamessagethatprovidesinformationaboutthe
causeoftheerror,allowingtheusertoreenterdatausingcorrectinput.

ErrorHandling

Therearethreekeyfactorstoconsiderwhenprogrammingtoavoiderrors:
prevention,detection,andrecovery.Takingadequatestepstopreventerrorswill
certainlyhelptoensureyouhaveahappyusercommunity. However,howdo
youpreventerrorsiftheycannotbedetectedbytheprogrambeforetheuserwill
suffertheconsequences?Haveyouandyourteamtakenthetimetoinvestigate
andaccountforeverypossiblekeystroke,input,anddatatypethatausercould
enter?Reallythinkaboutthiswhileyouarestillinthedesignphaseandagain

298
A Beginner's Guide to Gambas

duringtheinitialdevelopmentofthetestplansbecauseitcancomebacktohaunt
youformany,manybuildandretestiterations.Finally,iftheerrordoesoccur,
whatcanbedonetogettheprogrambacktothestateofusabilityitwasinbefore
theerroroccurred?

Most errors are the result of inadequate design, poor programming


practices,andpoortesting.Poorprogrammingpracticesincludecodingonlythe
method of achieving the desired results without accounting for user error,
mistakesininput,validationerrors,etc.Allprogrammersknowhowtodevelop
datavalidationchecksand usuallytrytoputthemoffuntiltheygetthecode
working.Makingdatavalidationarequirementbumpsthepriorityofdoingthis
workupanotchonthelistofthingstheprogrammerhastodo.Poortestingis
epitomizedbytestteamsfailingtoaccountforthesetypesoffactorsinthedesign
andconstructionoftheproducttestplansandtestcases.

BoundaryRelatedErrors

Whenaprogramexecutes,theprogramcursormovesfromonepartofthe
programtothenextexecutingthecodedinstructionssequentially.Thetransition
fromoneareatothenextintheprogramisdefinedbytheexitofoneboundary
condition and theentrytothenext. Thistransitional state,or boundary, can
includenumeric,text,andoperatorboundaries. Iftheuserisaskedtoentera
numberfrom0to99inaprogram,whathappensiftheuserenterstheletterB
ortypesin123instead?Whatiftheuserentersthenumber84andthesystem
tellsyouthenumberistoolarge,promptingtheusertotryenteringanumber
from099onceagain?Doestheprogramfailtovalidateinputandattemptto
processbadinput?Haveallpossibleboundaryconditionsbeenaccountedforin
designandtest?Really?

CalculationErrors

There are an infinite number of conditions that can cause calculation


errors. Theprogrammerlogicmayhavebeeninerrororhisorherformulafor
the calculation may be coded incorrectly. Rounding or truncation errors can
significantly alter desired results. A good design process should incorporate
pseudocodeforanyandallcalculatedresultstoshowhowtheseformulasare
intendedtobeimplementedorusedinproduction.Codereviewswouldcheckto
seethattheyareindeedimplementedasdesigned.Testcaseswouldexecuteall
boundaryconditionsagainstthecodeandverifytheimplementationisasrock
solidasitcanbebeforeturningitovertoproductionforgeneraluse.

299
A Beginner's Guide to Gambas

InitialandLaterStates

Whenaprogramexecutessubroutinesandusesvariables,thesevariables
oftenmustbeinitializedwithdefaultvalues.InGambas,suchdefaultsgenerally
take the form of a zero value or a NULL value. If initialization is not done
specifically by a developer, it is anyones guess as to what the value of that
variablewillbewhenfirstcalledunlessthevariableisoneofthedatatypesthat
Gambasinitializesautomatically.Remember,thesetypesoferrorsarearesult
ofprogrammersnotdoingthejobcorrectly.Asanexample,letusassumethat
inthepreviousexampleabovenovariable initialization iswhathashappened
when a routine calls for a variable to increment. The program processed 50
records,incrementingthevalueofthevariableeachtimetheroutineisexecuted.
When the value is output at the end of processing, it should be equal to 50.
However,theuninitializedvariablehadavalueof122(orsomeotherrandom
number) and the output shown to the user was 172. This describes what
constitutesaninitialstateerror.

Todemonstratelaterstateerrors,considerthesamesituationasabove,but
instead of passing the expected value of 50 to another module to use for
processing,thevalueof172ispassedalong. Theseerrorsareabitharderto
detectbecausetheoutputfromthecalledmoduleiswheretheuserthinksthe
error occurred. Programmers assigned to debug this problem have to trace
throughtheexecutionpathandfollowthechangingstateofthevariableuntilitis
discoveredtobeaprobleminthecallingmodule,notthecalledone.Theresult
ofthisisagreatdealoftimeandeffortwentintodiscoveringaproblemthatwas
avoidable. If the user reported this from a production system, project team
credibilityagaintakesahit.Asaprogrammanager,youmustensurethesetypes
of situations are prevented by facilitating adequate, indepth discussion in the
designphase.

ControlFlowErrors

Previously,westatedthatwhenaprogramexecutes,theprogramcursor
movesfromonepartoftheprogramtothenext,executingthecodedinstructions
sequentially. Someexecutioninstructionsforcetheprogramtojumpfromone
routine to another. This movementin execution isreferred to as programor
control flow. When a program does something wrong in control flow, it is
generallyaproblemwiththeprogramlogicoraprogrammererrorincodingthe
design. Such logic errors are often uncovered during code reviews in the
implementationphase.Sometimes,intestingtheyarediscoveredbybuildingtest

300
A Beginner's Guide to Gambas

cases to validate program flow based on the design specifications built in the
designphaseandthetestplansbuiltintheimplementationphase.Anyofthese
typesoferrorsdiscoveredbyauserwhenasystemisinproductionreflectsa
failureofthetestteamtoadequatelytesttheproduct. Asaprojectleader,you
areultimatelyresponsibleforpreventingthissituationfromoccurring. TRYto
workwiththedesignteamandtestcasedevelopersasearlyintheprocessas
possible to set proper expectations for the type of testing and the level of
thoroughnessyouexpect.

ErrorsinHandlingorInterpretingData

There are many ways data can become chock full of errors in a
developmentprocess.However,almostallofthesemyriadwaysdatacangoawry
are attributed to human error. These types of errors can be a result of
miscalculation, errors in logic, parameter passing errors, use of incorrect data
types,etc. Almostanythingthataprogrammercandotomakeamistakecan
causeanerrorindata.Thebestmeansofpreventingsucherrorsisacontinual
checkoflogic,reviewofexpectedandactualvalues,reviewofinputandoutput
data,etc.Thisisanongoingprocessanditinvolvesbothuseranddeveloper.

Fromtheuserperspective,thedatashouldbebenchmarkedagainstcurrent
meansofproducingthedata. Theusershouldcontinuallyreviewtheresultsof
outputtoensuresomethinghasnotrunafoulandcauseddatatobecomebad.
Fromthedeveloperperspective,basiccodingdisciplineshouldbeenforced;range
andboundaryconditionsneedtobechecked,parametricvaluesneedvalidation,
datatypevalidationmustoccur,anduseoftestdatamustbevalidatedtobeof
the right format, current and in sync with production data, and usable for
productionoutput. Itisalwaysgoodforteamleadstoreinforcetheseconcepts
withdevelopersandensureperiodiccodereviewstakeplace. Itisessentialto
teamsuccess.

RaceandLoadConditions

Araceconditionisbestdefinedasoneeventprecedinganother.Thetrick
ismakingsurethefirstconditionshouldbefirstorthelastconditionissupposed
to be last. Few programmers think about or even check for race conditions.
Theseconditionsaresometimesidentifiedonlyaftergreatmanpowerhasbeen
expended in doing traces into executable code, step by step, to see what is
happening.Whenyouhearthewordsirreproducibleastestersaretalkingabout
thistypeofbug,interpretittomeanapossibleraceconditionandasksomeoneif

301
A Beginner's Guide to Gambas

theyhavecheckedforit.

Loadconditions arecommonandaretheresultofputtingmoreworkon
thecomputerthanitcanbeartohandle.Asimplepointofillustrationishavinga
computerprocessmillionsofrecords. Itistheperfectjobforacomputerbut,
whenthetimetoprocesseachrecordismorethanafewmilliseconds,themillion
recordstobeprocessedcantakeagreatdealoftime.Forexample,letsassume
an ideal situation where your application does some complex validation,
necessary to properly process a record, and that it takes 10 milliseconds to
process each of these records in a perfectly managed test environment. This
translatestoaprocessingrateof100recordsasecond.Notbad,butwhenyou
divide100into1,000,000 records,youquicklyfindoutthatthisjobwilltake
10,000 secondsor2.7 hourstoruntocompletion. Again,acceptable inmost
cases,exceptthatyoumustrememberthemachineiscompletelytiedupwith
processing. Noreportscanbeproduced,noqueriescanberun,etc. Intodays
moderncomputingenvironment,thisisnotacceptable.

Letstakeanotherviewwhererealworldconditionsareapplied.Inatest
environment,wherethe10millisecondsareidealcomputingconditions,wewill
compoundtheproblemwithuserinteractionandsystemoverhead.Letslookat
recordretrievaltimesandfactorthatintotheequation.Your10millisecondsare
now 14.5 milliseconds per record. User queries and other user interactions
interactioncouldeasilyaddanother10orsomillisecondsperactivityandnow
weareat25millisecondsofprocessingtimeforjustasinglerecord.Wearenow
lookingat6.75hourstorunthesamejobthatranin2.7hoursinthetestlab.
The point here is that testing should account for such load conditions before
releaseintoproduction.Ifauserknowsbeforekickingoffaproductionjobthatit
willtake7hourstorun,theycangooffanddootherthingsorrunthejobat
night. However, if the EXPECTATION is a 2.5 hour job, they will always be
dissatisfiedwithperformancebecauseitisnotwhattheyexpected.

PlatformandHardwareIssues

Hardwareissuesareamongthemostfrustratingausercanencounter.An
examplewouldbehavingauserselecttoprintareportandwatchitscrollbyon
thescreen,atamillionwordsasecond. Theprinterdevicewasnotspecified
correctly or not specified at all. The user assumed a printer would print the
reportbutdeviceerrorsorlackofdevicehandlingcausedthesituationabove.
Therearemanytypesofdeviceswhichaprogrammermustaccountforandthe
testingprocessneedstoaccountforuserinteractiononallofthem.Asidefrom

302
A Beginner's Guide to Gambas

theconditioncitedabove,programscansendthewrongcodestotherightdevice,
overrunthedevicewithdata,etc. Programmersandtestersareresponsiblefor
ensuring these conditions are accounted for and tested before your user
communityareexposedtothem.Allthesetypesoferrorscandoisgiveyouabad
markincredibilityasyourusersrateyourperformance.

Source,Version,andIDControlErrors

Thesetypesoferrorsaregenerallyduetopoorconfigurationmanagement
and an internal lack of enforcement of existing configuration management
policiesandprocedures.Anexampleofthisishavinganewprogrammerinserta
betaversionofcodeintoaproductionstablereleaseforanormalbugfixandthen
nottellinganyoneachangehasbeenmadeinthatmodule.Normaltestingofthe
maintenancereleasewilllikelynotcatchtheproblemanditmaygounnoticed
forseveralsubsequentreleases.

Asanotherexample,thissituationcould besomethingasinsidiousas a
dataerrorthatonlyshowsuponlywhenquarterlyfinancialsareproduced.When
thereisnoreasontobefoundastowhythecompanybalancesheetisoffby
several hundred thousand dollars, much effort is expended in having senior
developers perform code traces to find a problem. Someone will eventually
discoverthatthereissomebetacodeinaproductionmodulethathaserrantly
roundedeverythingtothenearestdollarorsomeothersimilarstupidmistake.
Good intentions aside, the best cure for these types of problems is good
programmerdisciplineforconfigurationmanagementandtohavestrongpolicy
enforcementingrainedintoanorganizationscorporateculture.

TestingErrors

Eventestersmakemistakes. Theycaninterpretthelogicofatestcase
improperly,theycanmisinterprettestresults,failtoreportglitches,etc.Testers
mayforgettoexecutetestcasesorreportbugsthatreallydontexist.Thesefolks
arehumantoo.Thatmeanstheirresultsarealsosubjecttoquestioning.When
yourteamshaveworkedhardtodevelopsomethingand thetestresultscome
backskewedbadlyonewayoranother,questionthetestprocess.

TestPlanReviews

Forallbutthemostsimpletypesofprojects,aformalreviewprocessis
generally required. This also requires participation from the users, the

303
A Beginner's Guide to Gambas

developers, the systems analysts, data analysts, and testers. It is best for all
concerned if the formal test review include the most experienced users and
developers present in an organization. Some users may not have the proper
experiencewithasystemtoproperlyidentifyproblemsbeforetheyoccurandthis
addedexperiencecanonlybenefitareviewprocess. Ensureparticipationina
formaltestplanreviewisbased lesson theavailability ofuserand developer
personnelandmoreonthecontributionsthebestqualifieddevelopersandusers
canbringtothetable.Nowthatwehaveagoodunderstandingofthehowand
whyoferrors,letstalkabouthowwecanmanagesucherrorsinGambas.

GambasErrormanagement

Gambas provides builtin mechanisms to assist the programmer in error


management. Suchmechanismsaretoolsataprogrammer'sdisposal thatare
oftenoverlookedand,inmanyinstances,notusedatall.Gambaswasdesigned
withtheconceptsofsimplicityandavoidanceoferrantlogicinmind. Gambas
programsyouwriteshouldtrytoadheretotheseconceptsbyusingallofthe
meansavailabletopreventerrors.Thismeanstakingthetimetowritevalidation
routines,workingyourcodetotrackflowandprovideoutputlogs,etc.Itisreally
not that much more work and will make a huge difference in the long run.
Gambascanonlyprovideanenvironmentinwhichtodevelop,but,intheend,it
isyou,thecoder,thatisresponsibleforyourproduct.Let'stakesometimenow
tolearnhowtousetheGambasfeaturesforerrormanagement.

TRYstatement...IFERROR

TheTRYcommandprovidesaprogrammerwiththemeanstoperforman
errorcheckanywhereheorshesuspectsanerrormayoccur.Itis,ineffect,away
totestthewaterbeforejumpingin.Youcantrytoexecutethestatementand,if
anerroroccurs,itwillberecordedbythe Errorclass. Thisisdonebysetting
propertyvaluesthatyoucancheck.Thesepropertyvaluesinclude:

Error.Class
Error.Code
Error.Text
Error.Where

TheError.Classpropertywillreturntoyouthenameoftheclasswherethe
erroroccurredandthe Error.Codeproperty willtellyouwhatthespecificerror
code was. Thetextassociated withtheError.Code isstored inthe Error.Text

304
A Beginner's Guide to Gambas

property andthe Error.Whereproperty willtellyoutheoffendinglineofsource


code(ifpossible). Theerrorclassalsoprovidestwomethods, Error.Clear and
Error.Raise thatyoucanusetohelptrackdownproblems. Wewilldiscussthe
useofthesetwomethodsalittlebitlaterinthischapter.

The TRYstatement isusedtotestforspecificerrorswhereasthe CATCH


statement (described below) is more of a general purpose error catching
mechanism.ThegenerallogicusedforTRYisshowninthepseudocodebelow:

TRYaStatement
ifERRORTHEN
Message.Error(error.text)
endif
'endoftry

Let'screateaquickexampletodemonstratehowtousetry. OpentheGambas
IDEandcreateanewgraphicaluserinterfaceproject.Createastartupclassform
andputanExitbuttonontheform,namedExitBtn.Doubleclickonthebutton
andaddthiscode:

PUBLICSUBExitBtn_Click()
DIMaASInteger
DIMbASInteger

a=2
b=0

TRYPRINTa/b
IFERRORTHEN
Message.Error("CLASS:"&Str(Error.class)&",CODE:"&error.code&
",="&error.text&"AT:"&error.where,"OK")
ENDIF
END

Saveyourworkandexecutetheprogram.ClicktheExitbuttonandyoushould
seesomethingsimilartothis:

Figure86ErrorresultscaughtwithTRY.

305
A Beginner's Guide to Gambas

CatchandFinallyStatements

Catch is a general purpose error trap. Itis executed when an error is


raisedanywherebetweenwhereafunctionstartstoexecuteandwhereitends.
Catchprovidesamenstodealwitherrorsthatmayoccurinagivenfunctionand
stillallowtheusertokeepusingtheprogram. Anerrorcanberaisedbythe
functionitself,orbyanyotherfunctionitmaycallduringexecution.Ifthecalled
functionhasaCatchblock,themorenestedtheCatchblockis,themorepriority
ithas. Inotherwords,ifanyerroroccurredinthenestedsectionofcode,the
Catchinthatsectionwouldbeexecuted,nottheCatchfromthecallingfunction.
Ifanerrorisraisedwhiletheprogramisexecutingwithinthecatchblockitself,
theerrorwillnormallybepropagatedoutsidethecatchblockbecausecatchhas
nomeansofprotectingitself. Ifthereisa Finally partinthefunction,itmust
precedethecatchpart.Let'screateasimpleprogramtodemonstratethisfeature.
Createanewprojectnamed Chap13 asaGUIbasedprojectandwhentheIDE
appears,createastartupclassformnamedForm1.Addtwobuttons,Errorand
Quit,namedErrBtnandQuitBtn.Placethebuttonsonthebottomrightcornerof
theform.CreateaTextLabelandnameitTextLabel1.Putitatthetopleftcorner
oftheformandstretchitallthewayacrossandmakeitaboutoneinchinheight.
Doubleclickontheformandenterthiscode:

'Gambasclassfile

PUBLICSUB_new()
TextLabel1.Text="<center><strong>Noerrorspresent."
END

STATICPUBLICFUNCTIONRun()ASBoolean
DIMhFormASForm
hForm=NEWForm1
RETURNhForm.ShowModal()
END

PUBLICSUBQuitBtn_Click()
ME.Close(TRUE)
END

PUBLICSUBErrBtn_Click()
DIMaASInteger
DIMbASInteger

a=2
b=0
PRINTa/b'willgenerateadividebyzeroerror

306
A Beginner's Guide to Gambas

FINALLY
TextLabel1.Text="CLASS:"&Str(Error.class)&",CODE:"&
error.code&",="&error.text&"AT:"&error.where
TextLabel1.Refresh

CATCH
IFERRORTHEN
Message.Error("CLASS:"&Str(Error.class)&",CODE:"&
error.code&",="&error.text&"AT:"&error.where,"OK")
ENDIF
Message.Info("ClearedtheError","OK")
TextLabel1.Text="<center><strong>Errorhasbeencleared."

END

Whenyouruntheprogram,youshouldseethisastheopeningscreen:

Figure87CATCHtestprogramopeningscreen.

Now,clicktheerrorbuttontogenerateourerrorandyoushouldseethis:

Figure88DivbyZeroerrorcaughtbyCATCH.

YoushouldalsonoticethatthemainscreenTextLabelhaschangedtothis:

307
A Beginner's Guide to Gambas

Figure89TheTextLabelupdatedwitherrorinfo.

OnceyouclicktheOkbuttonfortheErrorMessagedialog,youwillseethis:

Figure90Infomessagethattheerroris
cleared.

Now,clicktheOKbuttonontheInfomessageandtheTextAreaisupdatedlike
this:

Figure91Mainscreenaftererrorhasbeencleared.

ThisshouldgiveyouaprettygoodideaofhowtousetheGambaserror
managementfeaturestohelpmanageerrorswhentheyoccurinyourcode(and
theyinevitablywilloccur). Nothandlingerrorslikethedivbyzeroweusedin
ourexamplewillbeashowstopperinmostcircumstances.Asaquickexample,

308
A Beginner's Guide to Gambas

gobacktoourcode,intheErrBtn_Clicksubroutineandcommentouttheselines:

'FINALLY
'TextLabel1.Text="CLASS:"&Str(Error.class)&",CODE:"&
error.code&",="&error.text&"AT:"&error.where
'TextLabel1.Refresh
'CATCH
'IFERRORTHEN
'Message.Error("CLASS:"&Str(Error.class)&",CODE:"&
error.code&",="&error.text&"AT:"&error.where,"OK")
'ENDIF
'Message.Info("ClearedtheError","OK")

Now,runtheprogramagainandclicktheErrorbutton.Hereiswhatyouget:

Figure92DefaultGambaserrordialog.

Youcantrytocontinue,butthereisnoguaranteethatyourprogramwill
workcorrectlyorthatitwillevencontinue.Thisisdefinitelynotwhatyouwould
wantyouruserstosee. Itjustmakesgoodsensetousethetoolsavailablein
Gambastopreventthiswhenyoucan.Now,letsmoveontoseehowwecanuse
eventstohelpwritebettercode.

GambasEventmanagement

Gambas is built around an eventdriven programming paradigm.


Traditionalcomputerprogramminglanguagesweredesignedtofollowtheirown
control flow changing flow direction (course) at branch points. In an event
drivenparadigm, the control flowis largely driven by external eventssuch as
mouse movements, button clicks, etc. Generally, an eventdriven system is
preprogrammedusinganeventloopwhichsystematicallypollsthesystemtolook
forinformationtoprocess(whichcouldbeanytypeofevent,eventhepassageof
time).Ifaneventisdetected,ittriggersaflagthatcanbecheckedintheevent
loop. Thisallowsprogrammerstocheckforandrespondtoeventsbywriting
subroutinesorfunctiontoprocessthem.

309
A Beginner's Guide to Gambas

How information on events is acquired by the system is not really


importanttotheprogrammer.Commontypesofeventinputdatacanbepolled
intheeventloop.Complexorproprietaryeventsmayrequiretheuseofinterrupt
handlersthatreacttohardwareevents,suchassignaldatatraversinganetwork
interfacecard(NIC).Mosteventdrivensystemsusebothtechniques.Algorithms
writtenbytheprogrammertorespondtoeventsensurethatwhenagiveneventis
triggered, code to handle the event in a manner acceptable to the user is
provided.Thiscreatesalayerofsoftwareabstractionthatemulatesaninterrupt
drivenenvironment.Eventdrivenprogramstypicallyconsistofanumberofsmall
programscalledeventhandlers.Eventhandlersarecalledinresponsetoevents.
A dispatcher is used to call the event handler. Most often, the dispatcher is
implementedbyusinganeventqueuetoholdunprocessedevents. Sometimes,
eventhandlerscantriggereventsthemselves.Thiscanpossiblyleadtoanevent
cascade(notgood).

Gambas, like most common graphical user interface programs, is


programmed in an eventdriven style. In Gambas, you have the capability of
creatingeventsforuseinyourprograms.Youcandeclareaneventlikethis:

EVENTIdentifier([Parameter#1[,Parameter#2...])[ASBoolean]

Thisdeclarationwilldeclarea classevent. Aclasseventisraisedbya


functioncall.Additionally,youcanspecifywhetherornottheeventhandlerwill
returna (Boolean)value. If areturnvalueisspecified, a TRUEreturn result
wouldindicatethattheeventwascanceled.

AuniquefeatureofGambasisthatanobjectcanraiseanevent.Inorder
toraiseanevent,theobjectmustbegivenaname(orhandle)atthetimeitis
createdwiththeNEWkeyword.Withoutbeingassignedaname,eventsraisedby
anobjectareignored.Eventsarecaughtbytheparentofanobject.Theparentis
actuallyanobject'suniqueeventobserver.Theparentactsasthedefaultobserver
fortheobjectwhenaneventisraised.Thisparentcanbeaclass,inwhichcase
theeventhandlermustbeastaticmethod.Inthiscase,thehandleandtheparent
bothcanbechangedatruntimeusingtheObject.Attach()andObject.Detach()
methodsoftheObjectclass.Thehandleoftheobjectisnotstoredwithanobject
andthereforecannotberetrieved.

InGambas,thestandardcallingconventionforaneventhandlerwouldbe
InstanceName_EventNametoinvokethemethodtobecalledbytheeventlistener

310
A Beginner's Guide to Gambas

whensuchaneventisraised.Let'saddtoourpreviousexampletodemonstrate
theuseofevents. Addanotherbuttontotheformforourpreviousexample,
namedEventBtn.Doubleclickandaddthiscodetotheprogram:

EVENTMyEvent(MsgASString)ASBoolean

PUBLICSUBEvent1Btn_Click()
DIMbResultASBoolean

RAISEMyEvent("Raiseanevent")ASbResult

IFbResultTHEN
TextLabel1.Text="Cancelledtheevent"
ELSE
TextLabel1.Text="Raisedtheevent"
bResult=NOTbResult
STOPEVENT
ENDIF
END

Saveyourworkandruntheprogram. ClicktheEventbuttonandyourdisplay
shouldlooklikethis:

Figure93Oureventwasraised.

311
A Beginner's Guide to Gambas

Chapter 14 Mouse, Keyboard and Bit


Operations
Themousewasdesignedtobeareplacementforgatheringkeyboardinput
fromauser.WhileGUIdesignhasadvancedsignificantlysincetheearlydaysof
windowedinterfaces,theevolutionofthemousehasnot. Probablythebiggest
change for the mouse was going optical and cordless. However, the basic
functionality remainsvirtually thesame. Provide an X,Y position, clicka left,
right, or middle button and detect it's state as up or down, and check the
movementofthemousewheelorchangethedeltavaluewhenthewheelmoves.
Gambas, of course, supports all of these basic features with an easy to code,
logicalapproach.Inthenextfewpages,wewillshowyouhowtomastermouse
andkeyboardinput.Finally,asalastexercise,wewillcreateaprogramtoshow
youhowtousebitoperators.Let'sstartwiththemouse.

MouseOperations

In Gambas, we can use the Mouse class to obtain information about a


mouseevent. Thisclassdefinestheconstantsusedwiththemouseproperties.
Theclassisstaticandthepropertiessupportedare:

Alt Button Control Delta Left


Meta Middle Normal Orientation Right
ScreenX ScreenY Shift X Y

Mostofthesepropertiesareselfexplainedbytheirname,butafewneed
furtherexplanation. The Alt, Control, Meta and Shift propertiesall return a
TRUEvalueifthoserespectivekeysarepressed.Normalcanbechecked(tested)
toseeifanyotherspecialkeywaspressed. Button canbeusedtoseeifany
buttonispressedbutyoucanuse Left,Right,and Middle todetermineifany
specificmousebuttonhasbeenpressed.AllofthesepropertiesreturnTRUEifa
button is pressed. Delta returns the (offset) value of the mouse wheel while
Orientation can be used to check the direction (forward, backwards) of the
wheel'sturn.ScreenXandScreenYreturntheabsolutevalueofthecursorbased
onthedesktopwhileXandYreturnthepositionrelativetothewindow.

ThereisonlyonemethodfortheMouseclass,Move.TheMovemethod
simply repositionsthemousecursor totheX,Y coordinatesspecified. Mouse
eventsyoucanmonitorinyourprogramareMousemove,MouseDown,Mouseup,

312
A Beginner's Guide to Gambas

andMousewheel. Anychangeinthecurrentstateofthoseeventsallowyouto
create a coded response for that event. When coding mouse (or keyboard)
operations,itisveryimportanttoalwaysusethepredefinedconstants. Usingany
other method of getting or setting properties is not guaranteed to be upward
compatible from one Gambas version to the next. The Mouse class uses the
followingconstantstospecifytheshapeofthemousecursor:

Arrow Blank Cross Custom Default


Horizontal Pointing SizeAll SizeE SizeH
SizeN SizeNE SizeNESW SizeNW SizeNWSE
SizeS SizeSE SizeSW SizeV SizeW
SplitH SplitV Text Vertical Wait

Let'screateashortGambasprogramtodemonstratehowtousethemouse
now.FromtheGambasIDE,createanewprojectnamedMouseOpsandmakeit
agraphicaluserinterfaceproject,translatablewithpubliccontrols.Createanew
form,Form1andmakeitastartupclassform.Next,addadrawingareanamed
da tothetopleftcorneroftheForm1window. Resizeittobeaboutoneinch
square. Now,let'saddsomecode. Firstofall,whentheprogramrunsandthe
windowopens,wewanttosetacaptionthattellstheuserhowtoclearorexitthe
window.Wealsoneedtoresizethedrawingareatofittheformfullyandsetthe
cachedbufferpropertytoTRUEsoourdrawingcanbeseenbytheuser.Hereis
howtodothis:
'Gambasclassfile

'whenformopensatruntime,setacaptionandresizethedrawingarea
PUBLICSUBForm_Open()
ME.Caption="Pressspacetoclear,mousewheelexits..."
da.W=ME.W5
da.H=ME.H5
da.ForeColor=color.Black'settheforegroundcolortoblack
'setcachedpropertytotruesowecanstorethedrawingbuffer
da.Cached=TRUE
draw.Begin(da)'starttodraw
'wewilldrawahorizandvertlinetosectionfourquadrants
draw.Line(1,da.h/2,da.W1,da.h/2)
draw.Line(da.W/2,1,da.W/2,da.H1)
draw.End
END

Ifthemousemoves,wewanttochangethecursorshape,dependingon
whichquadrantofthedrawingareathemouseisin.WewillusetheMousemove
eventandcodethis:

313
A Beginner's Guide to Gambas

'ifthemousemoves,wewillupdatethecursorshapedependingonthe
'quadrantthemouseislocatedat
PUBLICSUBda_MouseMove()
'checkthetopleftquadrant
IFmouse.X<=da.W/2ANDmouse.Y<=da.H/2THEN
da.Mouse=mouse.Pointing
'elsewecheckthebottomleftquadrant
ELSEIF
mouse.X<=da.W/2ANDmouse.Y>=da.H/2THEN
da.Mouse=mouse.Cross
'elsewecheckthetoprightquadrant
ELSEIF
mouse.X>=da.W/2ANDmouse.Y<=da.H/2THEN
da.Mouse=mouse.SizeNWSE
'otherwise,itmustbeinthebottomrightquadrant
ELSEIF
mouse.X>=da.W/2ANDmouse.Y>=da.H/2THEN
da.Mouse=mouse.SizeNESW
'ifitisanywhereelse,makeitthedefault
ELSE
da.Mouse=mouse.Default
ENDIF

Nowthatwehavesetthecursorshape,wewillchecktoseeiftheuseris
pressing a mouse button to draw. If the left buttonis pressed, we will draw
points.Ifitistherightbutton,wewilldrawtinyboxes.
'checkmousebuttonispressedtoseewhichoneispressedand
'drawpointsforleftbtn,boxesfortheright
IFMouse.LeftTHEN
'starttodraw
Draw.Begin(da)
'littletinydots
Draw.Point(Mouse.X,Mouse.Y)
Draw.End
ELSE'ifitisrightbutton
Draw.Begin(da)
Draw.Rect(Mouse.X,Mouse.Y,3,3)
Draw.End
ENDIF
END

Whenevertheusermovesthemousewheel,wewillterminatetheapplication.
'iftheusermovesthemousewheel,wewillterminatetheapplication
PUBLICSUBda_MouseWheel()
ME.Close
END

314
A Beginner's Guide to Gambas

Iftheuserhaspressedand releasedamousebutton,we willresetthemouse


cursortothenormalstate.
'wheneveramousebuttonisreleased,resetmousecursortonormal
PUBLICSUBda_MouseUp()
da.Mouse=mouse.Default
END

Finally,iftheuserpressesanykey,wewillresetthedrawingareabyclearingit
andredrawthequadrantbycallingthesameroutineusedtoopentheform:
'checkkbdeventstoclearthedrawingareaandredrawthequadrants
PUBLICSUBForm_KeyPress()
da.Clear
Form_Open()
END

That'sit.Whenyouruntheprogram,youshouldseesomethinglike
this:

Figure94MouseOpsprogramrunning.

Asyoumovethemousefromquadranttoquadrant,noticehowthecursor
changes. Tryboththeleftandrightmousebuttonsandpressthespacebarto
clearthedrawingandrestart.Whenyouaresatisfiedeverythingworks,movethe
mousewheelandtheprogramwillterminate. Now,let'slearnaboutkeyboard
operations.

315
A Beginner's Guide to Gambas

KeyboardOperations

This class is used for getting information about a keyboard event. It


containsallofthepredefinedconstantsGambasusestorepresentthekeysfound
on your keyboard. As we pointed out previously, you should never use the
integer key values directly. You should always use the Gambas predefined
constants.Thisclassisstaticanditactslikeareadonlyarray.Youcandeclare
an integer variable and obtain the value of a key constant using this calling
convention:

DIMMyIntegerASInteger
MyInteger=Key[KeyASString]

PropertiesthataresupportedfortheKeyclassincludeAlt,Code,Control,
Meta,Normal,Shift,StateandText.Statecanbeusedtotestwhetherornota
specialkeyispressedandTextwillreturnthesinglecharacterrepresentationfor
agivenkey. AlltheotherpropertiesworklikethoseusedwiththeMouseclass
we described in the previous section. The Key class supports the following
predefinedconstants:

Forcursorkeys: Up,Down,Left,andRight

Forfunctionkeys: F1F2F3F4F5F6F7F8F9F10F11F12

ForshiftedFkeys: F13F14F15F16F17F18F19F20F21F22F23F24

Forallotherkeys: BackSpace BackTab CapsLock Delete End


Enter Esc Escape Help Home
Insert Menu NumLock PageDown PageUp
Pause Print Return ScrollLock Space
SysReq Tab

Let'screateanothershortGambasprogramtodemonstratehowtousethe
keyboard.FromtheGambasIDE,createanewprojectnamedKbdOpsandmake
itagraphicaluserinterfaceproject,translatablewithpubliccontrols. Createa
newform,Form1andmakeitastartupclassform.Wewillonlyneedtousetwo
labelsinthisprogram,aTextLabelandaLabel.First,createaTextLabelnamed
TextLabel1andmakeitabout1/2highandstretchitacrossthewidthofthe
form. SettheTextLabel1.Alignmentpropertyto center. Now,createaLabel
named Label1 and place it below the TextLabel1 control. Make it about two

316
A Beginner's Guide to Gambas

incheswideand1/2tall. SettheLabel.TextpropertytoPressanykey...and
setthecontrolfontsizeto14pointandmakeitbold.Doubleclickontheform
andthecodewindowappears.Hereisthecodewewilladdtoourprogram:

'Gambasclassfile

'wewillcheckthekeyreleaseeventtoseewhattodo
PUBLICSUBForm_KeyRelease()
'wheneverakeyisreleased,checkthecode
SELECTkey.code
CASEkey.Tab'ifitisatabkey
textlabel1.Text="Keycodeis:"&key.Code&",TAB."
CASEkey.BackSpace'orbackspace
textlabel1.Text="Keycodeis:"&key.Code&",Backspace."
CASEkey.CapsLock'orcapslock
textlabel1.Text="Keycodeis:"&key.Code&",CapsLock."
CASEkey.F1'oraFkey
textlabel1.Text="Keycodeis:"&key.Code&",F1key."
CASEkey.F2
textlabel1.Text="Keycodeis:"&key.Code&",F2key."
CASEkey.F3
textlabel1.Text="Keycodeis:"&key.Code&",F3key."
CASEkey.F4
textlabel1.Text="Keycodeis:"&key.Code&",F4key."
CASEkey.F5
textlabel1.Text="Keycodeis:"&key.Code&",F5key."
CASEkey.F6
textlabel1.Text="Keycodeis:"&key.Code&",F6key."
CASEkey.F7
textlabel1.Text="Keycodeis:"&key.Code&",F7key."
CASEkey.F8
textlabel1.Text="Keycodeis:"&key.Code&",F8key."
'ifnoneoftheabove,isitprintable?Ifso,showcodeandvalue
CASEELSE
IFkey.Code>32ANDkey.Code<128THEN
textlabel1.Text="keycodeis:"&key.Code&","&Chr(key.Code)
ELSE'otherwisejustthecode
textlabel1.Text="keycodeis:"&key.Code
ENDIF
ENDSELECT
END

'checkkeydowneventtofilteroutshift,control,alt,etc.
PUBLICSUBForm_KeyPress()

IFkey.ShiftTHEN
textlabel1.Text="Keycodeis:"&key.Code&",SHIFT"
ELSEIFkey.AltTHEN

317
A Beginner's Guide to Gambas

textlabel1.Text="Keycodeis:"&key.Code&",ALT"
ELSEIFkey.ControlTHEN
textlabel1.Text="Keycodeis:"&key.Code&",CTRL"
ELSEIFkey.Code>32ANDkey.Code<128THEN
textlabel1.Text="keycodeis:"&key.Code&","&Chr(key.Code)
ELSEIFkey.EscTHEN'ifanESCkeyispressed
textlabel1.Text="keycodeis:"&key.Code&",ESC"
ELSE
textlabel1.Text="keycodeis:"&key.Code
ENDIF
END

PUBLICSUBForm_Open()
ME.Caption="KeyboardOperations"
END

As you can see, the code above is pretty straightforward and simple.
Whenyouruntheprogram,youshouldseesomethinglikethis:

Figure95KbdOpsprogramrunning.

BitOperations

Bits are the smallest elements used in computer operations. They are
indivisibleatomsofmemoryclusteredingroupscalledbytes.Abyteiscomposed
of n number of bits, which is dependent upon the machine word size. For
example,inaneightbitsystem,onebyteiscomposedofeightbits.Formodern
computingsystemsusedtoday,theoperatingsystemisbuiltusing32or64bit
word sizes. The word size increases in order to accommodate a larger
addressablememoryspace.Inanoldereightbitsystemforexample,thesystem
canonlyaddressmemorythatcanbeexpressedinbinaryformas11111111.In

318
A Beginner's Guide to Gambas

otherwords,thememoryspaceislimitedtoasizethatcanbeexpressedwith
thoseeightbits.Foraneightbitsystemsmemoryrangesextendfromthesingle
bytedecimalrepresentationof65537to+65538.Inamodern32bitsystem,it
takesthebinaryformof11111111111111111111111111111111 whichcanbe
expressedindecimalnotationas2,147,483,648to+2,147,483,647.Asyoucan
see,theaddressablerangeofmemorywith32bitsystemsishuge!

Inapplicationslevelprogramming,thereisgenerallynotmuchoccasionto
operate at the bitlevel when but occasionally the need does arise. Gambas
providesallofthetoolsyouneedtotestabit,clearit,change(invert)it,orsetit.
Additionally,bitwiseoperationsyoucanperformincluderotatingabitrightor
leftandshiftingabitrightorleft.Thetablebelowsummarizesthebitoperations
youcanperforminGambas:

Gambas Bit Operations


Operator Syntax Actiontaken
BTst Boolean=BTst(Number,Bit) Testtoseeifabitissetinoperand1usingoperand2
BClr Value=BClr(Number,Bit) Clearaspecificbitinoperand1usingoperand2
BSet Value=BSet(Number,Bit) ReturnTRUEifthethebitspecifiedinoperand2ofoperand1isset.
BChg Value=BChg(Number,Bit) Returnsoperand1withthebitspecifiedinoperand2inverted.
Shl Value=Shl(Number,Bit) Returnsoperand1withthebitspecifiedinoperand2shiftedleftonebit
position.
Shr Value=Shr(Number,Bit) Returnsoperand1withthebitspecifiedinoperand2shiftedrightonebit
position.
Rol Value=Rol(Number,Bit) Returnsoperand1rotatedleftoperand2bitpositions.
Ror Value=Ror(Number,Bit) Returnsoperand1rotatedrightoperand2bitpositions.

Now, we will create yet another short Gambas program todemonstrate


howtousethebitfunctions.FromtheGambasIDE,createanewprojectnamed
BitOps. Make it a graphical user interface project, translatable with public
controls. Create a new form,Form1 and make itastartup class form. Our
programwilltakeanintegernumberfrom0255anddisplaythehexadecimal
andbinaryvaluesforthatnumber.Itwillallowyoutoselectanyoneoftheeight
bitsusedtorepresenttheintegernumberandperformwhateveroperationthe
buttonyouclickrepresents.Thebinaryvalueofthatintegerwillbedisplayedso
you can compare that binary value to the value of the integer as originally
specified. Forthisprogram,wewillneedsevenTextLabels,namedTextLabel1
through Textlabel7. We will need two TextBoxes, TextBox1 and TextBox2.
Finally, we will add nine buttons named RolBtn, RorBtn, ShlBtn, ShrBtn,
ClearBtn, TestBtn, SetBtn, ChangeBtn, and the QuitBtn. Layout the controls

319
A Beginner's Guide to Gambas

aboveontheform,asshowninthefigurebelow:

Figure96TheBitOpsprogramindesignmode.

Once you have finished laying out the controls as shown in the figure
above,doubleclicksomewhereontheformandthecodewindowwillappear.
AddthefollowingcodefortheForm_Opensubroutine:

'Gambasclassfile
PUBLICSUBForm_Open()
ME.Caption="bitOpns"
END

Now,theprogramwilldisplaythecaptionbitOpnswhenitisexecuted.
Let's code an exit procedure so the user can terminate the application next.
DoubleclickontheQuitbuttonandaddthis:
PUBLICSUBQuitBtn_Click()
ME.Close'closethewindow
END

IftheuserentersanyvalueintheTextBox2fieldtochangeabit,weneed
toupdatetheformandreflectthechangedvalues.Wewillworryaboutwhatto
dowiththenewvaluealittlelateroninthecode.Fornow,itisasimplecallto
theRefreshmethodweneed:
PUBLICSUBTextBox2_Change()
form1.Refresh'refreshourdisplayanytimethebitvaluechanges
END

WhentheuserspecifiesanintegervalueintheTextBox1field,wewillonly
reacttotheentrywhentheTABkeyispressed. ThatcausesaLostFocusevent,
whichiswhatwewillcodefor.Hereiswhatweneedtodonext:

320
A Beginner's Guide to Gambas

PUBLICSUBTextBox1_LostFocus()
'weneedalocalintvartoworkwith
DIMmyIntASInteger
'convertourstringtextvaluetoanint
myInt=CInt(textbox1.text)
'checktoseeifitisin8bitrange
IFInt(myInt>=0)AND(myInt<256)THEN
Label2.Text="Hex:"&Hex(myInt)'converthexvalue
label3.Text="Bin:"&Bin(myInt)'convertbinvalue
label7.Text=Str$(myInt)'updateourtextfields
form1.Refresh'refreshtheform
ENDIF
END

Whentheuserpressestheclearbutton,wewanttoclearthebitspecifiedforthe
integerrepresentedbythefirstparameter.
PUBLICSUBClearBtn_Click()
DIMiASInteger
DIMresultASInteger
DIMmyIntASInteger
'convertourstringtextvaluetoanint
myInt=CInt(textbox1.text)
'iftheintegerisbetween0and255process,otherwiseignore
IFInt(myInt>=0)AND(myInt<256)THEN
'convertstringvaluetoanint
result=CInt(TextBox2.Text)
'clearthebit
i=BClr(myInt,result)
'updatethelabeldisplays
label5.Text="Bclr:"&Bin(i)
label7.Text=Str$(i)
ENDIF
END

WhentheuserpressestheSetbutton,wewanttosetthebitspecifiedforthe
integerrepresentedbythefirstparameter.Thisisessentiallytheoppositeofclear
discussedabove.
PUBLICSUBSetBtn_Click()
DIMiASInteger
DIMresultASInteger
DIMmyIntASInteger
'convertourstringtextvaluetoanint
myInt=CInt(textbox1.text)
'iftheintegerisbetween0and255process,otherwiseignore
IFInt(myInt>=0)AND(myInt<256)THEN
'convertstringvaluetoanint

321
A Beginner's Guide to Gambas

result=CInt(TextBox2.Text)
'setthebit
i=BSet(myInt,result)
'updatethelabels
label5.Text="Bset:"&Bin(i)
label7.Text=Str$(i)
ENDIF
END

TheBchgfunctionisreallyjustaninvertoperation. Whenouruserclicksthe
Changebutton,wewillexecutethiscode:
PUBLICSUBChangeBtn_Click()
DIMiASInteger
DIMresultASInteger
DIMmyIntASInteger

myInt=CInt(textbox1.text)
IFInt(myInt>=0)AND(myInt<256)THEN
result=CInt(TextBox2.Text)
i=BChg(myInt,result)
label5.Text="Bchg:"&Bin(i)
label7.Text=Str$(i)
ENDIF
END

The Shl function is will shift the value of MyInt n bits left where n is
specifiedbythesecondparameter.WhenouruserclickstheShlbutton,wewill
executethiscode:
PUBLICSUBSHLBtn_Click()
DIMiASInteger
DIMresultASInteger
DIMmyIntASInteger

myInt=CInt(textbox1.text)
IFInt(myInt>=0)AND(myInt<256)THEN
result=CInt(TextBox2.Text)
i=Shl(myInt,result)
label5.Text="SHL:"&Bin(i)
label7.Text=Str$(i)
ENDIF
END

TheShrfunctioniswillshiftthevalueof MyInt n bitsrightwhere n is


specified bythesecond parameter. Whenouruserclicks theShrbutton,this
subroutinewillbeexecuted:

322
A Beginner's Guide to Gambas

PUBLICSUBSHRBtn_Click()
DIMiASInteger
DIMresultASInteger
DIMmyIntASInteger

myInt=CInt(textbox1.text)
IFInt(myInt>=0)AND(myInt<256)THEN
result=CInt(TextBox2.Text)
i=Shr(myInt,result)
label5.Text="SHR:"&Bin(i)
label7.Text=Str$(i)
ENDIF
END

Inolder8bitsystems,itwasimpossibletoprocessnumberslargerthan
255unlesstheyweresplitupinto8bitchunks.Operationswerethenperformed
oneachpieceofanumber.Aftertheoperationswerecompleted,itwasnecessary
toreassembleeachnumberbacktogethertorecreatethewholenumber. Allof
thiswasaccomplishedbyusingonetinybit,thecarrybit.TheGambasfunctions
ROL(rotateleft)andROR(rotateright)areusedtoshiftbitsinbinarynumbers.
Thesefunctionsworkconceptuallylikethis:

The ROL Instruction

7 6 5 4 3 2 1 0
C

The ROR Instruction


7 6 5 4 3 2 1 0
C

ROLandRORworksuchthatthecarrybitisshiftedintotheendbitthatis
leftemptybytherotationprocessinsteadofinsertingazerovalue.ROLshiftsthe
contentsofabyteoneplacetotheleft. ROLdoesnotplaceazerointobit0.
Instead,itmovesthecarrybitfrombitposition7intobitposition0ofthenumber
beingshifted. The0bitpositionwasvacatedbytheshiftrotationandtheROL
instructionplacesbit7intothecarrybitposition.RORworksjustlikeROL,but
intheoppositedirection.Itmoveseachbitofabyterightoneposition,placing
thecarrybitintobit7andbit0intothecarrybit.

323
A Beginner's Guide to Gambas

'rotateleft
PUBLICSUBROLBtn_Click()
DIMiASInteger
DIMresultASInteger
DIMmyIntASInteger

myInt=CInt(textbox1.text)
IFInt(myInt>=0)AND(myInt<256)THEN
result=CInt(TextBox2.Text)
i=Rol(myInt,result)
label5.Text="ROL:"&Bin(i)
label7.Text=Str$(i)
ENDIF
END

'rotateright
PUBLICSUBRORBtn_Click()
DIMiASInteger
DIMresultASInteger
DIMmyIntASInteger

myInt=CInt(textbox1.text)
IFInt(myInt>=0)AND(myInt<256)THEN
result=CInt(TextBox2.Text)
i=Ror(myInt,result)
label5.Text="ROR:"&Bin(i)
label7.Text=Str$(i)
ENDIF
END

Ifyouwantyourprogramtocheckifabithasbeenset,youcancallBtst.This
functionwillreturnTRUEifthebitspecifiedinoperand2ofoperand1isTRUE.
PUBLICSUBTestBtn_Click()
DIMiASBoolean
DIMresultASInteger
DIMmyIntASInteger

myInt=CInt(textbox1.text)
IFInt(myInt>=0)AND(myInt<256)THEN
result=CInt(TextBox2.Text)
i=BTst(myInt,result)
label5.Text="Btst:"&i
ENDIF
END

That is all we have to do for our bitfiddling program. Save your work and

324
A Beginner's Guide to Gambas

executetheprogram.Yourresultsshouldbesimilartothis:

Figure97OurbitOpsprogramrunning.

Whenyouaresatisfiedthattheprogramworksasweplanned,saveyour
work.Itwouldbeagoodexerciseatthistimetogobackandmodifythecodeto
ensureonlyintegervaluesareinputintothetwoTextboxfields.Also,youcould
allownegativenumberstobeenteredtoseewhatresultswouldbeproduced.I
willleavethatexercisetothoseamongyoueagerandambitiousenoughtotryit
isreallynotverydifficultandwehavealreadyshownyouhowtodovalidation
routines(remember,backinthecollectionschapter?). Inthenextchapter,we
willcoverbasicdatabaseoperationswithGambas.Theabilitytoworkwithdata
in your programs is essential and we cannot overlook this vital aspect of
programminginourjourneythroughGambas.

325
A Beginner's Guide to Gambas

Chapter 15 Gambas and Databases


This chapter describes in detail the process of using a MySQL or
PostgreSQL databasefromwithintheGambasprogrammingenvironment. For
ourpurposes,wewillassumethatMySQLisalreadyinstalledonyourmachine
(oramachineaccessibletoyoufromyourmachine)andthataMySQLserveris
availableforyoutoconnecttofromwithinyourGambasprogram.Ifthisisnot
thecase,thenyouwillhavetorefertotheMySQLmanualandfigureouthowto
installtheMySQLdatabasedistributiononyourparticularsystem. Youshould
alsobeawareofthefactthatGambaswillalsoworkwithPostgreSQLandSQLite.
SQLiteisnotatrueclient/serverarchitecturelikeMySQLandPostgreSQL.Itisa
flatfiledatabasesystemanddoesnotusetheclient/serverdatabasemodel.For
ourpurposesinthischapter,wewillsticktoMySQLsinceitisprobablythemost
widelyusedofthethreedatabaseproducts.

The MySQL database package consists of the MySQL server and many
clientprograms.TheMySQLserverisaprogramthatstoresandmanagesallof
your databases within the MySQL environment. The client programsthat are
includedwithMySQLaretoonumeroustolistherebutitisimportantforyouto
understandthateachclientapplicationservesaspecificpurposerelatedtothe
managementand/or administration of data or metadata stored on theMySQL
server.Theclientprogramwewillbedealingwithinthischapteriscalledmysql
(noteitisspelledinlowercaseletters). Thisclientprogramprovidesa command
line interface (CLI) you can use to issue SQL statements interactively to the
MySQLserverandseetheresultsdisplayedimmediately. Themaindifference
between MySQL and mysql isthat MySQL isusedtorefertotheentire MySQL
distributionpackageortorefertothe MySQL serverwhile mysql referstothe
clientCLIprogram.

Whatpurposedoesitservetohavebothaclientandaserverinsteadofa
singleprogram?Theserverandclientprogramsaredividedintodifferententities
soyoucanusetheclientprogram(s)onyoursystemtoaccessdataonaMySQL
serverthatcouldberunningonanothercomputer. Byseparatingthepackage
into a server and n clients, it serves to separate data from the data retrieval
interface. Beforeyoubeginworkingonthischapter,itishighlyrecommended
thatyoufamiliarizeyourselfwithMySQLbydownloadingthelatestmanualfrom
theofficialMySQLwebsite18.Ataminimum,completethetutorialinChapter3
oftheMySQLUserManualbeforeproceedingwiththischapter. Onceyouare

18 See URL http://www.mysql.com/ .

326
A Beginner's Guide to Gambas

familiarwithhowbasicSQLoperationsworkwithintheMySQLenvironment,you
arereadytocontinuewiththischapter,whichfocusesmoreonhowtoaccomplish
thesametypesofthingsthe MySQL tutorialdemonstrated, but fromwithina
Gambasprogram.

InordertoaccessdatabaseswithintheGambasenvironment,youneedto
ensureyourprojectusesthegb.dbcomponent.Whenyoucreateanewproject,
you need to go to the project properties dialog and you will find a tab for
components.Fromwithinthistabbeddialog,youcanselectthecomponentsyou
needforyourprogram. Inthecaseofdatabases,youwillneedtocheck gb.db
beforeyoucanuseanyoftheclassesdefinedbythiscomponent. Aswestated
previously, the gb.db component allows you to access the following database
managementsystems:PostgreSQL,MySQLandSQLite.BecausePostgreSQLand
MySqlareclient/serverdatabases,itmeansyourprogramwillneedtomakea
connectiontoadatabaseserver.SQLiteisaflatfilebaseddatabasesothereisno
serverprocessforyourprogramtoconnectwith.However,thisalsomeansthat
yourprogrammayneedtousefullyqualifiedpathnamesforanydatabasefileit
usesifthedefaultpath(i.e.,theapplicationpath)isnotused.

The gb.db component has been designed to create an intermediate


(abstracted)layerbetweenthedatabaseserverandyourprogram. Thisallows
youtousethesamecoderegardlessofthedatabasebackendyoudecidetouse.
Thereareacoupleofcaveats,ofcourse.Thisabstractedapproachonlyworksif
youhavecreatedyourdatabasebyusingthedatabasemanagerorbyusingthe
gb.dbcomponent.Furthermore,youmustusetheFind,CreateandEditmethods
providedwiththegb.dbcomponent. YoucannotputSQLvaluesdirectlyina
requestyoumustusethesubstitutionfeatureoftheaforementionedmethodsto
accomplishthat.Finally,youcannotusetheExecmethodtosendSQLrequests
directlytotheservertoaccessserverspecificfeatures. Whilethissoundsfairly
restrictive, in reality it is not a hindrance to your program. Given these few
caveats,youcanaccomplishalmostanydatabaseoperationneededfromwithin
theGambasenvironment.Theclassesthataresupportedinthegb.dbcomponent
areConnection,DB,Database,Field,Index,Result,ResultField,Table,andUser.

ConnectionClass

TheConnectionclassestablishesyourconnectiontothedatabase.Inorder
tosuccessfullyconnecttoadatabase,youmustfirstcreatea connectionobject
andsetthenecessarypropertiesthatwillbeusedbythedatabase.Nextyoumust
calltheOpenmethod.IfyouareconnectingtoaSQLitedatabaseandtheName

327
A Beginner's Guide to Gambas

propertyisnull,adatabaseisopenedinmemory. IftheNamespecifiedisan
absolutepath,thepathnameisused.IftheNamespecifiedisarelativepathand
theHostpropertyisnull,thedatabaseislocated intheapplicationtemporary
directory /tmp/gambas.$UID/sqlite. Otherwise, Host will contain the database
directorynameandthedatabasefilepathistheresultofconcatenatingtheHost
andNamepropertyvalues.Thisclassiscreatableandthecallingconventionis:

DIMhConnectionASConnection
hConnection=NEWConnection()

ConnectionProperties

When the hConnection object is instantiated, it creates a new void


connection object. You will then need to set properties for this object. The
propertiesthatyoucanusewithaconnectionobjectincludeCharset,Databases,
Host,Login,Password,Name,Port,Tables,Type,Usersand Version. Wewill
explaineachoftheseinthefollowingsections.

Charset

Charset is a readonly property that returns the charset used by the


database. Itispossibleforyoutostoreyourstringsinthedatabasedirectlyin
UTF8format. However,youcanalsocanusethispropertycombinedwiththe
Conv$()subroutinetoconvertfromUTF8formattothedatabasecharsetformat.
Using the database charset comes at a cost in performance however. This is
becauseyoumustusetheConv$()subroutineeachandeverytimeyoureador
writestringdatatothedatabasefields.Fornow,thisistheonlywayyoucando
thisifyouwanttousethestringbasedSQLfunctionsandbuiltinsortroutinesof
theunderlying databasemanagementsystem(MySQL,PostgreSQL,orSQLite).
Future versions of Gambas may automatically make the conversion between
Gambasstringsandthedatabasecharset.

Databases

The Databasesproperty canbecheckedtoobtainacollectionobjectthat


will contain names of all databases that are managed by the database server.
Syntaxis:

PROPERTYDatabasesAS.ConnectionDatabases

The resulting collection of data (which is enumerable using the FOR EACH

328
A Beginner's Guide to Gambas

statement)wouldbethesameasifyoutypedSHOWDATABASESfromthemysql
clientCLI.

Host

Youcanusethe Hostproperty tosetorgetthehostnameofwherethe


databaseserverislocated.ThehostnamecanbeeitheramachinenameoranIP
address. The default host is named localhost. In SQLite, host name is not
relevant since SQLite is not a client/server database sytstem. However, from
version0.95forward,itispossibleforyoutosetthehomepathfortheSQLite
databasebyusingthisproperty.SyntaxforusingtheHostpropertyis:

PROPERTYHostASString

Login

TheLoginpropertyisusedtosetorgettheuserlogindatathatisusedfor
establishingtheconnectiontothedatabase. Onceagain,thisappliestoMySQL
andPostgreSQL,notSQLite. SinceSQLitehasnoconceptofusers,accesstoa
SQLitedatabaseiscontrolledbythefilepermissionsettingsofthedatabasefile
itself.ThismeansthattheLoginpropertyisalwaysgoingtobesettotheuserid
oftheuserthatisexecutingtheGambasprogramthatusestheSQLitedatabase.
Syntaxis:

PROPERTYLoginASString

Name

The Name property setsor gets the name of the database you want to
connectto.Ifyoudonotspecifyaname,adefaultsystemdatabaseisused.For
PostgreSQLthedefaultdatabaseisnamed template1andformySQLitisnamed
mysql.ForSQLite,thedefaultnameis/tmp/sqlite.db.Foranydatabaseaccess,
however,theuserneedstohaveatleastreadandconnectaccessprivilegestouse
these databases. Sqlite will locate the database first by trying to use the full
pathnameifithasbeengiven.Ifnot,itwillchecktoseeiftheHostvariablehas
beenset.Ifthatisthecase,SQLitewilllookatthepathnamethatwassetinthe
variable.IftheenvironmentvariableGAMBAS_SQLITE_DBHOMEhasbeenset,
thenSQLitewillusethatasthecurrentworkingdirectory.Itisalsopossibleto
create and use a database in memory by setting the Name property to
:memory:ratherthanmysqlorpostgresqlorsqlite.Syntaxis:

329
A Beginner's Guide to Gambas

PROPERTYNameASString

Password

ThePasswordpropertywillreturnorsetthepasswordusedforestablishing
aconnectiontothedatabase.Callingconventionis:

PROPERTYPasswordASString

Port

ThePortpropertyisusedtogetorsettheTCP/IPportusedforestablishing
theconnectiontoadatabase.ThedefaultportdependsontheconnectionType.
Syntaxis:

PROPERTYPortASString

Tables

TheTablespropertyisusedtoobtainavirtualcollectionthatcanbeused
formanagingallofthetablesofadatabase.Syntaxis:

PROPERTYTablesAS.ConnectionTables

Type

TheTypepropertyrepresentsthetypeofthedatabaseserveryouwantto
connectto. InGambas,thecurrentlysupporteddatabasetypeare:"postgresql",
"mysql",and"sqlite".Thetypepropertyusesthissyntax:

PROPERTYTypeASString

Users

The Users property returns a collection of all users registered in the


databaseserver.Likeanyothercollectionobject,itcanbeenumeratedwithFOR
EACH.Syntaxis:

PROPERTYUsersAS.ConnectionUsers
Version

The Versionproperty isareadonlyvaluethatreturnstheversionofthe

330
A Beginner's Guide to Gambas

databasethatthedriverhasconnectedwith.Syntaxis:

PROPERTYREADVersionASInteger

TheConceptofaTransaction

Therearetimeswhentheorderinwhichdatabaseactions(orqueries)are
executedisimportant.Sometimes,aprogrammustensureallqueriesinagroup
arerunsuccessfullyandinorderorprocessnoneofthematall.Aclassicexample
is taken from the banking environment. If a given amount of money (for
example,100dollars)istakenfromoneaccountandpostedtoanotheraccount,
wewouldexpectthefollowingactionstooccur:

UPDATEaccount1SETbalance=balance100;
UPDATEaccount2SETbalance=balance+100;

Bothqueriesmustexecutesuccessfullyorneithermustexecute. Money
cannot be transferred out of one account and fail to be posted to the other
account.Bothofthesequeriesformasingletransactionthatiscomposedoftwo
separate actions (debit 100 from account1 and credit 100 to account2). A
transaction issimplyoneormoreindividualdatabasequeriesgroupedtogether
between BEGIN and COMMIT statements. WithoutaCOMMITstatement,the
transactionisnotpermanentandcanbereversedwiththeROLLBACKstatement.

MySQLautomaticallycommitsstatementsthatarenotpartofatransaction
process. The results of any SQL UPDATE or INSERT statement that is not
preceded with BEGIN will immediately be visible to all connections to the
database because the commit is automatically performed. Within MySQL,
transactionsareonlyknownwithtransactionsafetables(i.e.,BDBandInnoDB).
The other table types COMMIT immediately. Mostdatabasesthat are able to
accomplishthisaresaidtobe ACIDcompliant. TheACIDmodelisoneofthe
oldestandmostimportantconceptsofdatabasetheory.Thefourgoalsthatmust
be met for any database to be considered reliable are Atomicity, Consistency,
Isolationand Durability(ACID).Letsexamineeachofthesefourcharacteristics
indetail.

Atomicity meansdatabasemodificationsmustfollowanallornothing
rule. Every transaction is considered an atomic unit. If any part of the
transactionfails,theentiretransactionfails.ItiscriticaltheDBMSmaintainthe
atomicnatureoftransactionsinanycircumstance.

331
A Beginner's Guide to Gambas

Consistency states only valid data will be written to a database. If a


transaction is executed that violates database consistency rules, the entire
transaction will be rolled back and the database will be restored to a state
consistentwiththoserules. Conversely,ifatransactionexecutessuccessfully,it
willmaintainastateofconsistency.

Isolation requires multiple transactions that occur simultaneously not


impacteachother.Forexample,ifUserAissuesatransactionagainstadatabase
atthesametimeUserBissuesatransaction,bothtransactionsshouldoperateon
the database in isolated bliss. The database should perform one transaction
before the other. This prevents a transaction from reading intermediate data
producedasasideeffectofanothertransaction.Isolationdoesnotensureeither
transactionwillexecutefirst,justthattheywillnotinterferewitheachother.

Durabilityensuresanytransactioncommittedtothedatabasewillnotbe
lost. This is accomplished via database backups and transaction logs that
facilitaterestorationofcommittedtransactionsdespiteanysubsequentfailures.
Now,let'stakealookatGambasConnectionclassmethodsavailabletoyouin
yourprograms.

ConnectionClassMethods

The Connection class provides most of the methods you will need to
establishaconnectiontoadatabaseandexecuteoneormoretransactionstofind,
add,change,ordeletedata.

Open/Close

TheOpenmethodisusedtoopenaconnectiontothedatabase.Priorto
makingthecalltoOpen,youshouldsettheconnectionpropertieswiththedata
necessarytousethedatabase.Generally,ataminimumyouwillneedtospecify
thetypeofdatabase,thehost,aloginIDandpassword,and thenameofthe
databaseyouwishtouse.Thesyntaxforopenis:

FUNCTIONOpen()ASBoolean

ThecodeexamplebelowshowshowtousetheOpenmethodtoconnect
user jrittinghouse toaMySQLdatabasenamedGambasBugsthatisstoredon
Hostlocalhost:

DIM$hConnAsNEWConnection

332
A Beginner's Guide to Gambas

WITH$hConn
.Type="mysql"
.Host="localhost"
.Login="jrittinghouse"
.Password="ab32e44"
.Name="GambasBugs"
ENDWITH

TRY$hConn.Open
IFErrorTHENPRINT"Databasecannotbeopened.Error=";Error.Text

Toclosetheconnection,simplyinvoketheClosemethod.Inourexampleabove,
youcouldusethiscode:

$hConn.Close

andtheconnectionwouldbeclosed.Inordertosubsequentlyuseanydatastored
inthedatabase,youwouldneedtoreopenthedatabaseusingtheOpenmethod.

Begin/Commit/Rollback

Aswestatedpreviously,atransactionisoneormoreindividualdatabase
queries that are grouped together between BEGIN and COMMIT statements.
Without a COMMIT statement, the transaction is not permanent and can be
reversed with a ROLLBACK statement. Remember thatMySQL automatically
commitsstatementsthatarenotpartofatransactionprocess(definedbyBEGIN
andCOMMIT).InGambas,itisrecommendedthatyouusetheFind,Create,and
Edit methods to make changes to the database. This helps to maintain code
independenceanditallowsyoutowriteasinglepieceofcodethatwillworkwith
anydatabasesupportedbyGambas. Gambasusesa resultobject toreturnthe
resultsofaSQLquery.

Find

The Find method returns a readonly Result object used for querying
recordsinthespecifiedtable.ThecallingconventionforFindis:

FUNCTIONFind(TableASString[,RequestASString,ArgumentsAS,...])ASResult

Request representsa SQLWHEREstatement thatisusedforqueryingthe


table. Arguments are quoted as necessary (dictated by SQL syntax), and
substitutedinsidetheRequeststring. ItworksliketheSubst()functioninthis

333
A Beginner's Guide to Gambas

case.UsingtheFindmethodallowsyoutowriterequeststhatareindependentof
theunderlyingdatabase,meaningitwillworkwithPostgreSQLorMySQLwithout
anycodechangerequired.

Create

TheCreatemethodisusedtobuildaread/writeResultobjectwhichcan
usedtocreaterecordsinatable.Standardcallingconventionis:

FUNCTIONCreate(TableASString)ASResult

Edit

TheEditmethodreturnsaread/writeResultobjectusedforeditingrecords
inthespecifiedtable.RequestisaSQLWHEREclauseusedforfilteringthetable,
andtheArgumentsarequotedasneededbytheSQLsyntaxandsubstitutedinthe
Requeststringasweexplainedpreviously.Standardcallingconventionis:

FUNCTIONEdit(TableASString[,RequestASString,ArgumentsAS,...])ASResult

HereisacodesampletoshowhowEdit()works:

DIMMyResultASResult
DIMsQueryASString
DIMiParmASInteger

sQuery="Select*fromtblDEFAULTwhereid="
'wewillinsertaparametervalue(12)attheendofthequerystring
iParm=12

$hConn.Begin
MyResult=$hConn.Edit("tblDEFAULT",sQuery,iParm)
MyResult!Name="MrRittinghouse"'Setafieldvalue
$hConn.Update'Updatewiththenewvalue
$hConn.Commit'makethechangespermanent
$hConn.Close'closethedatabaseconnection

Exec

TheExecmethodexecutesaSQLrequestandreturnsareadonlyResult
objectcontainingtheresultoftherequest.Standardcallingconventionis:

FUNCTIONExec(RequestASString,ArgumentsAS,...)ASResult

334
A Beginner's Guide to Gambas

Request is a SQL WHERE clause and Arguments should be quoted as


requiredbySQLsyntax.

Quote

The Quotemethod returnsaquotedidentifieryoucanusetoinsertina


SQLquery.Thisidentifiercanbeatableorfieldname.Syntaxis:

FUNCTIONQuote(NameASString)ASString

Thequotingmechanismisdependentupontheparticulardatabaseserver
driver which makes this method necessary if you need to write database
independentcode.HereisanexampleofhowtouseQuote:

'Returnsnumberofrecordsinaquery
'sDBTableisthenameofthetable.Sincethenamecanincludereserved
'charactersitneedstobesurroundedbyquotemarks

rResult=$hConn.Exec("SELECTCOUNT(*)ASiNumRecsFROM"&DB.Quote(sDBTable))
PRINTrResult!iNumRecs

ResultObjects

TheresultobjectisaclassthatisusedtoreturntheresultofaSQLrequest.
Thisclassisnotcreatableanditactsjustlikeareadonlyarray.Itisenumerable
usingtheFOREACHstatement.Declareanditeratearesultobjectasfollows:

DIMhResultASResult
FOREACHhResult
'dosomethingwiththedata
NEXT

Thecodesnippetbelowshowshowyoucangetthevalueofafieldinthecurrent
recordofaResultobject:

DIMMyResultASResult
DIMMyVariantASVariant

MyVariant=MyResult[FieldASString]

TheResultFieldclassrepresentsoneofthefieldsofaResultobject.You
canusetheFindmethodtoselectaparticularfieldbeforeusingit.Theproperties
this class supports are Length, Name, Result andType. It is also possible to

335
A Beginner's Guide to Gambas

enumeratetheResultFielddatawiththeFOREACHkeyword. Thisclassisnot
creatable. Thecodebelowshowsyouhowtomodifythevalueofafieldinthe
currentrecordofaResultobject:
DIMMyResultASResult
DIMMyVariantASVariant

MyResult[FieldASString]=MyVariant

Properties that you can use with a result object include Available,
Connection,Count,Fields,Index,andLength.AvailablewillreturnaTRUE
valueiftheresultpointstoanexistingdatabaserecord.Connectionreturnsthe
parentconnectionobject.Counttellsyouthenumberofrecords(rows)returned
withtheresultobject. Fieldsreturnsacollectionofthefieldsinthedatabase
table returned with the result object. Index returns the index (current row
pointerorcursor)ofthecurrentrecord,startingatzero. Lengthisthesameas
countandisusedinterchangeably.

Methods supported by the result object class include Delete, MoveFirst,


MoveLast,MoveNext,MovePrevious,MoveTo,andUpdate.Mostoftheseareself
explanatory,buttheUpdatemethodisusedtorewritethecurrentrecordtothe
databasewithanydatachangesthatarespecified.IfyouuseMoveToandspecify
anindexthatisvoidorinvalid,itwillreturnaTRUEvalueindicatinganerror.
Nowthatwehaveabasicunderstandingofwhataresultobjectisandhowtouse
it, let's see how Gambas allows you to find data in a database with the Find
method.

DBClass

Thisclassrepresentsthecurrentdatabaseconnection.Thisclassisstatic
andallofitsmembersarealsostatic.Mostofthepropertiesofthisclassarethe
same as those of the Connection class so we will only cover those that are
different, namely Current, Databases, and Debug. Current returns or sets the
currentconnection.Databasesreturnsacollectionofallofthedatabasesthatare
managedbythedatabaseserver. DebugsetsorreturnsTRUE ifthedatabase
componentisindebuggingmode.Whenthedebugflagisset,eachquerysentto
any database driver is printed on the standard error output (generally, the
console). ThemethodsusedintheDBclassarethesameasthoseusedinthe
Connectionclass(Begin,Close,Commit,Create,Edit,Exec,Find,Open,Quote
andRollback)sowewon'trepeatthatinformationhere.

336
A Beginner's Guide to Gambas

Database

The Database class is used to represent information pertaining to a


database. Thisclassisnotcreatable. Thepropertiesthatyoucanusewiththis
classincludeConnection,Name,andSystem.Connectioncanbeusedtoobtain
theparentconnectionobject. Namewillreturnthenameofthedatabaseand
System will return a TRUE value if the database is a system database. The
databaseclassonlyhasonemethod,Delete,whichwilldeleteadatabase.

Field

TheFieldclassisusedtorepresentdataforatablefield.Thisclassisnot
creatable. PropertiesthatthisclasssupportsareDefault,Length,Name,Table,
andType. Defaultreturnsthedefaultvalueofafield. Lentghwillreturnthe
maximum length of a text field. If the text field being checked has no limit
specified,azerovalueisreturned. NamewillreturnthefieldnameandTable
returnsthetableobjectinwhichthefieldwascreated.Typereturnsthedatatype
thatthefieldrepresents.Gambaswillreturnoneofthefollowingconstants:

gb.Booleangb.Integergb.Floatgb.Dateorgb.String

Index

TheIndexclassrepresentsatableindex.Thisclassisnotcreatable.The
properties this class supports are Fields, Name, Primary, Table, and Unique.
Fieldsreturnsacommaseparatedlistofstringsrepresentingthefieldsthatmake
uptheindex. NamereturnstheindexnamewhilePrimarywillreturnaTRUE
valueifanindexistheprimaryindexofthetable. Tablewillreturnthetable
objectthatownsthisindex.UniquereturnsTRUEiftheindexisunique.

Table

TheTableclassrepresentsthedefinitionofadatabasetable.Thisclassis
not creatable. The properties that are supported by the Table class include
Connection,Fields,Indexes,Name,PrimaryKey,SystemandType. Connection
canbeusedtoobtaintheparentconnectionobject.Fieldswillreturnacollection
ofthefieldsofthetablewhileIndexeswillreturnacollectionoftheindexesof
thetable.Namewillreturnthenameofthetable.PrimaryKeywillreturnorset
theprimarykeyofthetable. Theprimarykeyisastringarraycontainingthe

337
A Beginner's Guide to Gambas

nameofeachprimarykeyfield.SystemwillreturnaTRUEvalueifthedatabase
isasystemdatabase. Typereturnsorsetsthetypeofatable. Thispropertyis
uniquetoMySQLandisonlyusedwithMySQLdatabases. Thisclassonlyhas
onemethod,Update,whichiscalledtoactuallycreatethetableinthecurrently
connecteddatabase.

User

TheUserclassisusedtorepresentusersofadatabase. Thisclassisnot
creatable. The properties User class supports are Administrator, Connection,
NameandPassword.AdministratorisareadonlypropertythatreturnsTRUEif
a user is a database administrator. Connection returns the parent connection
objectoftheuser.NamewillreturnthenameoftheuserandPasswordwillget
orsetthepasswordassociated withauser. Whenyoureadtheproperty,you
should get the password in an encrypted form. The User class has a single
method,Deletewhichisusedtodeleteauserfromthedatabase.

TheDatabaseExampleProgram

The previous sections of this chapter have explained about the Gambas
database component and the features provided therein. However, nothing
substitutesworkingwithrealcodeinarealapplication. Gambasshipswithan
example database program that we are going to explore. Writtenby Gambas
founderBenoitMinisini,thisprogramisanexcellentexampleofhowtocodeyour
program to use database within the Gambas environment. To begin, start
GambasandchoosetheDatabaseprogramfromtheExamplesmenu.Whenthe
IDE appears, you will see that the program contains two forms, FMain and
FRequest.FMainshouldlooklikethefigurebelow.

Thisprogramwillallowyoutochoosewhatdatabaseplatformtouse(i.e.,
PostgreSQL,MySQL,orSQLite)andspecifythehostname,databasename,user
ID and password. An option to automatically create a database exists and is
activated whenever the checkbox is checked. Once you have successfully
connectedtothedatabase,youhavetheoptionofcreatingatable,deletingit,or
fillingitwithsometestdata.TheSQLrequestboxatthebottomoftheformwill
allowyoutoperformSQLqueriesagainstthedatabase. Allinall,thisprogram
demonstratesalmosteverythingyouneedtoknowtoconnecttoanydatabase
usingGambas.

338
A Beginner's Guide to Gambas

Figure98TheFMainformindesignmode.
TheFRequestformismuchsimplertobuild.Itisshowninthefigurebelow:

Figure99FRequestFormindesignmode.

TheFRequestformcontainsasinglecontrol,whichwehavenotpreviously
introduced,theTableViewcontrol. ThiscontrolisfoundintheQTtoolsetwe
discussedpreviously.Wewillshowyouhowtousethiscontrolwhenwediscuss
theFRequestformcodebelow.Fornow,let'sjumpintothecodefortheFMain
formandseehowthingswork.
'Gambasclassfile

$hConn isdeclaredasaprivatevariableandwillbeusedbyallsubroutinesin
thisclassfile.Notethatthevariableisprefixedwitha$symboltoindicateitisa

339
A Beginner's Guide to Gambas

privateclassvariable.Whilenotrequired,itisagoodprogrammingconvention
tofollow.
PRIVATE$hConnASConnection

Whenevertheuserhasfilledoutthedataatthetopoftheformwiththeir
username,host,password,etc.,andclickstheconnectbutton,theprogramwill
cometothissubroutineandtrytousethatdatatoestablishaconnectiontothe
database.
PUBLICSUBbtnConnect_Click()
'weneedtohaveastringtoworkwithsodeclaresNameaslocal
DIMsNameASString

'nowwegetalittletricky.ifadatabasewaspreviouslyopened
'andisstillopen,thisnextlinewouldcloseit.UsingTRY
'wouldallowanyerrortobecaught(seeCATCHbelow).
'Ifthereisnotanopendatabasetoclose,noharmwasdone
'andthecodeexecutionproceeds.

TRY$hConn.Close

'weassignthedataintheTextboxtxtNametoourstringvarsName
'andsetthedatabaseconnectionpropertiestothevaluesprovided
'bytheuserbyusingtheWITH/ENDWITHconstruct.

sName=txtName.Text
WITH$hConn
.Type=cmbType.Text'thetypeofdatabaseplatformtouse
.Host=txtHost.Text'hostnameofthedatabase
.Login=txtUser.Text'USERID
.Password=txtPassword.Text'USERpassword
ENDWITH

Atthispoint,alltheconnectionpropertiesaresetbutwehavenotopened
theconnectionyet. Thefollowingcodesegmentwillseeifadatabasewiththe
namespecifiedbysNameexistsand,ifnot,itwillcreateitifthecheckboxto
createdatabaseischecked.

IFchkCreate.ValueTHEN
$hConn.Open'opentheconnection
'seeifadatabasesNameexistsandifnot,addittotheserver
IFNOT$hConn.Databases.Exist(sName)THEN
$hConn.Databases.Add(sName)
ENDIF
'nowclosetheconnection
$hConn.Close

340
A Beginner's Guide to Gambas

ENDIF

Now,wearereadytoopenthedatabase.Eitheritalreadyexistedandwe
openthatdatabaseorwewillopenthenewonewecreatedifthecheckboxwas
checked.First,settheNamepropertyfortheconnectiontosNameandthencall
theOpenmethod:

$hConn.Name=sName
$hConn.Open
'wesettheenabledpropertiesforbothprogramformstoTRUE
'andplacesomedefaulttextintheSQLrequestboxatthe
'bottomoftheFMainform:

frmDatabase.Enabled=TRUE
frmRequest.Enabled=TRUE
txtRequest.Text="SHOWTABLES"

'ifourTRYfailedorifanyerroroccurredduringthissubroutine,
'theCATCHstatementwoulddisplayanERRORdialogwiththetextof
'theerrormessage.

CATCH
Message.Error(Error.Text)
END'ofconnectBtn_Clicksubroutine

If,afterthedatabaseconnectionisestablished,theuserwouldclickthe
Createtabletestbutton,thissubroutinewouldbeexecuted.Ihavemodifiedit
slightly to avoid using hardcoded strings and to use the same name as the
database.Theoriginalcodeiscommentedoutsoyoucanuseeithermethod.
PUBLICSUBbtnCreate_Click()
'declarealocalTablevariable
DIMhTableASTable

'addthetabletothedatabaseusingtheAddmethod
'hTable=$hConn.Tables.Add("test")

'thisisthecodeIchangedtoavoidhardcodingthestring
'aswasdoneinthepreviouslineofcode
hTable=$hConn.Tables.Add(txtName.text)

'nowaddthefieldsofthetabletothetablewejustadded
'notethatwespecifythefieldnameanddatatypeforeach
'ofthefieldsweinsertintothetable.Forstringdata,
'wealsospecifythemaximumlengthofthestringfield.
hTable.Fields.Add("id",gb.Integer)
hTable.Fields.Add("firstname",gb.String,16)

341
A Beginner's Guide to Gambas

hTable.Fields.Add("name",gb.String,32)
hTable.Fields.Add("birth",gb.Date)
hTable.Fields.Add("active",gb.Boolean)
hTable.Fields.Add("salary",gb.Float)

'wecanspecifyaprimarykeyforthedatabasetable.Inthis
'case,theidfieldisusedaswecancreateuniqueintegerindex
'data

hTable.PrimaryKey=["id"]

'thecalltotheUpdatemethodcommitsthechangestothedatabase
'andmakesthempermanent.

hTable.Update

'nowweputupasimpledialogtoinformtheuserwehave
'successfullycompletedthecreationtask.

Message.Info("Table"&txtName.Text&"hasbeencreated.")

This following segment of code was added by the author to enable or


disablethebuttonsdependingonthestateofthedatabase.Forexample,ifthere
isdataalready in thedatabasetable,itdoesnotmake sensetofillthattable
again,sothatbuttonwouldbedisabled.However,thedeletebuttonwouldbe
enabledsothedatacouldberemoved. Ifthedatabasetableisdeleted,thenit
wouldbereenabledandifthetableiscreatedandnodataexists,thefillbutton
would again be enabled, etc. This prevents errors from clicking on a button
whereanactioncouldnotbeperformedsuccessfully.
btnFill.Enabled=TRUE
btnDelete.Enabled=TRUE
btnCreate.Enabled=FALSE

'next,weaddsomedefaulttexttotheSQLquerybox
txtRequest.Text="ShowTABLES"

'theCATCHstatementwoulddisplayanERRORdialogwiththetextof
'theerrormessageifanyerroroccursinthissubroutine.

CATCH
Message.Error(Error.Text)
END'ofthecreatebuttonsubroutine

If,afterthedatabaseconnectionisestablished,theuserwouldclickthe
Delete table test button, this subroutine would be executed. I have also

342
A Beginner's Guide to Gambas

modifieditslightlytoavoidusinghardcodedstringsandtousethesamenameas
thedatabase.Theoriginalcodeiscommentedoutsoyoucanuseeithermethod.
PUBLICSUBbtnDelete_Click()

'removethetable
'$hConn.Tables.Remove("test")
$hConn.Tables.Remove(txtName.Text)

'putupamessagetoinformtheuserthetableisgone
Message.Info("Table"&txtName.Text&"hasbeenremoved")

'enableordisablethebuttonstomakesense.Ifthetable
'hasbeenremoved,itcannotbedeletedagainanditcannot
'befilledsinceitdoesnotexist.Allthatisleftisto
'recreateitandthatbuttonisenabled.

btnDelete.Enabled=FALSE
btnFill.Enabled=FALSE
btnCreate.Enabled=TRUE

'notableexiststoquerysoblankouttheSQLquerytext.
txtRequest.Text=""

'ifanerroroccursinthesubroutinecatchithereandshowadialog
'messagetotheuser.

CATCH
Message.Error(Error.Text)
END'thedeletebuttonsubroutine

Ifthedatabaseconnectionhasbeenestablishedandtheuserhascreated
thetable,thereneedstobesomedataaddedtomakeituseful.Thissubroutineis
executedandwilladdsemiarbitrarydatatothetable.Itwillrandomlyselecta
firstnamefromthearrayoffivenamesprovidedand concatenatethecounter
numbertothestringName#toserverasthelastname. Thebirthdateis
createdrandomlybypickingavaluethataddsarandomnumberfrom110,000
tothebasedateofJanuary1st,1970.Therecordhasanactiveflag,randomlyset
aswell.Salaryfiguresarerandomlyselectedwithintherangeof1,000to10,000.
Finally, the Update method will put all the data in the table and make the
COMMITtothedatabase.Let'slookateachlineofcodetoseehoweasythisis
accomplishedinGambas:
PUBLICSUBbtnFill_Click()
'weneedanintegercounteriIndtobeourindexandwe

343
A Beginner's Guide to Gambas

'needaResultobjecttostoreourresults
DIMiIndASInteger
DIMrTestASResult

'settheBusyflagtopreventinterruptionstoourprocess
INCApplication.Busy

'wearegoingtostartthedatabasetransactionprocesswithBEGIN
$hConn.Begin
'createthedatabasetablefirst
'rTest=$hConn.Create("test")
rTest=$hConn.Create(txtName.Text)

'now,setupalooptocreate100records
FORiInd=1TO100
'maketherecordidbethecountervariablevalue
rTest!id=iInd

'randomlysetthefirstnametobeoneofthefiveinthearray
rTest!firstname=["Paul","Pierre","Jacques","Antoine","Mathieu"][Int(Rnd(5))]

'makethelastnameacatenatedvaluewiththeintegerindexvalue
rTest!name="Name#"&iInd

'randomlychooseadatebyaddingavaluefrom110,000tothe
'basedateofJan1,1970
rTest!birth=CDate("01/01/1970")+Int(Rnd(10000))

'settheactiveflagtoeither0or1(TRUEorFALSE)
rTest!active=Int(Rnd(2))

'randomlychooseasalaryfigurefrom1,000to10,000
rTest!salary=Int(Rnd(1000,10000))

'updatethisrecordwiththedatasemiarbitrarydatavalues
rTest.Update
NEXT'iterationoftheloop

'commitalladdedrecordstothedatabase
$hConn.Commit

'lastthingtoexecutebeforeleavingthesubroutine
FINALLY
'decrementthebusyflag
DECApplication.Busy

'popupamessagetoinformtheuserwhatwedid
Message.Info(txtName.Text&"hasbeenfilled.")

344
A Beginner's Guide to Gambas

'putadefaultSQLqueryintheSQLQuerytextbox
txtRequest.Text="select*from"&txtName.Text

'fixourbuttonstomakesense
btnFill.Enabled=FALSE
btnDelete.Enabled=TRUE
btnCreate.Enabled=FALSE

'ifsomethinggoeswrong,abortallchangeswiththeRollbackand
'showtheerrormessagetotheuser
CATCH
$hConn.Rollback
Message.Error(Error.Text)
END'ofthefilldatasubroutine

IftheuserentersanarbitrarySQLrequestintheSQLqueryboxatthe
bottomoftheform,wewillusetheExecmethodtoperformthequeryanddisplay
theresultsoftherequestusingtheFRequestform.Hereishowthatisdone:

PUBLICSUBbtnRun_Click()
'declarearesultobjecttoholdtheresultsofthequery
DIMrDataASResult

'declareaformvariablesowecanshowtheFRequestform
DIMhFormASFRequest

'executethequeryusingtheExecmethodandassigntheresultsto
'theresultobjectrData
rData=$hConn.Exec(txtRequest.Text)

'passthedatabaseconnectionhandleandtheresultdatatothe
'FRequestformwhenitisinstantiated
hForm=NEWFRequest($hConn,rData)

'nowdisplaytheformtotheuserwiththeresultdata
hForm.Show

'comehereifthereisaprobleminthesubroutineanddisplayamsg
CATCH
Message.Error(Error.Text)
END'ofsqlquerysubroutine

Whenever our program runs and the FMain form opens, we need to
instantiateourconnectionvariable$hConn.Whenevertheformisclosed,wewill
closetheconnection.

PUBLICSUBForm_Open()

345
A Beginner's Guide to Gambas

$hConn=NEWConnection
END

PUBLICSUBForm_Close()
$hConn.Close
END

Next,weneedtotakealookattheFRequestformandseehowthatcode
displaystheresultobjectdatawhenitisinvoked.Hereisthecodeforthat:

'Gambasclassfile
'fRequest.classdeclarestwoprivatevariablestouseinthisclass
'onefortheconnection,onefortheresultdata.
PRIVATE$hConnASConnection
PRIVATE$rDataASResult

'aconstructorroutinewillbeusedtoreceivetheconnectionhandle
'andtheresultsofaqueryasparameterswhenFRequestiscalledby
'theFMainform.

PUBLICSUB_new(hConnASConnection,rDataASResult)
'assignthehConnparametertoourprivate$hConnvariable
$hConn=hConn

'assigntherDataparametertoour$rDataprivatevariable
'theseassignmentsaremadesothe$prefixedvariablesare
'visibletotheentireclass,notjusttheconstructorroutine.
$rData=rData

'callourlittlesubroutinetodisplaythetitleintheformwindow
RefreshTitle

'theReadDatasubroutineisusedtopopulateourTableViewcontrol
ReadData

'resizethewindowtocenteronthedesktop
ME.Move(Int(Rnd(Desktop.WME.W)),Int(Rnd((Desktop.HME.H))))
END'oftheconstructor

'thissubroutinesimplyupdatesthewindowcaption
PRIVATESUBRefreshTitle()

'weneedalocalstringvariable
DIMsTitleASString

'wewillconcatenatetheconnectionnametothetextforthecaption
sTitle=("SQLQueryResults")&""&$hConn.Name

346
A Beginner's Guide to Gambas

'andsetthetitlepropertytobethestringvariablevalue
ME.Title=sTitle
END

The ReadData() subroutine is used to define the structure of the data


passed in fromthe results object to the TableViewcontrol. It determines the
numberoffieldsfromtheresultsobjectand setsupthecolumnsinthetable,
assigning the proper column (field) name and data type. The data type is
determined by calling another subroutine, WidthFromType() to get that
information.

The QT librarybased TableView control is obsolete in the QT library,


havingbeenreplacedwiththeQTablecontrol. However,inGambas,itisstill
usableandwewillshowyouhowitisdone. Beaware,however,thatitis not
recommendedforuse as Trolltech,theownersofthe QTlibrary,havepublicly
declaredtheTableViewcontrolobsolete.TheGambasTableViewisbasedupon
QTableandQtableItem,bothofwhichwillbecomeobsoleteinQt4.0.TableView
willmorethanlikelythenbebaseduponQTableVieworQTableWidgetinstead.

PRIVATESUBReadData()
'thisvariableisdeclaredbutneverused,youcancommentitout
DIMhTableASTable

DIMhFieldASResultField

'thisvariableisdeclaredbutneverused,youcancommentitout
DIMsFieldASString
DIMiIndASInteger

'thisvariableisdeclaredbutneverused,youcancommentitout
DIMiLenASInteger

'settheapplicationbusyflagtoavoidinterruptions
INCApplication.Busy

'resetrowcountoftheTableViewcontroltozero
tbvData.Rows.Count=0

'setthenumberofcolumnstobethesamenumber
'asthenumberoffieldsintheresultobject
tbvData.Columns.Count=$rData.Fields.Count

'nowwewilliteratethrougheachfieldoftheresultobjectand
'getthenameofthefieldandthedatatypeandsettheTableView
'columnheadingsandfieldtype/sizeasappropriate

347
A Beginner's Guide to Gambas

FOREACHhFieldIN$rData.Fields
WITHhField
'thisisadebuglinethatwascommentedout
'PRINT.Name;":";.Type;"";.Length

'thisnextlinesetsthecolumnnametobethefieldname
tbvData.Columns[iInd].Text=.Name

'here,thecalltoWidthFromTypeisusedtodeterminewhatdata
'typethefieldisandwhattheappropriatewidthshouldbe
tbvData.Columns[iInd].Width=WidthFromType(tbvData,.Type,.Length,.Name)
ENDWITH
'incrementourindexcounter
INCiInd
NEXT'iterationofresultdata

'setthenumberofTableViewrowstobethesameasthenumber
'ofrowsofdataintheresultobject
tbvData.Rows.Count=$rData.Count

'lastthingwedointhissubroutineisdecrementthebusyflag
FINALLY
DECApplication.Busy

'iftherewereanyerrorsinthissubroutinewewouldshowamessage
CATCH
Message.Error("Cannotexecrequest."&"\n\n"&Error.Text)
END'ofReadDatasubroutine

Thenextbitofcodeisactivatedwheneverdataispresent.TheDataevent
oftheTableViewcontrolisusedasthedriverforactivationofthissubroutine.It
insertsarowofdatafromtheresultsobjectintothecurrentrowandcolumnof
the TableView control. Bear in mind that you don't ever call the data event
directly.ThereisverylittledocumentationavailablefortheTableViewcontrolso
nothingstatedhereinshouldbeconsideredasthedefinitiveanswerforusingit.
However,thegeneralapproachtousingtheTableViewcontrolistofirstloadall
datathatistobedisplayedintoanarrayandpreparetheTableViewcontrolwith
rows and columns as was done in the ReadData subroutine above. The very
processoffillingthearrayanddefiningthecolumnsinthismannerforcestheQt
widgetthatisusedintheTableViewcontroltomakeaninternalcalltotheData
eventthatactuallydoesfillthecellswithdatafromyourarray.Itisuptoyouto
codetheassignmentstatement(s)thatmovedatafromtheresultsobjecttothe
TableViewrowandcolumnwhereyouwantthedatadisplayed.Thekeythingto
remember is that you must have an event handler, tbvControl_Data( ... )
somewhereinyourclassfiletodothis.InaTableViewcontrol,thedatathatis

348
A Beginner's Guide to Gambas

refreshedisonlywhatisvisibleinthecontrol. Thecontrolcandisplayahuge
amountofdatawithoutholdinganyofthedatavaluesdirectlyinstorageitself.
Thatiswhatyourprogramarrayisusedfor.Whileitsoundsabitawkward,itis
apragmaticsolutionthatallowsGambastodisplaydatafromadatabaseina
prettyefficientmanner.

PUBLICSUBtbvData_Data(RowASInteger,ColumnASInteger)
'thisgetstothecorrectrow
$rData.MoveTo(Row)
'thisactuallyassignsdatafromtheresultsobjecttothetableview
tbvData.Data.Text=Str($rData[tbvData.Columns[Column].Text])
END

Iftheformisresizedbytheuser,weneedtoresizethecontrol.Thissubroutine
willdothetrick.

PUBLICSUBForm_Resize()
tbvData.Resize(ME.ClientW,ME.ClientH)
END

Whendataisbeingreadfromtheresultsobject,thissubroutineiscalledto
determinewhatthedatatypeisforeachfieldofarow.Thepropertiesfromthe
Field class are passed as parameters to this function and used in the select
statement.ThisensuresthedataplacedintheindividualcellsoftheTableView
controlisnottruncatedandwilldisplayproperly,regardlessofthefontproperty
settingestablishedbytheTableViewcontrolitself.

PRIVATEFUNCTIONWidthFromType(hCtrlAScontrol,iTypeASInteger,
iLengthASInteger,sTitleASString)ASInteger

DIMiWidthASInteger

SELECTCASEiType
CASEgb.Boolean
iWidth=hCtrl.Font.Width(Str(FALSE))+32

CASEgb.Integer
iWidth=hCtrl.Font.Width("1234567890")+16

CASEgb.Float
iWidth=hCtrl.Font.Width(CStr(Pi)&"E+999")+16

CASEgb.Date
iWidth=hCtrl.Font.Width(Str(Now))+16

CASEgb.String

349
A Beginner's Guide to Gambas

IFiLength=0THENiLength=255
iLength=Min(32,iLength)
iWidth=hCtrl.Font.Width("X")*iLength+16
ENDSELECT
iWidth=Max(iWidth,hCtrl.Font.Width(sTitle)+8)
RETURNiWidth
END

Finally,iftheuserclicksonthexatthetoprightcornerofthewindowto
closetheprogram,wecometothisroutineandclosethingsdown.
PUBLICSUBForm_Close()
ME.Close
END

When you execute the example Database program, it requires that you
haveadatabasesystemlikePostgreSQLorMySQLinstalledonyoursystem.You
musthaveauseraccountandpasswordtousethedatabasesystems.Giventhose
caveats,runtheprogramandlogintothedatabase.Youcanplayaround,create
andfillthetesttable,andmakequerieswiththeprogram.Atthispoint,youhave
learnedallthebasicsforconnectingtoandusingadatabaseinGambas.Inthe
nextchapter,wewillcovertheessentialsofmakingyourprogramavailableto
users globally, a process of globalization that involves two processes,
internationalization(I18N)andlocalization(L10N).

350
A Beginner's Guide to Gambas

Chapter 16 Global Gambas


Gambas has been designed from the very beginning to support an
internationalcommunity.Beinganopensourceproduct,peoplefromeverywhere
ontheplanetparticipateintheongoingcareanddevelopmentoftheGambas
product.TheabilityGambasprovidestodeveloperstocreateasinglecodebase
thatwillsatisfyusersfromeverycountryisasignificantstepintherecognitionof
aglobalcommunity.Gambasallowsdeveloperstowriteprogramsthatareeasily
translatedtonearlyanylanguage,withouthavingtorewritecodeandwithout
having to hire an expensive outsource firm to do the job. The processes of
Internationalization and Localization are significantly enhanced by the Gambas
approach. Thefollowingsectionswillprovidean overviewthateveryGambas
developershouldbeawareofinordertoproducegloballyacceptablecode.We
are,ofcourse,allfromoneplanetandshouldalwaysconsidertheramifications
andimplicationsofwhatweplaceinanopensourcecommunity.

Internationalization

Internationalization istheprocessofdesigninganapplicationsothatit
canbeadaptedtovariouslanguagesandregionswithoutengineeringchanges.
Sometimestheterminternationalizationisabbreviatedasi18n,becausethereare
18lettersbetweenthefirst"i"andthelast"n."Aninternationalizedprogram,with
theadditionoflocalizeddata,canusethesameexecutableworldwide.Textual
elements,suchasstatusmessagesandGUIcomponentlabels,arenothardcoded
inthe program.Instead theyarestoredoutsidethesourcecode and retrieved
dynamically. Support for new languages does not require recompilation.
Culturallydependentdata,suchasdatesandcurrencies,appearinformatsthat
conform to the end user's region and language. In this manner, an
internationalizedapplicationcanbelocalizedveryquickly.

Localization

Localization istheprocessofadaptingsoftwareforaspecific regionor


language by adding localespecific components and translating text. The term
localizationisoftenabbreviatedasL10N,becausethereare10lettersbetweenthe
"L" and the "N." Usually, the most timeconsuming portion of the localization
processistranslationoftext.Othertypesofdata,suchassoundsandimages,may
requirelocalizationiftheyareculturallysensitive. Localizationengineersverify
theformattingofdates,numbers,andcurrenciesconformstolocalrequirements.

351
A Beginner's Guide to Gambas

UniversalCharacterSet(UCS)

ISO/IEC 10646 defines a very large character set called the Universal
Character Set (UCS), which encompasses most of the world's writing systems.
Thesamesetofcharactersisalsodefinedbythe Unicode standard. Todate,
changesinUnicodeandamendmentsandadditionstoISO/IEC10646havebeen
madeinunisonsothatthecharacterrepertoiresandcodepointassignmentshave
stayedsynchronized.Therelevantstandardizationcommitteeshavecommittedto
maintainthisapproach.

Both UCS and Unicode arecodetablesthatassignanintegervaluetoa


character.Thereareseveralalternativesforhowastringofsuchcharacters(or
their integer values) can be represented as a byte sequence. The two most
obviousencodingformsstoreUnicodetextassequencesofeither2or4bytes.
TheseencodingschemesaredesignatedasUCS2andUCS4. Inbothofthese
schemes, the most significant byte comes first (Big Endian format). The
CharactersinUnicodeareidentifiedbytheirnumberorcodepointwhichis
usuallygiveninhexadecimalnotation.Forexample,inHebrew,theletterheis
codepoint5D4whichisusuallywrittenwiththeconventionofprefixingaU+
in front of the code point and padding it with leading zeros as needed, i.e.,
U+05D4.

Unicode

Unicodecurrentlydefinesjustunder100,000characters,buthasspacefor
1,114,112codepoints19.Thecodepointsareorganizedinto17planesof216
(65,536) characters, numbered 0 through 16. Plane 0 is called the Basic
MultilingualPlaneorBMPandcontainssymbolsfoundtobeuseful.Generally
speaking,itcontainseverycharacteravailabletoaprogrammerbeforeUnicode
came along. The characters in the BMP are distributed in a West to East
fashion,withtheASCIIcharactershavingtheirfamiliarASCIIvaluesfrom0to
127,theISOLatin1charactersretainingtheirvaluesfrom128to255.Then,the
charactersetsmoveeastwardacrossEurope(Greek,Cyrillic),ontotheMiddle
East(Arabic,Hebrew,etc.)andacrossIndiaonwardtoSoutheastAsia,endingup
withthecharactersetsfromChina,Japan,andKorea(CJK). BeyondthisBMP
existsplanes1through16.Theyaresometimesreferredtoastheastralplanes
because they are typically used for exotic, rare, and historically important
characters.

19 The reader is encouraged to visit http://www.tbray.org/ongoing/When/200x/2003/04/26/UTF for a full explanation.

352
A Beginner's Guide to Gambas

ASCIIfilescanbeconvertedintoaUCS2filebyinserting0x00infrontof
everyASCIIbyte. Tomakea UCS4 formattedfile,youmustinsertthree0x00
bytesbeforeeveryASCIIbyte. UsingeitherUCS2orUCS4onUnixplatforms
can lead to some very significant problems. Strings used with these encoding
schemescancontainpartsofmanywidecharacterbyteslike\0or/thathave
specialmeaninginfilenamesandotherClibraryfunctions.Thevastmajorityof
UNIXtoolsexpecttooperatewithASCIIbasedfilesandsimplycannotread16bit
wordsascharacters. Simplyput,UCS2/UCS4arenotsuitableforUnixwhen
usedwithfilenames,textfiles,environmentvariables,codelibraries,etc.

ThereareseveralotherencodingformscommontobothUCSandUnicode,
namelyUTF8,UTF16,andUTF32. Ineachoftheseencodingformats,each
character is represented as one or more encoding units. All standard UCS
encodingformsexceptUTF8haveanencodingunitlargerthanoneoctet. For
manyapplicationsandprotocols,anassumptionofan8bitor7bitcharacterset
makestheuseofanythingotherthanUTF8nearlyimpossible.SinceUTF8hasa
oneoctetencodingunit,itusesallbitsofanoctetbutcanstillcontainthefull
rangeofUSASCIIcharacters,allofwhichhappentobeencodedinasingleoctet.
AnyoctetwithsuchavaluecanonlyrepresentaUSASCIIcharacter.

UTF8

UTF8 wasinventedbyKenThompson20. AccordingtothestorybyRob


PikewhowaswithKenatthetime,itwasdevelopedduringtheeveninghoursof
September2ndin1992ataNewJerseydiner.Kendesigneditinthepresenceof
Rob Pike on a placemat (see Rob Pikes UTF8 history21). The new design
replaced an earlier attempt to design a File System Safe UCS Transformation
Format(FSS/UTF)thatwascirculatedinanX/OpenworkingdocumentinAugust
ofthesameyearbyGaryMiller(IBM),GregerLeijonhufvudandJohnEntenmann
(SMI)asareplacementforthedivisionheavyUTF1encodingpresentedinISO
10646122.Withinaweekofthattime,PikeandThompsonmadeAT&TBellLabs
Plan 9 the first operating system in the world to use UTF8 encoding. They
reportedthisattheUSENIXWinter1993TechnicalConference23.FSS/UTFwas
brieflyalsoreferredtoasUTF2andlaterrenamedUTF8andpushedthroughthe
standardsprocessbytheX/OpenJointInternationalizationGroup(XOJIG).

20 http://www.cs.bell-labs.com/who/ken/
21 http://www.cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt
22 http://64.233.167.104/search?q=cache:U4zV7dcaq0EJ:www.faqs.org/ftp/rfc/pdf/rfc2279.txt.pdf+Greger+Leijonhufvud&h
l=en
23 USENIX Technical Conference held in San Diego, CA, January 25-29, 1993, published in the Conference Proceedings, pp.
43-50.

353
A Beginner's Guide to Gambas

UTF8encodesUCScharactersasavaryingnumberofoctets.Thenumber
of octets and the value of each depend on the integer value assigned to the
characterinISO/IEC10646(thecharacternumber,a.k.a.,it'scodeposition,code
point or Unicode scalar value). This encoding form has the following
characteristics24(valuesinhexadecimal):

CharacternumbersfromU+0000toU+007F(USASCIIset)correspond
tooctets00to7F(7bitUSASCIIvalues).Adirectconsequenceisthat
aplainASCIIstringisalsoavalidUTF8string.

USASCII octet values do not appear otherwise in a UTF8 encoded


characterstream.Thisprovidescompatibilitywithfilesystemsorother
software(e.g.,theprintf()functioninClibraries)thatparsebasedon
USASCIIvaluesbutaretransparenttoothervalues.

RoundtripconversioniseasybetweenUTF8andotherencodingforms.

Thefirstoctetofamultioctetsequenceindicatesthenumberofoctets
inthesequence.

TheoctetvaluesC0,C1,F5toFFneverappear.

Character boundaries are easily found from anywhere in an octet


stream.

ThebytevaluelexicographicsortingorderofUTF8stringsisthesame
asiforderedbycharacternumbers.Ofcoursethisisoflimitedinterest
sinceasortorderbasedoncharacternumbersisalmostneverculturally
valid.

TheBoyerMoorefastsearchalgorithmcanbeusedwithUTF8data.

UTF8 strings can be fairly reliably recognized as such by a simple


algorithm,i.e.,theprobabilitythatastringofcharactersinanyother
encoding appears as valid UTF8 is low, diminishing with increasing
stringlength.

TheUTF8encodingisformallydefinedinISO106461:2000AnnexD.It
isalsodescribedinRFC3629aswellassection3.9oftheUnicode4.0standard.

24 See URL http://www.faqs.org/rfcs/rfc2279.html.

354
A Beginner's Guide to Gambas

InordertouseUnicode underUnixstyleoperatingsystems,UTF8isthebest
encodingschemetouse. ThisisbecauseUCScharactersU+0000toU+007F
(ASCII)areencodedasbytes0x00to0x7F(forASCIIcompatibility).Thismeans
files and strings that contain only 7bit ASCII characters will have the same
encodingunderbothASCIIandUTF8.AllUCScharactersthatfallintherange
greaterthanU+007Fareencodedasamultibytesequence,eachofwhichhas
themostsignificantbitset.Therefore,noASCIIbyte(0x000x7F)canappearas
partofanyothercharacter.

The first byte of a multibyte sequence that represents a nonASCII


characterwillalwaysfallintherangeof0xC0to0xFDanditindicateshowmany
byteswillfollowforthischaracter. Anyfurtherbytesinamultibytesequence
willbeintherangefrom0x80to0xBF.Thisallowseasyresynchronizationand
makesencodingstatelessandrobustagainstmissingbytes.Allpossible231UCS
codescanbeencoded.UTF8encodedcharactersmaytheoreticallybeuptosix
byteslong.ThesortingorderofBigEndianUCS4bytestringsispreserved.The
bytes0xFEand0xFFareneverusedintheUTF8encoding.Thefollowingbyte
sequencesareusedtorepresentacharacter.Thesequencetobeuseddependson
theUnicodenumberofthecharacter:

U-00000000 U-0000007F: 0xxxxxxx


U-00000080 U-000007FF: 110xxxxx 10xxxxxx
U-00000800 U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
U-00010000 U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

Thexxxbitpositionsarefilledwiththebitsofthecharactercodenumber
inbinaryrepresentation.Therightmostxbitistheleastsignificantbit.Onlythe
shortestpossiblemultibytesequencewhichcanrepresentthecodenumberofthe
charactercanbeused.Notethatinmultibytesequences,thenumberofleading
1bitsinthefirstbyteisidenticaltothenumberofbytesintheentiresequence.

HowtotranslateinGambas

TotranslateGambasintoyourownlanguage,opentheGambasprojectin
theIDE,and click onTranslate...in theProjectmenu,asshowninthefigure
below:

355
A Beginner's Guide to Gambas

Figure100ChoosingtheTranslate
optioninGambas.

Next,youmustselectthetargettranslationlanguageinthecomboboxof
thetranslatedialogbox,asshownbelow:

Figure101TheTranslateDialoginGambas.

Selectastringfromthelistofuntranslatedstringsandenteritstranslation
inthetextfieldshownatthebottomofthedialog. Youneed torepeatthis
processuntileverystringinyourapplicationhasbeentranslated.Whenyouhave
finished, click on the Closebutton. Itis not necessary to complete all of the
strings at one sitting. You can translate the projectin several attempts. The
toolbariconsyouseeatthetopoftheTranslatedialogallowyouto:

356
A Beginner's Guide to Gambas

Savethecurrenttranslation.

Reloadthecurrenttranslation(Note:changesarelostwhenyoureload).

Deletethecurrenttranslation.

Duplicateanexistingtranslation.

Exportthecurrenttranslationtoa.pofile.

Mergeatranslationfile.

Verifyatranslationbycheckingifeverysymbolcharacterispreserved.

Therearecertainoccasionswhereyoumaynotwanttoevertranslatea
string.InGambas,youcanindicateastringshouldnotbetranslatedbyentering
aminussigncharacterasthetranslatedstring. Yourtranslationisstoredina
*.pofileinthe.langdirectoryoftheproject.Thenameofthe.pofiledependson
thelanguagetranslated.Forexample,theFrenchtranslationfileisnamedfr.po.

WheneverthelatestGambasversionchanges,anyuntranslatedstringsin
yourprogramcouldchange.However,anystringsyouhavetranslatedstringswill
bepreserved.Ifanuntranslatedstringdisappearscompletely,thetranslationwill
alsodisappearandifanewuntranslatedstringisadded,itgetsanemptyornull
translation string assigned to it. All other untranslated stringswillkeep their
correspondingtranslationstrings.WhilethestringtranslationfeatureofGambas
allowsyoutoeasilymaintainstringconversions,otherlocalespecificthingssuch
as dates, number formats, etc. are left to you to manage. It is hoped that
Gambas2willaddressthesefeatureswhenitisreleased.Untilthattimearrives,
hereisashort,generalizedchecklistforhelpingyoulocalizeyourapplication:

Ensureallmessages,icons,andhumanreadablecontentarestoredin
externalresourcefilesandcanbeeasilytranslated.

Thetranslatedmessageorresourcefilesshouldbedynamicallyloaded
by the application, depending on the current language and locale
settingsforthesession.

Date/time,sortorder,numericandmonetaryformattingetc.areinthe
targetlanguage.Thesortordershouldbeconfigurable,dependingon

357
A Beginner's Guide to Gambas

thelanguageoftheuser.

Targetlanguagecharacterscanbecorrectlyenteredanddisplayedby
theuserandtheycanbereadfromandwrittentothenativefilesystem
ofthetargetplatform.

AccordingtoHuanget.al.,25youshouldconsidercreatinganI18Ntesting
checklist for your application. Some of the questions they recommend you
considerincludethefollowing:

1.Doesprogramdesignaccountforinternationalconsiderations?

2.Canauserentertext,accelerators,andshortcutkeycombinationsonan
internationalkeyboard?

3. Can a user enter dates, times, currencies, and numbers using


internationalformats?

4.Canausersuccessfullycut/pastetextwithaccented (ordoublebyte)
characters?

5.Cantheapplicationworkcorrectlyondifferenttypesofhardwaresoldin
thetargetmarket?

6.Doestheapplicationworkcorrectlyonlocalizedoperationssystems?

7.CanausertypeEuropeanaccented(orAsiandoublebyte)charactersin
documentsanddialogboxes?

8. Can documents created in a target language be opened in other


languagesandviceversa?

9.Canuserssaveandprintfileswithaccented(ordoublebyte)characters?

Whilethereisnosinglechecklistthatcanaccountforthewidedegreeof
variationfromapplicationtoapplication,considerationofthesebasicissueswill
likelygofarinhelpingyoutoreachaglobalaudience.TheInternethasmadethe
worldamuchsmallerplaceandtheaudienceforapplicationshavebecomemuch
25 Huang, E., Haft, R. and Hsu, J. Developing a Roadmap for Software Internationalization, Whitepaper dated October
2000, retrieved fromURL www.symbio-group.com/doc/Developing a Roadmap for Software Internationalization.pdf on
October 5th, 2005.

358
A Beginner's Guide to Gambas

larger. Youcannotsimplyassumeeveryoneusing yourapplicationisEnglish


speakingandusesthesamekeyboardorwillunderstandyouricons. Different
pictograms mean different things depending on the locale in which your user
resides. Most important of all, make the effort to accommodate the broadest
audiencepossibleandyouruserswillmostlikelyallowforafewmistakeshere
and there. Not making such an effort will generally leave them with the
impressionthatyoucould carelessand theywill probably feelthesame way
aboutusingyourprogram.

359
A Beginner's Guide to Gambas

This page intentionally blank.

360
A Beginner's Guide to Gambas

Alphabetical Index
Accessfunction................................................................(188) Consistency......................................................................(332)
ACIDcompliant..............................................................(331) Constant.............................................................................(34)
Activateevent...............................................(155,162,169p.) Constructorroutine...............................(150,210,213,248p.)
Addmethod...............................(89,152,154,159,167,176) Containerclass...................................................................(62)
ANDoperator.....................................................................(41) Controlclass.......................................................................(61)
APPENDkeyword...........................................................(192) ControlGroups................................................................(100)
Applicationpath..............................................................(327) Controls..............................................................................(58)
Arithmeticoperators..........................................................(36) COPYfunction.................................................................(195)
Assignmentstatement........................................................(35) Copyrightnotice..................................................................(3)
Atomicity.........................................................................(331) CopyrightNotice..............................................................(2p.)
BackColorproperty.............................................(62,67,268) Cursorproperty..................................................................(65)
Backgroundproperty.........................................................(62) Dataabstraction...............................................................(239)
BenotMinisini..............................................(1,19,149,157) Databasesproperty...........................................................(328)
BigEndian.......................................................................(192) Datedatatype....................................................................(32)
Bitfunctions.....................................................................(319) Dblclickevent...................................................................(78)
Bits...................................................................................(318) DECoperator.....................................................................(43)
Booleandatatypes.............................................................(31) Defaultbutton....................................................................(61)
Borderproperty..................................................................(63) Defaultproperty.................................................................(66)
Builtinconstants...............................................................(34) Deletemethod....................................................................(70)
Busyproperty................................................................(151p.) Designproperty..................................................................(66)
Byte......................................................................... .........(318) Desktop.Charset.......................................................(142,152)
Bytedatatype.................................................................(31p.) Dialogclass...................................................................... (103)
Cachedproperty...............................................................(267) DialogTitleproperty.......................................................(103)
Cancelbutton.....................................................................(61) Dirfunction...................................................................... (189)
Cancelproperty..................................................................(63) DIRECTkeyword............................................................(192)
Captionproperty..........................................................(64,81) Divisionbyzero..............................................................(39p.)
Carrybit...........................................................................(323) DivisionbyZero................................................................(40)
CASEELSEblock.............................................................(49) DO[WHILE]LOOP..........................................................(51)
CASEstatement.................................................(48,103,114) Dotnotation.......................................................................(36)
CASEStatement................................................................(48) Doubleclickevent.............................................................(77)
CATCHstatement............................................................(305) Dragmethod.......................................................................(70)
CheckBoxclass..................................................................(93) Drawclass.......................................................................(267)
CheckBoxcontrol.........................................................(92pp.) Draw.Ellipsemethod.......................................................(276)
Checkedproperty..................................................(100p.,157) Draw.FillStyle..................................................................(279)
Chr(10).............................................................................(166) Draw.Linemethod...........................................................(276)
Chr(13).............................................................................(199) Draw.LineWidthproperty................................................(276)
Chr(9).......................................................................(136,194) Draw.Pointmethod..........................................................(274)
Classevent.......................................................................(310) Draw.Polygonmethod..................................................(280p.)
Classhierarchy...................................................................(28) Draw.Polylinemethod.............................................(280,282)
Classinvariants................................................................(241) Draw.Rectmethod..................................................(274,279)
ClassbasedOOPapproach..............................................(241) DrawingAreacontrol.......................................................(271)
Clickevent.........................................................................(76) Dropproperty.....................................................................(66)
ClickNRun....................................................................(22) Durability.........................................................................(332)
Clipclass..........................................................................(268) Enabledproperty................................................................(66)
Clippingarea....................................................................(268) Encapsulation...................................................................(240)
Cohesion..........................................................................(241) ENDkeyword....................................................................(37)
Collections.........................................................................(55) ENDWITHinstruction......................................................(35)
Colorclass........................................................................(268) Enterevent.........................................................................(74)
ColumnViewcontrol.......................................(170,174,177) Eoffunction.....................................................................(190)
ComboBoxarrays..............................................................(89) Errorclass........................................................................(304)
ComboBoxcontrol...............................................(85pp.,186) Errormanagement............................................................(298)
ComboBoxitems...............................................................(89) Error.Classproperty.........................................................(304)
Commandlineinterface...................................................(326) Error.Clear........................................................................(305)
COMMITstatement.........................................................(331) Error.Codeproperty........................................................(304)
Comparisonoperators........................................................(36) Error.Raise.......................................................................(305)
Conditionals.......................................................................(46) Error.Textproperty..........................................................(304)
Connectionclass......................................................(327,332) Error.Whereproperty.......................................................(305)
Connectionobject............................................................(327)

361
A Beginner's Guide to Gambas

Errorsinlogic..................................................................(301) Html....................................................................................(70)
Eventdrivenlanguage.......................................................(46) HTML..............................................................(26,81p.,84p.)
Eventhandler.....................................................................(77) HungarianNotation...........................................................(31)
Eventdrivenprogramming..............................................(309) IconEditor.........................................................................(28)
Eventdrivensystem........................................................(309) IconViewcontrol........................................(149,154pp.,158)
Execmethod....................................................................(327) IFstatement...............................................(47,101,161,168)
Existfunction...................................................................(190) IFStatement.......................................................................(47)
Existmethod....................................................................(167) IFTHENELSE................................................................(110)
Expandproperty.................................................................(67) Imageclass....................................................................(284p.)
FileSystemSafeUCSTransformationFormat(FSS/UTF).... INCoperator......................................................................(43)
(353) Infiniteloop........................................................................(51)
Fillclass...........................................................................(269) Inheritance........................................................................(240)
FillColorproperty............................................................(268) Inkscape...........................................................................(292)
FillStyleconstants............................................................(269) Integerdatatype................................................................(32)
FillStyleproperty.............................................................(269) Internationalization....................................................(22,351)
FillXproperty..................................................................(269) Intrinsicandderivedfunctions........................................(215)
FillYproperty..................................................................(269) Invertproperty.........................................................(269,275)
Finally..............................................................................(306) IsDirfunction...................................................................(191)
Floatdatatype...................................................................(32) ISO/IEC10646.................................................................(352)
FLUSHfunction..............................................................(195) Isolation............................................................................(332)
Focuscontrol......................................................................(72) Java......................................................................(19,53,237)
Fontclass............................................................(108pp.,269) Javalikearrays..................................................................(53)
Fontproperty......................................................................(67) Keyclass..........................................................................(316)
FOREACH........................................................................(50) KILLfunction..................................................................(196)
FOREACHconstruct.......................................................(55) LABEL............................................................................ ...(49)
FORstatement..........................................................(49p.,55) Layoutcontrols.............................................................(177p.)
ForeColorproperty............................................................(67) Leaveevent........................................................................(74)
Foregroundproperty..........................................................(67) Leftproperty......................................................................(68)
Frameclass.........................................................................(92) LIKE....................................................................(43,45,189)
GambasCodeEditor..........................................................(28) LineStyleproperty...................................................(270,276)
Gambascodingenvironment.............................................(29) Linspire...........................................................................(22)
Gambascomponentlibrary................................................(91) Linux......................................(19,142,178,196p.,238,266)
Gambasconstants..............................................................(34) ListEditor........................................................................(186)
GambasConstants..............................................................(34) ListBoxcontrol...............................................................(89p.)
Gambasdatatypes.......................................................(30,33) ListViewcontrol.........................................................(158pp.)
GambasDevelopmentEnvironment..................................(66) LittleEndian....................................................................(192)
GambasIconEditor.................................................(162,198) Loadconditions...............................................................(302)
GambasIDE.................................................................(27,58) Localization.....................................(138pp.,142p.,145,351)
GambasInterpreter..............................................(19,21,266) Lof()function...................................................................(195)
GAMBASinterpreter.......................................................(141) Loginproperty................................................................(329)
Gambaskeywords..............................................................(46) Loopingstructures.............................................................(49)
Gambasmascot..................................................................(38) Lowermethod....................................................................(71)
GambasToolBox...............................................................(57) MenuEditor............................................................(98p.,197)
GambasWiki.............................................................(20,165) MenuItems.........................................................................(99)
Gb.dbcomponent.............................................................(327) Messageclass...................................................................(112)
GNUPublicLicense..........................................................(19) MessageBoxcontrol........................................................(112)
GOTOinstruction..............................................................(49) MicrosoftVisualBasic...................................................(19)
Grabmethod.......................................................................(71) MIMETYPE......................................................................(70)
GraphicalUserInterfaceclasses........................................(58) MKDIRfunction..............................................................(196)
GridCell............................................................................(171) MODfunction....................................................................(40)
GridViewarray................................................................(171) MODoperator....................................................................(40)
GridViewcontrol..........................................................(171p.) Mouseclass...................................................................... (312)
GTK+.................................................................................(21) Mouseproperty..................................................................(68)
Hproperty..........................................................................(68) Movemethod.....................................................................(71)
Handleproperty.................................................................(68) MoveCurrentmethod...................................(161,165p.,168)
Handles...............................................................................(61) MySQL.............................................................................(326)
Heightproperty.........................................................(68,272) MySQLmanual................................................................(326)
Hidemethod.......................................................................(71) MySQLserver..................................................................(326)
Hostproperty...................................................................(329) Nameproperty................................................................(329)
HSVfunction.....................................................................(63) Nativearray........................................................................(53)

362
A Beginner's Guide to Gambas

NEWkeyword...................................................................(30) ScreenYproperty..............................................................(69)
NewProjectWizard.....................................................(37,72) ScrollViewcontrol........................................................(293p.)
Nextproperty.....................................................................(69) SELECTstatement............................................(48,105,114)
NEXTstatement.................................................................(50) SelectColorDialog..................................................(103,105)
NEXTStatement................................................................(49) SelectDirectoryDialog............................................(104,119)
NOToperator.....................................................................(44) SelectFontDialog.......................................................(108pp.)
Objectdatatype.................................................................(33) SelectionTool....................................................................(28)
Objectorientedprogramming.........................................(237) SetFocusmethod................................................................(72)
Objecttypedata...............................................................(238) SetFocus()method.............................................................(69)
OOconcepts.....................................................................(238) Shortdatatype...................................................................(32)
OOparadigm....................................................................(237) Showmethod.....................................................................(71)
OOP..................................................................................(237) SQLWHEREstatement.................................................(333)
OOPL...............................................................................(238) SQLite..............................................................................(326)
OpenContentLicense.......................................................(2p.) Standaloneexecutable.......................................................(20)
OpenFileDialog...................................................(104,117p.) Statfunction.....................................................(150,153,191)
ORoperator................................................................(41,188) STATICkeyword...............................................................(30)
Panelclass.......................................................................... (95) StatusBar...........................................................................(26)
Panelcontrol......................................................(95,177,185) STEPkeyword...................................................................(50)
Parameterpassingerrors..................................................(301) Stringconstants...............................................................(34p.)
Parentproperty...................................................................(69) Stringdatatype.............................................(32,34,55,126)
Passwordproperty............................................................(330) Stringfunctions................................................................(125)
Pictureclass...............................................................(69,287) Stringoperators..................................................................(36)
Picturecontrol....................................................................(78) SubMenus..........................................................................(99)
Pictureobject...............................................................(65,79) SVG..................................................................................(292)
Pictureproperty..................................................................(69) SVGspecification............................................................(292)
PNGfile.............................................................................(79) Systemclass...............................................................(91,150)
Polymorphism..................................................................(240) Tablesproperty................................................................(330)
Portproperty....................................................................(330) TableViewcontrol...........................................................(348)
PostgreSQL......................................................................(326) TabStripcontrol............................................................(182p.)
Poweroperator...................................................................(41) Tagproperty.......................................................................(69)
Predefinedconstants....................................(62,67,103,148) Temp$function................................................................(192)
Previousproperty...............................................................(69) Terminalapplication..........................................(37,125,232)
PRINTstatement...................................................(38,46,51) Textproperty...............................................................(64,69)
PRINTStatement...............................................................(46) Textboxcontrol..........................................................(83,166)
PRIVATEkeyword............................................................(30) TextBoxcontrol......................................................(82p.,252)
ProgressBarcontrol............................................................(73) TextHeightproperty.........................................................(272)
ProjectExplorer...................................................(25pp.,37p.) TextWidthproperty.........................................................(272)
ProjectMenu......................................................................(27) Timerevent......................................................................(187)
PUBLICkeyword........................................................(30,34) ToggleButtoncontrol......................................................(92p.)
Qt.........................................................................(21,58,142) ToolBar..............................................................................(28)
QT................................................................................(58,60) ToolBox.............................................................................(27)
QTlibrary.........................................................................(347) ToolBoxwindow......................................................(27p.,60)
QUITcommand.................................................................(37) ToolTip..............................................................................(28)
Quotemethod...................................................................(335) ToolTipproperty................................................................(69)
Racecondition.................................................................(301) Topproperty.......................................................................(70)
RadioButtonclass..............................................................(95) Transaction.......................................................................(331)
RadioButtoncontrol..........................................................(95) Transparentproperty........................................................(270)
Raisemethod......................................................................(71) Treeview...........................................................................(105)
Recoverableerror.............................................................(298) TreeView......................................(25,28,37,57pp.,64,163)
Refreshmethod..................................................................(72) TreeViewcontrol...........................................(163pp.,167pp.)
Removemethod...............................................................(168) Trolltech......................................................................... ..(347)
REPEATandUNTIL.........................................................(53) TRY..................................................................................(304)
Resizemethod....................................................................(72) TRYstatement.................................................................(305)
Resultobject............................................................(333,335) Typeproperty...................................................................(330)
RETURNcommand...........................................................(37) UCS2...............................................................................(353)
RGBfunction.....................................................................(63) UCS4...............................................................................(353)
ROLLBACKstatement....................................................(331) Unicodestandard.............................................................(352)
SaveFileDialog.......................................................(104,118) Usersproperty..................................................................(330)
ScalableVectorGraphics................................................(292) UTF8............................................................................ ...(353)
ScreenXproperty...............................................................(69) UTF8charset..........................................................(135,141)

363
A Beginner's Guide to Gambas

Validationerror................................................................(298) WHILE...WEND..............................................................(52)
Valueproperty...................................................................(70) Widthproperty...................................................(68,272,276)
Variantdatatype.........................................................(33,55) Wikipedia.........................................................................(215)
VB....................................................................(19,32,37,59) Windowproperty...............................................................(70)
Versionproperty..............................................................(330) WITH.................................................................................(35)
Virtualclass.DrawClip...................................................(268) WITHkeyword..................................................................(35)
Virtualdispatch................................................................(242) Xproperty..........................................................................(68)
Visibleproperty.................................................................(70) XWindows........................................................................(78)
Wproperty.........................................................................(68) X/OpenJointInternationalizationGroup........................(353)
WAIT.................................................................................(71) XORoperator.....................................................................(42)
Warningmessages...........................................................(115) Yproperty..........................................................................(68)
WATCHkeyword............................................................(192)

364

You might also like