Professional Documents
Culture Documents
Gambas Beginner Guide PDF
Gambas Beginner Guide PDF
CoverdesignbyFabienBodard
ForewordbyFabienBodardandBenotMinisini
1
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
UpdateForm()Subroutine................................................253
CodingToolbuttons:First,Prev,Next,andLast.......................254
CodingToolButtons:Addingarecord.......................................256
CodingToolButtons:Clearingdata...........................................258
ValidatingUserInput.......................................................258
8
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
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
11
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
14
Thispageisintentionallyblank.
15
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. Iwouldalsoliketothank DanielCamposFernndez whowasagreat
assetinhelpingmetounderstandsomeofthefinerpointsofGambas. NigelGerrard
alsocontributedtothesuccessofthisprojectbyprovidingafinalreviewandeditofthe
databasematerial.FromamongtheseGambasHallofFamecoders,whoelsecouldhave
doneitbetter?
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
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
FabienBodardandBenoitMinisini
18
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
2
3
Thereaderisencouragedtovisithttp://gambas.sourceforge.net/index.htmltolearnmoreabouttheGambasproject.
Forinformationaboutthelicense,visithttp://www.gnu.org/licenses/licenses.html#GPL.
SeetheGambasWikiWebSiteIntroductionathttp://gambas.sourceforge.net/index.htmlformoredetails.
19
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
5
Figure2theGambasOpeningScreen.
6
7
8
authors.
FormoreinfoaboutGTK+,visithttp://www.gtk.org/.
FormoreinfoaboutQt,visithttp://www.trolltech.com/products/qt/.
http://doc.trolltech.com/3.3/index.html
21
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.
FormoreinfoaboutLinspire,visithttp://www.linspire.com.
22
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
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
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
Figure8TheGambasIDE.
Figure9ProjectExplorerFileMenu.
Figure10ProjectMenu.
Figure12ProjectExplorerToolsMenu.
Figure11ProjectExplorerViewMenu.
27
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
29
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
Byte
Float
Variant
Short
Date
Object
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
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
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
Short
32768...+32767
2bytes
Integer
2147483648...+2147483647
4bytes
Float
SimilartothedoubledatatypeinC
8bytes
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
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
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
Alocalvariable
Afunctionparameter
Aglobal(class)variable
Anarrayelement
Apublicobjectvariableorproperty
Herearesomeexampleofvariableassignments:
iMyVal=1984
stMyName="Orwell"
fMyNum=123.45
AssignmentUsingTheWITHStatement
Thisstatementismostcommonlyusedtosetpropertiesforcontrols.The
expressionthatexistsbetweentheWITHkeywordandtheENDWITHinstruction
35
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
Let'stakealookatsomeGambaskeywordsyoushouldknowabitmoreabout
beforeweproceed.
END,RETURNandQUITStatements
The END keyword indicatestheendofaprocedureorafunction. There
aredifferencesfrom VB whenusing END. In VB,the End commandclosesall
forms and files and terminates the program. In Gambas, the END command
worksmorelike VB's EndFunction combinedwith VB's EndSub. Itclosesthe
functionorsubroutine. Forsimilarfunctionalityto VB'sEnd command,usethe
QUITcommand.Itendstheprogramimmediately.Allwindowsareclosed,and
everythingisfreedupinmemoryascleanlyaspossible. InGambas,whenyou
wishtoexitaroutine,youcanusetheRETURNcommand.Usually,RETURNis
usedtoreturnavaluetothecallingprocedure.TheformatofRETURNis:
37
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
Theconsolewillrespondwiththefollowing:
==>40
Theconsolewillrespondwiththefollowing:
==>3
Nowtryusingthe\todivideinsteadofthe/character:
STATICPUBLICSUBMain()
DIMNASInteger
DIMRASInteger
N=9
R=5
PRINT"===>";N\R;
END
Theconsolewillrespondwiththequotient:
==>1
39
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
Theconsolewillrespondwiththefollowing:
==>8
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
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
Theconsolewillrespondwiththefollowing:
==>4|6
MatchNnumberofanytypeofcharacter.
Matchanysinglecharacter.
Matchanycharacterspecifiedbetweenthebracketsymbols.
Matchanycharacterthatexistsintheintervalxy.
Matchanycharacterthatdoesnotexistintheintervalxy.
STATICPUBLICSUBMain()
PRINT"Rittinghouse"LIKE"R*"
END
Theconsolerespondswith:
TRUE
Thespecialcharacter\preventsthenextcharacterfollowingitinastring
frombeinginterpretedasagenericpartofthestring.Thinkofthe\characteras
acontrolcode.Trythis:
STATICPUBLICSUBMain()
PRINT"Samson"LIKE"S*"
43
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
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
CASE
CONTINUE
ENDIF
END
FOREACHGOTO
REPEAT
RETURN
UNTIL
WAIT
DEFAULT
SELECT
IF
SELECT
WEND
DO
END
LOOP
STEP
WHILE
ELSE
WITH
NEXT
THEN
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
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
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
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
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
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
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
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
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
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
Yourconsoleshoulddisplaythisoutput:
312
Atthispoint,youshouldbegettingaprettygoodfeelforthesyntaxand
structureofGambas.Wearegoingtomoveawayfromconsolebased(terminal)
applicationsandreturntoourfirstprojecttobeginexploringtheGambasToolBox
andlearnhowtodevelopaGUIbasedprogram. Itistimetotakeabreakand
whenyoucomebacktothenextchapter,youwillberefreshedandreadytocode.
Ah,heck.Ifyoujustcannotwaittojumpin,goaheadandturnthepage!
56
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
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
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
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
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
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
DarkCyan
DarkRed
Green
Pink
White
Blue
Cyan
DarkBlue
DarkGray
DarkGreen DarkMagenta
DarkYellowDefault
Gray
LightGray
Magenta
Orange
Red
TransparentViolet
Yellow
TosettheBackColorpropertyforhButtontored,youwouldusethiscode:
hButton.BackColor=Color.Red
62
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
IftheCancelpropertyisusedinyourprogram,itwouldallowyoutohandlethe
eventandgracefullyexittheformjustasiftheuserhadclickedaQuit,Exitor
Cancelbutton.
63
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
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
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
Theoutputoftheabovecodewouldbeasfollows:
Figure18Demonstratingfontcapabilities.
ForeColorisdefinedasPROPERTYForeColorASIntegerandthisinteger
valuerepresentsthecolorusedforthecontrolforeground.Itissynonymouswith
theForegroundproperty.YoucanusetheGambaspredefinedconstantsforcolor
tosetcolorvalue:
Black
DarkCyan
DarkRed
Green
Pink
White
Blue
Cyan
DarkBlue
DarkGray
DarkGreen DarkMagenta
DarkYellowDefault
Gray
LightGray
Magenta
Orange
Red
TransparentViolet
Yellow
TosettheForeColorpropertyforhButtontored,youwouldusethiscode:
hButton.ForeColor=Color.Red
AswiththeBackColorproperty,ifyouknowtheRGBorHSVvaluesfora
specificcolor,youcanpassthemtotheForeColorpropertywiththiscode:
hButton.ForeColor=Color.RGB(255,255,255)
67
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
Arrow
Cross
Wait
Text
SizeS
SizeE
SizeNESW
SizeNWSE
SizeAll
Blank
10
SplitV
11
SplitH
12
Pointing
13
68
69
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
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
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
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
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
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
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
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
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
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
TextLabel
TextBox
ComboBox
ListBox
ToggleButton
Panel
Frame
Checkbox
RadioButton
Hereiswhatourprogramwilllooklikewhenwearefinishedwithit:
Figure26ThirdProject(almost)finalresult.
80
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
Fromthispointon,wewillbelearningtousenewcontrolsandfeaturesof
Gambas.WehavealreadywrittencodetoassigninputdatatotheTextLabel,so
let'stakethetimenowtolearnallwecanaboutit.Beforewestart,itisprobably
agoodideatogoaheadandclickthesavebuttonontheIDEtosaveyourwork.
TextLabel
ThisclassiscreatableanditinheritsitsattributesfromtheControlclass.It
implementsacontrolcapableofdisplayingsimpleHTMLtext.YoucanuseHTML
entitiessuchas<and>todisplaycharacterslike<and>.ForHTMLthat
requirestheuseof quotemarks, avoid the because itwill notwork. For
example,entering:
<divalign="center"><b>Thiswon'twork.</b>
Thefigurebelowshowsyouanexampleofhowthisworks:
Figure27UsingHTMLtoformatTextLabeloutput.
Whatwewanttodonowiscodetheupdatebuttontotakeadvantageof
thesecool HTML features. Toaccomplishthis,weneedtomodifythecodewe
previously entered for the update button's click event. Doubleclick on the
82
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
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
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
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
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
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
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
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
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
Now,saveyourprojectandruntheprogram.Tryselectingalltheitemsin
thelistandseewhatinformationisreturned. ListsandComboBoxesarevery
91
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
ToggleButton
TheToggleButtoncontrolinheritsitsattributesfromtheControlclassand
implementsatogglebutton.Thismeansiteithertogglesupordown.Thisclass
iscreatable.Todeclareandinstantiatethiscontrol,usetheformat:
DIMhToggleButtonASToggleButton
hToggleButton=NEWToggleButton(ParentASContainer)
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
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
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
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
Figure38MenuProjectFinalresults.
Doubleclickontheformanywhereoutsideacontrolboundaryandyou
willgetthePUBLICSUBForm_Open()subroutinetoappearinthecodeeditor.
Insertthiscodeinthatemptysubroutine:
ME.Caption="WorkingwithMenus"
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
Figure40EditfieldsfortheMenuEditor.
99
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
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
(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)
Name
Group
Caption
InfoMessage
Menu2Item1
InfoMessage
AlertMessages
Menu2Item2
AlertMessages
ErrorMessage
subMenuItem1
ErrorMessage
WarningMessage
subMenuItem2
WarningMessage
DeleteMessage
subMenuItem3
DeleteMessage
QuestionMessage
Menu2Item3
QuestionMessage
(Variable)Name
About
Menu4
Group
Caption
About
102
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
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
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
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
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
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
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
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
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
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
anditisusedtodisplayaninformationMessageBox,withonlyonebutton.Since
theuserdoesnothavetomakeadecision,theyonlyneedtoacknowledgethe
112
Figure45AnInformationMessageBox.
Prettysimple,eh?Whatifwewantedtotogglethecheckedpropertyvalue
fromTRUEtoFALSEorviceversaeachtimethismenuitemwasselected.Modify
thecodeaboveasfollows:
PUBLICSUBMenu2Item1_Click()
IFMenu2Item1.CheckedTHEN
Menu2Item1.Checked=FALSE
ELSE
Menu2Item1.Checked=TRUE
ENDIF
Message.Info("Hereissomeinformationtoconsider.")
END
Figure46Achecked
menuitem.
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
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
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
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
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
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
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
122
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
124
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
Len
Lenreturnsthelengthofastring.ThereturnvalueisanInteger.Hereis
howLenwouldbeusedincode:
Length=Len(String)
Fromthecodewindow,let'stypethefollowing:
STATICPUBLICSUBMain()
DIMiStringLengthASInteger
DIMsTestStringASString
sTestString="12345678901234567890"
sStringLength=Len(sTestString)
PRINT"==>"&iStringLength&"isthelengthofourteststring."
sTestString="12345"
iStringLength=Len(sTestString)
PRINT"==>"&iStringLength&"isthelengthofourteststring."
sTestString="12345678901"
iStringLength=Len(sTestString)
PRINT"==>"&iStringLength&"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
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
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])
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
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
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
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
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
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
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
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$returnsthebinaryrepresentationofanumber.IfDigitsisspecified,
the representation is padded with unnecessary zeros so that Digits digits are
returned.HereisthecallingconventionforBin$:
136
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
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:
138
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
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
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
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
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
Theoutputshouldbesimilartothis:
==>true
Youtyped:true
trueisBoolean.
==>214
Youtyped:214
214isanInteger.
ItcouldalsobeaByte.
Itcouldalsobeashort.
==>08/23/0512:23:55
Youtyped:08/23/0512:23:55
144
==>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
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
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?
IsDate/Date?
IsInteger/Integer?
IsNumber/Number?
IsShort/Short?
IsByte/Byte?
IsFloat/Float?
IsNull/Null?
IsObject/Object?
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
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
IconViewControl
Firstofall,startGambasandselecttheExplorerprojectfromtheMiscellaneous
sectionoftheExampleprograms:
Figure54ChoosingtheExplorerexample.
Once youselecttheExplorerproject,theIDEwillopenupandwewill
needtogettothecode.Youcandothisbydoubleclickingontheclassfileorif
theformisalreadyup,doubleclickonacontrolandthenmovetothetopofthe
149
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
Wewillassignthepathpassedin(System.Home)asaparametertoourglobal
variable$sPath:
$sPath=sPath
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
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
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
NowthatthecDirarrayissorted,wewillloopthroughthearrayusingthe
FOREACHstatementwhichisusedspecificallyforenumeratedobjectsinarrays
orcollections.
FOREACHsFileINcDir
Now,wecheckthetagofthefilenameusingthestringfunctionLeft$:
IFLeft$(sFile)="D"THEN
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
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
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
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
Thenextsubroutineisexecutedwhentheusersingleclicksonanitemin
theexplorerandoptstorenametheitem.Asitwasoriginallywritten,itdoesnot
checktoseeiftherenameactuallychangedtheitem. Forexample,iftheuser
pressedESC,theitemwouldreverttoitsoriginalname.
PUBLICSUBivwExplorer_Rename()
Message("'"&Mid$(LAST.Item.Key,2)&
"'hasbeenrenamedto'"&LAST.Item.Text&"'")
END
157
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)
158
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
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
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
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
Figure56CreatinganewIconimageinGambas.
SimplytypesquareintheNamefieldandclickok.Now,theiconeditor
appears and you can create an icon. Use the rectangle option from the Icon
EditorToolBoxandcreateabluesquareandsaveitwiththediskshapedicon.
Figure57Oursquareicon
image.
Figure59Ourcircleicon
image.
Figure58Icon
EditorToolBox.
Repeatthisprocess,creatinganothericonnamedcircle.pngandsavethat
too.Thatisit!Yourprogramisreadytorun.TryitoutandseehowtheListView
controlworks.
TheTreeView
Control
TheTreeViewcontrolworksalmostidenticallytotheListViewcontrol.The
chiefdifferenceisthattheTreeViewsupportsnestedchildrenandallowsyouto
traversefromaninner(child)leveloutwardtotheparentofthechild,alltheway
163
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
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")
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
Thisnextlinewillupdateourlabelandreflectthenewnumberofkids:
TreeView1_Click
ThiscalltoEnsureVisiblewillmakesurethattheitemwejustaddedtothe
listisinthevisibleareaofthecontrol.Ifnecessary,thecontrolwillscrollsothe
itemisvisible.
TreeView1.Item.EnsureVisible
ENDIF
END
167
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
Iftheuserdoubleclicksonaniteminthe TreeViewcontrol,itsetsoffa
Dbl_Clickevent.ItisbasicallythesameasanActivateevent.Theroutinebelow
is called. It simply updates the event stack, as described previously, and
168
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()
TextArea1.Text=""
'IntEventNumber=0
END
169
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
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:
Figure61WhatourGridViewwilllooklike.
171
Whentheprogramstarts,ifaconstructorexists,itisexecutedfirst. Our
constructorwillloadourthreeiconsandpopulatethegrid. First,declarethree
localvariablesforthepictures,hPic1,hPic2,andhPic3,asshownbelow:
PUBLICSUB_new()
DIMhPic1ASPicture
DIMhPic2ASPicture
DIMhPic3ASPicture
Now,wemustinstantiatethepicturevariablesandloadthepictures.
hPic1=NEWPicture
hPic1.Load("GridPic.png")
hPic2=NEWPicture
hPic2.Load("GridPic2.png")
hPic3=NEWPicture
hPic3.Load("GridPic1.png")
Thenextthingweneedtodoisdefinethedimensionsofthegrid. Our
172
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:
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
173
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
TheColumnViewControl
Forournextexample,wearegoingtocreateaprogramthatdisplaysdata
inaColumnView,asshownbelow:
Figure62OurColumnViewexample.
174
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
'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
175
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.
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,
176
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
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
177
Figure63Layoutprojecticons.
Ourprogramisquitesimple.WearegoingtocreateanHBox,aVBox,an
HPanel,andaVPanelandputsomesimplecontrolsineachcontainer. Wewill
simplyupdateatextlabeltoshowwhensomethinghasbeenclicked.Hereishow
ourformwilllookindesignmode:
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
178
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."
179
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
180
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
181
Invoking the code above will return a virtual tab object from its index.
TabStripsareusefulfororganizingandpresentinginformationinselfcontained
units.TabStripsallowyoutoobtaininputfromusersbypresentingasimple,easy
tofollowinterfacethatcanliterallyguidethemthroughaconfigurationorsetup
process.HereisasampleofaTabStripinuse:
Figure66ATabStripcontrol.
TodemonstratehoweasyTabStripsaretocreate,wewillbuildasmall
applicationthatimplementsthetabbedinterfaceyouseeabove.Ourapplication
thatwillshowyouhowtousetabbedcontrolstopresentinformationtoauser
andrespondtoitinyourapplications.StartGambasandcreateanewgraphical
userinterfaceprogram.NametheprojectTabs,clickthroughtheProjectCreation
WizardandwhenyougettotheGambasIDE,makeanewform,Form1thatisa
startupclass.
Next,youwillneedtoplaceaTabStripcontrolonthenewform.Onceyou
place the TabStrip, you will only see one tab displayed. You must go to the
propertieswindowandsettheCountpropertyto5tohavethecontrollooklike
theoneweshowabove.NotethattabnumberingstartsatzeroinGambas.Each
tabactslikeacontainerforthecontrolsyouplaceonit.Wewillalsoneedtoadd
aTextLabelandabuttontoourform. TheTextLabelwillbeusedtoshowthe
useractionsinresponsetoourtabbedinterface.ThebuttonwillbeaQuitbutton
whichwewillusetoterminatetheapplication. Hereiswhatyourformshould
looklikeasyoustarttodesigntheinterface:
182
Figure67TabProjectForm1.formDesign.
Figure68Tab0layout.
Next,doubleclickoneachRadioButtonandenterthiscode:
PUBLICSUBRadioButton1_Click()
TextLabel1.Text="Youhaveclicked:<br><center><strong>RadioButton1"
END
PUBLICSUBRadioButton2_Click()
TextLabel1.Text="Youhaveclicked:<br><center><strong>RadioButton2"
END
183
Figure69Tab1layout.
DoubleclickoneachCheckBoxandenterthiscode:
PUBLICSUBCheckBox1_Click()
IFCheckBox1.Value=TRUETHEN
TextLabel1.Text="Youhavechecked:<br><center><strong>CheckBox1"
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:
184
Figure70Tab2ToolButtonlayoutwith
icons.
ThenextstepistodoubleclickoneachToolButtonandaddthiscode:
PUBLICSUBToolButton1_Click()
TextLabel1.Text="Youclicked:<br><center>the<strong>ConfigureIcon"
END
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
185
Forourlasttab,Tab4,wearegoingtosimplydisplaythecurrenttime.
ThiswillrequireuseoftheTimercontrol.WearegoingtoneedtoaddaLabel
andaTimercontroltoTab4,asshownbelow:
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)
186
ThislineofcodewillupdatetheLabel1.Textfieldeverysecondthatthe
Tab4isdisplayed.Ineffect,youhavecreatedaclockontheTabbydoingthis.
Thatisallthereistoit.RuntheprogramandseehowTabStripswork.Next,we
movetoFileoperations.
187
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
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.
Hereisanexamplecodesegmenttohelpyou
'Printadirectory
SUBPrintDirectory(DirectoryASString)
DIMsFileASString
FOREACHsFileINDir(Directory,"*.*")
PRINTsFile
NEXT
END
189
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
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
.Mode
.Sticky
.Hidden
.Perm
.Time
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
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
IftheBIGorLITTLEkeywordisspecified,allsubsequentREADandWRITE
operationsonthisfilewill use bigEndian or littleEndian data representation.
Variable receives the object that represents the opened stream. CLOSE is the
reciprocalfunctionandsimplyclosesanopenedfile.SyntaxforusingCLOSEis:
192
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
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
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
HereisanexampleofhowtouseCOPY:
'Savethegambasconfigurationfile
COPYSystem.Home&/".gambas/gambas.conf"TO"/mnt/save/gambas.conf.save"
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
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
SelectAll
EditUndo
EditRedo
EditCut
EditPaste
EditCopy
Edit
Configure
Format
Colors
Format
Fonts
HelpAbout
Help
Contents
197
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
EditMenu
VariableName
"Exit"
Picture["exit.png"]
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
FormatMenu
VariableName
"Preferences"
Picture["configure.png"]
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
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
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
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.
OPENsCurrentFileNameFORREADAShFileIn
201
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
specificallyusedtocatenatefilenames.
202
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
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
iBottomMargin=Printer.Resolution
204
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")
Inourcodebelow,wehavecalledtheDraw.Rectfunctiontodrawaborderatone
inchmarginsaroundourpage.
'makeaborderaroundthepage
Draw.Rect(iLeftMargin,iTopMargin,iRightMargin,iBottomMargin)
'nowwewillloopthrougheachlineinthearrayandprintit
FOREACHsTxtLineINarsTxtToPrint
205
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()
DIMaStringASString
206
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
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
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
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
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
212
Selectingthefontanditsattributesforourprogramisjustassimpleasit
wastochoosecolors.Basically,wewillsetthedialogcaption,callthestandard
Dialog.SelectFontroutine,andupdateourTextArea1.Fontproperty,likethis:
PUBLICSUBFormatFontItem_Click()
Dialog.Title="Selectfont"
Dialog.SelectFont
TextArea1.Font=Dialog.Font
END
ThelastmenuisourHelpmenu.Ithastwooptions,ContentsandAbout.
PUBLICSUBHelpContentsItem_Click()
SHELL"konqueror\"file:/root/MyDocuments/GambasforBeginners/FileOps/Help.html\""
END
Runtheprogramandwhenyouaresatisfied,let'smoveontodosomemath.
214
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
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
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
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
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
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
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
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
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
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
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
The number argument can be any valid numeric expression. The Rnd
functionreturnsavaluelessthan1butgreaterthanorequalto0.Thevalueof
numberdetermineshowRndgeneratesarandomnumber. Toproducerandom
integersthatfallwithinanygivenrange,usethisformula:
Int((upperboundlowerbound+1)*Rnd+lowerbound)
Here,upperboundisthehighestnumberintherange,andlowerboundisthe
lowestnumberintherange.Hereisanexampleprogramtotryontheconsole:
STATICPUBLICSUBMain()
DIMDiceASInteger
PRINT"Between0and1:";
PRINTRnd
PRINT"Between0and2:";
PRINTRnd(2)
PRINT"BetweenPiandPi*2:";
226
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
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
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
229
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
1
230
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.
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
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
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
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
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:
236
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
239
240
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
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
concept of virtual dispatch. In other words, when you invoke a method (or
set/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
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
'fordebugonly,wewilllistalltherecordsinthecollection
PRINT"HereiswhatisstoredincTheData:"
FOREACHMyContactRecordINcTheData
PRINTMyContactRecord.FirstName&""&MyContactRecord.LastName
NEXT
RETURNcTheData'returnthecollection(nowfilled)withdata
END'ofGetData
245
'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
Form1.classfile
Save the Contact.class file and close it. Our contact class definition is
completesonowwewillneedtocreateaformnamedForm1.Form1willserve
asthemaininterfacebetweentheuserandtheprogramandit'sdata. Hereis
whatourfinishedformwilllooklike:
247
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
248
249
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
Startofdata
Prev
Next
Endofdata
Updatefields
Addnew
Deletecurrent
Savetofile
Clearfields
The ToolButtons
The nine ToolButtons that use these icons in their Picture property are
named:
FirstRecordBtn
LastRecordBtn
AddBtn
PrevRecordBtn
ClearBtn
DeleteRecordBtn
NextRecordBtn
Update
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
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
252
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
253
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
254
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
255
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."
256
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
258
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
260
Figure76Contactssearchformdesign.
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
261
Atthispoint,wehavepoppeduptheform,obtainedtheuserinputofalast
nametosearchfor,andhavepassedthatvariablebacktoourprogramusingthe
moduleconduitmethoddescribedabove.Now,wearereadytoactuallysearch
thecollectionandfindtheentry.Hereisthecodetodothat:
PUBLICSUBDoFind()
'declareacontactobjectforlocaluse
DIMMyContactRecordASContact
'instantiateit
MyContactRecord=NEWContact
'settherecordpointertothefirstrecordinthecollection
RecordPointer=1
'fordebugonly
PRINT"InDoFindwith:"&SearchKey
262
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
263
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
264
ToolButtonsagain:SavingData
Thelastthingweneedtocodeisthesavebutton. Thisisreallysimple
becausewehavealreadybuiltamethodinourContactclassfiletodothat.Here,
allwedoiscallthePutDatamethod:
PUBLICSUBSaveAllBtn_Click()
'invokethePutDatamethod
ContactRecord.PutData(Contacts)
'fordebugonly
PRINT"Contactssavedtocontact.datafile."
END
265
CreatingaStandaloneExecutable
Itisveryeasytocreatetheexecutable.Simplymakesureyourprogramis
readyforrelease(testitfirst!)andthengototheProjectmenuandchooseMake
Executable.TheGambasIDEwillcreateanexecutionscriptthatwillinvokethe
GambasInterpreterandallowyoutoexecuteyourcode.Icreatedadesktoplink
totheprogramandusedthisfortheapplicationpathonmysystem:
'/rittingj/MyDocuments/GambasforBeginners/Classes/Classes'
Ofcourse,yoursystemwillbedifferent.Youwillneedtopointthedesktoplink
totheapplicationtowhereeveryouhadtheIDEsavetheexecutablefile.Onthe
LinuxdistributionIusedforthisprogram,itwouldnotworkuntilIenclosedthe
fullpathwithtickmarks,asshownabove. Becausethe GambasInterpreter is
invokedasasystemcall,theticksareneededtokeepthesystemfromthinkingit
ispassingparametersto /rittingj/My (wherethefirstspacecharacteroccurs).
Here is the final result, our program executing in standalone mode on the
desktop:
Figure77ContactsManagerrunningstandaloneonmydesktop.
266
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
This integer value represents the color used for the current drawing
background or foreground color. It is synonymous with the
Background/Foregroundproperties. Notethat PROPERTY isapredefineddata
typeusedinternallyinGambas.YoucanusetheGambaspredefinedconstantsfor
colortosetcolorvalue:
Black
DarkCyan
DarkRed
Green
Pink
White
Blue
Cyan
DarkBlue
DarkGray
DarkGreen DarkMagenta
DarkYellowDefault
Gray
LightGray
Magenta
Orange
Red
TransparentViolet
Yellow
267
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)
Cross
Dense50
Dense94
Solid
CrossDiagonal
Dense6
Diagonal
Vertical
Dense12
Dense63
Horizontal
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
LineStyle/LineWidth
The LineStyle property returns or sets the style used for drawing lines.
LineWidthreturnsorsetsthewidthusedfordrawinglines.TheLineclassisstatic
anddefinestheconstantsusedbytheDraw.LineStyleproperty.Theseconstants
include:
Dash
DashDotDot
Dot
None
DashDot
Solid
StandardGambaslanguagesyntaxis:
STATICPROPERTYLineStyleASInteger
STATICPROPERTYLineWidthASInteger
Transparent
DrawMethods
OneofthebestwaystolearnhowtouseGambasdrawingmethodsisto
writecodethatdemonstratestheuseofeachmethod. Inthismanner,youcan
seehowtoprogramthemethodandgetimmediategratificationbyseeingthe
results.Wearegoingtobuildademoapplicationthatwillshowyouhowtouse
nearlyallofthemethodsthataresupportedbytheDrawclass.
Wewillstartbecreatinganewgraphicaluserinterfaceapplication.Name
theprojectgfxDemoandwhentheIDEappears,createaform,Form1.Makesure
youspecifyitasastartupclassandensurethecontrolsarepublic.Hereiswhat
theForm1layoutwilllooklikeatruntime:
270
Figure78gfxDemoForm1layout.
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)
271
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
272
'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
Figure79ResultsofclickingtheTextButton.
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
274
Saveyourworkandruntheprogram.WhenyouclicktheInvRectbutton,
youshouldseesomethingsimilartothis:
Figure80ResultsofInvRectbuttonclick.Note
thetinyblackcrosshaircenterscreen.
275
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
'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
'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:
Figure81Ellipsesdemonstratesdrawinglinesand
ellipses.
278
279
Saveyourworkandruntheprogram.WhenyouclicktheFillRectbutton,
youshouldseesomethingsimilartothis:
Figure82OutputafterclickingtheFillRectbutton.
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
'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
Saveyourworkandruntheprogram.WhenyouclicktheFillPolybutton,
youshouldseesomethingsimilartothis:
Figure83UsingDraw.Polygontodrawa
triangle.
'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
Figure84UsingDraw.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
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
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)
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
Heightisareadonlyattributethatreturnstheheightofthepictureasaninteger.
Itisdeclaredas:
287
Widthisareadonlyattributethatreturnsthewidthinpixelsofthepicture.Itis
declaredas:
PROPERTYREADWidthASInteger
Imageisareadonlypropertythatconvertsthepictureintoanimageandreturns
it.Itisdeclaredas:
PROPERTYREADImageASImage
Wewilluseaverysimpleexampletoshowyouhowthisworks.Wewill
showyouhowtotakeascreenshotwithcodeandsavetheimage.Theimageof
thedesktopistakenasapictureobjectwhenthebuttonontheformisclicked.
Thispictureobjectissubsequentlyconvertedintoanimageobjectanddisplayed
asanimageinaDrawingArea.
Start Gambas and create a new graphical user interface project, named
gfxDemo2.MaketheprojecttranslatablewithpubliccontrolsandwhentheIDE
appears,createastartupclassformnamedForm1.Fromthepropertieswindow
forForm1,settheresizepropertytoTruesoyoucanstretchtheformtoseethe
imagewhenitisadded.AddabuttonnamedButton1andaDrawingAreanamed
DrawingArea1. Place theDrawingArea atthetopleft cornerof theformand
makeitaboutoneinchwideand oneinchhigh. Now,putthebuttonatthe
bottom right corner of the form. Add the caption Snapshot to the button.
Doubleclickonthebuttontocreateaclickeventandaddthiscode:
'Gambasclassfile
PUBLICSUBButton1_Click()
'declareavarforourpicture
pASNEWPicture
'andoneforourimage
iASNEWImage
'getthepictureojbectfromthedesktopusing.Grabmethod
p=Desktop.Grab()
'assignthepictureusingtheimagepropertyto
'convertscreenshottoanimage
i=p.image
288
'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.Clickthebuttonandascreenshotof
yourdesktopwillbeplacedonthedrawingareaoftheform. Prettyeasyusing
theGambasmethods,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
289
FlushFlushestheinternalpicturecache.Themethodtakesnoparametersandis
calledusingthisconvention:
STATICSUBFlush()
LoadandSaveloadsorsavesapicturefromafileortoafilerespectively.The
fileextensionof Path willspecifythegraphicsfileformatusedwiththesaved
picture. CurrentlysupportedfileformatsareJPEG,PNG,BMP,GIFandXPM.
Gambaslanguagesyntaxis:
SUBLoad(PathASString)
SUBSave(PathASString)
Resizeresizestheimagetothesizespecifiedbythewidthandheightparameter
given:
SUBResize(WidthASInteger,HeightASInteger)
Let'snowgobacktoouroriginalgfxDemoprogramandfinishcodingthelast
button. StartGambasandloadthegfxDemoproject.OpenForm1anddouble
clickontheTileImgbutton.Whenthecodewindowappears,addthiscode:
PUBLICSUBTileBtn_Click()
'declareourlocalvarshere
'wewillneedapicturevartoholdthepictureweload
DIMmypicASPicture
'weneedacountervarforourloopwork
DIMcounterASInteger
'wearealsogoingtoneedsomeintegervars
DIMiASInteger
DIMjASInteger
290
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
291
Figure85Usingtiledimageswiththe
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.
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
In Gambas, you can load, save, clear, or copy an SVG image. The
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:
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
294
Figure86LoadinganSVGfileinGambas.
IhopeyouhaveenjoyedourshortlittletourdeforceofGambasdrawing
capabilities. ThischapterhaspresentedallofthebasicsneededtouseGambas
foralmostanygraphicsrelatedneeds.Attheendofthisbook,inAppendixA,we
presentaspecialgraphicsprogramthatyoucanusetodrawevenmoreadvanced
2D/3DrenderedobjectsusingaGKStypegraphicsclasscreatedinGambas.
295
297
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
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:
Figure87ErrorresultscaughtwithTRY.
305
a=2
b=0
PRINTa/b'willgenerateadividebyzeroerror
306
Whenyouruntheprogram,youshouldseethisastheopeningscreen:
Figure88CATCHtestprogramopeningscreen.
Now,clicktheerrorbuttontogenerateourerrorandyoushouldseethis:
Figure89DivbyZeroerrorcaughtbyCATCH.
YoushouldalsonoticethatthemainscreenTextLabelhaschangedtothis:
307
Figure90TheTextLabelupdatedwitherrorinfo.
OnceyouclicktheOkbuttonfortheErrorMessagedialog,youwillseethis:
Figure91Infomessagethattheerroris
cleared.
Now,clicktheOKbuttonontheInfomessageandtheTextAreaisupdatedlike
this:
Figure92Mainscreenaftererrorhasbeencleared.
ThisshouldgiveyouaprettygoodideaofhowtousetheGambaserror
managementfeaturestohelpmanageerrorswhentheyoccurinyourcode(and
theyinevitablywilloccur). Nothandlingerrorslikethedivbyzeroweusedin
308
Now,runtheprogramagainandclicktheErrorbutton.Hereiswhatyouget:
Figure93DefaultGambaserrordialog.
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
309
Saveyourworkandruntheprogram. ClicktheEventbuttonandyourdisplay
shouldlooklikethis:
Figure94Oureventwasraised.
311
MouseOperations
In Gambas, we can use the Mouse class to obtain information about a
mouseevent. Thisclassdefinestheconstantsusedwiththemouseproperties.
Theclassisstaticandthepropertiessupportedare:
Alt
Meta
ScreenX
Button
Middle
ScreenY
Control
Normal
Shift
Delta
Orientation
X
Left
Right
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
Blank
Pointing
SizeNE
SizeSE
SplitV
Cross
SizeAll
SizeNESW
SizeSW
Text
Custom
SizeE
SizeNW
SizeV
Vertical
Default
SizeH
SizeNWSE
SizeW
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
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
Finally,iftheuserpressesanykey,wewillresetthedrawingareabyclearingit
andredrawthequadrantbycallingthesameroutineusedtoopentheform:
'checkkbdeventstoclearthedrawingareaandredrawthequadrants
PUBLICSUBForm_KeyPress()
da.Clear
Form_Open()
END
That'sit.Whenyouruntheprogram,youshouldseesomethinglike
this:
Figure95MouseOpsprogramrunning.
Asyoumovethemousefromquadranttoquadrant,noticehowthecursor
changes. Tryboththeleftandrightmousebuttonsandpressthespacebarto
clearthedrawingandrestart.Whenyouaresatisfiedeverythingworks,movethe
mousewheelandtheprogramwillterminate. Now,let'slearnaboutkeyboard
operations.
315
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
Enter
Insert
Pause
SysReq
Esc
Menu
Print
Tab
CapsLock
Escape
NumLock
Return
Delete
Help
PageDown
ScrollLock
End
Home
PageUp
Space
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
As you can see, the code above is pretty straightforward and simple.
Whenyouruntheprogram,youshouldseesomethinglikethis:
Figure96KbdOpsprogramrunning.
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
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.
Figure97TheBitOpsprogramindesignmode.
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
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
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
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
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
Figure98OurbitOpsprogramrunning.
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
ConnectionClass
TheConnectionclassestablishesyourconnectiontothedatabase.Inorder
tosuccessfullyconnecttoadatabase,youmustfirstcreatea connectionobject
andsetthenecessarypropertiesthatwillbeusedbythedatabase.Nextyoumust
calltheOpenmethod.IfyouareconnectingtoaSQLitedatabaseandtheName
327
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
The resulting collection of data (which is enumerable using the FOR EACH
328
Host
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
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
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
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
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
TheCreatemethodisusedtobuildaread/writeResultobjectwhichcan
usedtocreaterecordsinatable.Standardcallingconventionis:
FUNCTIONCreate(TableASString)ASResult
Edit
TheEditmethodreturnsaread/writeResultobjectusedforeditingrecords
inthespecifiedtable. Query isequivalenttoanembeddedSQLWHEREclause
usedforfilteringthetable,andtheArgumentsarequotedasneededbytheSQL
syntaxandsubstitutedintheRequeststring(likeinsscanfinC)asweexplained
previously.Standardcallingconventionis:
FUNCTIONEdit(TableASString[,QueryASString,ArgumentsAS,...])ASResult
HereisacodesampletoshowhowEdit()works:
DIMMyResultASResult
DIMsQueryASString
DIMiParmASInteger
sQuery="id=&1"
'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
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
335
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
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
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
Figure99TheFMainformindesignmode.
TheFRequestformismuchsimplertobuild.Itisshowninthefigurebelow:
Figure100FRequestFormindesignmode.
TheFRequestformcontainsasinglecontrol,whichwehavenotpreviously
introduced,theTableViewcontrol. ThiscontrolisfoundintheQTtoolsetwe
discussedpreviously.Wewillshowyouhowtousethiscontrolwhenwediscuss
theFRequestformcodebelow.Fornow,let'sjumpintothecodefortheFMain
formandseehowthingswork.
'Gambasclassfile
$hConn isdeclaredasaprivatevariableandwillbeusedbyallsubroutinesin
339
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
340
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.
341
If,afterthedatabaseconnectionisestablished,theuserwouldclickthe
342
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
'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
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
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
347
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
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
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
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
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
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
CharacternumbersfromU+0000toU+007F(USASCIIset)correspond
tooctets00to7F(7bitUSASCIIvalues).Adirectconsequenceisthat
aplainASCIIstringisalsoavalidUTF8string.
RoundtripconversioniseasybetweenUTF8andotherencodingforms.
Thefirstoctetofamultioctetsequenceindicatesthenumberofoctets
inthesequence.
TheoctetvaluesC0,C1,F5toFFneverappear.
ThebytevaluelexicographicsortingorderofUTF8stringsisthesame
asiforderedbycharacternumbers.Ofcoursethisisoflimitedinterest
sinceasortorderbasedoncharacternumbersisalmostneverculturally
valid.
TheBoyerMoorefastsearchalgorithmcanbeusedwithUTF8data.
TheUTF8encodingisformallydefinedinISO106461:2000AnnexD.It
isalsodescribedinRFC3629aswellassection3.9oftheUnicode4.0standard.
24 See URL http://www.faqs.org/rfcs/rfc2279.html.
354
U-0000007F: 0xxxxxxx
U-000007FF: 110xxxxx 10xxxxxx
U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
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
Figure101ChoosingtheTranslate
optioninGambas.
Next,youmustselectthetargettranslationlanguageinthecomboboxof
thetranslatedialogbox,asshownbelow:
Figure102TheTranslateDialoginGambas.
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
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
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
359
360
Alphabetical Index
Accessfunction................................................................(188)
ACIDcompliant..............................................................(331)
Activateevent..........................................(155,162,168,170)
Addmethod...............................(89,152,154,159,167,175)
ANDoperator.....................................................................(41)
APPENDkeyword...........................................................(192)
Applicationpath..............................................................(327)
Arithmeticoperators..........................................................(36)
Assignmentstatement........................................................(35)
Atomicity.........................................................................(331)
BackColorproperty.............................................(62,67,268)
Backgroundproperty.........................................................(62)
BenotMinisini..............................................(1,19,149,157)
BigEndian.......................................................................(192)
Bitfunctions.....................................................................(319)
Bits...................................................................................(318)
Booleandatatypes.............................................................(31)
Borderproperty..................................................................(63)
Builtinconstants...............................................................(34)
Busyproperty................................................................(151p.)
Byte......................................................................... .........(318)
Bytedatatype.................................................................(31p.)
Cachedproperty...............................................................(267)
Cancelbutton.....................................................................(61)
Cancelproperty..................................................................(63)
Captionproperty..........................................................(64,81)
Carrybit...........................................................................(323)
CASEELSEblock.............................................................(49)
CASEstatement.................................................(48,103,114)
CASEStatement................................................................(48)
CATCHstatement............................................................(305)
CheckBoxclass..................................................................(93)
CheckBoxcontrol.........................................................(92pp.)
Checkedproperty..................................................(100p.,157)
Chr(10).............................................................................(166)
Chr(13).............................................................................(199)
Chr(9).......................................................................(136,194)
Classevent.......................................................................(310)
Classhierarchy...................................................................(28)
Classinvariants................................................................(241)
ClassbasedOOPapproach..............................................(241)
Clickevent.........................................................................(76)
ClickNRun....................................................................(22)
Clipclass..........................................................................(268)
Clippingarea....................................................................(268)
Cohesion..........................................................................(241)
Collections.........................................................................(55)
Colorclass........................................................................(268)
ColumnViewcontrol.......................................(170,174,176)
ComboBoxarrays..............................................................(89)
ComboBoxcontrol............................................(85pp.,185p.)
ComboBoxitems...............................................................(89)
Commandlineinterface...................................................(326)
COMMITstatement.........................................................(331)
Comparisonoperators........................................................(36)
Conditionals.......................................................................(46)
Connectionclass......................................................(327,332)
Connectionobject............................................................(327)
Consistency......................................................................(332)
Constant.............................................................................(34)
Constructorroutine...............................(150,210,213,248p.)
Containerclass...................................................................(62)
Controlclass.......................................................................(61)
ControlGroups................................................................(100)
Controls..............................................................................(58)
COPYfunction.................................................................(195)
Copyrightnotice..................................................................(3)
CopyrightNotice..............................................................(2p.)
Cursorproperty..................................................................(65)
Dataabstraction...............................................................(239)
Databasesproperty...........................................................(328)
Datedatatype....................................................................(32)
Dblclickevent...................................................................(78)
DECoperator.....................................................................(43)
Defaultbutton....................................................................(61)
Defaultproperty.................................................................(66)
Deletemethod....................................................................(70)
Designproperty..................................................................(66)
Desktop.Charset.......................................................(142,152)
Dialogclass...................................................................... (103)
DialogTitleproperty.......................................................(103)
Dirfunction...................................................................... (189)
DIRECTkeyword............................................................(192)
Divisionbyzero..............................................................(39p.)
DivisionbyZero................................................................(40)
DO[WHILE]LOOP..........................................................(51)
Dotnotation.......................................................................(36)
Doubleclickevent.............................................................(77)
Dragmethod.......................................................................(70)
Drawclass.......................................................................(267)
Draw.Ellipsemethod.......................................................(276)
Draw.FillStyle..................................................................(279)
Draw.Linemethod...........................................................(276)
Draw.LineWidthproperty................................................(276)
Draw.Pointmethod..........................................................(274)
Draw.Polygonmethod..................................................(280p.)
Draw.Polylinemethod.............................................(280,282)
Draw.Rectmethod..................................................(274,279)
DrawingAreacontrol.......................................................(271)
Dropproperty.....................................................................(66)
Durability.........................................................................(332)
Enabledproperty................................................................(66)
Encapsulation...................................................................(240)
ENDkeyword....................................................................(37)
ENDWITHinstruction......................................................(35)
Enterevent.........................................................................(74)
Eoffunction.....................................................................(190)
Errorclass........................................................................(304)
Errormanagement............................................................(298)
Error.Classproperty.........................................................(304)
Error.Clear........................................................................(305)
Error.Codeproperty........................................................(304)
Error.Raise.......................................................................(305)
Error.Textproperty..........................................................(304)
Error.Whereproperty.......................................................(305)
Errorsinlogic..................................................................(301)
361
HTML..............................................................(26,81p.,84p.)
HungarianNotation...........................................................(31)
IconEditor.........................................................................(28)
IconViewcontrol........................................(149,154pp.,158)
IFstatement...............................................(47,101,161,168)
IFStatement.......................................................................(47)
IFTHENELSE................................................................(110)
Imageclass....................................................................(284p.)
INCoperator......................................................................(43)
Infiniteloop........................................................................(51)
Inheritance........................................................................(240)
Inkscape...........................................................................(292)
Integerdatatype................................................................(32)
Internationalization....................................................(22,351)
Intrinsicandderivedfunctions........................................(215)
Invertproperty.........................................................(269,275)
IsDirfunction...................................................................(191)
ISO/IEC10646.................................................................(352)
Isolation............................................................................(332)
Java......................................................................(19,53,237)
Javalikearrays..................................................................(53)
Keyclass..........................................................................(316)
KILLfunction..................................................................(196)
LABEL............................................................................ ...(49)
Layoutcontrols.............................................................(176p.)
Leaveevent........................................................................(74)
Leftproperty......................................................................(68)
LIKE....................................................................(43,45,189)
LineStyleproperty...................................................(270,276)
Linspire...........................................................................(22)
Linux......................................(19,142,177,196p.,238,266)
ListEditor........................................................................(185)
ListBoxcontrol...............................................................(89p.)
ListViewcontrol.........................................................(158pp.)
LittleEndian....................................................................(192)
Loadconditions...............................................................(302)
Localization.....................................(138pp.,142p.,145,351)
Lof()function...................................................................(195)
Loginproperty................................................................(329)
Loopingstructures.............................................................(49)
Lowermethod....................................................................(71)
MenuEditor............................................................(98p.,197)
MenuItems.........................................................................(99)
Messageclass...................................................................(112)
MessageBoxcontrol........................................................(112)
MicrosoftVisualBasic...................................................(19)
MIMETYPE......................................................................(70)
MKDIRfunction..............................................................(196)
MODfunction....................................................................(40)
MODoperator....................................................................(40)
Mouseclass...................................................................... (312)
Mouseproperty..................................................................(68)
Movemethod.....................................................................(71)
MoveCurrentmethod...................................(161,165p.,168)
MySQL.............................................................................(326)
MySQLmanual................................................................(326)
MySQLserver..................................................................(326)
Nameproperty................................................................(329)
Nativearray........................................................................(53)
NEWkeyword....................................................................(30)
362
ScrollViewcontrol...........................................................(294)
SELECTstatement............................................(48,105,114)
SelectColorDialog..................................................(103,105)
SelectDirectoryDialog............................................(104,119)
SelectFontDialog.......................................................(108pp.)
SelectionTool....................................................................(28)
SetFocusmethod................................................................(72)
SetFocus()method.............................................................(69)
Shortdatatype...................................................................(32)
Showmethod.....................................................................(71)
SQLWHEREstatement.................................................(333)
SQLite..............................................................................(326)
Standaloneexecutable.......................................................(20)
Statfunction.....................................................(150,153,191)
STATICkeyword...............................................................(30)
StatusBar...........................................................................(26)
STEPkeyword...................................................................(50)
Stringconstants...............................................................(34p.)
Stringdatatype.............................................(32,34,55,126)
Stringfunctions................................................................(125)
Stringoperators..................................................................(36)
SubMenus..........................................................................(99)
SVG..................................................................................(292)
SVGspecification............................................................(292)
Systemclass...............................................................(91,150)
Tablesproperty................................................................(330)
TableViewcontrol...........................................................(348)
TabStripcontrol............................................................(181p.)
Tagproperty.......................................................................(69)
Temp$function................................................................(192)
Terminalapplication..........................................(37,125,232)
Textproperty...............................................................(64,69)
Textboxcontrol..........................................................(83,166)
TextBoxcontrol......................................................(82p.,252)
TextHeightproperty.........................................................(272)
TextWidthproperty.........................................................(272)
Timerevent......................................................................(186)
ToggleButtoncontrol......................................................(92p.)
ToolBar..............................................................................(28)
ToolBox.............................................................................(27)
ToolBoxwindow......................................................(27p.,60)
ToolTip..............................................................................(28)
ToolTipproperty................................................................(69)
Topproperty.......................................................................(70)
Transaction.......................................................................(331)
Transparentproperty........................................................(270)
Treeview...........................................................................(105)
TreeView......................................(25,28,37,57pp.,64,163)
TreeViewcontrol...........................................(163pp.,167pp.)
Trolltech......................................................................... ..(347)
TRY..................................................................................(304)
TRYstatement.................................................................(305)
Typeproperty...................................................................(330)
UCS2...............................................................................(353)
UCS4...............................................................................(353)
Unicodestandard.............................................................(352)
Usersproperty..................................................................(330)
UTF8............................................................................ ...(353)
UTF8charset..........................................................(135,141)
Validationerror................................................................(298)
363
WHILE...WEND..............................................................(52)
Widthproperty...................................................(68,272,276)
Wikipedia.........................................................................(215)
Windowproperty...............................................................(70)
WITH.................................................................................(35)
WITHkeyword..................................................................(35)
Xproperty..........................................................................(68)
XWindows........................................................................(78)
X/OpenJointInternationalizationGroup........................(353)
XORoperator.....................................................................(42)
Yproperty..........................................................................(68)
364